From 9561fb406e351468c36294c11175925227f5a3ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nacho=20Verd=C3=B3n?= Date: Mon, 1 Aug 2022 07:20:14 +0200 Subject: [PATCH] encoding.binary: add functions to read/write with an offset and at the end of the array, split files by endianness (#15301) --- vlib/encoding/binary/big_endian.v | 153 ++++++++++++++++++ vlib/encoding/binary/big_endian_test.v | 169 +++++++++++++++++++ vlib/encoding/binary/binary.v | 110 ------------- vlib/encoding/binary/binary_test.v | 107 ------------ vlib/encoding/binary/little_endian.v | 153 ++++++++++++++++++ vlib/encoding/binary/little_endian_test.v | 188 ++++++++++++++++++++++ 6 files changed, 663 insertions(+), 217 deletions(-) create mode 100644 vlib/encoding/binary/big_endian.v create mode 100644 vlib/encoding/binary/big_endian_test.v delete mode 100644 vlib/encoding/binary/binary.v delete mode 100644 vlib/encoding/binary/binary_test.v create mode 100644 vlib/encoding/binary/little_endian.v create mode 100644 vlib/encoding/binary/little_endian_test.v diff --git a/vlib/encoding/binary/big_endian.v b/vlib/encoding/binary/big_endian.v new file mode 100644 index 0000000000..3ce5cfb796 --- /dev/null +++ b/vlib/encoding/binary/big_endian.v @@ -0,0 +1,153 @@ +// Copyright (c) 2019-2022 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 creates a u16 from the first two bytes in the array b in big endian order. +[direct_array_access; inline] +pub fn big_endian_u16(b []u8) u16 { + _ = b[1] // bounds check + return u16(b[1]) | (u16(b[0]) << u16(8)) +} + +// big_endian_u16 creates a u16 from two bytes in the array b at the specified offset in big endian order. +[direct_array_access; inline] +pub fn big_endian_u16_at(b []u8, o int) u16 { + _ = b[o] // bounds check + _ = b[o + 1] // bounds check + return u16(b[o + 1]) | (u16(b[o]) << u16(8)) +} + +// big_endian_u16 creates a u16 from two bytes in the array b at the specified offset in big endian order. +[direct_array_access; inline] +pub fn big_endian_u16_end(b []u8) u16 { + return big_endian_u16_at(b, b.len - 2) +} + +// big_endian_put_u16 writes a u16 to the first two bytes in the array b in big endian order. +[direct_array_access; inline] +pub fn big_endian_put_u16(mut b []u8, v u16) { + _ = b[1] // bounds check + b[0] = u8(v >> u16(8)) + b[1] = u8(v) +} + +// big_endian_put_u16 writes a u16 to the two bytes in the array b at the specified offset in big endian order. +[direct_array_access; inline] +pub fn big_endian_put_u16_at(mut b []u8, v u16, o int) { + _ = b[o] // bounds check + _ = b[o + 1] // bounds check + b[o] = u8(v >> u16(8)) + b[o + 1] = u8(v) +} + +// big_endian_put_u16 writes a u16 to the last two bytes in the array b in big endian order. +[direct_array_access; inline] +pub fn big_endian_put_u16_end(mut b []u8, v u16) { + big_endian_put_u16_at(mut b, v, b.len - 2) +} + +// big_endian_u32 creates a u32 from four bytes in the array b in big endian order. +[direct_array_access; inline] +pub fn big_endian_u32(b []u8) u32 { + _ = b[3] // bounds check + return u32(b[3]) | (u32(b[2]) << u32(8)) | (u32(b[1]) << u32(16)) | (u32(b[0]) << u32(24)) +} + +// big_endian_u32 creates a u32 from four bytes in the array b at the specified offset in big endian order. +[direct_array_access; inline] +pub fn big_endian_u32_at(b []u8, o int) u32 { + _ = b[o] // bounds check + _ = b[o + 3] // bounds check + return u32(b[o + 3]) | (u32(b[o + 2]) << u32(8)) | (u32(b[o + 1]) << u32(16)) | (u32(b[o]) << u32(24)) +} + +// big_endian_u32 creates a u32 from the last four bytes in the array b in big endian order. +[direct_array_access; inline] +pub fn big_endian_u32_end(b []u8) u32 { + return big_endian_u32_at(b, b.len - 4) +} + +// big_endian_put_u32 writes a u32 to the first four bytes in the array b in big endian order. +[direct_array_access; inline] +pub fn big_endian_put_u32(mut b []u8, v u32) { + _ = b[3] // bounds check + b[0] = u8(v >> u32(24)) + b[1] = u8(v >> u32(16)) + b[2] = u8(v >> u32(8)) + b[3] = u8(v) +} + +// big_endian_put_u32 writes a u32 to four bytes in the array b at the specified offset in big endian order. +[direct_array_access; inline] +pub fn big_endian_put_u32_at(mut b []u8, v u32, o int) { + _ = b[o] // bounds check + _ = b[o + 3] // bounds check + b[o] = u8(v >> u32(24)) + b[o + 1] = u8(v >> u32(16)) + b[o + 2] = u8(v >> u32(8)) + b[o + 3] = u8(v) +} + +// big_endian_put_u32 writes a u32 to the last four bytes in the array b in big endian order. +[direct_array_access; inline] +pub fn big_endian_put_u32_end(mut b []u8, v u32) { + big_endian_put_u32_at(mut b, v, b.len - 4) +} + +// big_endian_u64 creates a u64 from the first eight bytes in the array b in big endian order. +[direct_array_access; inline] +pub fn big_endian_u64(b []u8) u64 { + _ = b[7] // bounds check + 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_u64 creates a u64 from eight bytes in the array b at the specified offset in big endian order. +[direct_array_access; inline] +pub fn big_endian_u64_at(b []u8, o int) u64 { + _ = b[o] // bounds check + _ = b[o + 7] // bounds check + return u64(b[o + 7]) | (u64(b[o + 6]) << u64(8)) | (u64(b[o + 5]) << u64(16)) | (u64(b[o + 4]) << u64(24)) | (u64(b[ + o + 3]) << u64(32)) | (u64(b[o + 2]) << u64(40)) | (u64(b[o + 1]) << u64(48)) | (u64(b[o]) << u64(56)) +} + +// big_endian_u64 creates a u64 from the last eight bytes in the array b in big endian order. +[direct_array_access; inline] +pub fn big_endian_u64_end(b []u8) u64 { + return big_endian_u64_at(b, b.len - 8) +} + +// big_endian_put_u64 writes a u64 to the first eight bytes in the array b in big endian order. +[direct_array_access; inline] +pub fn big_endian_put_u64(mut b []u8, v u64) { + _ = b[7] // bounds check + 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) +} + +// big_endian_put_u64 writes a u64 to eight bytes in the array b at the specified offset in big endian order. +[direct_array_access; inline] +pub fn big_endian_put_u64_at(mut b []u8, v u64, o int) { + _ = b[o] // bounds check + _ = b[o + 7] // bounds check + b[o] = u8(v >> u64(56)) + b[o + 1] = u8(v >> u64(48)) + b[o + 2] = u8(v >> u64(40)) + b[o + 3] = u8(v >> u64(32)) + b[o + 4] = u8(v >> u64(24)) + b[o + 5] = u8(v >> u64(16)) + b[o + 6] = u8(v >> u64(8)) + b[o + 7] = u8(v) +} + +// big_endian_put_u64 writes a u64 to the last eight bytes in the array b at the specified offset in big endian order. +[direct_array_access; inline] +pub fn big_endian_put_u64_end(mut b []u8, v u64) { + big_endian_put_u64_at(mut b, v, b.len - 8) +} diff --git a/vlib/encoding/binary/big_endian_test.v b/vlib/encoding/binary/big_endian_test.v new file mode 100644 index 0000000000..d2c07bfafd --- /dev/null +++ b/vlib/encoding/binary/big_endian_test.v @@ -0,0 +1,169 @@ +module binary + +// Big Endian Tests +fn test_big_endian_u16() { + assert big_endian_u16([u8(0), 1]) == u16(1) + assert big_endian_u16([u8(5), 4]) == u16(0x0504) + assert big_endian_u16([u8(0x35), 0x57]) == u16(0x3557) + assert big_endian_u16([u8(0x35), 0x57]) != u16(0x5735) +} + +fn test_big_endian_u16_at() { + assert big_endian_u16_at([u8(0), 0, 1, 0], 1) == u16(1) + assert big_endian_u16_at([u8(0), 5, 4, 0], 1) == u16(0x0504) + assert big_endian_u16_at([u8(0), 0x35, 0x57, 0], 1) == u16(0x3557) + assert big_endian_u16_at([u8(0), 0x35, 0x57, 0], 1) != u16(0x5735) +} + +fn test_big_endian_u16_end() { + assert big_endian_u16_end([u8(0), 0, 0, 1]) == u16(1) + assert big_endian_u16_end([u8(0), 0, 5, 4]) == u16(0x0504) + assert big_endian_u16_end([u8(0), 0, 0x35, 0x57]) == u16(0x3557) + assert big_endian_u16_end([u8(0), 0, 0x35, 0x57]) != u16(0x5735) +} + +fn test_big_endian_put_u16() { + mut buf := []u8{len: 2} + big_endian_put_u16(mut buf, 0x8725) + assert buf == [u8(0x87), 0x25] + big_endian_put_u16(mut buf, 0) + assert buf == [u8(0), 0] + big_endian_put_u16(mut buf, 0xfdff) + assert buf == [u8(0xfd), 0xff] +} + +fn test_big_endian_put_u16_at() { + mut buf := []u8{len: 4} + big_endian_put_u16_at(mut buf, 0x8725, 1) + assert buf == [u8(0), 0x87, 0x25, 0] + + buf = []u8{len: 4} + big_endian_put_u16_at(mut buf, 1, 1) + assert buf == [u8(0), 0, 1, 0] + + buf = []u8{len: 4} + big_endian_put_u16_at(mut buf, 0xfdff, 1) + assert buf == [u8(0), 0xfd, 0xff, 0] +} + +fn test_big_endian_u32() { + assert big_endian_u32([u8(0), 0, 0, 1]) == u32(1) + assert big_endian_u32([u8(5), 4, 9, 1]) == u32(0x05040901) + assert big_endian_u32([u8(0xf8), 0xa2, 0x9e, 0x21]) == u32(0xf8a29e21) + assert big_endian_u32([u8(0xf8), 0xa2, 0x9e, 0x21]) != u32(0x2192a2f8) +} + +fn test_big_endian_u32_at() { + assert big_endian_u32_at([u8(0), 0, 0, 0, 1, 0, 0, 0], 1) == u32(1) + assert big_endian_u32_at([u8(0), 5, 4, 9, 1, 0, 0, 0], 1) == u32(0x05040901) + assert big_endian_u32_at([u8(0), 0xf8, 0xa2, 0x9e, 0x21, 0, 0, 0], 1) == u32(0xf8a29e21) + assert big_endian_u32_at([u8(0), 0xf8, 0xa2, 0x9e, 0x21, 0, 0, 0], 1) != u32(0x2192a2f8) +} + +fn test_big_endian_u32_end() { + assert big_endian_u32_end([u8(0), 0, 0, 0, 0, 0, 1]) == u32(1) + assert big_endian_u32_end([u8(0), 0, 0, 0, 5, 4, 9, 1]) == u32(0x05040901) + assert big_endian_u32_end([u8(0), 0, 0, 0, 0xf8, 0xa2, 0x9e, 0x21]) == u32(0xf8a29e21) + assert big_endian_u32_end([u8(0), 0, 0, 0, 0xf8, 0xa2, 0x9e, 0x21]) != u32(0x2192a2f8) +} + +fn test_big_endian_put_u32() { + mut buf := []u8{len: 4} + big_endian_put_u32(mut buf, 0x872fea95) + assert buf == [u8(0x87), 0x2f, 0xea, 0x95] + big_endian_put_u32(mut buf, 0) + assert buf == [u8(0), 0, 0, 0] + big_endian_put_u32(mut buf, 0xfdf2e68f) + assert buf == [u8(0xfd), 0xf2, 0xe6, 0x8f] +} + +fn test_big_endian_put_u32_at() { + mut buf := []u8{len: 8} + big_endian_put_u32_at(mut buf, 0x872fea95, 1) + assert buf == [u8(0), 0x87, 0x2f, 0xea, 0x95, 0, 0, 0] + + buf = []u8{len: 8} + big_endian_put_u32_at(mut buf, 1, 1) + assert buf == [u8(0), 0, 0, 0, 1, 0, 0, 0] + + buf = []u8{len: 8} + big_endian_put_u32_at(mut buf, 0xfdf2e68f, 1) + assert buf == [u8(0), 0xfd, 0xf2, 0xe6, 0x8f, 0, 0, 0] +} + +fn test_big_endian_put_u32_end() { + mut buf := []u8{len: 8} + big_endian_put_u32_end(mut buf, 0x872fea95) + assert buf == [u8(0), 0, 0, 0, 0x87, 0x2f, 0xea, 0x95] + + buf = []u8{len: 8} + big_endian_put_u32_end(mut buf, 1) + assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 1] + + buf = []u8{len: 8} + big_endian_put_u32_end(mut buf, 0xfdf2e68f) + assert buf == [u8(0), 0, 0, 0, 0xfd, 0xf2, 0xe6, 0x8f] +} + +fn test_big_endian_u64() { + assert big_endian_u64([u8(0), 0, 0, 0, 0, 0, 0, 1]) == u64(1) + assert big_endian_u64([u8(5), 4, 9, 1, 7, 3, 6, 8]) == u64(0x0504090107030608) + assert big_endian_u64([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]) == u64(0xf8a29e217f9f8e8f) + assert big_endian_u64([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]) != u64(0x8f8e9f7f219ea2f8) +} + +fn test_big_endian_u64_at() { + assert big_endian_u64_at([u8(0), 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], 1) == u64(1) + assert big_endian_u64_at([u8(0), 5, 4, 9, 1, 7, 3, 6, 8, 0, 0, 0, 0, 0, 0, 0], 1) == u64(0x0504090107030608) + assert big_endian_u64_at([u8(0), 0xf8, 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f, 0, 0, 0, 0, + 0, 0, 0], 1) == u64(0xf8a29e217f9f8e8f) + assert big_endian_u64_at([u8(0), 0xf8, 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f, 0, 0, 0, 0, + 0, 0, 0], 1) != u64(0x8f8e9f7f219ea2f8) +} + +fn test_big_endian_u64_end() { + assert big_endian_u64_end([u8(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) == u64(1) + assert big_endian_u64_end([u8(0), 0, 0, 0, 0, 0, 0, 0, 5, 4, 9, 1, 7, 3, 6, 8]) == u64(0x0504090107030608) + assert big_endian_u64_end([u8(0), 0, 0, 0, 0, 0, 0, 0, 0xf8, 0xa2, 0x9e, 0x21, 0x7f, 0x9f, + 0x8e, 0x8f]) == u64(0xf8a29e217f9f8e8f) + assert big_endian_u64_end([u8(0), 0, 0, 0, 0, 0, 0, 0, 0xf8, 0xa2, 0x9e, 0x21, 0x7f, 0x9f, + 0x8e, 0x8f]) != u64(0x8f8e9f7f219ea2f8) +} + +fn test_big_endian_put_u64() { + mut buf := []u8{len: 8} + big_endian_put_u64(mut buf, 0x872fea95fdf2e68f) + assert buf == [u8(0x87), 0x2f, 0xea, 0x95, 0xfd, 0xf2, 0xe6, 0x8f] + big_endian_put_u64(mut buf, 0) + assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 0] + big_endian_put_u64(mut buf, 0xfdf2e68f8e9f7f21) + assert buf == [u8(0xfd), 0xf2, 0xe6, 0x8f, 0x8e, 0x9f, 0x7f, 0x21] +} + +fn test_big_endian_put_u64_at() { + mut buf := []u8{len: 16} + big_endian_put_u64_at(mut buf, 0x872fea95fdf2e68f, 1) + assert buf == [u8(0), 0x87, 0x2f, 0xea, 0x95, 0xfd, 0xf2, 0xe6, 0x8f, 0, 0, 0, 0, 0, 0, 0] + + buf = []u8{len: 16} + big_endian_put_u64_at(mut buf, 1, 1) + assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0] + + buf = []u8{len: 16} + big_endian_put_u64_at(mut buf, 0xfdf2e68f8e9f7f21, 1) + assert buf == [u8(0), 0xfd, 0xf2, 0xe6, 0x8f, 0x8e, 0x9f, 0x7f, 0x21, 0, 0, 0, 0, 0, 0, 0] +} + +fn test_big_endian_put_u64_end() { + mut buf := []u8{len: 16} + big_endian_put_u64_end(mut buf, 0x872fea95fdf2e68f) + assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 0, 0x87, 0x2f, 0xea, 0x95, 0xfd, 0xf2, 0xe6, 0x8f] + + buf = []u8{len: 16} + big_endian_put_u64_end(mut buf, 1) + assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] + + buf = []u8{len: 16} + big_endian_put_u64_end(mut buf, 0xfdf2e68f8e9f7f21) + assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 0, 0xfd, 0xf2, 0xe6, 0x8f, 0x8e, 0x9f, 0x7f, 0x21] +} diff --git a/vlib/encoding/binary/binary.v b/vlib/encoding/binary/binary.v deleted file mode 100644 index 7512863a4b..0000000000 --- a/vlib/encoding/binary/binary.v +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2019-2022 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 creates a u16 from two bytes in the array b in little endian order. -[direct_array_access; inline] -pub fn little_endian_u16(b []u8) u16 { - _ = b[1] // bounds check - return u16(b[0]) | (u16(b[1]) << u16(8)) -} - -// little_endian_put_u16 writes a u16 to the first two bytes in the array b in little endian order. -[direct_array_access; inline] -pub fn little_endian_put_u16(mut b []u8, v u16) { - _ = b[1] // bounds check - b[0] = u8(v) - b[1] = u8(v >> u16(8)) -} - -// little_endian_u32 creates a u32 from four bytes in the array b in little endian order. -[direct_array_access; inline] -pub fn little_endian_u32(b []u8) u32 { - _ = b[3] // bounds check - return u32(b[0]) | (u32(b[1]) << u32(8)) | (u32(b[2]) << u32(16)) | (u32(b[3]) << u32(24)) -} - -// little_endian_put_u32 writes a u32 to the first four bytes in the array b in little endian order. -[direct_array_access; inline] -pub fn little_endian_put_u32(mut b []u8, v u32) { - _ = b[3] // bounds check - 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 creates a u64 from eight bytes in the array b in little endian order. -[direct_array_access; inline] -pub fn little_endian_u64(b []u8) u64 { - _ = b[7] // bounds check - 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 writes a u64 to the first eight bytes in the array b in little endian order. -[direct_array_access; inline] -pub fn little_endian_put_u64(mut b []u8, v u64) { - _ = b[7] // bounds check - 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)) -} - -// big_endian_u16 creates a u16 from two bytes in the array b in big endian order. -[direct_array_access; inline] -pub fn big_endian_u16(b []u8) u16 { - _ = b[1] // bounds check - return u16(b[1]) | (u16(b[0]) << u16(8)) -} - -// big_endian_put_u16 writes a u16 to the first two bytes in the array b in big endian order. -[direct_array_access; inline] -pub fn big_endian_put_u16(mut b []u8, v u16) { - _ = b[1] // bounds check - b[0] = u8(v >> u16(8)) - b[1] = u8(v) -} - -// big_endian_u32 creates a u32 from four bytes in the array b in big endian order. -[direct_array_access; inline] -pub fn big_endian_u32(b []u8) u32 { - _ = b[3] // bounds check - return u32(b[3]) | (u32(b[2]) << u32(8)) | (u32(b[1]) << u32(16)) | (u32(b[0]) << u32(24)) -} - -// big_endian_put_u32 writes a u32 to the first four bytes in the array b in big endian order. -[direct_array_access; inline] -pub fn big_endian_put_u32(mut b []u8, v u32) { - _ = b[3] // bounds check - 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 creates a u64 from eight bytes in the array b in big endian order. -[direct_array_access; inline] -pub fn big_endian_u64(b []u8) u64 { - _ = b[7] // bounds check - 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 writes a u64 to the first eight bytes in the array b in big endian order. -[direct_array_access; inline] -pub fn big_endian_put_u64(mut b []u8, v u64) { - _ = b[7] // bounds check - 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/binary_test.v b/vlib/encoding/binary/binary_test.v deleted file mode 100644 index b1a34a74ed..0000000000 --- a/vlib/encoding/binary/binary_test.v +++ /dev/null @@ -1,107 +0,0 @@ -module binary - -// Little Endian Tests - -fn test_little_endian_u16() { - assert little_endian_u16([u8(0), 0]) == u16(0) - assert little_endian_u16([u8(5), 4]) == u16(0x0405) - assert little_endian_u16([u8(0x35), 0x57]) == u16(0x5735) - assert little_endian_u16([u8(0x35), 0x57]) != u16(0x3557) -} - -fn test_little_endian_put_u16() { - mut buf := []u8{len: 2} - little_endian_put_u16(mut buf, 0x8725) - assert buf == [u8(0x25), 0x87] - little_endian_put_u16(mut buf, 0) - assert buf == [u8(0), 0] - little_endian_put_u16(mut buf, 0xfdff) - assert buf == [u8(0xff), 0xfd] -} - -fn test_little_endian_u32() { - assert little_endian_u32([u8(0), 0, 0, 0]) == u32(0) - assert little_endian_u32([u8(5), 4, 9, 1]) == u32(0x01090405) - assert little_endian_u32([u8(0xf8), 0xa2, 0x9e, 0x21]) == u32(0x219ea2f8) - assert little_endian_u32([u8(0xf8), 0xa2, 0x9e, 0x21]) != u32(0xf8a29e21) -} - -fn test_little_endian_put_u32() { - mut buf := []u8{len: 4} - little_endian_put_u32(mut buf, 0x872fea95) - assert buf == [u8(0x95), 0xea, 0x2f, 0x87] - little_endian_put_u32(mut buf, 0) - assert buf == [u8(0), 0, 0, 0] - little_endian_put_u32(mut buf, 0xfdf2e68f) - assert buf == [u8(0x8f), 0xe6, 0xf2, 0xfd] -} - -fn test_little_endian_u64() { - assert little_endian_u64([u8(0), 0, 0, 0, 0, 0, 0, 0]) == u64(0) - assert little_endian_u64([u8(5), 4, 9, 1, 7, 3, 6, 8]) == u64(0x0806030701090405) - assert little_endian_u64([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]) == u64(0x8f8e9f7f219ea2f8) - assert little_endian_u64([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]) != u64(0xf8a29e217f9f8e8f) -} - -fn test_little_endian_put_u64() { - mut buf := []u8{len: 8} - little_endian_put_u64(mut buf, 0x872fea95fdf2e68f) - assert buf == [u8(0x8f), 0xe6, 0xf2, 0xfd, 0x95, 0xea, 0x2f, 0x87] - little_endian_put_u64(mut buf, 0) - assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 0] - little_endian_put_u64(mut buf, 0xfdf2e68f8e9f7f21) - assert buf == [u8(0x21), 0x7f, 0x9f, 0x8e, 0x8f, 0xe6, 0xf2, 0xfd] -} - -// Big Endian Tests - -fn test_big_endian_u16() { - assert big_endian_u16([u8(0), 0]) == u16(0) - assert big_endian_u16([u8(5), 4]) == u16(0x0504) - assert big_endian_u16([u8(0x35), 0x57]) == u16(0x3557) - assert big_endian_u16([u8(0x35), 0x57]) != u16(0x5735) -} - -fn test_big_endian_put_u16() { - mut buf := []u8{len: 2} - big_endian_put_u16(mut buf, 0x8725) - assert buf == [u8(0x87), 0x25] - big_endian_put_u16(mut buf, 0) - assert buf == [u8(0), 0] - big_endian_put_u16(mut buf, 0xfdff) - assert buf == [u8(0xfd), 0xff] -} - -fn test_big_endian_u32() { - assert big_endian_u32([u8(0), 0, 0, 0]) == u32(0) - assert big_endian_u32([u8(5), 4, 9, 1]) == u32(0x05040901) - assert big_endian_u32([u8(0xf8), 0xa2, 0x9e, 0x21]) == u32(0xf8a29e21) - assert big_endian_u32([u8(0xf8), 0xa2, 0x9e, 0x21]) != u32(0x2192a2f8) -} - -fn test_big_endian_put_u32() { - mut buf := []u8{len: 4} - big_endian_put_u32(mut buf, 0x872fea95) - assert buf == [u8(0x87), 0x2f, 0xea, 0x95] - big_endian_put_u32(mut buf, 0) - assert buf == [u8(0), 0, 0, 0] - big_endian_put_u32(mut buf, 0xfdf2e68f) - assert buf == [u8(0xfd), 0xf2, 0xe6, 0x8f] -} - -fn test_big_endian_u64() { - assert big_endian_u64([u8(0), 0, 0, 0, 0, 0, 0, 0]) == u64(0) - assert big_endian_u64([u8(5), 4, 9, 1, 7, 3, 6, 8]) == u64(0x0504090107030608) - assert big_endian_u64([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]) == u64(0xf8a29e217f9f8e8f) - assert big_endian_u64([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]) != u64(0x8f8e9f7f219ea2f8) -} - -fn test_big_endian_put_u64() { - mut buf := []u8{len: 8} - big_endian_put_u64(mut buf, 0x872fea95fdf2e68f) - assert buf == [u8(0x87), 0x2f, 0xea, 0x95, 0xfd, 0xf2, 0xe6, 0x8f] - big_endian_put_u64(mut buf, 0) - assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 0] - big_endian_put_u64(mut buf, 0xfdf2e68f8e9f7f21) - assert buf == [u8(0xfd), 0xf2, 0xe6, 0x8f, 0x8e, 0x9f, 0x7f, 0x21] -} diff --git a/vlib/encoding/binary/little_endian.v b/vlib/encoding/binary/little_endian.v new file mode 100644 index 0000000000..b827521e65 --- /dev/null +++ b/vlib/encoding/binary/little_endian.v @@ -0,0 +1,153 @@ +// Copyright (c) 2019-2022 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 creates a u16 from the first two bytes in the array b in little endian order. +[direct_array_access; inline] +pub fn little_endian_u16(b []u8) u16 { + _ = b[1] // bounds check + return u16(b[0]) | (u16(b[1]) << u16(8)) +} + +// little_endian_u16 creates a u16 from two bytes in the array b at the specified offset in little endian order. +[direct_array_access; inline] +pub fn little_endian_u16_at(b []u8, o int) u16 { + _ = b[o] // bounds check + _ = b[o + 1] // bounds check + return u16(b[o]) | (u16(b[o + 1]) << u16(8)) +} + +// little_endian_u16 creates a u16 from the last two bytes of the array b in little endian order. +[direct_array_access; inline] +pub fn little_endian_u16_end(b []u8) u16 { + return little_endian_u16_at(b, b.len - 2) +} + +// little_endian_put_u16 writes a u16 to the first two bytes in the array b in little endian order. +[direct_array_access; inline] +pub fn little_endian_put_u16(mut b []u8, v u16) { + _ = b[1] // bounds check + b[0] = u8(v) + b[1] = u8(v >> u16(8)) +} + +// little_endian_put_u16 writes a u16 to the two bytes in the array b at the specified offset in little endian order. +[direct_array_access; inline] +pub fn little_endian_put_u16_at(mut b []u8, v u16, o int) { + _ = b[o] // bounds check + _ = b[o + 1] // bounds check + b[o] = u8(v) + b[o + 1] = u8(v >> u16(8)) +} + +// little_endian_put_u16 writes a u16 to the last two bytes of the array b in little endian order. +[direct_array_access; inline] +pub fn little_endian_put_u16_end(mut b []u8, v u16) { + little_endian_put_u16_at(mut b, v, b.len - 2) +} + +// little_endian_u32 creates a u32 from the first four bytes in the array b in little endian order. +[direct_array_access; inline] +pub fn little_endian_u32(b []u8) u32 { + _ = b[3] // bounds check + return u32(b[0]) | (u32(b[1]) << u32(8)) | (u32(b[2]) << u32(16)) | (u32(b[3]) << u32(24)) +} + +// little_endian_u32 creates a u32 from four bytes in the array b at the specified offset in little endian order. +[direct_array_access; inline] +pub fn little_endian_u32_at(b []u8, o int) u32 { + _ = b[o] // bounds check + _ = b[o + 3] // bounds check + return u32(b[o]) | (u32(b[o + 1]) << u32(8)) | (u32(b[o + 2]) << u32(16)) | (u32(b[o + 3]) << u32(24)) +} + +// little_endian_u32 creates a u32 from the last four bytes in the array b in little endian order. +[direct_array_access; inline] +pub fn little_endian_u32_end(b []u8) u32 { + return little_endian_u32_at(b, b.len - 4) +} + +// little_endian_put_u32 writes a u32 to the first four bytes in the array b in little endian order. +[direct_array_access; inline] +pub fn little_endian_put_u32(mut b []u8, v u32) { + _ = b[3] // bounds check + b[0] = u8(v) + b[1] = u8(v >> u32(8)) + b[2] = u8(v >> u32(16)) + b[3] = u8(v >> u32(24)) +} + +// little_endian_put_u32 writes a u32 to the two bytes in the array b at the specified offset in little endian order. +[direct_array_access; inline] +pub fn little_endian_put_u32_at(mut b []u8, v u32, o int) { + _ = b[o] // bounds check + _ = b[o + 3] // bounds check + b[o] = u8(v) + b[o + 1] = u8(v >> u32(8)) + b[o + 2] = u8(v >> u32(16)) + b[o + 3] = u8(v >> u32(24)) +} + +// little_endian_put_u32 writes a u32 to the last two bytes in the array b in little endian order. +[direct_array_access; inline] +pub fn little_endian_put_u32_end(mut b []u8, v u32) { + little_endian_put_u32_at(mut b, v, b.len - 4) +} + +// little_endian_u64 creates a u64 from the first eight bytes in the array b in little endian order. +[direct_array_access; inline] +pub fn little_endian_u64(b []u8) u64 { + _ = b[7] // bounds check + 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_u64 creates a u64 from eight bytes in the array b at the specified offset in little endian order. +[direct_array_access; inline] +pub fn little_endian_u64_at(b []u8, o int) u64 { + _ = b[o] // bounds check + _ = b[o + 7] // bounds check + return u64(b[o]) | (u64(b[o + 1]) << u64(8)) | (u64(b[o + 2]) << u64(16)) | (u64(b[o + 3]) << u64(24)) | (u64(b[ + o + 4]) << u64(32)) | (u64(b[o + 5]) << u64(40)) | (u64(b[o + 6]) << u64(48)) | (u64(b[o + 7]) << u64(56)) +} + +// little_endian_u64 creates a u64 from the last eight bytes in the array b in little endian order. +[direct_array_access; inline] +pub fn little_endian_u64_end(b []u8) u64 { + return little_endian_u64_at(b, b.len - 8) +} + +// little_endian_put_u64 writes a u64 to the first eight bytes in the array b in little endian order. +[direct_array_access; inline] +pub fn little_endian_put_u64(mut b []u8, v u64) { + _ = b[7] // bounds check + 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)) +} + +// little_endian_put_u64 writes a u64 to the eight bytes in the array b at the specified offset in little endian order. +[direct_array_access; inline] +pub fn little_endian_put_u64_at(mut b []u8, v u64, o int) { + _ = b[o] // bounds check + _ = b[o + 7] // bounds check + b[o] = u8(v) + b[o + 1] = u8(v >> u64(8)) + b[o + 2] = u8(v >> u64(16)) + b[o + 3] = u8(v >> u64(24)) + b[o + 4] = u8(v >> u64(32)) + b[o + 5] = u8(v >> u64(40)) + b[o + 6] = u8(v >> u64(48)) + b[o + 7] = u8(v >> u64(56)) +} + +// little_endian_put_u64 writes a u64 to the last eight bytes in the array b at in little endian order. +[direct_array_access; inline] +pub fn little_endian_put_u64_end(mut b []u8, v u64) { + little_endian_put_u64_at(mut b, v, b.len - 8) +} diff --git a/vlib/encoding/binary/little_endian_test.v b/vlib/encoding/binary/little_endian_test.v new file mode 100644 index 0000000000..195cd01b18 --- /dev/null +++ b/vlib/encoding/binary/little_endian_test.v @@ -0,0 +1,188 @@ +module binary + +// Little Endian Tests + +fn test_little_endian_u16() { + assert little_endian_u16([u8(0), 0]) == u16(0) + assert little_endian_u16([u8(5), 4]) == u16(0x0405) + assert little_endian_u16([u8(0x35), 0x57]) == u16(0x5735) + assert little_endian_u16([u8(0x35), 0x57]) != u16(0x3557) +} + +fn test_little_endian_u16_at() { + assert little_endian_u16_at([u8(1), 0, 0, 1], 1) == u16(0) + assert little_endian_u16_at([u8(5), 4, 9, 1], 1) == u16(0x0904) + assert little_endian_u16_at([u8(0xf8), 0xa2, 0x9e, 0x21], 1) == u16(0x9ea2) + assert little_endian_u16_at([u8(0xf8), 0xa2, 0x9e, 0x21], 1) != u16(0xa29e) +} + +fn test_little_endian_u16_end() { + assert little_endian_u16_end([u8(1), 0, 0, 1]) == u16(0x0100) + assert little_endian_u16_end([u8(5), 4, 9, 1]) == u16(0x0109) + assert little_endian_u16_end([u8(0xf8), 0xa2, 0x9e, 0x21]) == u16(0x219e) + assert little_endian_u16_end([u8(0xf8), 0xa2, 0x9e, 0x21]) != u16(0x9e21) +} + +fn test_little_endian_put_u16() { + mut buf := []u8{len: 2} + little_endian_put_u16(mut buf, 0x8725) + assert buf == [u8(0x25), 0x87] + little_endian_put_u16(mut buf, 0) + assert buf == [u8(0), 0] + little_endian_put_u16(mut buf, 0xfdff) + assert buf == [u8(0xff), 0xfd] +} + +fn test_little_endian_put_u16_at() { + mut buf := []u8{len: 4} + little_endian_put_u16_at(mut buf, 0x8725, 1) + assert buf == [u8(0), 0x25, 0x87, 0] + + buf = []u8{len: 4} + little_endian_put_u16_at(mut buf, 1, 1) + assert buf == [u8(0), 1, 0, 0] + + buf = []u8{len: 4} + little_endian_put_u16_at(mut buf, 0xfdff, 1) + assert buf == [u8(0), 0xff, 0xfd, 0] +} + +fn test_little_endian_put_u16_end() { + mut buf := []u8{len: 4} + little_endian_put_u16_end(mut buf, 0x8725) + assert buf == [u8(0), 0, 0x25, 0x87] + + buf = []u8{len: 4} + little_endian_put_u16_end(mut buf, 1) + assert buf == [u8(0), 0, 1, 0] + + buf = []u8{len: 4} + little_endian_put_u16_end(mut buf, 0xfdff) + assert buf == [u8(0), 0, 0xff, 0xfd] +} + +fn test_little_endian_u32() { + assert little_endian_u32([u8(0), 0, 0, 0]) == u32(0) + assert little_endian_u32([u8(5), 4, 9, 1]) == u32(0x01090405) + assert little_endian_u32([u8(0xf8), 0xa2, 0x9e, 0x21]) == u32(0x219ea2f8) + assert little_endian_u32([u8(0xf8), 0xa2, 0x9e, 0x21]) != u32(0xf8a29e21) +} + +fn test_little_endian_u32_at() { + assert little_endian_u32_at([u8(1), 0, 0, 0, 0, 0, 0, 0], 1) == u32(0) + assert little_endian_u32_at([u8(5), 4, 9, 1, 7, 3, 6, 8], 1) == u32(0x07010904) + assert little_endian_u32_at([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f], + 1) == u32(0x7f219ea2) + assert little_endian_u32_at([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f], + 1) != u32(0xa29e217f) +} + +fn test_little_endian_u32_end() { + assert little_endian_u32_end([u8(1), 0, 0, 0, 0, 0, 0, 0]) == u32(0) + assert little_endian_u32_end([u8(5), 4, 9, 1, 7, 3, 6, 8]) == u32(0x08060307) + assert little_endian_u32_end([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]) == u32(0x8f8e9f7f) + assert little_endian_u32_end([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]) != u32(0x7f9f8e8f) +} + +fn test_little_endian_put_u32() { + mut buf := []u8{len: 4} + little_endian_put_u32(mut buf, 0x872fea95) + assert buf == [u8(0x95), 0xea, 0x2f, 0x87] + little_endian_put_u32(mut buf, 0) + assert buf == [u8(0), 0, 0, 0] + little_endian_put_u32(mut buf, 0xfdf2e68f) + assert buf == [u8(0x8f), 0xe6, 0xf2, 0xfd] +} + +fn test_little_endian_put_u32_at() { + mut buf := []u8{len: 8} + little_endian_put_u32_at(mut buf, 0x872fea95, 1) + assert buf == [u8(0), 0x95, 0xea, 0x2f, 0x87, 0, 0, 0] + + buf = []u8{len: 8} + little_endian_put_u32_at(mut buf, 1, 1) + assert buf == [u8(0), 1, 0, 0, 0, 0, 0, 0] + + buf = []u8{len: 8} + little_endian_put_u32_at(mut buf, 0xfdf2e68f, 1) + assert buf == [u8(0), 0x8f, 0xe6, 0xf2, 0xfd, 0, 0, 0] +} + +fn test_little_endian_put_u32_end() { + mut buf := []u8{len: 8} + little_endian_put_u32_end(mut buf, 0x872fea95) + assert buf == [u8(0), 0, 0, 0, 0x95, 0xea, 0x2f, 0x87] + + buf = []u8{len: 8} + little_endian_put_u32_end(mut buf, 1) + assert buf == [u8(0), 0, 0, 0, 1, 0, 0, 0] + + buf = []u8{len: 8} + little_endian_put_u32_end(mut buf, 0xfdf2e68f) + assert buf == [u8(0), 0, 0, 0, 0x8f, 0xe6, 0xf2, 0xfd] +} + +fn test_little_endian_u64() { + assert little_endian_u64([u8(0), 0, 0, 0, 0, 0, 0, 0]) == u64(0) + assert little_endian_u64([u8(5), 4, 9, 1, 7, 3, 6, 8]) == u64(0x0806030701090405) + assert little_endian_u64([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]) == u64(0x8f8e9f7f219ea2f8) + assert little_endian_u64([u8(0xf8), 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f]) != u64(0xf8a29e217f9f8e8f) +} + +fn test_little_endian_u64_at() { + assert little_endian_u64_at([u8(1), 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1], + 1) == u64(0) + assert little_endian_u64_at([u8(0), 5, 4, 9, 1, 7, 3, 6, 8, 0, 0, 0, 0, 0, 0, 0], + 1) == u64(0x0806030701090405) + assert little_endian_u64_at([u8(0), 0xf8, 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f, 0, 0, 0, + 0, 0, 0, 0], 1) == u64(0x8f8e9f7f219ea2f8) + assert little_endian_u64_at([u8(0), 0xf8, 0xa2, 0x9e, 0x21, 0x7f, 0x9f, 0x8e, 0x8f, 0, 0, 0, + 0, 0, 0, 0], 1) != u64(0xf8a29e217f9f8e8f) +} + +fn test_little_endian_u64_end() { + assert little_endian_u64_end([u8(1), 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]) == u64(0) + assert little_endian_u64_end([u8(0), 0, 0, 0, 0, 0, 0, 0, 5, 4, 9, 1, 7, 3, 6, 8]) == u64(0x0806030701090405) + assert little_endian_u64_end([u8(0), 0, 0, 0, 0, 0, 0, 0, 0xf8, 0xa2, 0x9e, 0x21, 0x7f, 0x9f, + 0x8e, 0x8f]) == u64(0x8f8e9f7f219ea2f8) + assert little_endian_u64_end([u8(0), 0, 0, 0, 0, 0, 0, 0, 0xf8, 0xa2, 0x9e, 0x21, 0x7f, 0x9f, + 0x8e, 0x8f]) != u64(0xf8a29e217f9f8e8f) +} + +fn test_little_endian_put_u64() { + mut buf := []u8{len: 8} + little_endian_put_u64(mut buf, 0x872fea95fdf2e68f) + assert buf == [u8(0x8f), 0xe6, 0xf2, 0xfd, 0x95, 0xea, 0x2f, 0x87] + little_endian_put_u64(mut buf, 0) + assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 0] + little_endian_put_u64(mut buf, 0xfdf2e68f8e9f7f21) + assert buf == [u8(0x21), 0x7f, 0x9f, 0x8e, 0x8f, 0xe6, 0xf2, 0xfd] +} + +fn test_little_endian_put_u64_at() { + mut buf := []u8{len: 16} + little_endian_put_u64_at(mut buf, 0x872fea95fdf2e68f, 1) + assert buf == [u8(0), 0x8f, 0xe6, 0xf2, 0xfd, 0x95, 0xea, 0x2f, 0x87, 0, 0, 0, 0, 0, 0, 0] + + buf = []u8{len: 16} + little_endian_put_u64_at(mut buf, 1, 1) + assert buf == [u8(0), 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + + buf = []u8{len: 16} + little_endian_put_u64_at(mut buf, 0xfdf2e68f8e9f7f21, 1) + assert buf == [u8(0), 0x21, 0x7f, 0x9f, 0x8e, 0x8f, 0xe6, 0xf2, 0xfd, 0, 0, 0, 0, 0, 0, 0] +} + +fn test_little_endian_put_u64_end() { + mut buf := []u8{len: 16} + little_endian_put_u64_end(mut buf, 0x872fea95fdf2e68f) + assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 0, 0x8f, 0xe6, 0xf2, 0xfd, 0x95, 0xea, 0x2f, 0x87] + + buf = []u8{len: 16} + little_endian_put_u64_end(mut buf, 1) + assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0] + + buf = []u8{len: 16} + little_endian_put_u64_end(mut buf, 0xfdf2e68f8e9f7f21) + assert buf == [u8(0), 0, 0, 0, 0, 0, 0, 0, 0x21, 0x7f, 0x9f, 0x8e, 0x8f, 0xe6, 0xf2, 0xfd] +}