mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
encoding.binary: add unit tests and module documentation (#15000)
This commit is contained in:
parent
d4b0ebf215
commit
8ee614d3f8
3
.gitignore
vendored
3
.gitignore
vendored
@ -105,3 +105,6 @@ thirdparty/stdatomic/nix/cpp/*.h
|
|||||||
|
|
||||||
# ignore VLS log
|
# ignore VLS log
|
||||||
vls.log
|
vls.log
|
||||||
|
|
||||||
|
# ignore v2go tmperror files
|
||||||
|
*.tmperr
|
||||||
|
23
vlib/encoding/binary/README.md
Normal file
23
vlib/encoding/binary/README.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
## Description
|
||||||
|
|
||||||
|
`encoding.binary` contains utility functions for converting between an array of bytes (`[]u8`)
|
||||||
|
and unsigned integers of various widths (`u16`, `u32`, and `u64`).
|
||||||
|
|
||||||
|
There are two ways in which bytes can be encoded:
|
||||||
|
|
||||||
|
1. Little endian: The least significant bytes are stored first, followed by the most
|
||||||
|
significant bytes.
|
||||||
|
2. Big endian: The most significant bytes are stored first, opposite to the little endian
|
||||||
|
convention.
|
||||||
|
|
||||||
|
For example, let us take the number `0x12345678`. In little endian, the bytes are extracted as
|
||||||
|
`0x78`, `0x56`, `0x34`, and `0x12`. In big endian, the bytes are `0x12`, `0x34`, `0x56`,
|
||||||
|
and `0x78`.
|
||||||
|
|
||||||
|
We follow a similar procedure when we want to go the other way around. Consider the second
|
||||||
|
sequence of bytes in the previous example: `0x12`, `0x34`, `0x56`, and `0x78`. If we encode
|
||||||
|
this sequence in little endian format, we get the integer `0x78563412`. If we encode this
|
||||||
|
sequence in big endian, we get `0x12345678`.
|
||||||
|
|
||||||
|
**NOTE:** The functions in this module assume appropriately sized u8 arrays. If the sizes
|
||||||
|
are not valid, the functions will panic.
|
@ -3,13 +3,14 @@
|
|||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module binary
|
module binary
|
||||||
|
|
||||||
// Little Endian
|
// little_endian_u16 creates a u16 from two bytes in the array b in little endian order.
|
||||||
[direct_array_access; inline]
|
[direct_array_access; inline]
|
||||||
pub fn little_endian_u16(b []u8) u16 {
|
pub fn little_endian_u16(b []u8) u16 {
|
||||||
_ = b[1] // bounds check
|
_ = b[1] // bounds check
|
||||||
return u16(b[0]) | (u16(b[1]) << u16(8))
|
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]
|
[direct_array_access; inline]
|
||||||
pub fn little_endian_put_u16(mut b []u8, v u16) {
|
pub fn little_endian_put_u16(mut b []u8, v u16) {
|
||||||
_ = b[1] // bounds check
|
_ = b[1] // bounds check
|
||||||
@ -17,12 +18,14 @@ pub fn little_endian_put_u16(mut b []u8, v u16) {
|
|||||||
b[1] = u8(v >> u16(8))
|
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]
|
[direct_array_access; inline]
|
||||||
pub fn little_endian_u32(b []u8) u32 {
|
pub fn little_endian_u32(b []u8) u32 {
|
||||||
_ = b[3] // bounds check
|
_ = b[3] // bounds check
|
||||||
return u32(b[0]) | (u32(b[1]) << u32(8)) | (u32(b[2]) << u32(16)) | (u32(b[3]) << u32(24))
|
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]
|
[direct_array_access; inline]
|
||||||
pub fn little_endian_put_u32(mut b []u8, v u32) {
|
pub fn little_endian_put_u32(mut b []u8, v u32) {
|
||||||
_ = b[3] // bounds check
|
_ = b[3] // bounds check
|
||||||
@ -32,12 +35,14 @@ pub fn little_endian_put_u32(mut b []u8, v u32) {
|
|||||||
b[3] = u8(v >> u32(24))
|
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]
|
[direct_array_access; inline]
|
||||||
pub fn little_endian_u64(b []u8) u64 {
|
pub fn little_endian_u64(b []u8) u64 {
|
||||||
_ = b[7] // bounds check
|
_ = 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))
|
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]
|
[direct_array_access; inline]
|
||||||
pub fn little_endian_put_u64(mut b []u8, v u64) {
|
pub fn little_endian_put_u64(mut b []u8, v u64) {
|
||||||
_ = b[7] // bounds check
|
_ = b[7] // bounds check
|
||||||
@ -51,13 +56,14 @@ pub fn little_endian_put_u64(mut b []u8, v u64) {
|
|||||||
b[7] = u8(v >> u64(56))
|
b[7] = u8(v >> u64(56))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Big Endian
|
// big_endian_u16 creates a u16 from two bytes in the array b in big endian order.
|
||||||
[direct_array_access; inline]
|
[direct_array_access; inline]
|
||||||
pub fn big_endian_u16(b []u8) u16 {
|
pub fn big_endian_u16(b []u8) u16 {
|
||||||
_ = b[1] // bounds check
|
_ = b[1] // bounds check
|
||||||
return u16(b[1]) | (u16(b[0]) << u16(8))
|
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]
|
[direct_array_access; inline]
|
||||||
pub fn big_endian_put_u16(mut b []u8, v u16) {
|
pub fn big_endian_put_u16(mut b []u8, v u16) {
|
||||||
_ = b[1] // bounds check
|
_ = b[1] // bounds check
|
||||||
@ -65,12 +71,14 @@ pub fn big_endian_put_u16(mut b []u8, v u16) {
|
|||||||
b[1] = u8(v)
|
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]
|
[direct_array_access; inline]
|
||||||
pub fn big_endian_u32(b []u8) u32 {
|
pub fn big_endian_u32(b []u8) u32 {
|
||||||
_ = b[3] // bounds check
|
_ = b[3] // bounds check
|
||||||
return u32(b[3]) | (u32(b[2]) << u32(8)) | (u32(b[1]) << u32(16)) | (u32(b[0]) << u32(24))
|
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]
|
[direct_array_access; inline]
|
||||||
pub fn big_endian_put_u32(mut b []u8, v u32) {
|
pub fn big_endian_put_u32(mut b []u8, v u32) {
|
||||||
_ = b[3] // bounds check
|
_ = b[3] // bounds check
|
||||||
@ -80,12 +88,14 @@ pub fn big_endian_put_u32(mut b []u8, v u32) {
|
|||||||
b[3] = u8(v)
|
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]
|
[direct_array_access; inline]
|
||||||
pub fn big_endian_u64(b []u8) u64 {
|
pub fn big_endian_u64(b []u8) u64 {
|
||||||
_ = b[7] // bounds check
|
_ = 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))
|
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]
|
[direct_array_access; inline]
|
||||||
pub fn big_endian_put_u64(mut b []u8, v u64) {
|
pub fn big_endian_put_u64(mut b []u8, v u64) {
|
||||||
_ = b[7] // bounds check
|
_ = b[7] // bounds check
|
||||||
|
107
vlib/encoding/binary/binary_test.v
Normal file
107
vlib/encoding/binary/binary_test.v
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
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]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user