Files
herolib/lib/data/encoder/encoder_decode.v
Mahmoud-Emad a65cbd606b feat: improve build and serialization logic
- Update v fmt exit code handling
- Support dynamic organization for symlinks
- Add f32 and list f64 serialization/deserialization
- Improve JSON decoding for bid requirements/pricing
- Add basic tests for Bid and Node creation
2025-10-12 13:27:10 +03:00

276 lines
5.6 KiB
V

module encoder
import encoding.binary as bin
import incubaid.herolib.data.ourtime
import time
import incubaid.herolib.data.gid
import incubaid.herolib.data.currency
pub struct Decoder {
pub mut:
version u8 = 1 // is important
data []u8
}
pub fn decoder_new(data []u8) Decoder {
mut e := Decoder{}
e.data = data
return e
}
pub fn (mut d Decoder) get_string() !string {
n := d.get_u16()!
// THIS IS ALWAYS TRUE BECAUSE u16 is max 64KB
// if n > 64 * 1024 { // 64KB limit
// return error('string length ${n} exceeds 64KB limit')
// }
if n > d.data.len {
return error('string length ${n} exceeds remaining data length ${d.data.len}')
}
mut bytes := []u8{len: int(n)}
for i in 0 .. n {
bytes[i] = d.data[i]
}
d.data.delete_many(0, n)
return bytes.bytestr()
}
pub fn (mut d Decoder) get_int() !int {
return int(d.get_u32()!)
}
pub fn (mut d Decoder) get_bytes() ![]u8 {
n := int(d.get_u32()!)
if n > 64 * 1024 { // 64KB limit
return error('bytes length ${n} exceeds 64KB limit')
}
if n > d.data.len {
return error('bytes length ${n} exceeds remaining data length ${d.data.len}')
}
mut bytes := []u8{len: int(n)}
for i in 0 .. n {
bytes[i] = d.data[i]
}
d.data.delete_many(0, n)
return bytes
}
pub fn (mut d Decoder) get_bool() !bool {
val := d.get_u8()!
return val == 1
}
// adds u16 length of string in bytes + the bytes
pub fn (mut d Decoder) get_u8() !u8 {
if d.data.len < 1 {
return error('not enough data for u8')
}
v := d.data.first()
d.data.delete(0)
return v
}
pub fn (mut d Decoder) get_u16() !u16 {
if d.data.len < 2 {
return error('not enough data for u16')
}
mut bytes := []u8{len: 2}
bytes[0] = d.data[0]
bytes[1] = d.data[1]
d.data.delete_many(0, 2)
return bin.little_endian_u16(bytes)
}
pub fn (mut d Decoder) get_u32() !u32 {
if d.data.len < 4 {
return error('not enough data for u32')
}
mut bytes := []u8{len: 4}
bytes[0] = d.data[0]
bytes[1] = d.data[1]
bytes[2] = d.data[2]
bytes[3] = d.data[3]
d.data.delete_many(0, 4)
return bin.little_endian_u32(bytes)
}
pub fn (mut d Decoder) get_u64() !u64 {
if d.data.len < 8 {
return error('not enough data for u64')
}
mut bytes := []u8{len: 8}
bytes[0] = d.data[0]
bytes[1] = d.data[1]
bytes[2] = d.data[2]
bytes[3] = d.data[3]
bytes[4] = d.data[4]
bytes[5] = d.data[5]
bytes[6] = d.data[6]
bytes[7] = d.data[7]
d.data.delete_many(0, 8)
return bin.little_endian_u64(bytes)
}
pub fn (mut d Decoder) get_i64() !i64 {
if d.data.len < 8 {
return error('not enough data for i64')
}
mut bytes := []u8{len: 8}
bytes[0] = d.data[0]
bytes[1] = d.data[1]
bytes[2] = d.data[2]
bytes[3] = d.data[3]
bytes[4] = d.data[4]
bytes[5] = d.data[5]
bytes[6] = d.data[6]
bytes[7] = d.data[7]
d.data.delete_many(0, 8)
return u64(bin.little_endian_u64(bytes))
}
pub fn (mut d Decoder) get_f64() !f64 {
// Get the u64 bits first and then convert back to f64
bits := d.get_u64()!
// Use unsafe to convert bits to f64
f := unsafe { *(&f64(&bits)) }
return f
}
pub fn (mut d Decoder) get_f32() !f32 {
// Get the u32 bits first and then convert back to f32
bits := d.get_u32()!
// Use unsafe to convert bits to f32
f := unsafe { *(&f32(&bits)) }
return f
}
pub fn (mut d Decoder) get_time() !time.Time {
secs_ := d.get_u32()!
secs := i64(secs_)
return time.unix(secs)
}
pub fn (mut d Decoder) get_ourtime() !ourtime.OurTime {
return ourtime.OurTime{
unixt: d.get_u32()!
}
}
pub fn (mut d Decoder) get_currency() !currency.Amount {
curstring := d.get_string()!
if curstring.len == 0 {
return error('currency string is empty')
}
currencyo := currency.get(curstring)!
return currency.Amount{
currency: currencyo
val: d.get_f64()!
}
}
pub fn (mut d Decoder) get_percentage() !u8 {
val := d.get_u8()!
if val > 100 {
return error('percentage value ${val} exceeds 100')
}
return val
}
pub fn (mut d Decoder) get_list_string() ![]string {
n := d.get_u16()!
mut v := []string{len: int(n)}
for i in 0 .. n {
v[i] = d.get_string()!
}
return v
}
pub fn (mut d Decoder) get_list_int() ![]int {
n := d.get_u16()!
mut v := []int{len: int(n)}
for i in 0 .. n {
v[i] = d.get_int()!
}
return v
}
pub fn (mut d Decoder) get_list_u8() ![]u8 {
n := d.get_u16()!
if n > 64 * 1024 { // 64KB limit
return error('list length ${n} exceeds 64KB limit')
}
if n > d.data.len {
return error('list length ${n} exceeds remaining data length ${d.data.len}')
}
mut bytes := []u8{len: int(n)}
for i in 0 .. n {
bytes[i] = d.data[i]
}
d.data.delete_many(0, n)
return bytes
}
pub fn (mut d Decoder) get_list_u16() ![]u16 {
n := d.get_u16()!
mut v := []u16{len: int(n)}
for i in 0 .. n {
v[i] = d.get_u16()!
}
return v
}
pub fn (mut d Decoder) get_list_u32() ![]u32 {
n := d.get_u16()!
mut v := []u32{len: int(n)}
for i in 0 .. n {
v[i] = d.get_u32()!
}
return v
}
pub fn (mut d Decoder) get_list_u64() ![]u64 {
n := d.get_u16()!
mut v := []u64{len: int(n)}
for i in 0 .. n {
v[i] = d.get_u64()!
}
return v
}
pub fn (mut d Decoder) get_list_f64() ![]f64 {
n := d.get_u16()!
mut v := []f64{len: int(n)}
for i in 0 .. n {
v[i] = d.get_f64()!
}
return v
}
pub fn (mut d Decoder) get_map_string() !map[string]string {
n := d.get_u16()!
mut v := map[string]string{}
for _ in 0 .. n {
key := d.get_string()!
val := d.get_string()!
v[key] = val
}
return v
}
pub fn (mut d Decoder) get_map_bytes() !map[string][]u8 {
n := d.get_u16()!
mut v := map[string][]u8{}
for _ in 0 .. n {
key := d.get_string()!
val := d.get_bytes()!
v[key] = val
}
return v
}
// Gets GID from encoded string
pub fn (mut d Decoder) get_gid() !gid.GID {
gid_str := d.get_string()!
return gid.new(gid_str)
}