diff --git a/context.go b/context.go index 5491bcc..1adcc43 100644 --- a/context.go +++ b/context.go @@ -273,7 +273,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) { ev := value.Elem() elem_value = &ev } - elem, err := serializeValue(ctx, reflect_type.Elem(), elem_value) + elem, err := SerializeValue(ctx, reflect_type.Elem(), elem_value) if err != nil { return SerializedValue{}, err } @@ -286,7 +286,9 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) { }, nil }, func(ctx *Context, value SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) { if value.Data == nil { - elem_type, _, _, err := DeserializeValue(ctx, value) + var elem_type reflect.Type + var err error + elem_type, _, value, err = DeserializeValue(ctx, value) if err != nil { return nil, nil, SerializedValue{}, err } @@ -338,14 +340,14 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) { // Add to the type stack and data stack field_hash := Hash(FieldNameBase, gv_tag) if value == nil { - field_ser, err := serializeValue(ctx, field.Type, nil) + field_ser, err := SerializeValue(ctx, field.Type, nil) if err != nil { return SerializedValue{}, err } field_values[field_hash] = field_ser } else { field_value := value.FieldByIndex(field.Index) - field_ser, err := serializeValue(ctx, field.Type, &field_value) + field_ser, err := SerializeValue(ctx, field.Type, &field_value) if err != nil { return SerializedValue{}, err } @@ -573,7 +575,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) { var type_stack []SerializedType = nil for i := 0; i < value.Len(); i += 1 { val := value.Index(i) - element, err := serializeValue(ctx, reflect_type.Elem(), &val) + element, err := SerializeValue(ctx, reflect_type.Elem(), &val) if err != nil { return SerializedValue{}, err } @@ -584,7 +586,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) { } } - elem, err := serializeValue(ctx, reflect_type.Elem(), nil) + elem, err := SerializeValue(ctx, reflect_type.Elem(), nil) if err != nil { return SerializedValue{}, err } @@ -610,7 +612,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) { return SerializedValue{}, fmt.Errorf("Cannot serialize nil interfaces") } else { elem_value := value.Elem() - elem, err := serializeValue(ctx, value.Elem().Type(), &elem_value) + elem, err := SerializeValue(ctx, value.Elem().Type(), &elem_value) if err != nil { return SerializedValue{}, err } @@ -631,8 +633,87 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) { err = ctx.RegisterKind(reflect.Map, NewSerializedType("map"), func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){ - return SerializedValue{}, fmt.Errorf("serialize map unimplemented") + var data []byte + type_stack := []SerializedType{ctx_type} + if value == nil { + data = nil + } else if value.IsZero() { + data = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + } else if value.Len() == 0 { + data = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + } else { + data = make([]byte, 8) + map_size := 0 + var key_types, elem_types []SerializedType + + map_iter := value.MapRange() + for map_iter.Next() { + map_size += 1 + key_reflect := map_iter.Key() + elem_reflect := map_iter.Value() + + key_value, err := SerializeValue(ctx, key_reflect.Type(), &key_reflect) + if err != nil { + return SerializedValue{}, err + } + elem_value, err := SerializeValue(ctx, elem_reflect.Type(), &elem_reflect) + if err != nil { + return SerializedValue{}, err + } + + data = append(data, key_value.Data...) + data = append(data, elem_value.Data...) + + if key_types == nil { + key_types = key_value.TypeStack + elem_types = elem_value.TypeStack + } + } + + binary.BigEndian.PutUint64(data[0:8], uint64(map_size)) + + type_stack = append(type_stack, key_types...) + type_stack = append(type_stack, elem_types...) + return SerializedValue{ + type_stack, + data, + }, nil + } + key_value, err := SerializeValue(ctx, reflect_type.Key(), nil) + if err != nil { + return SerializedValue{}, nil + } + elem_value, err := SerializeValue(ctx, reflect_type.Elem(), nil) + if err != nil { + return SerializedValue{}, nil + } + + type_stack = append(type_stack, key_value.TypeStack...) + type_stack = append(type_stack, elem_value.TypeStack...) + + return SerializedValue{ + type_stack, + data, + }, nil }, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){ + if value.Data == nil { + var key_type, elem_type reflect.Type + var err error + key_type, _, value, err = DeserializeValue(ctx, value) + if err != nil { + return nil, nil, value, err + } + elem_type, _, value, err = DeserializeValue(ctx, value) + if err != nil { + return nil, nil, value, err + } + reflect_type := reflect.MapOf(key_type, elem_type) + return reflect_type, nil, value, nil + } else if len(value.Data) < 8 { + + } else { + + } return nil, nil, value, fmt.Errorf("deserialize map unimplemented") }) if err != nil { @@ -884,7 +965,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) { var err error for i := 0; i < value.Len(); i += 1 { val := value.Index(i) - element, err = serializeValue(ctx, reflect_type.Elem(), &val) + element, err = SerializeValue(ctx, reflect_type.Elem(), &val) if err != nil { return SerializedValue{}, err } @@ -895,7 +976,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) { data, }, nil } - element, err := serializeValue(ctx, reflect_type.Elem(), nil) + element, err := SerializeValue(ctx, reflect_type.Elem(), nil) if err != nil { return SerializedValue{}, err } @@ -930,7 +1011,10 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) { value.Data, }, nil } else if slice_length == 0x00 { - elem_type, _, remaining, err := DeserializeValue(ctx, value) + elem_type, _, remaining, err := DeserializeValue(ctx, SerializedValue{ + value.TypeStack, + nil, + }) if err != nil { return nil, nil, SerializedValue{}, err } diff --git a/gql_test.go b/gql_test.go index 0bd3072..29c0b0c 100644 --- a/gql_test.go +++ b/gql_test.go @@ -16,7 +16,6 @@ import ( "bytes" "golang.org/x/net/websocket" "github.com/google/uuid" - "reflect" ) func TestGQLServer(t *testing.T) { @@ -240,10 +239,10 @@ func TestGQLDB(t *testing.T) { }) fatalErr(t, err) - ser1, err := SerializeValue(ctx, reflect.ValueOf(gql)) + ser1, err := SerializeAny(ctx, gql) fatalErr(t, err) ctx.Log.Logf("test", "SER_1: \n%+v\n\n", ser1) - ser2, err := SerializeValue(ctx, reflect.ValueOf(u1)) + ser2, err := SerializeAny(ctx, u1) fatalErr(t, err) ctx.Log.Logf("test", "SER_2: \n%+v\n\n", ser2) diff --git a/node.go b/node.go index 11db05c..b1c2840 100644 --- a/node.go +++ b/node.go @@ -249,7 +249,7 @@ func nodeLoop(ctx *Context, node *Node) error { select { case msg := <- node.MsgChan: ctx.Log.Logf("node_msg", "NODE_MSG: %s - %+v", node.ID, msg.Signal) - signal_ser, err := SerializeValue(ctx, reflect.ValueOf(msg.Signal)) + signal_ser, err := SerializeAny(ctx, msg.Signal) if err != nil { ctx.Log.Logf("signal", "SIGNAL_SERIALIZE_ERR: %s - %+v", err, msg.Signal) } @@ -437,7 +437,7 @@ func (msgs Messages) Add(ctx *Context, source NodeID, principal ed25519.PrivateK } func NewMessage(ctx *Context, dest NodeID, source NodeID, principal ed25519.PrivateKey, signal Signal) (*Message, error) { - signal_ser, err := SerializeValue(ctx, reflect.ValueOf(signal)) + signal_ser, err := SerializeAny(ctx, signal) if err != nil { return nil, err } @@ -612,7 +612,7 @@ func NewNode(ctx *Context, key ed25519.PrivateKey, node_type NodeType, buffer_si func WriteNode(ctx *Context, node *Node) error { ctx.Log.Logf("db", "DB_WRITE: %s", node.ID) - node_serialized, err := SerializeValue(ctx, reflect.ValueOf(node)) + node_serialized, err := SerializeAny(ctx, node) if err != nil { return err } diff --git a/serialize.go b/serialize.go index 7965ada..cf887e2 100644 --- a/serialize.go +++ b/serialize.go @@ -107,18 +107,19 @@ func (value SerializedValue) PopData(n int) ([]byte, SerializedValue, error) { return data, value, nil } -func SerializeValue(ctx *Context, value reflect.Value) (SerializedValue, error) { - val, err := serializeValue(ctx, value.Type(), &value) - ctx.Log.Logf("serialize", "SERIALIZED_VALUE(%+v): %+v - %+v", value.Type(), val.TypeStack, val.Data) - return val, err +func SerializeAny[T any](ctx *Context, value T) (SerializedValue, error) { + reflect_value := reflect.ValueOf(value) + return SerializeValue(ctx, reflect_value.Type(), &reflect_value) } -func serializeValue(ctx *Context, t reflect.Type, value *reflect.Value) (SerializedValue, error) { +func SerializeValue(ctx *Context, t reflect.Type, value *reflect.Value) (SerializedValue, error) { + ctx.Log.Logf("serialize", "Serializing: %+v - %+v", t, value) ctx_type, type_exists := ctx.TypeReflects[t] + var serialize TypeSerialize = nil if type_exists == true { type_info := ctx.Types[ctx_type] if type_info.Serialize != nil { - return type_info.Serialize(ctx, ctx_type, t, value) + serialize = type_info.Serialize } } @@ -130,8 +131,13 @@ func serializeValue(ctx *Context, t reflect.Type, value *reflect.Value) (Seriali ctx_type = kind_info.Type } - return kind_info.Serialize(ctx, ctx_type, t, value) + if serialize == nil { + serialize = kind_info.Serialize + } + serialized_value, err := serialize(ctx, ctx_type, t, value) + ctx.Log.Logf("serialize", "Serialized %+v: %+v - %+v", value, serialized_value, err) + return serialized_value, err } func SerializeField(ctx *Context, ext Extension, field_name string) (SerializedValue, error) { @@ -143,7 +149,7 @@ func SerializeField(ctx *Context, ext Extension, field_name string) (SerializedV if field.IsValid() == false { return SerializedValue{}, fmt.Errorf("%s is not a field in %+v", field_name, ext) } else { - return SerializeValue(ctx, field) + return SerializeValue(ctx, field.Type(), &field) } } @@ -187,7 +193,7 @@ func ParseSerializedValue(data []byte) (SerializedValue, []byte, error) { } func DeserializeValue(ctx *Context, value SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) { - ctx.Log.Logf("serialize", "DeserializeValue: %+v", value) + ctx.Log.Logf("serialize", "Deserializing: %+v", value) var deserialize TypeDeserialize = nil var reflect_type reflect.Type = nil @@ -211,8 +217,6 @@ func DeserializeValue(ctx *Context, value SerializedValue) (reflect.Type, *refle deserialize = kind_info.Deserialize } - ctx.Log.Logf("serialize", "Deserializing: %d", ctx_type) - if value.Data == nil { reflect_type, _, value, err = deserialize(ctx, value) } else { @@ -222,6 +226,6 @@ func DeserializeValue(ctx *Context, value SerializedValue) (reflect.Type, *refle return nil, nil, value, err } - ctx.Log.Logf("serialize", "DeserializeValue: DONE %+v - %+v - %+v", value, reflect_type, reflect_value) + ctx.Log.Logf("serialize", "Deserialized %+v - %+v - %+v - remaining %+v", reflect_type, reflect_value, err, value) return reflect_type, reflect_value, value, nil } diff --git a/serialize_test.go b/serialize_test.go index ebc65f0..6aee6f3 100644 --- a/serialize_test.go +++ b/serialize_test.go @@ -27,6 +27,15 @@ func TestSerializeBasic(t *testing.T) { testSerializeSliceSlice[[][]int](t, ctx, [][]int{{123, 456, 789, 101112}, {3253, 2341, 735, 212}, {123, 51}, nil}) testSerializeSliceSlice[[][]string](t, ctx, [][]string{{"123", "456", "789", "101112"}, {"3253", "2341", "735", "212"}, {"123", "51"}, nil}) + testSerialize(t, ctx, []map[int8]map[*int8]string{}) + + testSerializeMap(t, ctx, map[int8]int32{ + 0: 1234, + 2: 5678, + 4: 9101, + 6: 1121, + }) + testSerialize(t, ctx, struct{ int `gv:"0"` string `gv:"1"` @@ -82,7 +91,7 @@ func testSerializeComparable[T comparable](t *testing.T, ctx *Context, val T) { } func testSerialize[T any](t *testing.T, ctx *Context, val T) T { - value, err := SerializeValue(ctx, reflect.ValueOf(val)) + value, err := SerializeAny(ctx, val) fatalErr(t, err) ctx.Log.Logf("test", "Serialized %+v to %+v", val, value)