From f1ea6cd0da1877917cf8e95986e350592f1b2599 Mon Sep 17 00:00:00 2001 From: Hitalo Souza Date: Mon, 12 Dec 2022 09:27:52 -0300 Subject: [PATCH 1/7] feat: new example --- examples/bench_msgpack_json_vs_json2.v | 72 ++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 examples/bench_msgpack_json_vs_json2.v diff --git a/examples/bench_msgpack_json_vs_json2.v b/examples/bench_msgpack_json_vs_json2.v new file mode 100644 index 0000000..003f952 --- /dev/null +++ b/examples/bench_msgpack_json_vs_json2.v @@ -0,0 +1,72 @@ +import os +import json +import x.json2 +import msgpack +import time +import benchmark + +struct Person { + name string + age int + created_at time.Time +} + +fn main() { + max_iterations := os.getenv_opt('MAX_ITERATIONS') or { '1000' }.int() + s := '{"name":"Bilbo Baggins","age":99,"created_at":1670840340}' + mut b := benchmark.start() + + for _ in 0 .. max_iterations { + p := json2.decode[Person](s)! + if p.age != 99 { + println('error: ${p}') + } + } + b.measure('json2.decode') + + for _ in 0 .. max_iterations { + p := json.decode(Person, s)! + if p.age != 99 { + println('error: ${p}') + } + } + b.measure('json.decode') + + // encoding measurements: + p := json.decode(Person, s)! + + for _ in 0 .. max_iterations { + es := json2.encode(p) + if es[0] != `{` { + println('json2.encode error: ${es}') + } + } + b.measure('json2.encode') + + for _ in 0 .. max_iterations { + es := json.encode(p) + if es[0] != `{` { + println('json.encode error: ${es}') + } + } + b.measure('json.encode') + + for _ in 0 .. max_iterations { + es := msgpack.encode(p) + if p.age != 99 { + println('error: ${es}') + } + } + b.measure('msgpack.encode') + + encoded := msgpack.encode(p) + + mut decoder := msgpack.new_decoder() + for _ in 0 .. max_iterations { + p := decoder.decode(encoded) + if p.age != 99 { + println('error: ${p}') + } + } + b.measure('msgpack.decode') +} \ No newline at end of file From e40c61a3c99911cd80557500f4db4f689c7d13c8 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 12 Dec 2022 15:26:25 +0200 Subject: [PATCH 2/7] fix compilation --- examples/bench_msgpack_json_vs_json2.v | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/bench_msgpack_json_vs_json2.v b/examples/bench_msgpack_json_vs_json2.v index 003f952..46e7f1d 100644 --- a/examples/bench_msgpack_json_vs_json2.v +++ b/examples/bench_msgpack_json_vs_json2.v @@ -50,23 +50,23 @@ fn main() { } } b.measure('json.encode') - + for _ in 0 .. max_iterations { - es := msgpack.encode(p) + es := msgpack.encode[Person](p) if p.age != 99 { println('error: ${es}') } } b.measure('msgpack.encode') - encoded := msgpack.encode(p) + encoded := msgpack.encode[Person](p) mut decoder := msgpack.new_decoder() for _ in 0 .. max_iterations { - p := decoder.decode(encoded) - if p.age != 99 { - println('error: ${p}') + m := decoder.decode(encoded) + if m.age != 99 { + println('error: ${m}') } } b.measure('msgpack.decode') -} \ No newline at end of file +} From 70cd495ce4738d921ffd516a656942d1ff2eece3 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 12 Dec 2022 15:30:56 +0200 Subject: [PATCH 3/7] fix decoder.decode call --- examples/bench_msgpack_json_vs_json2.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/bench_msgpack_json_vs_json2.v b/examples/bench_msgpack_json_vs_json2.v index 46e7f1d..e26dbbf 100644 --- a/examples/bench_msgpack_json_vs_json2.v +++ b/examples/bench_msgpack_json_vs_json2.v @@ -63,7 +63,7 @@ fn main() { mut decoder := msgpack.new_decoder() for _ in 0 .. max_iterations { - m := decoder.decode(encoded) + m := decoder.decode(encoded)! if m.age != 99 { println('error: ${m}') } From e2e0bd4c1827f014ef4051147cf87c66829ced53 Mon Sep 17 00:00:00 2001 From: Hitalo Souza Date: Mon, 12 Dec 2022 10:47:36 -0300 Subject: [PATCH 4/7] fix --- examples/bench_msgpack_json_vs_json2.v | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/examples/bench_msgpack_json_vs_json2.v b/examples/bench_msgpack_json_vs_json2.v index e26dbbf..a37abdf 100644 --- a/examples/bench_msgpack_json_vs_json2.v +++ b/examples/bench_msgpack_json_vs_json2.v @@ -58,15 +58,4 @@ fn main() { } } b.measure('msgpack.encode') - - encoded := msgpack.encode[Person](p) - - mut decoder := msgpack.new_decoder() - for _ in 0 .. max_iterations { - m := decoder.decode(encoded)! - if m.age != 99 { - println('error: ${m}') - } - } - b.measure('msgpack.decode') } From ee3bd71cef9fde7dad99b272c4bd07e0fb753347 Mon Sep 17 00:00:00 2001 From: Hitalo Souza Date: Sun, 26 Nov 2023 12:08:03 -0400 Subject: [PATCH 5/7] fix: make msgpack work --- encode.v | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/encode.v b/encode.v index 4941644..7a62603 100644 --- a/encode.v +++ b/encode.v @@ -28,50 +28,50 @@ pub fn (e &Encoder) bytes() []u8 { } pub fn (mut e Encoder) encode[T](data T) []u8 { - $if T.typ is string { + $if T is string { e.encode_string(data) - } $else $if T.typ is bool { + } $else $if T is bool { e.encode_bool(data) } // TODO: if int encode_int, if uint encode_uint // instead of needing to check each type, also // then we will be using the smallest storage - $else $if T.typ is i8 { + $else $if T is i8 { e.encode_i8(data) - } $else $if T.typ is i16 { + } $else $if T is i16 { e.encode_i16(data) - } $else $if T.typ is int { + } $else $if T is int { e.encode_i32(data) - } $else $if T.typ is i64 { + } $else $if T is i64 { e.encode_i64(data) - } $else $if T.typ is u8 { + } $else $if T is u8 { e.encode_u8(data) - } $else $if T.typ is u16 { + } $else $if T is u16 { e.encode_u16(data) - } $else $if T.typ is u32 { + } $else $if T is u32 { e.encode_u32(data) - } $else $if T.typ is u64 { + } $else $if T is u64 { e.encode_u64(data) - } $else $if T.typ is f32 { + } $else $if T is f32 { e.encode_f32(data) - } $else $if T.typ is f64 { + } $else $if T is f64 { e.encode_f64(data) - } $else $if T.typ is time.Time { + } $else $if T is time.Time { e.encode_time(data) - } $else $if T.typ is []u8 { + } $else $if T is []u8 { e.encode_string_bytes_raw(data) - } $else $if T is $Array { + } $else $if T is $array { e.write_array_start(data.len) for value in data { e.encode(value) } - } $else $if T is $Map { + } $else $if T is $map { e.write_map_start(data.len) for key, value in data { e.encode(key) e.encode(value) } - } $else $if T is $Struct { + } $else $if T is $struct { // TODO: is there currently a way to get T.fields.len? if not, add it. mut fields_len := 0 $for _ in T.fields { @@ -84,6 +84,7 @@ pub fn (mut e Encoder) encode[T](data T) []u8 { e.write_map_start(fields_len) } $for field in T.fields { + value := data.$(field.name) mut codec_attr := '' for attr in field.attrs { if attr.starts_with('codec:') { @@ -97,7 +98,9 @@ pub fn (mut e Encoder) encode[T](data T) []u8 { } else { e.encode_string(field.name) } - e.encode(data.$(field.name)) + + // e.encode(data.$(field.name)) // FIXME - not work - bug + e.encode(value) } } return e.buffer From 5140bc869970a16b9b4901ac5f9763ba4e85f6f3 Mon Sep 17 00:00:00 2001 From: Hitalo Souza Date: Sun, 26 Nov 2023 14:43:03 -0400 Subject: [PATCH 6/7] style: v fmt . -w --- decode.v | 4 +- examples/basic.v | 8 +-- types.v | 176 ++++++++++++++++++++++++++--------------------- 3 files changed, 101 insertions(+), 87 deletions(-) diff --git a/decode.v b/decode.v index c27a882..e455e92 100644 --- a/decode.v +++ b/decode.v @@ -4,9 +4,7 @@ import time import encoding.hex import encoding.binary -const ( - msg_bad_desc = 'unrecognized descriptor byte' -) +const msg_bad_desc = 'unrecognized descriptor byte' struct Decoder { config Config = default_config() diff --git a/examples/basic.v b/examples/basic.v index 7f3ca09..d1eb5dc 100644 --- a/examples/basic.v +++ b/examples/basic.v @@ -4,8 +4,8 @@ import msgpack import time pub struct TestStructA { - field_a int [codec: 'codecdata1'] - field_b string [codec: 'codecdata2'] + field_a int @[codec: 'codecdata1'] + field_b string @[codec: 'codecdata2'] field_c TestStructB field_d []string // TODO: fix compiler (comptime generic infer) @@ -16,8 +16,8 @@ pub struct TestStructA { } pub struct TestStructB { - field_a int [codec: 'codecdata1'] - field_b string [codec: 'codecdata2'] + field_a int @[codec: 'codecdata1'] + field_b string @[codec: 'codecdata2'] } fn main() { diff --git a/types.v b/types.v index 95a2908..ef77b0e 100644 --- a/types.v +++ b/types.v @@ -3,83 +3,101 @@ module msgpack import math // Spec: https://github.com/msgpack/msgpack/blob/master/spec.md -const ( - // 7-bit positive integer - mp_pos_fix_int_min = u8(0x00) - mp_pos_fix_int_max = u8(0x7f) - // map whose length is up to 15 elements - mp_fix_map_min = u8(0x80) - mp_fix_map_max = u8(0x8f) - // array whose length is up to 15 elements - mp_fix_array_min = u8(0x90) - mp_fix_array_max = u8(0x9f) - // byte array whose length is up to 31 bytes - mp_fix_str_min = u8(0xa0) - mp_fix_str_max = u8(0xbf) - // nil - mp_nil = u8(0xc0) - // _ = u8(0xc1) // never used - // booleans - mp_false = u8(0xc2) - mp_true = u8(0xc3) - // byte array whose length is up to: - mp_bin_8 = u8(0xc4) // (2^8)-1 bytes - mp_bin_16 = u8(0xc5) // (2^16)-1 bytes (big-endian) - mp_bin_32 = u8(0xc6) // (2^32)-1 bytes (big-endian) - // integer and a byte array whose length is up to: - mp_ext_8 = u8(0xc7) // (2^8)-1 bytes - mp_ext_16 = u8(0xc8) // (2^16)-1 bytes (big-endian) - mp_ext_32 = u8(0xc9) // (2^32)-1 bytes (big-endian) - // single|double precision floating point number (big-endian, IEEE 754) - mp_f32 = u8(0xca) - mp_f64 = u8(0xcb) - // 8|16|32|64-bit unsigned integer - mp_u8 = u8(0xcc) - mp_u16 = u8(0xcd) // (big-endian) - mp_u32 = u8(0xce) // (big-endian) - mp_u64 = u8(0xcf) // (big-endian) - // 8|16|32|64-bit signed integer - mp_i8 = u8(0xd0) - mp_i16 = u8(0xd1) // (big-endian) - mp_i32 = u8(0xd2) // (big-endian) - mp_i64 = u8(0xd3) // (big-endian) - // integer and a byte array whose length is: - mp_fix_ext_1 = u8(0xd4) // 1 byte - mp_fix_ext_2 = u8(0xd5) // 2 bytes - mp_fix_ext_4 = u8(0xd6) // 4 bytes - mp_fix_ext_8 = u8(0xd7) // 8 bytes - mp_fix_ext_16 = u8(0xd8) // 16 bytes - // byte array whose length is up to: - mp_str_8 = u8(0xd9) // (2^8)-1 bytes - mp_str_16 = u8(0xda) // (2^16)-1 bytes (big-endian) - mp_str_32 = u8(0xdb) // (2^32)-1 bytes (big-endian) - // array whose length is up to (big-endian): - mp_array_16 = u8(0xdc) // (2^16)-1 elements - mp_array_32 = u8(0xdd) // (2^32)-1 elements - // map whose length is up to (big-endian): - mp_map_16 = u8(0xde) // (2^16)-1 elements - mp_map_32 = u8(0xdf) // (2^32)-1 elements - // 5-bit negative integer - mp_neg_fix_int_min = u8(0xe0) - mp_neg_fix_int_max = u8(0xff) -) +// 7-bit positive integer +const mp_pos_fix_int_min = u8(0x00) +const mp_pos_fix_int_max = u8(0x7f) +// map whose length is up to 15 elements +const mp_fix_map_min = u8(0x80) +const mp_fix_map_max = u8(0x8f) +// array whose length is up to 15 elements +const mp_fix_array_min = u8(0x90) +const mp_fix_array_max = u8(0x9f) +// byte array whose length is up to 31 bytes +const mp_fix_str_min = u8(0xa0) +const mp_fix_str_max = u8(0xbf) +// nil +const mp_nil = u8(0xc0) +// _ = u8(0xc1) // never used +// booleans +const mp_false = u8(0xc2) +const mp_true = u8(0xc3) +// byte array whose length is up to: +const mp_bin_8 = u8(0xc4) +// (2^8)-1 bytes +const mp_bin_16 = u8(0xc5) +// (2^16)-1 bytes (big-endian) +const mp_bin_32 = u8(0xc6) +// (2^32)-1 bytes (big-endian) +// integer and a byte array whose length is up to: +const mp_ext_8 = u8(0xc7) +// (2^8)-1 bytes +const mp_ext_16 = u8(0xc8) +// (2^16)-1 bytes (big-endian) +const mp_ext_32 = u8(0xc9) +// (2^32)-1 bytes (big-endian) +// single|double precision floating point number (big-endian, IEEE 754) +const mp_f32 = u8(0xca) +const mp_f64 = u8(0xcb) +// 8|16|32|64-bit unsigned integer +const mp_u8 = u8(0xcc) +const mp_u16 = u8(0xcd) +// (big-endian) +const mp_u32 = u8(0xce) +// (big-endian) +const mp_u64 = u8(0xcf) +// (big-endian) +// 8|16|32|64-bit signed integer +const mp_i8 = u8(0xd0) +const mp_i16 = u8(0xd1) +// (big-endian) +const mp_i32 = u8(0xd2) +// (big-endian) +const mp_i64 = u8(0xd3) +// (big-endian) +// integer and a byte array whose length is: +const mp_fix_ext_1 = u8(0xd4) +// 1 byte +const mp_fix_ext_2 = u8(0xd5) +// 2 bytes +const mp_fix_ext_4 = u8(0xd6) +// 4 bytes +const mp_fix_ext_8 = u8(0xd7) +// 8 bytes +const mp_fix_ext_16 = u8(0xd8) +// 16 bytes +// byte array whose length is up to: +const mp_str_8 = u8(0xd9) +// (2^8)-1 bytes +const mp_str_16 = u8(0xda) +// (2^16)-1 bytes (big-endian) +const mp_str_32 = u8(0xdb) +// (2^32)-1 bytes (big-endian) +// array whose length is up to (big-endian): +const mp_array_16 = u8(0xdc) +// (2^16)-1 elements +const mp_array_32 = u8(0xdd) +// (2^32)-1 elements +// map whose length is up to (big-endian): +const mp_map_16 = u8(0xde) +// (2^16)-1 elements +const mp_map_32 = u8(0xdf) +// (2^32)-1 elements +// 5-bit negative integer +const mp_neg_fix_int_min = u8(0xe0) +const mp_neg_fix_int_max = u8(0xff) // Applications can assign 0 to 127 to store application-specific type information. // MessagePack reserves -1 to -128 for future extension to add predefined types. -const ( - // Timestamp - mp_time_ext_type = u8(-1) -) +// Timestamp +const mp_time_ext_type = u8(-1) -const ( - // container_len_unknown is length returned from read_(map|array)_len - // when a format doesn't prefix the length. - // For example, json doesn't pre-determine the length of a container (sequence/map). - // container_len_unknown = -1 - // container_len_nil is length returned from read_(map|array)_len - // when a 'nil' was encountered in the stream. - container_len_nil = math.min_i32 -) +// container_len_unknown is length returned from read_(map|array)_len +// when a format doesn't prefix the length. +// For example, json doesn't pre-determine the length of a container (sequence/map). +// container_len_unknown = -1 +// container_len_nil is length returned from read_(map|array)_len +// when a 'nil' was encountered in the stream. +const container_len_nil = math.min_i32 struct RawExt { tag u64 @@ -101,13 +119,11 @@ struct ContainerType { b32 u8 } -const ( - container_raw_legacy = ContainerType{32, mp_fix_str_min, 0, mp_str_16, mp_str_32} - container_str = ContainerType{32, mp_fix_str_min, mp_str_8, mp_str_16, mp_str_32} - container_bin = ContainerType{0, 0, mp_bin_8, mp_bin_16, mp_bin_32} - container_array = ContainerType{16, mp_fix_array_min, 0, mp_array_16, mp_array_32} - container_map = ContainerType{16, mp_fix_map_min, 0, mp_map_16, mp_map_32} -) +const container_raw_legacy = ContainerType{32, mp_fix_str_min, 0, mp_str_16, mp_str_32} +const container_str = ContainerType{32, mp_fix_str_min, mp_str_8, mp_str_16, mp_str_32} +const container_bin = ContainerType{0, 0, mp_bin_8, mp_bin_16, mp_bin_32} +const container_array = ContainerType{16, mp_fix_array_min, 0, mp_array_16, mp_array_32} +const container_map = ContainerType{16, mp_fix_map_min, 0, mp_map_16, mp_map_32} // valueType is the stream type enum ValueType { From 49efd47ec07f0c9499298691a9f227a3fb2fa4dc Mon Sep 17 00:00:00 2001 From: Hitalo Souza Date: Sun, 26 Nov 2023 14:48:06 -0400 Subject: [PATCH 7/7] refactor: remove depre --- encode.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/encode.v b/encode.v index 7a62603..40ce497 100644 --- a/encode.v +++ b/encode.v @@ -250,7 +250,7 @@ pub fn (mut e Encoder) encode_string_bytes_raw(bs []u8) { pub fn (mut e Encoder) encode_time(t time.Time) { // if t.is_zero() { - if t.second == 0 && t.microsecond == 0 { + if t.second == 0 && t.nanosecond == 0 { e.encode_nil() return }