Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: encode_to_json_using_fixed_buffer #9

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 199 additions & 14 deletions decode.v
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,27 @@ const msg_bad_desc = 'unrecognized descriptor byte'
struct Decoder {
config Config = default_config()
mut:
pos int
buffer []u8
bd u8 // actual buffer value
pos int
buffer []u8
bd u8 // actual buffer value
char_count int
}

pub fn new_decoder() Decoder {
return Decoder{}
pub fn new_decoder(src []u8) Decoder {
return Decoder{
buffer: src
}
}

pub fn decode_to_json[T](src []u8) !string {
mut d := new_decoder()
mut d := new_decoder(src)

json := d.decode_to_json[T](src) or { return error('error decoding to JSON: ${err}') }

return json
}

pub fn (mut d Decoder) decode_to_json[T](src []u8) !string {
d.buffer = src
d.next()!

mut result := []u8{}
Expand All @@ -43,7 +45,7 @@ pub fn (mut d Decoder) decode_to_json[T](src []u8) !string {
mp_array_16, mp_array_32, mp_fix_array_min...mp_fix_array_max {
array_len := d.read_array_len(data) or { return error('error reading array length') }

mut d_for_array := new_decoder()
mut d_for_array := new_decoder(src[1..])

result << `[`

Expand All @@ -52,7 +54,7 @@ pub fn (mut d Decoder) decode_to_json[T](src []u8) !string {
result << `,`
}

element_json := d_for_array.decode_to_json[T](data[1..]) or {
element_json := d_for_array.decode_to_json[T](src[1..]) or {
return error('error converting array element to JSON ${err}')
}

Expand Down Expand Up @@ -87,6 +89,7 @@ pub fn (mut d Decoder) decode_to_json[T](src []u8) !string {
}
mp_nil {
unsafe { result.push_many('null'.str, 'null'.len) }
// d.pos +=
enghitalo marked this conversation as resolved.
Show resolved Hide resolved
}
mp_true, mp_false {
mut bool_val := false
Expand All @@ -106,6 +109,7 @@ pub fn (mut d Decoder) decode_to_json[T](src []u8) !string {
mp_str_8, mp_str_16, mp_str_32, mp_fix_str_min...mp_fix_str_max {
mut str_val := ''
d.decode_string(mut str_val) or { return error('error decoding string: ${err}') }
// TODO remove (result << `\"`) like in decode_to_json_using_fixed_buffer
result << `\"`
enghitalo marked this conversation as resolved.
Show resolved Hide resolved
unsafe { result.push_many(str_val.str, str_val.len) }
result << `\"`
enghitalo marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -118,19 +122,200 @@ pub fn (mut d Decoder) decode_to_json[T](src []u8) !string {

d.pos += bin_len
}
mp_ext_8, mp_ext_16, mp_ext_32 {}
mp_fix_ext_1, mp_fix_ext_2, mp_fix_ext_4, mp_fix_ext_8, mp_fix_ext_16 {}
mp_ext_8, mp_ext_16, mp_ext_32 {
// ext_len := d.read_ext_len(src) or { return error('error reading extension length') }
// ext_type := d.read_ext_type(src) or { return error('error reading extension type') }
// match ext_type {
// else {
// return error('unsupported extension type')
// }
// }
// d.pos += ext_len
enghitalo marked this conversation as resolved.
Show resolved Hide resolved
}
mp_fix_ext_1, mp_fix_ext_2, mp_fix_ext_4, mp_fix_ext_8, mp_fix_ext_16 {
// ext_len := int(d.bd - mp_fix_ext_1)
// ext_type := d.read_ext_type(src) or { return error('error reading extension type') }
// match ext_type {
// else {
// return error('unsupported extension type')
// }
// }
// d.pos += ext_len
}
else {
return error('unsupported descriptor byte for conversion to JSON')
}
}
return result.bytestr()
}

pub fn decode_to_json_using_fixed_buffer[T, F](src []u8, mut fixed_buf F) !string {
mut d := new_decoder(src)

json := d.decode_to_json_using_fixed_buffer[T, F](src, mut fixed_buf) or {
return error('error decoding to JSON: ${err}')
}

return json
}

pub fn (mut d Decoder) decode_to_json_using_fixed_buffer[T, F](src []u8, mut fixed_buf F) !string {
d.next()!

match d.bd {
mp_array_16, mp_array_32, mp_fix_array_min...mp_fix_array_max {
array_len := d.read_array_len(src) or { return error('error reading array length') }

// mut d_for_array := new_decoder(src)

fixed_buf[d.char_count] = `[`

for i in 0 .. array_len {
if i > 0 {
fixed_buf[d.char_count] = `,`
}
}
enghitalo marked this conversation as resolved.
Show resolved Hide resolved
fixed_buf[d.char_count] = `]`
}
mp_u8, mp_u16, mp_u32, mp_u64, mp_i8, mp_i16, mp_i32, mp_i64 {
mut int_val := 0
d.decode_integer(mut int_val) or { return error('error decoding integer: ${err}') }
for letter in int_val.str() {
fixed_buf[d.char_count] = letter
d.char_count++
}
}
mp_str_8, mp_str_16, mp_str_32, mp_fix_str_min...mp_fix_str_max {
data := d.buffer
// REVIEW - why it is slow??
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know what or why.

str_len := d.read_str_len(data) or { return error('error reading string length') }

for letter in data[d.pos..d.pos + str_len] {
enghitalo marked this conversation as resolved.
Show resolved Hide resolved
fixed_buf[d.char_count] = letter
d.char_count++
}
d.pos += str_len
}
mp_map_16, mp_map_32, mp_fix_map_min...mp_fix_map_max {
map_len := d.read_map_len(src) or { return error('error reading map length') }

fixed_buf[d.char_count] = `{`

d.char_count++

for map_idx in 0 .. map_len {
if map_idx > 0 {
fixed_buf[d.char_count] = `,`
d.char_count++
}

_ := d.decode_to_json_using_fixed_buffer[string, F](src, mut fixed_buf) or {
return error('error converting map key to JSON: ${err}')
}

fixed_buf[d.char_count] = `:`
d.char_count++

mut is_string := false
if d.buffer[d.pos] == mp_str_8 || d.buffer[d.pos] == mp_str_16
|| d.buffer[d.pos] == mp_str_32
|| (d.buffer[d.pos] >= mp_fix_str_min && d.buffer[d.pos] <= mp_fix_str_max) {
is_string = true
fixed_buf[d.char_count] = `"`
d.char_count++
}
_ := d.decode_to_json_using_fixed_buffer[string, F](src, mut fixed_buf) or {
return error('error converting map value to JSON')
}

if is_string {
fixed_buf[d.char_count] = `"`
d.char_count++
}
}

fixed_buf[d.char_count] = `}`
d.char_count++
}
mp_nil {
for letter in 'null' {
fixed_buf[d.char_count] = letter
d.char_count++
}
// d.pos +=
}
mp_true {
for letter in 'true' {
fixed_buf[d.char_count] = letter
d.char_count++
}
// d.pos +=
}
mp_false {
for letter in 'false' {
fixed_buf[d.char_count] = letter
d.char_count++
}
// d.pos +=
}
mp_f32, mp_f64 {
mut float_val := 0.0
d.decode_float(mut float_val) or { return error('error decoding float: ${err}') }
for letter in float_val.str() {
fixed_buf[d.char_count] = letter
d.char_count++
}
}
mp_bin_8, mp_bin_16, mp_bin_32 {
bin_len := d.read_bin_len(src) or { return error('error reading binary length') }
for i := 0; i < bin_len; i++ {
for letter in src[d.pos].str() {
fixed_buf[d.char_count] = letter
d.char_count++
}

d.pos++
}
}
mp_ext_8, mp_ext_16, mp_ext_32 {
// ext_len := d.read_ext_len(src) or { return error('error reading extension length') }
// ext_type := d.read_ext_type(src) or { return error('error reading extension type') }
// match ext_type {
// else {
// return error('unsupported extension type')
// }
// }
// d.pos += ext_len
enghitalo marked this conversation as resolved.
Show resolved Hide resolved
}
mp_fix_ext_1, mp_fix_ext_2, mp_fix_ext_4, mp_fix_ext_8, mp_fix_ext_16 {
// ext_len := int(d.bd - mp_fix_ext_1)
// ext_type := d.read_ext_type(src) or { return error('error reading extension type') }
// match ext_type {
// else {
// return error('unsupported extension type')
// }
// }
// d.pos += ext_len
}
else {
return error('unsupported descriptor byte for conversion to JSON')
}
}

mut result := []u8{len: d.char_count}
for id, variable in fixed_buf {
if id == d.char_count {
break
}
result[id] = variable
}
return result.bytestr()
}

pub fn decode[T](src []u8) !T {
mut val := T{}

mut d := new_decoder()
mut d := new_decoder(src)
d.decode[T](src, mut val) or { return error('error decoding data: ${err}') }

return val
Expand All @@ -141,7 +326,6 @@ pub fn (mut d Decoder) decode_from_string[T](data string) ! {
}

pub fn (mut d Decoder) decode[T](data []u8, mut val T) ! {
d.buffer = data
d.next()!

$if T is $int {
Expand Down Expand Up @@ -260,7 +444,7 @@ pub fn (mut d Decoder) decode_array[T](mut val []T) ! {
array_len := d.read_array_len(data) or { return error('error reading array length') }
elements_buffer := data[1..]

mut d_for_array := new_decoder()
mut d_for_array := new_decoder(elements_buffer)

for _ in 0 .. array_len {
mut element := T{}
Expand Down Expand Up @@ -313,6 +497,7 @@ pub fn (mut d Decoder) decode_struct[T](mut val T) ! {

pub fn (mut d Decoder) decode_bool[T](mut val T) ! {
val = d.bd == mp_true
// d.pos +=
enghitalo marked this conversation as resolved.
Show resolved Hide resolved
}

pub fn (mut d Decoder) decode_time[T](mut val T) ! {
Expand Down
4 changes: 2 additions & 2 deletions decode_to_json_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fn test_decode_to_json_map() {

fn test_to_json_array() {
src := msgpack.encode([1, 2])
mut d := msgpack.new_decoder()
mut d := msgpack.new_decoder(src)
result := d.decode_to_json[[]u64](src) or { panic('error converting to JSON: ${err}') }
assert result == '[1,2]'
}
Expand All @@ -32,7 +32,7 @@ fn test_to_json_map() {
'key1': 1
'key2': 2
})
mut d := msgpack.new_decoder()
mut d := msgpack.new_decoder(src)
result := d.decode_to_json[map[string]int](src) or { panic('error converting to JSON') }
assert result == '{"key1":1,"key2":2}'
}
16 changes: 14 additions & 2 deletions encode.v
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module msgpack
import math
import time

struct Encoder {
mut:
pub struct Encoder {
pub mut:
buffer []u8
config Config = default_config()
}
Expand All @@ -24,6 +24,18 @@ pub fn encode_to_json[T](data T) string {
return decode_to_json[T](encoded) or { '' }
}

pub fn encode_to_json_using_fixed_buffer[T, F](data T, mut fixed_buf F) string {
mut encoder := new_encoder()
encoded := encoder.encode(data)

$if F is $array_fixed {
return decode_to_json_using_fixed_buffer[T, F](encoded, mut fixed_buf) or { '' }
} $else {
eprintln('fixed_buf need be a fixed array')
return ''
}
}

pub fn (e &Encoder) str() string {
return e.buffer.hex()
}
Expand Down
Loading
Loading