mirror of
https://github.com/vlang/v.git
synced 2025-09-24 04:48:28 -04:00
encoding.binary: add encode_binary()/decode_binary() generic functions (#24106)
This commit is contained in:
parent
42ac6885df
commit
592615c049
@ -3,6 +3,9 @@
|
|||||||
`encoding.binary` contains utility functions for converting between an array of bytes (`[]u8`)
|
`encoding.binary` contains utility functions for converting between an array of bytes (`[]u8`)
|
||||||
and unsigned integers of various widths (`u16`, `u32`, and `u64`).
|
and unsigned integers of various widths (`u16`, `u32`, and `u64`).
|
||||||
|
|
||||||
|
Also, it provide functions `encode_binary[T]()` and `decode_binary[T]()` which can converting
|
||||||
|
between an array of bytes (`[]u8`) and generic type `T`.
|
||||||
|
|
||||||
There are two ways in which bytes can be encoded:
|
There are two ways in which bytes can be encoded:
|
||||||
|
|
||||||
1. Little endian: The least significant bytes are stored first, followed by the most
|
1. Little endian: The least significant bytes are stored first, followed by the most
|
||||||
@ -22,3 +25,65 @@ sequence in big endian, we get `0x12345678`.
|
|||||||
> **Note**
|
> **Note**
|
||||||
> The functions in this module assume appropriately sized u8 arrays. If the sizes
|
> The functions in this module assume appropriately sized u8 arrays. If the sizes
|
||||||
> are not valid, the functions will panic.
|
> are not valid, the functions will panic.
|
||||||
|
|
||||||
|
For generic `T` data encoding/decoding, you can use `encode_binary[T]()` and `decode_binary[T]()`:
|
||||||
|
|
||||||
|
```v
|
||||||
|
module main
|
||||||
|
|
||||||
|
import encoding.binary
|
||||||
|
|
||||||
|
struct MyStruct {
|
||||||
|
g_u8 u8
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ComplexStruct {
|
||||||
|
mut:
|
||||||
|
f_u8 u8
|
||||||
|
f_u32 u32 @[serialize: '-'] // this field will be skipped
|
||||||
|
f_u64 u64
|
||||||
|
f_string string
|
||||||
|
f_structs []MyStruct
|
||||||
|
f_maps []map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
a := ComplexStruct{
|
||||||
|
f_u8: u8(10)
|
||||||
|
f_u32: u32(1024)
|
||||||
|
f_u64: u64(2048)
|
||||||
|
f_string: 'serialize me'
|
||||||
|
f_structs: [
|
||||||
|
MyStruct{
|
||||||
|
g_u8: u8(1)
|
||||||
|
},
|
||||||
|
MyStruct{
|
||||||
|
g_u8: u8(2)
|
||||||
|
},
|
||||||
|
MyStruct{
|
||||||
|
g_u8: u8(3)
|
||||||
|
},
|
||||||
|
]
|
||||||
|
f_maps: [
|
||||||
|
{
|
||||||
|
'abc': 'def'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'123': '456'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
',./': '!@#'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
b := binary.encode_binary(a)!
|
||||||
|
mut c := binary.decode_binary[ComplexStruct](b)!
|
||||||
|
|
||||||
|
// because there skipped field in `a`, a != c
|
||||||
|
assert a != c
|
||||||
|
|
||||||
|
c.f_u32 = u32(1024)
|
||||||
|
assert a == c
|
||||||
|
}
|
||||||
|
```
|
||||||
|
502
vlib/encoding/binary/serialize.v
Normal file
502
vlib/encoding/binary/serialize.v
Normal file
@ -0,0 +1,502 @@
|
|||||||
|
module binary
|
||||||
|
|
||||||
|
struct EncodeState {
|
||||||
|
mut:
|
||||||
|
b []u8
|
||||||
|
// pre-allocated buffers
|
||||||
|
b2 []u8 = [u8(0), 0]
|
||||||
|
b4 []u8 = [u8(0), 0, 0, 0]
|
||||||
|
b8 []u8 = [u8(0), 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
big_endian bool
|
||||||
|
}
|
||||||
|
|
||||||
|
@[params]
|
||||||
|
pub struct EncodeConfig {
|
||||||
|
pub mut:
|
||||||
|
buffer_len int = 1024
|
||||||
|
big_endian bool // use big endian encoding the data
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode_binary encode a T type data into u8 array.
|
||||||
|
// for encoding struct, you can use `@[serialize: '-']` to skip field.
|
||||||
|
pub fn encode_binary[T](obj T, config EncodeConfig) ![]u8 {
|
||||||
|
mut s := EncodeState{
|
||||||
|
b: []u8{cap: config.buffer_len}
|
||||||
|
big_endian: config.big_endian
|
||||||
|
}
|
||||||
|
$if T is $array {
|
||||||
|
encode_array(mut s, obj)!
|
||||||
|
} $else $if T is $string {
|
||||||
|
encode_string(mut s, obj)!
|
||||||
|
} $else $if T is $struct {
|
||||||
|
encode_struct(mut s, obj)!
|
||||||
|
} $else $if T is $map {
|
||||||
|
encode_map(mut s, obj)!
|
||||||
|
} $else {
|
||||||
|
encode_primitive(mut s, obj)!
|
||||||
|
}
|
||||||
|
return s.b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_struct[T](mut s EncodeState, obj T) ! {
|
||||||
|
$for field in T.fields {
|
||||||
|
mut is_skip := false
|
||||||
|
for attr in field.attrs {
|
||||||
|
f := attr.split_any(':')
|
||||||
|
if f.len == 2 {
|
||||||
|
match f[0].trim_space() {
|
||||||
|
'serialize' {
|
||||||
|
// @[serialize:'-']
|
||||||
|
if f[1].trim_space() == '-' {
|
||||||
|
is_skip = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !is_skip {
|
||||||
|
value := obj.$(field.name)
|
||||||
|
$if field.typ is $array {
|
||||||
|
encode_array(mut s, value)!
|
||||||
|
} $else $if field.typ is $string {
|
||||||
|
encode_string(mut s, value)!
|
||||||
|
} $else $if field.typ is $struct {
|
||||||
|
encode_struct(mut s, value)!
|
||||||
|
} $else $if field.typ is $map {
|
||||||
|
encode_map(mut s, value)!
|
||||||
|
} $else {
|
||||||
|
encode_primitive(mut s, value)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// help unions for bypass `-cstrict`/ `-Wstrict-aliasing` check.
|
||||||
|
union U32_F32 {
|
||||||
|
u u32
|
||||||
|
f f32
|
||||||
|
}
|
||||||
|
|
||||||
|
union U64_F64 {
|
||||||
|
u u64
|
||||||
|
f f64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_primitive[T](mut s EncodeState, value T) ! {
|
||||||
|
$if T is int {
|
||||||
|
// NOTE: `int` always use 64bit
|
||||||
|
s.put_u64(u64(value))
|
||||||
|
} $else $if T is u8 {
|
||||||
|
s.put_u8(u8(value))
|
||||||
|
} $else $if T is u16 {
|
||||||
|
s.put_u16(u16(value))
|
||||||
|
} $else $if T is u32 {
|
||||||
|
s.put_u32(u32(value))
|
||||||
|
} $else $if T is u64 {
|
||||||
|
s.put_u64(u64(value))
|
||||||
|
} $else $if T is i8 {
|
||||||
|
s.put_u8(u8(value))
|
||||||
|
} $else $if T is i16 {
|
||||||
|
s.put_u16(u16(value))
|
||||||
|
} $else $if T is i32 {
|
||||||
|
s.put_u32(u32(value))
|
||||||
|
} $else $if T is i64 {
|
||||||
|
s.put_u64(u64(value))
|
||||||
|
} $else $if T is f32 {
|
||||||
|
unsafe { s.put_u32(U32_F32{ f: value }.u) }
|
||||||
|
} $else $if T is f64 {
|
||||||
|
unsafe { s.put_u64(U64_F64{ f: value }.u) }
|
||||||
|
} $else $if T is bool {
|
||||||
|
s.put_u8(u8(value))
|
||||||
|
} $else $if T is rune {
|
||||||
|
s.put_u32(u32(value))
|
||||||
|
} $else $if T is isize {
|
||||||
|
if sizeof(isize) == 4 {
|
||||||
|
s.put_u32(u32(value))
|
||||||
|
} else {
|
||||||
|
s.put_u64(u64(value))
|
||||||
|
}
|
||||||
|
} $else $if T is usize {
|
||||||
|
if sizeof(usize) == 4 {
|
||||||
|
s.put_u32(u32(value))
|
||||||
|
} else {
|
||||||
|
s.put_u64(u64(value))
|
||||||
|
}
|
||||||
|
} $else $if T is voidptr {
|
||||||
|
s.put_u64(u64(value))
|
||||||
|
} $else {
|
||||||
|
// TODO: `any` type support?
|
||||||
|
return error('${@FN}unsupported type ${typeof(value).name}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_array[T](mut s EncodeState, arr []T) ! {
|
||||||
|
s.put_u64(u64(arr.len))
|
||||||
|
|
||||||
|
$if T is u8 {
|
||||||
|
// optimization for `[]u8`
|
||||||
|
s.b << arr
|
||||||
|
} $else {
|
||||||
|
for element in arr {
|
||||||
|
$if T is $string {
|
||||||
|
encode_string(mut s, element)!
|
||||||
|
} $else $if T is $struct {
|
||||||
|
encode_struct(mut s, element)!
|
||||||
|
} $else $if T is $map {
|
||||||
|
encode_map(mut s, element)!
|
||||||
|
} $else {
|
||||||
|
encode_primitive(mut s, element)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_string(mut s EncodeState, str string) ! {
|
||||||
|
s.put_u64(u64(str.len))
|
||||||
|
s.b << str.bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_map[K, V](mut s EncodeState, m map[K]V) ! {
|
||||||
|
s.put_u64(u64(m.len))
|
||||||
|
|
||||||
|
for k, v in m {
|
||||||
|
// encode key first
|
||||||
|
// Maps can have keys of type string, rune, integer, float or voidptr.
|
||||||
|
$if K is $string {
|
||||||
|
encode_string(mut s, k)!
|
||||||
|
} $else {
|
||||||
|
encode_primitive(mut s, k)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode value
|
||||||
|
$if V is $string {
|
||||||
|
encode_string(mut s, v)!
|
||||||
|
} $else $if V is $struct {
|
||||||
|
encode_struct(mut s, v)!
|
||||||
|
} $else $if V is $map {
|
||||||
|
encode_map(mut s, v)!
|
||||||
|
} $else {
|
||||||
|
encode_primitive(mut s, v)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DecodeState {
|
||||||
|
mut:
|
||||||
|
b []u8
|
||||||
|
b2 []u8 = [u8(0), 0]
|
||||||
|
b4 []u8 = [u8(0), 0, 0, 0]
|
||||||
|
b8 []u8 = [u8(0), 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
offset int
|
||||||
|
big_endian bool
|
||||||
|
}
|
||||||
|
|
||||||
|
@[params]
|
||||||
|
pub struct DecodeConfig {
|
||||||
|
pub mut:
|
||||||
|
buffer_len int = 1024
|
||||||
|
big_endian bool // use big endian decode the data
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode_binary decode a u8 array into T type data.
|
||||||
|
// for decoding struct, you can use `@[serialize: '-']` to skip field.
|
||||||
|
pub fn decode_binary[T](b []u8, config DecodeConfig) !T {
|
||||||
|
mut s := DecodeState{
|
||||||
|
b: b
|
||||||
|
big_endian: config.big_endian
|
||||||
|
}
|
||||||
|
$if T is $array {
|
||||||
|
return decode_array(mut s, T{})!
|
||||||
|
} $else $if T is $string {
|
||||||
|
return decode_string(mut s)!
|
||||||
|
} $else $if T is $struct {
|
||||||
|
return decode_struct(mut s, T{})!
|
||||||
|
} $else $if T is $map {
|
||||||
|
return decode_map(mut s, T{})!
|
||||||
|
} $else {
|
||||||
|
return decode_primitive(mut s, unsafe { T(0) })!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_struct[T](mut s DecodeState, _ T) !T {
|
||||||
|
mut obj := T{}
|
||||||
|
|
||||||
|
$for field in T.fields {
|
||||||
|
mut is_skip := false
|
||||||
|
for attr in field.attrs {
|
||||||
|
f := attr.split_any(':')
|
||||||
|
if f.len == 2 {
|
||||||
|
match f[0].trim_space() {
|
||||||
|
'serialize' {
|
||||||
|
// @[serialize:'-']
|
||||||
|
if f[1].trim_space() == '-' {
|
||||||
|
is_skip = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !is_skip {
|
||||||
|
$if field.typ is $array {
|
||||||
|
obj.$(field.name) = decode_array(mut s, obj.$(field.name))!
|
||||||
|
} $else $if field.typ is $string {
|
||||||
|
obj.$(field.name) = decode_string(mut s)!
|
||||||
|
} $else $if field.typ is $struct {
|
||||||
|
obj.$(field.name) = decode_struct(mut s, obj.$(field.name))!
|
||||||
|
} $else $if field.typ is $map {
|
||||||
|
obj.$(field.name) = decode_map(mut s, obj.$(field.name))!
|
||||||
|
} $else {
|
||||||
|
obj.$(field.name) = decode_primitive(mut s, obj.$(field.name))!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_primitive[T](mut s DecodeState, value T) !T {
|
||||||
|
$if T is int {
|
||||||
|
// NOTE: int always use 64bit
|
||||||
|
return T(s.get_u64()!)
|
||||||
|
} $else $if T is u8 {
|
||||||
|
return T(s.get_u8()!)
|
||||||
|
} $else $if T is u16 {
|
||||||
|
return T(s.get_u16()!)
|
||||||
|
} $else $if T is u32 {
|
||||||
|
return T(s.get_u32()!)
|
||||||
|
} $else $if T is u64 {
|
||||||
|
return T(s.get_u64()!)
|
||||||
|
} $else $if T is i8 {
|
||||||
|
return T(s.get_u8()!)
|
||||||
|
} $else $if T is i16 {
|
||||||
|
return T(s.get_u16()!)
|
||||||
|
} $else $if T is i32 {
|
||||||
|
return T(s.get_u32()!)
|
||||||
|
} $else $if T is i64 {
|
||||||
|
return T(s.get_u64()!)
|
||||||
|
} $else $if T is f32 {
|
||||||
|
v := s.get_u32()!
|
||||||
|
return unsafe {
|
||||||
|
U32_F32{
|
||||||
|
u: v
|
||||||
|
}.f
|
||||||
|
}
|
||||||
|
} $else $if T is f64 {
|
||||||
|
v := s.get_u64()!
|
||||||
|
return unsafe {
|
||||||
|
U64_F64{
|
||||||
|
u: v
|
||||||
|
}.f
|
||||||
|
}
|
||||||
|
} $else $if T is bool {
|
||||||
|
return s.get_u8()! != 0
|
||||||
|
} $else $if T is rune {
|
||||||
|
return T(s.get_u32()!)
|
||||||
|
} $else $if T is isize {
|
||||||
|
if sizeof(isize) == 4 {
|
||||||
|
return T(s.get_u32()!)
|
||||||
|
} else {
|
||||||
|
return T(s.get_u64()!)
|
||||||
|
}
|
||||||
|
} $else $if T is usize {
|
||||||
|
if sizeof(usize) == 4 {
|
||||||
|
return T(s.get_u32()!)
|
||||||
|
} else {
|
||||||
|
return T(s.get_u64()!)
|
||||||
|
}
|
||||||
|
} $else $if T is voidptr {
|
||||||
|
return T(s.get_u64()!)
|
||||||
|
} $else {
|
||||||
|
// TODO: `any` type support?
|
||||||
|
return error('${@FN}unsupported type ${typeof(value).name}')
|
||||||
|
}
|
||||||
|
return error('impossiable error')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_array[T](mut s DecodeState, _ []T) ![]T {
|
||||||
|
len := int(s.get_u64()!)
|
||||||
|
if len <= 0 || s.offset + len > s.b.len {
|
||||||
|
return error('invalid array length decode from stream')
|
||||||
|
}
|
||||||
|
mut arr := []T{cap: len}
|
||||||
|
$if T is u8 {
|
||||||
|
// optimization for `[]u8`
|
||||||
|
arr << s.b[s.offset..s.offset + len]
|
||||||
|
s.offset += len
|
||||||
|
} $else {
|
||||||
|
for _ in 0 .. len {
|
||||||
|
if s.offset >= s.b.len {
|
||||||
|
return error('unexpected end of data')
|
||||||
|
}
|
||||||
|
$if T is $array {
|
||||||
|
arr << decode_array(mut s, T{})!
|
||||||
|
} $else $if T is $string {
|
||||||
|
arr << decode_string(mut s)!
|
||||||
|
} $else $if T is $struct {
|
||||||
|
arr << decode_struct(mut s, T{})!
|
||||||
|
} $else $if T is $map {
|
||||||
|
arr << decode_map(mut s, T{})!
|
||||||
|
} $else {
|
||||||
|
arr << decode_primitive(mut s, unsafe { T(0) })!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_string(mut s DecodeState) !string {
|
||||||
|
len := int(s.get_u64()!)
|
||||||
|
if len <= 0 || s.offset + len > s.b.len {
|
||||||
|
return error('invalid string length decode from stream')
|
||||||
|
}
|
||||||
|
str := unsafe { s.b[s.offset..s.offset + len].bytestr() }
|
||||||
|
s.offset += len
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Any` is a sum type that lists the possible types to be decoded and used.
|
||||||
|
type Any = int
|
||||||
|
| bool
|
||||||
|
| f64
|
||||||
|
| f32
|
||||||
|
| i64
|
||||||
|
| i32
|
||||||
|
| i16
|
||||||
|
| i8
|
||||||
|
| map[string]Any
|
||||||
|
| map[int]Any
|
||||||
|
| string
|
||||||
|
| u64
|
||||||
|
| u32
|
||||||
|
| u16
|
||||||
|
| u8
|
||||||
|
| rune
|
||||||
|
| isize
|
||||||
|
| usize
|
||||||
|
| []Any
|
||||||
|
|
||||||
|
fn decode_map[K, V](mut s DecodeState, _ map[K]V) !map[K]V {
|
||||||
|
len := int(s.get_u64()!)
|
||||||
|
if len <= 0 || s.offset + len > s.b.len {
|
||||||
|
return error('invalid map length decode from stream')
|
||||||
|
}
|
||||||
|
|
||||||
|
mut m := map[K]V{}
|
||||||
|
|
||||||
|
for _ in 0 .. len {
|
||||||
|
// decode key first
|
||||||
|
// Maps can have keys of type string, rune, integer, float or voidptr.
|
||||||
|
mut k := Any(0)
|
||||||
|
$if K is $string {
|
||||||
|
k = decode_string(mut s)!
|
||||||
|
} $else {
|
||||||
|
k = decode_primitive(mut s, unsafe { K(0) })!
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode value
|
||||||
|
mut v := Any(0)
|
||||||
|
$if V is $string {
|
||||||
|
v = decode_string(mut s)!
|
||||||
|
} $else $if V is $struct {
|
||||||
|
v = decode_struct(mut s, V{})!
|
||||||
|
} $else $if V is $map {
|
||||||
|
v = decode_map(mut s, V{})!
|
||||||
|
} $else {
|
||||||
|
v = decode_primitive(mut s, unsafe { V(0) })!
|
||||||
|
}
|
||||||
|
m[k as K] = v as V
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
@[inline]
|
||||||
|
fn (mut s DecodeState) get_u64() !u64 {
|
||||||
|
if s.offset + 8 > s.b.len {
|
||||||
|
return error('bytes length is not enough for u64')
|
||||||
|
}
|
||||||
|
defer {
|
||||||
|
s.offset += 8
|
||||||
|
}
|
||||||
|
if s.big_endian {
|
||||||
|
return big_endian_u64_at(s.b, s.offset)
|
||||||
|
} else {
|
||||||
|
return little_endian_u64_at(s.b, s.offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@[inline]
|
||||||
|
fn (mut s DecodeState) get_u32() !u32 {
|
||||||
|
if s.offset + 4 > s.b.len {
|
||||||
|
return error('bytes length is not enough for u32')
|
||||||
|
}
|
||||||
|
defer {
|
||||||
|
s.offset += 4
|
||||||
|
}
|
||||||
|
if s.big_endian {
|
||||||
|
return big_endian_u32_at(s.b, s.offset)
|
||||||
|
} else {
|
||||||
|
return little_endian_u32_at(s.b, s.offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@[inline]
|
||||||
|
fn (mut s DecodeState) get_u16() !u16 {
|
||||||
|
if s.offset + 2 > s.b.len {
|
||||||
|
return error('bytes length is not enough for u16')
|
||||||
|
}
|
||||||
|
defer {
|
||||||
|
s.offset += 2
|
||||||
|
}
|
||||||
|
if s.big_endian {
|
||||||
|
return big_endian_u16_at(s.b, s.offset)
|
||||||
|
} else {
|
||||||
|
return little_endian_u16_at(s.b, s.offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@[inline]
|
||||||
|
fn (mut s DecodeState) get_u8() !u8 {
|
||||||
|
if s.offset + 1 > s.b.len {
|
||||||
|
return error('bytes length is not enough for u8')
|
||||||
|
}
|
||||||
|
defer {
|
||||||
|
s.offset += 1
|
||||||
|
}
|
||||||
|
return s.b[s.offset]
|
||||||
|
}
|
||||||
|
|
||||||
|
@[inline]
|
||||||
|
fn (mut s EncodeState) put_u64(value u64) {
|
||||||
|
if s.big_endian {
|
||||||
|
big_endian_put_u64(mut s.b8, value)
|
||||||
|
} else {
|
||||||
|
little_endian_put_u64(mut s.b8, value)
|
||||||
|
}
|
||||||
|
s.b << s.b8
|
||||||
|
}
|
||||||
|
|
||||||
|
@[inline]
|
||||||
|
fn (mut s EncodeState) put_u32(value u32) {
|
||||||
|
if s.big_endian {
|
||||||
|
big_endian_put_u32(mut s.b4, value)
|
||||||
|
} else {
|
||||||
|
little_endian_put_u32(mut s.b4, value)
|
||||||
|
}
|
||||||
|
s.b << s.b4
|
||||||
|
}
|
||||||
|
|
||||||
|
@[inline]
|
||||||
|
fn (mut s EncodeState) put_u16(value u16) {
|
||||||
|
if s.big_endian {
|
||||||
|
big_endian_put_u16(mut s.b2, value)
|
||||||
|
} else {
|
||||||
|
little_endian_put_u16(mut s.b2, value)
|
||||||
|
}
|
||||||
|
s.b << s.b2
|
||||||
|
}
|
||||||
|
|
||||||
|
@[inline]
|
||||||
|
fn (mut s EncodeState) put_u8(value u8) {
|
||||||
|
s.b << value
|
||||||
|
}
|
520
vlib/encoding/binary/serialize_test.v
Normal file
520
vlib/encoding/binary/serialize_test.v
Normal file
@ -0,0 +1,520 @@
|
|||||||
|
module binary
|
||||||
|
|
||||||
|
fn test_encode_decode_primitive_string() ! {
|
||||||
|
a_u8 := u8(137)
|
||||||
|
a_u16 := u16(5325)
|
||||||
|
a_u32 := u32(255421)
|
||||||
|
a_u64 := u64(2483294832)
|
||||||
|
a_i8 := i8(-11)
|
||||||
|
a_i16 := i16(-2321)
|
||||||
|
a_i32 := i32(-54322)
|
||||||
|
a_i64 := i64(-54212245)
|
||||||
|
a_int := int(-32135)
|
||||||
|
a_f32 := f32(1.37)
|
||||||
|
a_f64 := f64(-32144.3133)
|
||||||
|
a_bool := bool(true)
|
||||||
|
a_rune := `♥`
|
||||||
|
a_isize := isize(-45433)
|
||||||
|
a_usize := usize(432211)
|
||||||
|
a_string := '♥🖊dsser333100'
|
||||||
|
|
||||||
|
b_u8 := encode_binary(a_u8)!
|
||||||
|
b_u16 := encode_binary(a_u16)!
|
||||||
|
b_u32 := encode_binary(a_u32)!
|
||||||
|
b_u64 := encode_binary(a_u64)!
|
||||||
|
b_i8 := encode_binary(a_i8)!
|
||||||
|
b_i16 := encode_binary(a_i16)!
|
||||||
|
b_i32 := encode_binary(a_i32)!
|
||||||
|
b_i64 := encode_binary(a_i64)!
|
||||||
|
b_int := encode_binary(a_int)!
|
||||||
|
b_f32 := encode_binary(a_f32)!
|
||||||
|
b_f64 := encode_binary(a_f64)!
|
||||||
|
b_bool := encode_binary(a_bool)!
|
||||||
|
b_rune := encode_binary(a_rune)!
|
||||||
|
b_isize := encode_binary(a_isize)!
|
||||||
|
b_usize := encode_binary(a_usize)!
|
||||||
|
b_string := encode_binary(a_string)!
|
||||||
|
|
||||||
|
c_u8 := decode_binary[u8](b_u8)!
|
||||||
|
c_u16 := decode_binary[u16](b_u16)!
|
||||||
|
c_u32 := decode_binary[u32](b_u32)!
|
||||||
|
c_u64 := decode_binary[u64](b_u64)!
|
||||||
|
c_i8 := decode_binary[i8](b_i8)!
|
||||||
|
c_i16 := decode_binary[i16](b_i16)!
|
||||||
|
c_i32 := decode_binary[i32](b_i32)!
|
||||||
|
c_i64 := decode_binary[i64](b_i64)!
|
||||||
|
c_int := decode_binary[int](b_int)!
|
||||||
|
c_f32 := decode_binary[f32](b_f32)!
|
||||||
|
c_f64 := decode_binary[f64](b_f64)!
|
||||||
|
c_bool := decode_binary[bool](b_bool)!
|
||||||
|
c_rune := decode_binary[rune](b_rune)!
|
||||||
|
c_isize := decode_binary[isize](b_isize)!
|
||||||
|
c_usize := decode_binary[usize](b_usize)!
|
||||||
|
c_string := decode_binary[string](b_string)!
|
||||||
|
|
||||||
|
assert a_u8 == c_u8
|
||||||
|
assert a_u16 == c_u16
|
||||||
|
assert a_u32 == c_u32
|
||||||
|
assert a_u64 == c_u64
|
||||||
|
assert a_i8 == c_i8
|
||||||
|
assert a_i16 == c_i16
|
||||||
|
assert a_i32 == c_i32
|
||||||
|
assert a_i64 == c_i64
|
||||||
|
assert a_int == c_int
|
||||||
|
assert a_f32 == c_f32
|
||||||
|
assert a_f64 == c_f64
|
||||||
|
assert a_bool == c_bool
|
||||||
|
assert a_rune == c_rune
|
||||||
|
assert a_isize == c_isize
|
||||||
|
assert a_usize == c_usize
|
||||||
|
assert a_string == c_string
|
||||||
|
|
||||||
|
assert b_u8 == [u8(137)]
|
||||||
|
assert b_u16 == [u8(205), 20]
|
||||||
|
assert b_u32 == [u8(189), 229, 3, 0]
|
||||||
|
assert b_u64 == [u8(112), 18, 4, 148, 0, 0, 0, 0]
|
||||||
|
assert b_i8 == [u8(245)]
|
||||||
|
assert b_i16 == [u8(239), 246]
|
||||||
|
assert b_i32 == [u8(206), 43, 255, 255]
|
||||||
|
assert b_i64 == [u8(107), 201, 196, 252, 255, 255, 255, 255]
|
||||||
|
assert b_int == [u8(121), 130, 255, 255, 255, 255, 255, 255]
|
||||||
|
assert b_f32 == [u8(41), 92, 175, 63]
|
||||||
|
assert b_f64 == [u8(118), 113, 27, 13, 20, 100, 223, 192]
|
||||||
|
assert b_bool == [u8(1)]
|
||||||
|
assert b_rune == [u8(101), 38, 0, 0]
|
||||||
|
assert b_string == [u8(18), 0, 0, 0, 0, 0, 0, 0, 226, 153, 165, 240, 159, 150, 138, 100, 115,
|
||||||
|
115, 101, 114, 51, 51, 51, 49, 48, 48]
|
||||||
|
$if x64 {
|
||||||
|
assert b_isize == [u8(135), 78, 255, 255, 255, 255, 255, 255]
|
||||||
|
assert b_usize == [u8(83), 152, 6, 0, 0, 0, 0, 0]
|
||||||
|
} $else {
|
||||||
|
assert b_isize == [u8(135), 78, 255, 255]
|
||||||
|
assert b_usize == [u8(83), 152, 6, 0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_encode_decode_array() {
|
||||||
|
a_u8 := [u8(137), 21]
|
||||||
|
a_u16 := [u16(5325), 322]
|
||||||
|
a_u32 := [u32(255421), 34255]
|
||||||
|
a_u64 := [u64(2483294832), 321554321]
|
||||||
|
a_i8 := [i8(-11), 17]
|
||||||
|
a_i16 := [i16(-2321), 6543]
|
||||||
|
a_i32 := [i32(-54322), 23326]
|
||||||
|
a_i64 := [i64(-54212245), 54223333]
|
||||||
|
a_int := [int(-32135), 732561]
|
||||||
|
a_f32 := [f32(1.37), -5442.3]
|
||||||
|
a_f64 := [f64(-32144.3133), 432e-13]
|
||||||
|
a_bool := [bool(true), false]
|
||||||
|
a_rune := [`♥`, `🖊`]
|
||||||
|
a_isize := [isize(-45433), 24342]
|
||||||
|
a_usize := [usize(432211), 888533]
|
||||||
|
a_string := ['♥', '🖊', 'dfd21']
|
||||||
|
|
||||||
|
b_u8 := encode_binary(a_u8)!
|
||||||
|
b_u16 := encode_binary(a_u16)!
|
||||||
|
b_u32 := encode_binary(a_u32)!
|
||||||
|
b_u64 := encode_binary(a_u64)!
|
||||||
|
b_i8 := encode_binary(a_i8)!
|
||||||
|
b_i16 := encode_binary(a_i16)!
|
||||||
|
b_i32 := encode_binary(a_i32)!
|
||||||
|
b_i64 := encode_binary(a_i64)!
|
||||||
|
b_int := encode_binary(a_int)!
|
||||||
|
b_f32 := encode_binary(a_f32)!
|
||||||
|
b_f64 := encode_binary(a_f64)!
|
||||||
|
b_bool := encode_binary(a_bool)!
|
||||||
|
b_rune := encode_binary(a_rune)!
|
||||||
|
b_isize := encode_binary(a_isize)!
|
||||||
|
b_usize := encode_binary(a_usize)!
|
||||||
|
b_string := encode_binary(a_string)!
|
||||||
|
|
||||||
|
c_u8 := decode_binary[[]u8](b_u8)!
|
||||||
|
c_u16 := decode_binary[[]u16](b_u16)!
|
||||||
|
c_u32 := decode_binary[[]u32](b_u32)!
|
||||||
|
c_u64 := decode_binary[[]u64](b_u64)!
|
||||||
|
c_i8 := decode_binary[[]i8](b_i8)!
|
||||||
|
c_i16 := decode_binary[[]i16](b_i16)!
|
||||||
|
c_i32 := decode_binary[[]i32](b_i32)!
|
||||||
|
c_i64 := decode_binary[[]i64](b_i64)!
|
||||||
|
c_int := decode_binary[[]int](b_int)!
|
||||||
|
c_f32 := decode_binary[[]f32](b_f32)!
|
||||||
|
c_f64 := decode_binary[[]f64](b_f64)!
|
||||||
|
c_bool := decode_binary[[]bool](b_bool)!
|
||||||
|
c_rune := decode_binary[[]rune](b_rune)!
|
||||||
|
c_isize := decode_binary[[]isize](b_isize)!
|
||||||
|
c_usize := decode_binary[[]usize](b_usize)!
|
||||||
|
c_string := decode_binary[[]string](b_string)!
|
||||||
|
|
||||||
|
assert a_u8 == c_u8
|
||||||
|
assert a_u16 == c_u16
|
||||||
|
assert a_u32 == c_u32
|
||||||
|
assert a_u64 == c_u64
|
||||||
|
assert a_i8 == c_i8
|
||||||
|
assert a_i16 == c_i16
|
||||||
|
assert a_i32 == c_i32
|
||||||
|
assert a_i64 == c_i64
|
||||||
|
assert a_int == c_int
|
||||||
|
assert a_f32 == c_f32
|
||||||
|
assert a_f64 == c_f64
|
||||||
|
assert a_bool == c_bool
|
||||||
|
assert a_rune == c_rune
|
||||||
|
assert a_isize == c_isize
|
||||||
|
assert a_usize == c_usize
|
||||||
|
assert a_string == c_string
|
||||||
|
|
||||||
|
assert b_u8 == [u8(2), 0, 0, 0, 0, 0, 0, 0, 137, 21]
|
||||||
|
assert b_u16 == [u8(2), 0, 0, 0, 0, 0, 0, 0, 205, 20, 66, 1]
|
||||||
|
assert b_u32 == [u8(2), 0, 0, 0, 0, 0, 0, 0, 189, 229, 3, 0, 207, 133, 0, 0]
|
||||||
|
assert b_u64 == [u8(2), 0, 0, 0, 0, 0, 0, 0, 112, 18, 4, 148, 0, 0, 0, 0, 145, 135, 42, 19,
|
||||||
|
0, 0, 0, 0]
|
||||||
|
assert b_i8 == [u8(2), 0, 0, 0, 0, 0, 0, 0, 245, 17]
|
||||||
|
assert b_i16 == [u8(2), 0, 0, 0, 0, 0, 0, 0, 239, 246, 143, 25]
|
||||||
|
assert b_i32 == [u8(2), 0, 0, 0, 0, 0, 0, 0, 206, 43, 255, 255, 30, 91, 0, 0]
|
||||||
|
assert b_i64 == [u8(2), 0, 0, 0, 0, 0, 0, 0, 107, 201, 196, 252, 255, 255, 255, 255, 229, 97,
|
||||||
|
59, 3, 0, 0, 0, 0]
|
||||||
|
assert b_int == [u8(2), 0, 0, 0, 0, 0, 0, 0, 121, 130, 255, 255, 255, 255, 255, 255, 145, 45,
|
||||||
|
11, 0, 0, 0, 0, 0]
|
||||||
|
assert b_f32 == [u8(2), 0, 0, 0, 0, 0, 0, 0, 41, 92, 175, 63, 102, 18, 170, 197]
|
||||||
|
assert b_f64 == [u8(2), 0, 0, 0, 0, 0, 0, 0, 118, 113, 27, 13, 20, 100, 223, 192, 253, 251,
|
||||||
|
253, 7, 220, 191, 199, 61]
|
||||||
|
assert b_bool == [u8(2), 0, 0, 0, 0, 0, 0, 0, 1, 0]
|
||||||
|
assert b_rune == [u8(2), 0, 0, 0, 0, 0, 0, 0, 101, 38, 0, 0, 138, 245, 1, 0]
|
||||||
|
assert b_string == [u8(3), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 226, 153, 165, 4, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 240, 159, 150, 138, 5, 0, 0, 0, 0, 0, 0, 0, 100, 102, 100, 50, 49]
|
||||||
|
$if x64 {
|
||||||
|
assert b_isize == [u8(2), 0, 0, 0, 0, 0, 0, 0, 135, 78, 255, 255, 255, 255, 255, 255, 22,
|
||||||
|
95, 0, 0, 0, 0, 0, 0]
|
||||||
|
assert b_usize == [u8(2), 0, 0, 0, 0, 0, 0, 0, 83, 152, 6, 0, 0, 0, 0, 0, 213, 142, 13,
|
||||||
|
0, 0, 0, 0, 0]
|
||||||
|
} $else {
|
||||||
|
assert b_isize == [u8(2), 0, 0, 0, 0, 0, 0, 0, 135, 78, 255, 255, 22, 95, 0, 0]
|
||||||
|
assert b_usize == [u8(2), 0, 0, 0, 0, 0, 0, 0, 83, 152, 6, 0, 213, 142, 13, 0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_encode_decode_map() {
|
||||||
|
a_map_string_string := {
|
||||||
|
'abc': 'def'
|
||||||
|
}
|
||||||
|
a_map_string_int := {
|
||||||
|
'abc': int(21343)
|
||||||
|
}
|
||||||
|
a_map_string_u8 := {
|
||||||
|
'abc': u8(37)
|
||||||
|
}
|
||||||
|
a_map_string_u16 := {
|
||||||
|
'abc': u16(3347)
|
||||||
|
}
|
||||||
|
a_map_string_u32 := {
|
||||||
|
'abc': u32(333347)
|
||||||
|
}
|
||||||
|
a_map_string_u64 := {
|
||||||
|
'abc': u64(64423)
|
||||||
|
}
|
||||||
|
a_map_string_i8 := {
|
||||||
|
'abc': i8(-37)
|
||||||
|
}
|
||||||
|
a_map_string_i16 := {
|
||||||
|
'abc': i16(-3347)
|
||||||
|
}
|
||||||
|
a_map_string_i32 := {
|
||||||
|
'abc': i32(-333347)
|
||||||
|
}
|
||||||
|
a_map_string_i64 := {
|
||||||
|
'abc': i64(-64423)
|
||||||
|
}
|
||||||
|
a_map_string_f32 := {
|
||||||
|
'abc': f32(1.543)
|
||||||
|
}
|
||||||
|
a_map_string_f64 := {
|
||||||
|
'abc': f64(1.54e31)
|
||||||
|
}
|
||||||
|
a_map_string_bool := {
|
||||||
|
'abc': true
|
||||||
|
}
|
||||||
|
a_map_string_rune := {
|
||||||
|
'abc': `♥`
|
||||||
|
}
|
||||||
|
a_map_string_isize := {
|
||||||
|
'abc': isize(-45433)
|
||||||
|
}
|
||||||
|
a_map_string_usize := {
|
||||||
|
'abc': usize(432211)
|
||||||
|
}
|
||||||
|
|
||||||
|
b_map_string_string := encode_binary(a_map_string_string)!
|
||||||
|
b_map_string_int := encode_binary(a_map_string_int)!
|
||||||
|
b_map_string_u8 := encode_binary(a_map_string_u8)!
|
||||||
|
b_map_string_u16 := encode_binary(a_map_string_u16)!
|
||||||
|
b_map_string_u32 := encode_binary(a_map_string_u32)!
|
||||||
|
b_map_string_u64 := encode_binary(a_map_string_u64)!
|
||||||
|
b_map_string_i8 := encode_binary(a_map_string_i8)!
|
||||||
|
b_map_string_i16 := encode_binary(a_map_string_i16)!
|
||||||
|
b_map_string_i32 := encode_binary(a_map_string_i32)!
|
||||||
|
b_map_string_i64 := encode_binary(a_map_string_i64)!
|
||||||
|
b_map_string_f32 := encode_binary(a_map_string_f32)!
|
||||||
|
b_map_string_f64 := encode_binary(a_map_string_f64)!
|
||||||
|
b_map_string_bool := encode_binary(a_map_string_bool)!
|
||||||
|
b_map_string_rune := encode_binary(a_map_string_rune)!
|
||||||
|
b_map_string_isize := encode_binary(a_map_string_isize)!
|
||||||
|
b_map_string_usize := encode_binary(a_map_string_usize)!
|
||||||
|
|
||||||
|
c_map_string_string := decode_binary[map[string]string](b_map_string_string)!
|
||||||
|
c_map_string_int := decode_binary[map[string]int](b_map_string_int)!
|
||||||
|
c_map_string_u8 := decode_binary[map[string]u8](b_map_string_u8)!
|
||||||
|
c_map_string_u16 := decode_binary[map[string]u16](b_map_string_u16)!
|
||||||
|
c_map_string_u32 := decode_binary[map[string]u32](b_map_string_u32)!
|
||||||
|
c_map_string_u64 := decode_binary[map[string]u64](b_map_string_u64)!
|
||||||
|
c_map_string_i8 := decode_binary[map[string]i8](b_map_string_i8)!
|
||||||
|
c_map_string_i16 := decode_binary[map[string]i16](b_map_string_i16)!
|
||||||
|
c_map_string_i32 := decode_binary[map[string]i32](b_map_string_i32)!
|
||||||
|
c_map_string_i64 := decode_binary[map[string]i64](b_map_string_i64)!
|
||||||
|
c_map_string_f32 := decode_binary[map[string]f32](b_map_string_f32)!
|
||||||
|
c_map_string_f64 := decode_binary[map[string]f64](b_map_string_f64)!
|
||||||
|
c_map_string_bool := decode_binary[map[string]bool](b_map_string_bool)!
|
||||||
|
c_map_string_rune := decode_binary[map[string]rune](b_map_string_rune)!
|
||||||
|
c_map_string_isize := decode_binary[map[string]isize](b_map_string_isize)!
|
||||||
|
c_map_string_usize := decode_binary[map[string]usize](b_map_string_usize)!
|
||||||
|
|
||||||
|
assert a_map_string_string == c_map_string_string
|
||||||
|
assert a_map_string_int == c_map_string_int
|
||||||
|
assert a_map_string_u8 == c_map_string_u8
|
||||||
|
assert a_map_string_u16 == c_map_string_u16
|
||||||
|
assert a_map_string_u32 == c_map_string_u32
|
||||||
|
assert a_map_string_i8 == c_map_string_i8
|
||||||
|
assert a_map_string_i16 == c_map_string_i16
|
||||||
|
assert a_map_string_i32 == c_map_string_i32
|
||||||
|
assert a_map_string_i64 == c_map_string_i64
|
||||||
|
assert a_map_string_f32 == c_map_string_f32
|
||||||
|
assert a_map_string_f64 == c_map_string_f64
|
||||||
|
assert a_map_string_bool == c_map_string_bool
|
||||||
|
assert a_map_string_rune == c_map_string_rune
|
||||||
|
assert a_map_string_isize == c_map_string_isize
|
||||||
|
assert a_map_string_usize == c_map_string_usize
|
||||||
|
|
||||||
|
assert b_map_string_string == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98,
|
||||||
|
99, 3, 0, 0, 0, 0, 0, 0, 0, 100, 101, 102]
|
||||||
|
assert b_map_string_int == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99,
|
||||||
|
95, 83, 0, 0, 0, 0, 0, 0]
|
||||||
|
assert b_map_string_u8 == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99,
|
||||||
|
37]
|
||||||
|
assert b_map_string_u16 == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99,
|
||||||
|
19, 13]
|
||||||
|
assert b_map_string_u32 == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99,
|
||||||
|
35, 22, 5, 0]
|
||||||
|
assert b_map_string_u64 == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99,
|
||||||
|
167, 251, 0, 0, 0, 0, 0, 0]
|
||||||
|
assert b_map_string_i8 == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99,
|
||||||
|
219]
|
||||||
|
assert b_map_string_i16 == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99,
|
||||||
|
237, 242]
|
||||||
|
assert b_map_string_i32 == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99,
|
||||||
|
221, 233, 250, 255]
|
||||||
|
assert b_map_string_i64 == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99,
|
||||||
|
89, 4, 255, 255, 255, 255, 255, 255]
|
||||||
|
assert b_map_string_f32 == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99,
|
||||||
|
6, 129, 197, 63]
|
||||||
|
assert b_map_string_f64 == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99,
|
||||||
|
212, 186, 221, 173, 2, 76, 104, 70]
|
||||||
|
assert b_map_string_bool == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99,
|
||||||
|
1]
|
||||||
|
assert b_map_string_rune == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99,
|
||||||
|
101, 38, 0, 0]
|
||||||
|
$if x64 {
|
||||||
|
assert b_map_string_isize == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98,
|
||||||
|
99, 135, 78, 255, 255, 255, 255, 255, 255]
|
||||||
|
assert b_map_string_usize == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98,
|
||||||
|
99, 83, 152, 6, 0, 0, 0, 0, 0]
|
||||||
|
} $else {
|
||||||
|
assert b_map_string_isize == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98,
|
||||||
|
99, 135, 78, 255, 255]
|
||||||
|
assert b_map_string_usize == [u8(1), 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 97, 98,
|
||||||
|
99, 83, 152, 6, 0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyStruct {
|
||||||
|
f_u8 u8
|
||||||
|
f_u16 u16
|
||||||
|
f_u32 u32
|
||||||
|
f_u64 u64
|
||||||
|
f_i8 i8
|
||||||
|
f_i16 i16
|
||||||
|
f_i32 i32
|
||||||
|
f_i64 i64
|
||||||
|
f_int int
|
||||||
|
f_f32 f32
|
||||||
|
f_f64 f64
|
||||||
|
f_bool bool
|
||||||
|
f_rune rune
|
||||||
|
f_isize isize
|
||||||
|
f_usize usize
|
||||||
|
f_string string
|
||||||
|
f_array_u8 []u8
|
||||||
|
f_array_string []string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_encode_decode_struct() {
|
||||||
|
a_struct := MyStruct{
|
||||||
|
f_u8: u8(31)
|
||||||
|
f_u16: u16(57)
|
||||||
|
f_u32: u32(6432)
|
||||||
|
f_u64: u64(7896423)
|
||||||
|
f_i8: i8(-22)
|
||||||
|
f_i16: i16(-5433)
|
||||||
|
f_i32: i32(-54244)
|
||||||
|
f_i64: i64(-8322234)
|
||||||
|
f_int: int(4235)
|
||||||
|
f_f32: f32(1.5382)
|
||||||
|
f_f64: f64(22421.32)
|
||||||
|
f_bool: bool(true)
|
||||||
|
f_rune: rune(`♥`)
|
||||||
|
f_isize: isize(42323)
|
||||||
|
f_usize: usize(83842)
|
||||||
|
f_string: 'fds♥323s'
|
||||||
|
f_array_u8: [u8(32), 22, 55, 72]
|
||||||
|
f_array_string: ['dfdss', 'dfsd3', '54344']
|
||||||
|
}
|
||||||
|
|
||||||
|
b_struct := encode_binary(a_struct)!
|
||||||
|
c_struct := decode_binary[MyStruct](b_struct)!
|
||||||
|
|
||||||
|
assert a_struct == c_struct
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyStruct_SkipFields {
|
||||||
|
mut:
|
||||||
|
f_u8 u8
|
||||||
|
f_u16 u16 @[serialize: '-']
|
||||||
|
f_u32 u32
|
||||||
|
f_u64 u64
|
||||||
|
f_i8 i8
|
||||||
|
f_i16 i16
|
||||||
|
f_i32 i32
|
||||||
|
f_i64 i64
|
||||||
|
f_int int
|
||||||
|
f_f32 f32
|
||||||
|
f_f64 f64
|
||||||
|
f_bool bool
|
||||||
|
f_rune rune
|
||||||
|
f_isize isize
|
||||||
|
f_usize usize
|
||||||
|
f_string string
|
||||||
|
f_array_u8 []u8 @[serialize: '-']
|
||||||
|
f_array_string []string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_encode_decode_struct_skip_fields() {
|
||||||
|
a_struct := MyStruct_SkipFields{
|
||||||
|
f_u8: u8(31)
|
||||||
|
f_u16: u16(57)
|
||||||
|
f_u32: u32(6432)
|
||||||
|
f_u64: u64(7896423)
|
||||||
|
f_i8: i8(-22)
|
||||||
|
f_i16: i16(-5433)
|
||||||
|
f_i32: i32(-54244)
|
||||||
|
f_i64: i64(-8322234)
|
||||||
|
f_int: int(4235)
|
||||||
|
f_f32: f32(1.5382)
|
||||||
|
f_f64: f64(22421.32)
|
||||||
|
f_bool: bool(true)
|
||||||
|
f_rune: rune(`♥`)
|
||||||
|
f_isize: isize(42323)
|
||||||
|
f_usize: usize(83842)
|
||||||
|
f_string: 'fds♥323s'
|
||||||
|
f_array_u8: [u8(32), 22, 55, 72]
|
||||||
|
f_array_string: ['dfdss', 'dfsd3', '54344']
|
||||||
|
}
|
||||||
|
|
||||||
|
b_struct := encode_binary(a_struct)!
|
||||||
|
mut c_struct := decode_binary[MyStruct_SkipFields](b_struct)!
|
||||||
|
|
||||||
|
assert a_struct != c_struct
|
||||||
|
|
||||||
|
c_struct.f_u16 = u16(57)
|
||||||
|
c_struct.f_array_u8 = [u8(32), 22, 55, 72]
|
||||||
|
assert a_struct == c_struct
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ComplexStruct {
|
||||||
|
f_u8 u8
|
||||||
|
f_u32 u32
|
||||||
|
f_u64 u64
|
||||||
|
f_string string
|
||||||
|
f_structs []MyStruct
|
||||||
|
f_maps []map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_encode_decode_complex() {
|
||||||
|
a_complex := ComplexStruct{
|
||||||
|
f_u8: u8(78)
|
||||||
|
f_u32: u32(0x11223344)
|
||||||
|
f_u64: u64(0x55667788)
|
||||||
|
f_string: 'complex'
|
||||||
|
f_structs: [
|
||||||
|
MyStruct{
|
||||||
|
f_u8: u8(31)
|
||||||
|
f_u16: u16(57)
|
||||||
|
f_u32: u32(6432)
|
||||||
|
f_u64: u64(7896423)
|
||||||
|
f_i8: i8(-22)
|
||||||
|
f_i16: i16(-5433)
|
||||||
|
f_i32: i32(-54244)
|
||||||
|
f_i64: i64(-8322234)
|
||||||
|
f_int: int(4235)
|
||||||
|
f_f32: f32(1.5382)
|
||||||
|
f_f64: f64(22421.32)
|
||||||
|
f_bool: bool(true)
|
||||||
|
f_rune: rune(`♥`)
|
||||||
|
f_isize: isize(42323)
|
||||||
|
f_usize: usize(83842)
|
||||||
|
f_string: 'fds♥323s'
|
||||||
|
f_array_u8: [u8(32), 22, 55, 72]
|
||||||
|
f_array_string: ['dfdss', 'dfsd3', '54344']
|
||||||
|
},
|
||||||
|
MyStruct{
|
||||||
|
f_u8: u8(41)
|
||||||
|
f_u16: u16(67)
|
||||||
|
f_u32: u32(7432)
|
||||||
|
f_u64: u64(8896423)
|
||||||
|
f_i8: i8(-32)
|
||||||
|
f_i16: i16(-6433)
|
||||||
|
f_i32: i32(-64244)
|
||||||
|
f_i64: i64(-9322234)
|
||||||
|
f_int: int(5235)
|
||||||
|
f_f32: f32(2.5382)
|
||||||
|
f_f64: f64(32421.32)
|
||||||
|
f_bool: bool(true)
|
||||||
|
f_rune: rune(`♥`)
|
||||||
|
f_isize: isize(52323)
|
||||||
|
f_usize: usize(93842)
|
||||||
|
f_string: 'ads♥323s'
|
||||||
|
f_array_u8: [u8(22), 22, 55, 72]
|
||||||
|
f_array_string: ['dxfdss', 'dsefsd3', 'po54344']
|
||||||
|
},
|
||||||
|
]
|
||||||
|
f_maps: [
|
||||||
|
{
|
||||||
|
'abc': 'def'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'123': '456'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
',./': '!@#'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
b_complex := encode_binary(a_complex)!
|
||||||
|
c_complex := decode_binary[ComplexStruct](b_complex)!
|
||||||
|
|
||||||
|
assert a_complex == c_complex
|
||||||
|
|
||||||
|
// big endian test
|
||||||
|
b_complex_big_endian := encode_binary(a_complex, big_endian: true)!
|
||||||
|
c_complex_big_endian := decode_binary[ComplexStruct](b_complex_big_endian, big_endian: true)!
|
||||||
|
|
||||||
|
assert b_complex != b_complex_big_endian
|
||||||
|
assert a_complex == c_complex_big_endian
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user