module encoder import time // example see https://github.com/vlang/v/blob/master/examples/compiletime/reflection.v pub fn encode[T](obj T) ![]u8 { mut d := new() // compile-time `for` loop // T.fields gives an array of a field metadata type $for field in T.fields { // Primitive types $if field.typ is string { // $(string_expr) produces an identifier d.add_string(obj.$(field.name).str()) } $else $if field.typ is bool { d.add_bool(bool(obj.$(field.name))) } $else $if field.typ is int { d.add_int(int(obj.$(field.name))) } $else $if field.typ is u8 { d.add_u8(u8(obj.$(field.name))) } $else $if field.typ is u16 { d.add_u16(u16(obj.$(field.name))) } $else $if field.typ is u32 { d.add_u32(u32(obj.$(field.name))) } $else $if field.typ is u64 { d.add_u64(u64(obj.$(field.name))) } $else $if field.typ is i64 { d.add_i64(i64(obj.$(field.name))) } $else $if field.typ is time.Time { d.add_time(time.new(obj.$(field.name))) // Arrays of primitive types } $else $if field.typ is []string { // d.add_list_string(obj.$(field.name)) why error?? d.add_list_string(obj.$(field.name)[..]) } $else $if field.typ is []int { d.add_list_int(obj.$(field.name)[..]) } $else $if field.typ is []u8 { d.add_list_u8(obj.$(field.name)[..]) } $else $if field.typ is []u16 { d.add_list_u16(obj.$(field.name)[..]) } $else $if field.typ is []u32 { d.add_list_u32(obj.$(field.name)[..]) } $else $if field.typ is []u64 { d.add_list_u64(obj.$(field.name)[..]) // Maps of primitive types } $else $if field.typ is map[string]string { d.add_map_string(obj.$(field.name).clone()) } $else $if field.typ is map[string][]u8 { d.add_map_bytes(obj.$(field.name).clone()) // Structs } $else $if field.is_struct { e := encode(obj.$(field.name))! d.add_list_u8(e) } $else { typ_name := typeof(obj.$(field.name)).name return error("The type `${typ_name}` of field `${field.name}` can't be encoded") } } return d.data } pub fn decode[T](data []u8) !T { mut d := decoder_new(data) mut result := T{} // compile-time `for` loop // T.fields gives an array of a field metadata type $for field in T.fields { // console.print_debug(field.name) // console.print_debug(typeof(result.$(field.name)).name) // console.print_debug(result.$(field.name)) // Primitive types $if field.typ is string { // $(string_expr) produces an identifier result.$(field.name) = d.get_string()! } $else $if field.typ is bool { result.$(field.name) = d.get_bool()! } $else $if field.typ is int { result.$(field.name) = d.get_int()! } $else $if field.typ is u8 { result.$(field.name) = d.get_u8()! } $else $if field.typ is u16 { result.$(field.name) = d.get_u16()! } $else $if field.typ is u32 { result.$(field.name) = d.get_u32()! } $else $if field.typ is u64 { result.$(field.name) = d.get_u64()! } $else $if field.typ is time.Time { result.$(field.name) = d.get_time()! // Arrays of primitive types } $else $if field.typ is []string { result.$(field.name) = d.get_list_string()! } $else $if field.typ is []int { result.$(field.name) = d.get_list_int()! } $else $if field.typ is []u8 { result.$(field.name) = d.get_list_u8()! } $else $if field.typ is []u16 { result.$(field.name) = d.get_list_u16()! } $else $if field.typ is []u32 { result.$(field.name) = d.get_list_u32()! } $else $if field.typ is []u64 { result.$(field.name) = d.get_list_u64()! // Maps of primitive types } $else $if field.typ is map[string]string { result.$(field.name) = d.get_map_string()! } $else $if field.typ is map[string][]u8 { result.$(field.name) = d.get_map_bytes()! // Structs } $else $if field.is_struct { // TODO handle recursive behavior } $else { typ_name := typeof(result.$(field.name)).name return error("The type `${typ_name}` of field `${field.name}` can't be decoded") } } return result } // TODO: complete, the recursive behavior will be little tricky