From 729a1cbc9fc4a2b8879d19bc3fa28036e09e4d9e Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Fri, 9 Feb 2024 22:07:59 +0200 Subject: [PATCH] encoding.binary: add _fixed variants for the conversion fns, that accept fixed arrays (#20766) --- vlib/encoding/binary/big_endian_fixed.v | 51 ++++++++++++++++++ vlib/encoding/binary/big_endian_fixed_test.v | 53 ++++++++++++++++++ vlib/encoding/binary/little_endian_fixed.v | 51 ++++++++++++++++++ .../binary/little_endian_fixed_test.v | 54 +++++++++++++++++++ 4 files changed, 209 insertions(+) create mode 100644 vlib/encoding/binary/big_endian_fixed.v create mode 100644 vlib/encoding/binary/big_endian_fixed_test.v create mode 100644 vlib/encoding/binary/little_endian_fixed.v create mode 100644 vlib/encoding/binary/little_endian_fixed_test.v diff --git a/vlib/encoding/binary/big_endian_fixed.v b/vlib/encoding/binary/big_endian_fixed.v new file mode 100644 index 0000000000..7ca8b46bb8 --- /dev/null +++ b/vlib/encoding/binary/big_endian_fixed.v @@ -0,0 +1,51 @@ +// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. +module binary + +// big_endian_u16_fixed creates a u16 from the first two bytes in the fixed array b in big endian order. +@[direct_array_access; inline] +pub fn big_endian_u16_fixed(b [2]u8) u16 { + return u16(b[1]) | (u16(b[0]) << u16(8)) +} + +// big_endian_put_u16_fixed writes a u16 to the fixed array b in big endian order. +@[direct_array_access; inline] +pub fn big_endian_put_u16_fixed(mut b [2]u8, v u16) { + b[0] = u8(v >> u16(8)) + b[1] = u8(v) +} + +// big_endian_u32_fixed creates a u32 from four bytes in the fixed array b in big endian order. +@[direct_array_access; inline] +pub fn big_endian_u32_fixed(b [4]u8) u32 { + return u32(b[3]) | (u32(b[2]) << u32(8)) | (u32(b[1]) << u32(16)) | (u32(b[0]) << u32(24)) +} + +// big_endian_put_u32_fixed writes a u32 to the fixed array b in big endian order. +@[direct_array_access; inline] +pub fn big_endian_put_u32_fixed(mut b [4]u8, v u32) { + b[0] = u8(v >> u32(24)) + b[1] = u8(v >> u32(16)) + b[2] = u8(v >> u32(8)) + b[3] = u8(v) +} + +// big_endian_u64_fixed creates a u64 from the fixed array b in big endian order. +@[direct_array_access; inline] +pub fn big_endian_u64_fixed(b [8]u8) u64 { + return u64(b[7]) | (u64(b[6]) << u64(8)) | (u64(b[5]) << u64(16)) | (u64(b[4]) << u64(24)) | (u64(b[3]) << u64(32)) | (u64(b[2]) << u64(40)) | (u64(b[1]) << u64(48)) | (u64(b[0]) << u64(56)) +} + +// big_endian_put_u64_fixed writes a u64 to the fixed array b in big endian order. +@[direct_array_access; inline] +pub fn big_endian_put_u64_fixed(mut b [8]u8, v u64) { + b[0] = u8(v >> u64(56)) + b[1] = u8(v >> u64(48)) + b[2] = u8(v >> u64(40)) + b[3] = u8(v >> u64(32)) + b[4] = u8(v >> u64(24)) + b[5] = u8(v >> u64(16)) + b[6] = u8(v >> u64(8)) + b[7] = u8(v) +} diff --git a/vlib/encoding/binary/big_endian_fixed_test.v b/vlib/encoding/binary/big_endian_fixed_test.v new file mode 100644 index 0000000000..dec4dffb0e --- /dev/null +++ b/vlib/encoding/binary/big_endian_fixed_test.v @@ -0,0 +1,53 @@ +module binary + +// Big Endian Tests +fn test_big_endian_u16_fixed() { + assert big_endian_u16_fixed([u8(0), 1]!) == u16(1) + assert big_endian_u16_fixed([u8(5), 4]!) == u16(0x0504) + assert big_endian_u16_fixed([u8(0x35), 0x57]!) == u16(0x3557) + assert big_endian_u16_fixed([u8(0x35), 0x57]!) != u16(0x5735) +} + +fn test_big_endian_put_u16_fixed() { + mut buf := [2]u8{} + big_endian_put_u16_fixed(mut buf, 0x8725) + assert buf == [u8(0x87), 0x25]! + big_endian_put_u16_fixed(mut buf, 0) + assert buf == [u8(0), 0]! + big_endian_put_u16_fixed(mut buf, 0xfdff) + assert buf == [u8(0xfd), 0xff]! +} + +fn test_big_endian_u32_fixed() { + assert big_endian_u32_fixed([u8(0), 0, 0, 1]!) == u32(1) + assert big_endian_u32_fixed([u8(5), 4, 9, 1]!) == u32(0x05040901) + assert big_endian_u32_fixed([u8(0xf8), 0xa2, 0x9e, 0x21]!) == u32(0xf8a29e21) + assert big_endian_u32_fixed([u8(0xf8), 0xa2, 0x9e, 0x21]!) != u32(0x2192a2f8) +} + +fn test_big_endian_put_u32_fixed() { + mut buf := [4]u8{} + big_endian_put_u32_fixed(mut buf, 0x872fea95) + assert buf == [u8(0x87), 0x2f, 0xea, 0x95]! + big_endian_put_u32_fixed(mut buf, 0) + assert buf == [u8(0), 0, 0, 0]! + big_endian_put_u32_fixed(mut buf, 0xfdf2e68f) + assert buf == [u8(0xfd), 0xf2, 0xe6, 0x8f]! +} + +fn test_big_endian_u64_fixed() { + assert big_endian_u64_fixed([u8(0), 0, 0, 0, 0, 0, 0, 1]!) == u64(1) + assert big_endian_u64_fixed([u8(5), 4, 9, 1, 7, 3, 6, 8]!) == u64(0x0504090107030608) + assert big_endian_u64_fixed([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]!) == u64(0xf8a29e217f9f8e8f) + assert big_endian_u64_fixed([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]!) != u64(0x8f8e9f7f219ea2f8) +} + +fn test_big_endian_put_u64_fixed() { + mut buf := [8]u8{} + big_endian_put_u64_fixed(mut buf, 0x872fea95fdf2e68f) + assert buf == [u8(0x87), 0x2f, 0xea, 0x95, 0xfd, 0xf2, 0xe6, 0x8f]! + big_endian_put_u64_fixed(mut buf, 0) + assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 0]! + big_endian_put_u64_fixed(mut buf, 0xfdf2e68f8e9f7f21) + assert buf == [u8(0xfd), 0xf2, 0xe6, 0x8f, 0x8e, 0x9f, 0x7f, 0x21]! +} diff --git a/vlib/encoding/binary/little_endian_fixed.v b/vlib/encoding/binary/little_endian_fixed.v new file mode 100644 index 0000000000..5074f0a0ae --- /dev/null +++ b/vlib/encoding/binary/little_endian_fixed.v @@ -0,0 +1,51 @@ +// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. +module binary + +// little_endian_u16_fixed creates a u16 from the fixed array b in little endian order. +@[direct_array_access; inline] +pub fn little_endian_u16_fixed(b [2]u8) u16 { + return u16(b[0]) | (u16(b[1]) << u16(8)) +} + +// little_endian_put_u16_fixed writes a u16 to the fixed array b in little endian order. +@[direct_array_access; inline] +pub fn little_endian_put_u16_fixed(mut b [2]u8, v u16) { + b[0] = u8(v) + b[1] = u8(v >> u16(8)) +} + +// little_endian_u32_fixed creates a u32 from the fixed array b in little endian order. +@[direct_array_access; inline] +pub fn little_endian_u32_fixed(b [4]u8) u32 { + return u32(b[0]) | (u32(b[1]) << u32(8)) | (u32(b[2]) << u32(16)) | (u32(b[3]) << u32(24)) +} + +// little_endian_put_u32_fixed writes a u32 to the fixed array b in little endian order. +@[direct_array_access; inline] +pub fn little_endian_put_u32_fixed(mut b [4]u8, v u32) { + b[0] = u8(v) + b[1] = u8(v >> u32(8)) + b[2] = u8(v >> u32(16)) + b[3] = u8(v >> u32(24)) +} + +// little_endian_u64_fixed creates a u64 from the fixed array b in little endian order. +@[direct_array_access; inline] +pub fn little_endian_u64_fixed(b [8]u8) u64 { + return u64(b[0]) | (u64(b[1]) << u64(8)) | (u64(b[2]) << u64(16)) | (u64(b[3]) << u64(24)) | (u64(b[4]) << u64(32)) | (u64(b[5]) << u64(40)) | (u64(b[6]) << u64(48)) | (u64(b[7]) << u64(56)) +} + +// little_endian_put_u64_fixed writes a u64 to the fixed array b in little endian order. +@[direct_array_access; inline] +pub fn little_endian_put_u64_fixed(mut b [8]u8, v u64) { + b[0] = u8(v) + b[1] = u8(v >> u64(8)) + b[2] = u8(v >> u64(16)) + b[3] = u8(v >> u64(24)) + b[4] = u8(v >> u64(32)) + b[5] = u8(v >> u64(40)) + b[6] = u8(v >> u64(48)) + b[7] = u8(v >> u64(56)) +} diff --git a/vlib/encoding/binary/little_endian_fixed_test.v b/vlib/encoding/binary/little_endian_fixed_test.v new file mode 100644 index 0000000000..c6be570921 --- /dev/null +++ b/vlib/encoding/binary/little_endian_fixed_test.v @@ -0,0 +1,54 @@ +module binary + +// Little Endian Tests + +fn test_little_endian_u16_fixed() { + assert little_endian_u16_fixed([u8(0), 0]!) == u16(0) + assert little_endian_u16_fixed([u8(5), 4]!) == u16(0x0405) + assert little_endian_u16_fixed([u8(0x35), 0x57]!) == u16(0x5735) + assert little_endian_u16_fixed([u8(0x35), 0x57]!) != u16(0x3557) +} + +fn test_little_endian_put_u16_fixed() { + mut buf := [2]u8{} + little_endian_put_u16_fixed(mut buf, 0x8725) + assert buf == [u8(0x25), 0x87]! + little_endian_put_u16_fixed(mut buf, 0) + assert buf == [u8(0), 0]! + little_endian_put_u16_fixed(mut buf, 0xfdff) + assert buf == [u8(0xff), 0xfd]! +} + +fn test_little_endian_u32_fixed() { + assert little_endian_u32_fixed([u8(0), 0, 0, 0]!) == u32(0) + assert little_endian_u32_fixed([u8(5), 4, 9, 1]!) == u32(0x01090405) + assert little_endian_u32_fixed([u8(0xf8), 0xa2, 0x9e, 0x21]!) == u32(0x219ea2f8) + assert little_endian_u32_fixed([u8(0xf8), 0xa2, 0x9e, 0x21]!) != u32(0xf8a29e21) +} + +fn test_little_endian_put_u32_fixed() { + mut buf := [4]u8{} + little_endian_put_u32_fixed(mut buf, 0x872fea95) + assert buf == [u8(0x95), 0xea, 0x2f, 0x87]! + little_endian_put_u32_fixed(mut buf, 0) + assert buf == [u8(0), 0, 0, 0]! + little_endian_put_u32_fixed(mut buf, 0xfdf2e68f) + assert buf == [u8(0x8f), 0xe6, 0xf2, 0xfd]! +} + +fn test_little_endian_u64_fixed() { + assert little_endian_u64_fixed([u8(0), 0, 0, 0, 0, 0, 0, 0]!) == u64(0) + assert little_endian_u64_fixed([u8(5), 4, 9, 1, 7, 3, 6, 8]!) == u64(0x0806030701090405) + assert little_endian_u64_fixed([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]!) == u64(0x8f8e9f7f219ea2f8) + assert little_endian_u64_fixed([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]!) != u64(0xf8a29e217f9f8e8f) +} + +fn test_little_endian_put_u64_fixed() { + mut buf := [8]u8{} + little_endian_put_u64_fixed(mut buf, 0x872fea95fdf2e68f) + assert buf == [u8(0x8f), 0xe6, 0xf2, 0xfd, 0x95, 0xea, 0x2f, 0x87]! + little_endian_put_u64_fixed(mut buf, 0) + assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 0]! + little_endian_put_u64_fixed(mut buf, 0xfdf2e68f8e9f7f21) + assert buf == [u8(0x21), 0x7f, 0x9f, 0x8e, 0x8f, 0xe6, 0xf2, 0xfd]! +}