module encoder import time import encoding.binary as bin import incubaid.herolib.data.ourtime import incubaid.herolib.data.gid import incubaid.herolib.data.currency const kb = 1024 pub struct Encoder { pub mut: data []u8 // datatypes []DataType } // enum DataType{ // string // int // bytes // u8 // u16 // u32 // u64 // time // list_string // list_int // list_u8 // list_u16 // list_u32 // list_u64 // map_string // map_bytes // } pub fn new() Encoder { mut e := Encoder{} return e } // adds u16 length of string in bytes + the bytes pub fn (mut b Encoder) add_string(data string) { if data.len > 64 * kb { panic('string cannot be bigger than 64kb') } b.add_u16(u16(data.len)) b.data << data.bytes() } // Please note that unlike C and Go, int is always a 32 bit integer. // We borrow the add_u32() function to handle the encoding of a 32 bit type pub fn (mut b Encoder) add_int(data int) { b.add_u32(u32(data)) } // add bytes or bytestring pub fn (mut b Encoder) add_bytes(data []u8) { b.add_u32(u32(data.len)) b.data << data } pub fn (mut b Encoder) add_bool(data bool) { if data { b.add_u8(1) } else { b.add_u8(0) } } pub fn (mut b Encoder) add_u8(data u8) { b.data << data } pub fn (mut b Encoder) add_u16(data u16) { mut d := []u8{len: 2} bin.little_endian_put_u16(mut d, data) b.data << d } pub fn (mut b Encoder) add_u32(data u32) { mut d := []u8{len: 4} bin.little_endian_put_u32(mut d, data) b.data << d } pub fn (mut b Encoder) add_u64(data u64) { mut d := []u8{len: 8} bin.little_endian_put_u64(mut d, data) b.data << d } pub fn (mut b Encoder) add_i64(data i64) { mut d := []u8{len: 8} bin.little_endian_put_u64(mut d, u64(data)) b.data << d } pub fn (mut b Encoder) add_time(data time.Time) { b.add_u32(u32(data.unix())) // add as epoch time } pub fn (mut b Encoder) add_ourtime(data ourtime.OurTime) { b.add_u32(u32(data.unixt)) } pub fn (mut b Encoder) add_currency(data currency.Amount) { b.add_string(data.currency.name) b.add_f64(data.val) } // adds a float64 value pub fn (mut b Encoder) add_f64(data f64) { // Convert f64 to bits first, then store as u64 bits := unsafe { *(&u64(&data)) } b.add_u64(bits) } // adds a float32 value pub fn (mut b Encoder) add_f32(data f32) { // Convert f32 to bits first, then store as u32 bits := unsafe { *(&u32(&data)) } b.add_u32(bits) } // adds gid as a string pub fn (mut b Encoder) add_gid(data gid.GID) { b.add_string(data.str()) } pub fn (mut b Encoder) add_percentage(data u8) { if data > 100 { panic('percentage cannot be greater than 100') } b.add_u8(data) } pub fn (mut b Encoder) add_list_string(data []string) { if data.len > 64 * kb { panic('list cannot have more than 64kb items.') } b.add_u16(u16(data.len)) for item in data { b.add_string(item) } } pub fn (mut b Encoder) add_list_int(data []int) { if data.len > 64 * kb { panic('list cannot have more than 64kb items.') } b.add_u16(u16(data.len)) // how many items in list for item in data { b.add_int(item) } } pub fn (mut b Encoder) add_list_u8(data []u8) { if data.len > 64 * kb { panic('list cannot have more than 64kb items.') } b.add_u16(u16(data.len)) // how many items in list b.data << data } pub fn (mut b Encoder) add_list_u16(data []u16) { if data.len > 64 * kb { panic('list cannot have more than 64kb items.') } b.add_u16(u16(data.len)) // how many items in list for item in data { b.add_u16(item) } } pub fn (mut b Encoder) add_list_u32(data []u32) { if data.len > 64 * kb { panic('list cannot have more than 64kb items.') } b.add_u16(u16(data.len)) // how many items in list for item in data { b.add_u32(item) } } pub fn (mut b Encoder) add_list_u64(data []u64) { if data.len > 64 * kb { panic('list cannot have more than 64kb items.') } b.add_u16(u16(data.len)) // how many items in list for item in data { b.add_u64(item) } } pub fn (mut b Encoder) add_list_f64(data []f64) { if data.len > 64 * kb { panic('list cannot have more than 64kb items.') } b.add_u16(u16(data.len)) // how many items in list for item in data { b.add_f64(item) } } // when complicated hash e.g. map of other object need to serialize each sub object pub fn (mut b Encoder) add_map_string(data map[string]string) { if data.len > 64 * kb { panic('map cannot have more than 64kb items.') } b.add_u16(u16(data.len)) // max nr of items in the map for key, val in data { b.add_string(key) b.add_string(val) } } // when complicated hash e.g. map of other object need to serialize each sub object pub fn (mut b Encoder) add_map_bytes(data map[string][]u8) { if data.len > 64 * kb { panic('map cannot have more than 64kb items.') } b.add_u16(u16(data.len)) // max nr of items in the map for key, val in data { b.add_string(key) b.add_bytes(val) } }