This is an automated email from the ASF dual-hosted git repository.

xiazcy pushed a commit to branch go-type-ser
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 3735d7eb61c8517c0de038217e611214bbebc3d6
Author: Yang Xia <[email protected]>
AuthorDate: Thu Jan 23 15:33:56 2025 -0800

    update graph binary serializer to 4.0.0 spec
---
 gremlin-go/driver/graphBinary.go      | 630 ++++++++++------------------------
 gremlin-go/driver/graphBinary_test.go |  35 +-
 gremlin-go/driver/serializer.go       |  62 +---
 gremlin-go/go.mod                     |   4 +
 gremlin-go/go.sum                     |   9 +
 5 files changed, 231 insertions(+), 509 deletions(-)

diff --git a/gremlin-go/driver/graphBinary.go b/gremlin-go/driver/graphBinary.go
index 39c6d2f029..fb6b2f30dd 100644
--- a/gremlin-go/driver/graphBinary.go
+++ b/gremlin-go/driver/graphBinary.go
@@ -23,6 +23,7 @@ import (
        "bytes"
        "encoding/binary"
        "fmt"
+       "github.com/wk8/go-ordered-map/v2"
        "math"
        "math/big"
        "reflect"
@@ -38,54 +39,33 @@ type dataType uint8
 
 // dataType defined as constants.
 const (
-       customType            dataType = 0x00
-       intType               dataType = 0x01
-       longType              dataType = 0x02
-       stringType            dataType = 0x03
-       dateType              dataType = 0x04
-       timestampType         dataType = 0x05
-       classType             dataType = 0x06
-       doubleType            dataType = 0x07
-       floatType             dataType = 0x08
-       listType              dataType = 0x09
-       mapType               dataType = 0x0a
-       setType               dataType = 0x0b
-       uuidType              dataType = 0x0c
-       edgeType              dataType = 0x0d
-       pathType              dataType = 0x0e
-       propertyType          dataType = 0x0f
-       vertexType            dataType = 0x11
-       vertexPropertyType    dataType = 0x12
-       barrierType           dataType = 0x13
-       bindingType           dataType = 0x14
-       cardinalityType       dataType = 0x16
-       bytecodeType          dataType = 0x15
-       columnType            dataType = 0x17
-       directionType         dataType = 0x18
-       operatorType          dataType = 0x19
-       orderType             dataType = 0x1a
-       pickType              dataType = 0x1b
-       popType               dataType = 0x1c
-       lambdaType            dataType = 0x1d
-       pType                 dataType = 0x1e
-       scopeType             dataType = 0x1f
-       tType                 dataType = 0x20
-       traverserType         dataType = 0x21
-       bigDecimalType        dataType = 0x22
-       bigIntegerType        dataType = 0x23
-       byteType              dataType = 0x24
-       byteBuffer            dataType = 0x25
-       shortType             dataType = 0x26
-       booleanType           dataType = 0x27
-       textPType             dataType = 0x28
-       traversalStrategyType dataType = 0x29
-       bulkSetType           dataType = 0x2a
-       mergeType             dataType = 0x2e
-       dtType                dataType = 0x2f
-       metricsType           dataType = 0x2c
-       traversalMetricsType  dataType = 0x2d
-       durationType          dataType = 0x81
-       nullType              dataType = 0xFE
+       customType         dataType = 0x00
+       intType            dataType = 0x01
+       longType           dataType = 0x02
+       stringType         dataType = 0x03
+       datetimeType       dataType = 0x04
+       doubleType         dataType = 0x07
+       floatType          dataType = 0x08
+       listType           dataType = 0x09
+       mapType            dataType = 0x0a
+       setType            dataType = 0x0b
+       uuidType           dataType = 0x0c
+       edgeType           dataType = 0x0d
+       pathType           dataType = 0x0e
+       propertyType       dataType = 0x0f
+       vertexType         dataType = 0x11
+       vertexPropertyType dataType = 0x12
+       directionType      dataType = 0x18
+       tType              dataType = 0x20
+       bigDecimalType     dataType = 0x22
+       bigIntegerType     dataType = 0x23
+       byteType           dataType = 0x24
+       byteBuffer         dataType = 0x25
+       shortType          dataType = 0x26
+       booleanType        dataType = 0x27
+       mergeType          dataType = 0x2e
+       durationType       dataType = 0x81
+       nullType           dataType = 0xFE
 )
 
 var nullBytes = []byte{nullType.getCodeByte(), 0x01}
@@ -168,92 +148,45 @@ func mapWriter(value interface{}, buffer *bytes.Buffer, 
typeSerializer *graphBin
                return buffer.Bytes(), nil
        }
 
-       v := reflect.ValueOf(value)
-       keys := v.MapKeys()
-       err := binary.Write(buffer, binary.BigEndian, int32(len(keys)))
-       if err != nil {
-               return nil, err
-       }
-       for _, k := range keys {
-               convKey := k.Convert(v.Type().Key())
-               // serialize k
-               _, err := typeSerializer.write(k.Interface(), buffer)
+       if val, ok := value.(*orderedmap.OrderedMap[interface{}, interface{}]); 
ok {
+               err := binary.Write(buffer, binary.BigEndian, int32(val.Len()))
                if err != nil {
                        return nil, err
                }
-               // serialize v.MapIndex(c_key)
-               val := v.MapIndex(convKey)
-               _, err = typeSerializer.write(val.Interface(), buffer)
-               if err != nil {
-                       return nil, err
-               }
-       }
-       return buffer.Bytes(), nil
-}
-
-func instructionWriter(instructions []instruction, buffer *bytes.Buffer, 
typeSerializer *graphBinaryTypeSerializer) error {
-       // Write {steps_length}, i.e number of steps.
-       err := binary.Write(buffer, binary.BigEndian, int32(len(instructions)))
-       if err != nil {
-               return err
-       }
-
-       // Write {step_0} to {step_n}.
-       for _, instruction := range instructions {
-               // Write {name} of {step_i}.
-               // Note: {name} follows string writing, therefore write string 
length followed by actual string.
-               _, err = typeSerializer.writeValue(instruction.operator, 
buffer, false)
-               if err != nil {
-                       return err
+               for pair := val.Oldest(); pair != nil; pair = pair.Next() {
+                       // serialize k
+                       _, err := typeSerializer.write(pair.Key, buffer)
+                       if err != nil {
+                               return nil, err
+                       }
+                       // serialize v
+                       _, err = typeSerializer.write(pair.Value, buffer)
+                       if err != nil {
+                               return nil, err
+                       }
                }
-
-               // Write {values_length} of {step_i}.
-               err = binary.Write(buffer, binary.BigEndian, 
int32(len(instruction.arguments)))
+       } else {
+               v := reflect.ValueOf(value)
+               keys := v.MapKeys()
+               err := binary.Write(buffer, binary.BigEndian, int32(len(keys)))
                if err != nil {
-                       return err
+                       return nil, err
                }
-
-               // Write {values_0} to {values_n}.
-               for _, argument := range instruction.arguments {
-                       _, err = typeSerializer.write(argument, buffer)
+               for _, k := range keys {
+                       convKey := k.Convert(v.Type().Key())
+                       // serialize k
+                       _, err := typeSerializer.write(k.Interface(), buffer)
+                       if err != nil {
+                               return nil, err
+                       }
+                       // serialize v.MapIndex(c_key)
+                       val := v.MapIndex(convKey)
+                       _, err = typeSerializer.write(val.Interface(), buffer)
                        if err != nil {
-                               return err
+                               return nil, err
                        }
                }
        }
-       return nil
-}
-
-// Format: {steps_length}{step_0}…{step_n}{sources_length}{source_0}…{source_n}
-// Where:
-//
-//                     {steps_length} is an Int value describing the amount of 
steps.
-//                     {step_i} is composed of 
{name}{values_length}{value_0}…{value_n}, where:
-//          {name} is a String. This is also known as the operator.
-//                     {values_length} is an Int describing the amount values.
-//                     {value_i} is a fully qualified typed value composed of 
{type_code}{type_info}{value_flag}{value} describing the step argument.
-func bytecodeWriter(value interface{}, buffer *bytes.Buffer, typeSerializer 
*graphBinaryTypeSerializer) ([]byte, error) {
-       var bc Bytecode
-       switch typedVal := value.(type) {
-       case *GraphTraversal:
-               bc = *typedVal.Bytecode
-       case Bytecode:
-               bc = typedVal
-       case *Bytecode:
-               bc = *typedVal
-       default:
-               return nil, newError(err0402BytecodeWriterError)
-       }
-
-       // Write {steps_length} and {step_0} through {step_n}, then 
{sources_length} and {source_0} through {source_n}
-       err := instructionWriter(bc.stepInstructions, buffer, typeSerializer)
-       if err != nil {
-               return nil, err
-       }
-       err = instructionWriter(bc.sourceInstructions, buffer, typeSerializer)
-       if err != nil {
-               return nil, err
-       }
        return buffer.Bytes(), nil
 }
 
@@ -366,16 +299,6 @@ func bigDecimalWriter(value interface{}, buffer 
*bytes.Buffer, typeSerializer *g
        return bigIntWriter(v.UnscaledValue, buffer, typeSerializer)
 }
 
-func classWriter(value interface{}, buffer *bytes.Buffer, typeSerializer 
*graphBinaryTypeSerializer) ([]byte, error) {
-       var v GremlinType
-       if reflect.TypeOf(value).Kind() == reflect.Ptr {
-               v = *(value.(*GremlinType))
-       } else {
-               v = value.(GremlinType)
-       }
-       return stringWriter(v.Fqcn, buffer, typeSerializer)
-}
-
 // Format: {Id}{Label}{properties}
 func vertexWriter(value interface{}, buffer *bytes.Buffer, typeSerializer 
*graphBinaryTypeSerializer) ([]byte, error) {
        v := value.(*Vertex)
@@ -385,7 +308,7 @@ func vertexWriter(value interface{}, buffer *bytes.Buffer, 
typeSerializer *graph
        }
 
        // Not fully qualified.
-       _, err = typeSerializer.writeValue(v.Label, buffer, false)
+       _, err = typeSerializer.writeValue([1]string{v.Label}, buffer, false)
        if err != nil {
                return nil, err
        }
@@ -403,7 +326,7 @@ func edgeWriter(value interface{}, buffer *bytes.Buffer, 
typeSerializer *graphBi
        }
 
        // Not fully qualified
-       _, err = typeSerializer.writeValue(e.Label, buffer, false)
+       _, err = typeSerializer.writeValue([1]string{e.Label}, buffer, false)
        if err != nil {
                return nil, err
        }
@@ -465,7 +388,7 @@ func vertexPropertyWriter(value interface{}, buffer 
*bytes.Buffer, typeSerialize
        }
 
        // Not fully qualified.
-       _, err = typeSerializer.writeValue(vp.Label, buffer, false)
+       _, err = typeSerializer.writeValue([1]string{vp.Label}, buffer, false)
        if err != nil {
                return nil, err
        }
@@ -502,7 +425,29 @@ func setWriter(value interface{}, buffer *bytes.Buffer, 
typeSerializer *graphBin
 
 func timeWriter(value interface{}, buffer *bytes.Buffer, _ 
*graphBinaryTypeSerializer) ([]byte, error) {
        t := value.(time.Time)
-       err := binary.Write(buffer, binary.BigEndian, t.UnixMilli())
+       err := binary.Write(buffer, binary.BigEndian, int32(t.Year()))
+       if err != nil {
+               return nil, err
+       }
+       err = binary.Write(buffer, binary.BigEndian, byte(t.Month()))
+       if err != nil {
+               return nil, err
+       }
+       err = binary.Write(buffer, binary.BigEndian, byte(t.Day()))
+       if err != nil {
+               return nil, err
+       }
+       // construct time of day in nanoseconds
+       h := t.Hour()
+       m := t.Minute()
+       s := t.Second()
+       ns := (h * 60 * 60 * 1e9) + (m * 60 * 1e9) + (s * 1e9) + t.Nanosecond()
+       err = binary.Write(buffer, binary.BigEndian, int64(ns))
+       if err != nil {
+               return nil, err
+       }
+       _, os := t.Zone()
+       err = binary.Write(buffer, binary.BigEndian, int32(os))
        if err != nil {
                return nil, err
        }
@@ -534,32 +479,6 @@ func enumWriter(value interface{}, buffer *bytes.Buffer, 
typeSerializer *graphBi
        return buffer.Bytes(), err
 }
 
-// Format: {language}{script}{arguments_length}
-func lambdaWriter(value interface{}, buffer *bytes.Buffer, typeSerializer 
*graphBinaryTypeSerializer) ([]byte, error) {
-       lambda := value.(*Lambda)
-       if lambda.Language == "" {
-               lambda.Language = "gremlin-groovy"
-       }
-       _, err := typeSerializer.writeValue(lambda.Language, buffer, false)
-       if err != nil {
-               return nil, err
-       }
-
-       _, err = typeSerializer.writeValue(lambda.Script, buffer, false)
-       if err != nil {
-               return nil, err
-       }
-
-       // It's hard to know how many parameters there are without extensive 
string parsing.
-       // Instead, we can set -1 which means unknown.
-       err = binary.Write(buffer, binary.BigEndian, int32(-1))
-       if err != nil {
-               return nil, err
-       }
-
-       return buffer.Bytes(), nil
-}
-
 // Format: {strategy_class}{configuration}
 func traversalStrategyWriter(value interface{}, buffer *bytes.Buffer, 
typeSerializer *graphBinaryTypeSerializer) ([]byte, error) {
        ts := value.(*traversalStrategy)
@@ -572,84 +491,8 @@ func traversalStrategyWriter(value interface{}, buffer 
*bytes.Buffer, typeSerial
        return mapWriter(ts.configuration, buffer, typeSerializer)
 }
 
-func pWriter(value interface{}, buffer *bytes.Buffer, typeSerializer 
*graphBinaryTypeSerializer) ([]byte, error) {
-       var v p
-       if reflect.TypeOf(value).Kind() == reflect.Ptr {
-               v = *(value.(*p))
-       } else {
-               v = value.(p)
-       }
-       _, err := typeSerializer.writeValue(v.operator, buffer, false)
-       if err != nil {
-               return nil, err
-       }
-
-       err = binary.Write(buffer, binary.BigEndian, int32(len(v.values)))
-       if err != nil {
-               return nil, err
-       }
-
-       for _, pValue := range v.values {
-               _, err := typeSerializer.write(pValue, buffer)
-               if err != nil {
-                       return nil, err
-               }
-       }
-       return buffer.Bytes(), err
-}
-
-func textPWriter(value interface{}, buffer *bytes.Buffer, typeSerializer 
*graphBinaryTypeSerializer) ([]byte, error) {
-       var v textP
-       if reflect.TypeOf(value).Kind() == reflect.Ptr {
-               v = *(value.(*textP))
-       } else {
-               v = value.(textP)
-       }
-       _, err := typeSerializer.writeValue(v.operator, buffer, false)
-       if err != nil {
-               return nil, err
-       }
-
-       err = binary.Write(buffer, binary.BigEndian, int32(len(v.values)))
-       if err != nil {
-               return nil, err
-       }
-
-       for _, pValue := range v.values {
-               _, err := typeSerializer.write(pValue, buffer)
-               if err != nil {
-                       return nil, err
-               }
-       }
-       return buffer.Bytes(), err
-}
-
-// Format: {key}{value}
-func bindingWriter(value interface{}, buffer *bytes.Buffer, typeSerializer 
*graphBinaryTypeSerializer) ([]byte, error) {
-       var v Binding
-       if reflect.TypeOf(value).Kind() == reflect.Ptr {
-               v = *(value.(*Binding))
-       } else {
-               v = value.(Binding)
-       }
-
-       // Not fully qualified.
-       _, err := typeSerializer.writeValue(v.Key, buffer, false)
-       if err != nil {
-               return nil, err
-       }
-
-       _, err = typeSerializer.write(v.Value, buffer)
-       if err != nil {
-               return nil, err
-       }
-       return buffer.Bytes(), nil
-}
-
 func (serializer *graphBinaryTypeSerializer) getType(val interface{}) 
(dataType, error) {
        switch val.(type) {
-       case *Bytecode, Bytecode, *GraphTraversal:
-               return bytecodeType, nil
        case string:
                return stringType, nil
        case uint, uint64, *big.Int:
@@ -678,58 +521,26 @@ func (serializer *graphBinaryTypeSerializer) getType(val 
interface{}) (dataType,
                return propertyType, nil
        case *VertexProperty:
                return vertexPropertyType, nil
-       case *Lambda:
-               return lambdaType, nil
-       case *traversalStrategy:
-               return traversalStrategyType, nil
        case *Path:
                return pathType, nil
        case Set:
                return setType, nil
        case time.Time:
-               return dateType, nil
+               return datetimeType, nil
        case time.Duration:
                return durationType, nil
-       case cardinality:
-               return cardinalityType, nil
-       case column:
-               return columnType, nil
        case direction:
                return directionType, nil
-       case operator:
-               return operatorType, nil
-       case order:
-               return orderType, nil
-       case pick:
-               return pickType, nil
-       case pop:
-               return popType, nil
        case t:
                return tType, nil
-       case barrier:
-               return barrierType, nil
-       case scope:
-               return scopeType, nil
        case merge:
                return mergeType, nil
-       case dt:
-               return dtType, nil
-       case p, Predicate:
-               return pType, nil
-       case textP, TextPredicate:
-               return textPType, nil
-       case *Binding, Binding:
-               return bindingType, nil
        case *BigDecimal, BigDecimal:
                return bigDecimalType, nil
-       case *GremlinType, GremlinType:
-               return classType, nil
-       case *Metrics, Metrics:
-               return metricsType, nil
-       case *TraversalMetrics, TraversalMetrics:
-               return traversalMetricsType, nil
        case *ByteBuffer, ByteBuffer:
                return byteBuffer, nil
+       case *orderedmap.OrderedMap[interface{}, interface{}], 
orderedmap.OrderedMap[interface{}, interface{}]:
+               return mapType, nil
        default:
                switch reflect.TypeOf(val).Kind() {
                case reflect.Map:
@@ -926,8 +737,6 @@ func getDefaultValue(dataType dataType) interface{} {
        switch dataType {
        case intType, bigIntegerType, longType, shortType, byteType, 
booleanType, floatType, doubleType:
                return 0
-       case traverserType, stringType:
-               return ""
        case uuidType:
                return uuid.Nil
        case vertexType:
@@ -942,7 +751,7 @@ func getDefaultValue(dataType dataType) interface{} {
                return Path{}
        case setType:
                return SimpleSet{}
-       case dateType, timestampType:
+       case datetimeType:
                return time.Time{}
        case durationType:
                return time.Duration(0)
@@ -952,15 +761,28 @@ func getDefaultValue(dataType dataType) interface{} {
 }
 
 // Composite
-func readList(data *[]byte, i *int) (interface{}, error) {
+func readList(data *[]byte, i *int, flag byte) (interface{}, error) {
        sz := readIntSafe(data, i)
        var valList []interface{}
-       for j := int32(0); j < sz; j++ {
-               val, err := readFullyQualifiedNullable(data, i, true)
-               if err != nil {
-                       return nil, err
+       if flag == 0x02 {
+               for j := int32(0); j < sz; j++ {
+                       val, err := readFullyQualifiedNullable(data, i, true)
+                       if err != nil {
+                               return nil, err
+                       }
+                       bulk := readIntSafe(data, i)
+                       for k := int32(0); k < bulk; k++ {
+                               valList = append(valList, val)
+                       }
+               }
+       } else {
+               for j := int32(0); j < sz; j++ {
+                       val, err := readFullyQualifiedNullable(data, i, true)
+                       if err != nil {
+                               return nil, err
+                       }
+                       valList = append(valList, val)
                }
-               valList = append(valList, val)
        }
        return valList, nil
 }
@@ -975,32 +797,59 @@ func readByteBuffer(data *[]byte, i *int) (interface{}, 
error) {
        return r, nil
 }
 
-func readMap(data *[]byte, i *int) (interface{}, error) {
+func readMap(data *[]byte, i *int, flag byte) (interface{}, error) {
        sz := readUint32Safe(data, i)
-       var mapData = make(map[interface{}]interface{})
-       for j := uint32(0); j < sz; j++ {
-               k, err := readFullyQualifiedNullable(data, i, true)
-               if err != nil {
-                       return nil, err
-               }
-               v, err := readFullyQualifiedNullable(data, i, true)
-               if err != nil {
-                       return nil, err
+       if flag == 0x02 {
+               var mapData = orderedmap.New[interface{}, interface{}]()
+               for j := uint32(0); j < sz; j++ {
+                       k, err := readFullyQualifiedNullable(data, i, true)
+                       if err != nil {
+                               return nil, err
+                       }
+                       v, err := readFullyQualifiedNullable(data, i, true)
+                       if err != nil {
+                               return nil, err
+                       }
+                       if k == nil {
+                               mapData.Set(nil, v)
+                       } else if reflect.TypeOf(k).Comparable() {
+                               mapData.Set(k, v)
+                       } else {
+                               switch reflect.TypeOf(k).Kind() {
+                               case reflect.Map:
+                                       mapData.Set(&k, v)
+                               default:
+                                       mapData.Set(fmt.Sprint(k), v)
+                               }
+                       }
                }
-               if k == nil {
-                       mapData[nil] = v
-               } else if reflect.TypeOf(k).Comparable() {
-                       mapData[k] = v
-               } else {
-                       switch reflect.TypeOf(k).Kind() {
-                       case reflect.Map:
-                               mapData[&k] = v
-                       default:
-                               mapData[fmt.Sprint(k)] = v
+               return mapData, nil
+       } else {
+               var mapData = make(map[interface{}]interface{})
+               for j := uint32(0); j < sz; j++ {
+                       k, err := readFullyQualifiedNullable(data, i, true)
+                       if err != nil {
+                               return nil, err
+                       }
+                       v, err := readFullyQualifiedNullable(data, i, true)
+                       if err != nil {
+                               return nil, err
+                       }
+                       if k == nil {
+                               mapData[nil] = v
+                       } else if reflect.TypeOf(k).Comparable() {
+                               mapData[k] = v
+                       } else {
+                               switch reflect.TypeOf(k).Kind() {
+                               case reflect.Map:
+                                       mapData[&k] = v
+                               default:
+                                       mapData[fmt.Sprint(k)] = v
+                               }
                        }
                }
+               return mapData, nil
        }
-       return mapData, nil
 }
 
 func readMapUnqualified(data *[]byte, i *int) (interface{}, error) {
@@ -1028,7 +877,8 @@ func readMapUnqualified(data *[]byte, i *int) 
(interface{}, error) {
 }
 
 func readSet(data *[]byte, i *int) (interface{}, error) {
-       list, err := readList(data, i)
+       // TODO placeholder flag
+       list, err := readList(data, i, 0x00)
        if err != nil {
                return nil, err
        }
@@ -1041,7 +891,15 @@ func readUuid(data *[]byte, i *int) (interface{}, error) {
 }
 
 func timeReader(data *[]byte, i *int) (interface{}, error) {
-       return time.UnixMilli(readLongSafe(data, i)), nil
+       year := readIntSafe(data, i)
+       month := readByteSafe(data, i)
+       day := readByteSafe(data, i)
+       ns := readLongSafe(data, i)
+       offset := readIntSafe(data, i)
+       // only way to pass offset info, timezone display is fixed to UTC as 
consequence (offset is calculated properly)
+       loc := time.FixedZone("UTC", int(offset))
+       datetime := time.Date(int(year), time.Month(month), int(day), 0, 0, 0, 
int(ns), loc)
+       return datetime, nil
 }
 
 func durationReader(data *[]byte, i *int) (interface{}, error) {
@@ -1063,11 +921,11 @@ func vertexReaderReadingProperties(data *[]byte, i *int, 
readProperties bool) (i
        if err != nil {
                return nil, err
        }
-       label, err := readUnqualified(data, i, stringType, false)
+       label, err := readUnqualified(data, i, listType, false)
        if err != nil {
                return nil, err
        }
-       v.Label = label.(string)
+       v.Label = label.([]interface{})[0].(string)
        if readProperties {
                props, err := readFullyQualifiedNullable(data, i, true)
                if err != nil {
@@ -1090,11 +948,11 @@ func edgeReader(data *[]byte, i *int) (interface{}, 
error) {
        if err != nil {
                return nil, err
        }
-       label, err := readUnqualified(data, i, stringType, false)
+       label, err := readUnqualified(data, i, listType, false)
        if err != nil {
                return nil, err
        }
-       e.Label = label.(string)
+       e.Label = label.([]interface{})[0].(string)
        v, err := vertexReaderReadingProperties(data, i, false)
        if err != nil {
                return nil, err
@@ -1142,11 +1000,11 @@ func vertexPropertyReader(data *[]byte, i *int) 
(interface{}, error) {
        if err != nil {
                return nil, err
        }
-       label, err := readUnqualified(data, i, stringType, false)
+       label, err := readUnqualified(data, i, listType, false)
        if err != nil {
                return nil, err
        }
-       vp.Label = label.(string)
+       vp.Label = label.([]interface{})[0].(string)
        vp.Value, err = readFullyQualifiedNullable(data, i, true)
        if err != nil {
                return nil, err
@@ -1186,35 +1044,6 @@ func pathReader(data *[]byte, i *int) (interface{}, 
error) {
        return path, err
 }
 
-// {bulk int}{fully qualified value}
-func traverserReader(data *[]byte, i *int) (interface{}, error) {
-       var err error
-       traverser := new(Traverser)
-       traverser.bulk = readLongSafe(data, i)
-       traverser.value, err = readFullyQualifiedNullable(data, i, true)
-       if err != nil {
-               return nil, err
-       }
-       return traverser, nil
-}
-
-// {int32 length}{fully qualified item_0}{int64 repetition_0}...{fully 
qualified item_n}{int64 repetition_n}
-func bulkSetReader(data *[]byte, i *int) (interface{}, error) {
-       sz := int(readIntSafe(data, i))
-       var valList []interface{}
-       for j := 0; j < sz; j++ {
-               val, err := readFullyQualifiedNullable(data, i, true)
-               if err != nil {
-                       return nil, err
-               }
-               rep := readLongSafe(data, i)
-               for k := 0; k < int(rep); k++ {
-                       valList = append(valList, val)
-               }
-       }
-       return valList, nil
-}
-
 // {type code (always string so ignore)}{nil code (always false so 
ignore)}{int32 size}{string enum}
 func enumReader(data *[]byte, i *int) (interface{}, error) {
        typeCode := readDataType(data, i)
@@ -1225,113 +1054,6 @@ func enumReader(data *[]byte, i *int) (interface{}, 
error) {
        return readString(data, i)
 }
 
-// {unqualified key}{fully qualified value}
-func bindingReader(data *[]byte, i *int) (interface{}, error) {
-       b := new(Binding)
-       val, err := readUnqualified(data, i, stringType, false)
-       if err != nil {
-               return nil, err
-       }
-       b.Key = val.(string)
-
-       b.Value, err = readFullyQualifiedNullable(data, i, true)
-       if err != nil {
-               return nil, err
-       }
-       return b, nil
-}
-
-// {id}{name}{duration}{counts}{annotations}{nested_metrics}
-func metricsReader(data *[]byte, i *int) (interface{}, error) {
-       metrics := new(Metrics)
-       val, err := readUnqualified(data, i, stringType, false)
-       if err != nil {
-               return nil, err
-       }
-       metrics.Id = val.(string)
-
-       val, err = readUnqualified(data, i, stringType, false)
-       if err != nil {
-               return nil, err
-       }
-       metrics.Name = val.(string)
-
-       dur, err := readLong(data, i)
-       if err != nil {
-               return nil, err
-       }
-       metrics.Duration = dur.(int64)
-
-       counts, err := readMap(data, i)
-       cmap := counts.(map[interface{}]interface{})
-       if err != nil {
-               return nil, err
-       }
-       metrics.Counts = make(map[string]int64, len(cmap))
-       for k := range cmap {
-               metrics.Counts[k.(string)] = cmap[k].(int64)
-       }
-
-       annotations, err := readMap(data, i)
-       if err != nil {
-               return nil, err
-       }
-       amap := annotations.(map[interface{}]interface{})
-       if err != nil {
-               return nil, err
-       }
-       metrics.Annotations = make(map[string]interface{}, len(amap))
-       for k := range amap {
-               metrics.Annotations[k.(string)] = amap[k]
-       }
-
-       nested, err := readList(data, i)
-       if err != nil {
-               return nil, err
-       }
-       list := nested.([]interface{})
-       metrics.NestedMetrics = make([]Metrics, len(list))
-       for i, metric := range list {
-               metrics.NestedMetrics[i] = metric.(Metrics)
-       }
-
-       return metrics, nil
-}
-
-// {id}{name}{duration}{counts}{annotations}{nested_metrics}
-func traversalMetricsReader(data *[]byte, i *int) (interface{}, error) {
-       m := new(TraversalMetrics)
-       dur, err := readLong(data, i)
-       if err != nil {
-               return nil, err
-       }
-       m.Duration = dur.(int64)
-
-       nested, err := readList(data, i)
-       if err != nil {
-               return nil, err
-       }
-       list := nested.([]interface{})
-       m.Metrics = make([]Metrics, len(list))
-       for i, metric := range list {
-               m.Metrics[i] = *metric.(*Metrics)
-       }
-
-       return m, nil
-}
-
-// Format: A String containing the fqcn.
-func readClass(data *[]byte, i *int) (interface{}, error) {
-       gremlinType := new(GremlinType)
-       str, err := readString(data, i)
-       if err != nil {
-               return nil, err
-       }
-       gremlinType.Fqcn = str.(string)
-
-       return gremlinType, nil
-}
-
 func readUnqualified(data *[]byte, i *int, dataTyp dataType, nullable bool) 
(interface{}, error) {
        if nullable && readByteSafe(data, i) == valueFlagNull {
                return getDefaultValue(dataTyp), nil
@@ -1351,9 +1073,17 @@ func readFullyQualifiedNullable(data *[]byte, i *int, 
nullable bool) (interface{
                }
                return nil, nil
        } else if nullable {
-               if readByteSafe(data, i) == valueFlagNull {
+               flag := readByteSafe(data, i)
+               fmt.Println(flag)
+               if flag == valueFlagNull {
                        return getDefaultValue(dataTyp), nil
                }
+               if dataTyp == listType {
+                       return readList(data, i, flag)
+               }
+               if dataTyp == mapType {
+                       return readMap(data, i, flag)
+               }
        }
        deserializer, ok := deserializers[dataTyp]
        if !ok {
diff --git a/gremlin-go/driver/graphBinary_test.go 
b/gremlin-go/driver/graphBinary_test.go
index d8c66d2816..a4d76596ae 100644
--- a/gremlin-go/driver/graphBinary_test.go
+++ b/gremlin-go/driver/graphBinary_test.go
@@ -24,6 +24,7 @@ import (
        "encoding/binary"
        "fmt"
        "github.com/stretchr/testify/assert"
+       "github.com/wk8/go-ordered-map/v2"
        "golang.org/x/text/language"
        "math/big"
        "reflect"
@@ -83,16 +84,6 @@ func TestGraphBinaryV1(t *testing.T) {
                        assert.Nil(t, err)
                        assert.Equal(t, str, res)
                })
-               t.Run("read-write GremlinType", func(t *testing.T) {
-                       pos := 0
-                       var buffer bytes.Buffer
-                       source := &GremlinType{"test fqcn"}
-                       buf, err := classWriter(source, &buffer, nil)
-                       assert.Nil(t, err)
-                       res, err := readClass(&buf, &pos)
-                       assert.Nil(t, err)
-                       assert.Equal(t, source, res)
-               })
                t.Run("read-write bool", func(t *testing.T) {
                        pos := 0
                        var buffer bytes.Buffer
@@ -198,7 +189,7 @@ func TestGraphBinaryV1(t *testing.T) {
                        source := []interface{}{int32(111), "str"}
                        buf, err := listWriter(source, &buffer, nil)
                        assert.Nil(t, err)
-                       res, err := readList(&buf, &pos)
+                       res, err := readList(&buf, &pos, 0x00)
                        assert.Nil(t, err)
                        assert.Equal(t, source, res)
                })
@@ -228,10 +219,23 @@ func TestGraphBinaryV1(t *testing.T) {
                        source := map[interface{}]interface{}{1: "s1", "s2": 2, 
nil: nil}
                        buf, err := mapWriter(source, &buffer, nil)
                        assert.Nil(t, err)
-                       res, err := readMap(&buf, &pos)
+                       res, err := readMap(&buf, &pos, 0x00)
                        assert.Nil(t, err)
                        assert.Equal(t, fmt.Sprintf("%v", source), 
fmt.Sprintf("%v", res))
                })
+               t.Run("read-write ordered map", func(t *testing.T) {
+                       pos := 0
+                       var buffer bytes.Buffer
+                       source := orderedmap.New[interface{}, interface{}]()
+                       source.Set(int32(1), "s1")
+                       source.Set(int32(2), "s2")
+                       source.Set(nil, nil)
+                       buf, err := mapWriter(source, &buffer, nil)
+                       assert.Nil(t, err)
+                       res, err := readMap(&buf, &pos, 0x02)
+                       assert.Nil(t, err)
+                       assert.Equal(t, source, res)
+               })
                t.Run("read incomparable map: a map value as the key", func(t 
*testing.T) {
                        // prepare test data
                        var buf = &bytes.Buffer{}
@@ -255,7 +259,7 @@ func TestGraphBinaryV1(t *testing.T) {
 
                        data := buf.Bytes()
                        i := 0
-                       result, err := readMap(&data, &i)
+                       result, err := readMap(&data, &i, 0x00)
                        if err != nil {
                                t.Fatalf("readMap failed: %v", err)
                        }
@@ -291,7 +295,7 @@ func TestGraphBinaryV1(t *testing.T) {
 
                        data := buf.Bytes()
                        i := 0
-                       result, err := readMap(&data, &i)
+                       result, err := readMap(&data, &i, 0x00)
                        if err != nil {
                                t.Fatalf("readMap failed: %v", err)
                        }
@@ -310,7 +314,8 @@ func TestGraphBinaryV1(t *testing.T) {
                        assert.Nil(t, err)
                        res, err := timeReader(&buf, &pos)
                        assert.Nil(t, err)
-                       assert.Equal(t, source, res)
+                       // ISO format
+                       assert.Equal(t, source.Format(time.RFC3339Nano), 
res.(time.Time).Format(time.RFC3339Nano))
                })
        })
 
diff --git a/gremlin-go/driver/serializer.go b/gremlin-go/driver/serializer.go
index 04a7e468b5..30ffef001a 100644
--- a/gremlin-go/driver/serializer.go
+++ b/gremlin-go/driver/serializer.go
@@ -228,7 +228,6 @@ func (gs graphBinarySerializer) deserializeMessage(message 
[]byte) (response, er
 
 func initSerializers() {
        serializers = map[dataType]writer{
-               bytecodeType:   bytecodeWriter,
                stringType:     stringWriter,
                bigDecimalType: bigDecimalWriter,
                bigIntegerType: bigIntWriter,
@@ -255,35 +254,20 @@ func initSerializers() {
                        err := binary.Write(buffer, binary.BigEndian, value)
                        return buffer.Bytes(), err
                },
-               vertexType:            vertexWriter,
-               edgeType:              edgeWriter,
-               propertyType:          propertyWriter,
-               vertexPropertyType:    vertexPropertyWriter,
-               lambdaType:            lambdaWriter,
-               traversalStrategyType: traversalStrategyWriter,
-               pathType:              pathWriter,
-               setType:               setWriter,
-               dateType:              timeWriter,
-               durationType:          durationWriter,
-               cardinalityType:       enumWriter,
-               columnType:            enumWriter,
-               directionType:         enumWriter,
-               dtType:                enumWriter,
-               operatorType:          enumWriter,
-               orderType:             enumWriter,
-               pickType:              enumWriter,
-               popType:               enumWriter,
-               tType:                 enumWriter,
-               barrierType:           enumWriter,
-               scopeType:             enumWriter,
-               mergeType:             enumWriter,
-               pType:                 pWriter,
-               textPType:             textPWriter,
-               bindingType:           bindingWriter,
-               mapType:               mapWriter,
-               listType:              listWriter,
-               byteBuffer:            byteBufferWriter,
-               classType:             classWriter,
+               vertexType:         vertexWriter,
+               edgeType:           edgeWriter,
+               propertyType:       propertyWriter,
+               vertexPropertyType: vertexPropertyWriter,
+               pathType:           pathWriter,
+               setType:            setWriter,
+               datetimeType:       timeWriter,
+               durationType:       durationWriter,
+               directionType:      enumWriter,
+               tType:              enumWriter,
+               mergeType:          enumWriter,
+               mapType:            mapWriter,
+               listType:           listWriter,
+               byteBuffer:         byteBufferWriter,
        }
 }
 
@@ -302,34 +286,24 @@ func initDeserializers() {
                stringType:     readString,
 
                // Composite
-               listType:   readList,
-               mapType:    readMap,
+               //listType:   readList,
+               //mapType:    readMap,
                setType:    readSet,
                uuidType:   readUuid,
                byteBuffer: readByteBuffer,
-               classType:  readClass,
 
                // Date Time
-               dateType:      timeReader,
-               timestampType: timeReader,
-               durationType:  durationReader,
+               datetimeType: timeReader,
+               durationType: durationReader,
 
                // Graph
-               traverserType:      traverserReader,
                vertexType:         vertexReader,
                edgeType:           edgeReader,
                propertyType:       propertyReader,
                vertexPropertyType: vertexPropertyReader,
                pathType:           pathReader,
-               bulkSetType:        bulkSetReader,
                tType:              enumReader,
                directionType:      enumReader,
-               dtType:             enumReader,
-               bindingType:        bindingReader,
-
-               // Metrics
-               metricsType:          metricsReader,
-               traversalMetricsType: traversalMetricsReader,
 
                // Customer
                customType: customTypeReader,
diff --git a/gremlin-go/go.mod b/gremlin-go/go.mod
index 39cb593de2..0123714f30 100644
--- a/gremlin-go/go.mod
+++ b/gremlin-go/go.mod
@@ -25,11 +25,14 @@ require (
        github.com/gorilla/websocket v1.5.3
        github.com/nicksnyder/go-i18n/v2 v2.4.1
        github.com/stretchr/testify v1.9.0
+       github.com/wk8/go-ordered-map/v2 v2.1.8
        golang.org/x/text v0.21.0
        gopkg.in/yaml.v3 v3.0.1
 )
 
 require (
+       github.com/bahlo/generic-list-go v0.2.0 // indirect
+       github.com/buger/jsonparser v1.1.1 // indirect
        github.com/cucumber/gherkin/go/v26 v26.2.0 // indirect
        github.com/cucumber/messages/go/v21 v21.0.1 // indirect
        github.com/davecgh/go-spew v1.1.1 // indirect
@@ -37,6 +40,7 @@ require (
        github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
        github.com/hashicorp/go-memdb v1.3.4 // indirect
        github.com/hashicorp/golang-lru v0.5.4 // indirect
+       github.com/mailru/easyjson v0.7.7 // indirect
        github.com/pmezard/go-difflib v1.0.0 // indirect
        github.com/spf13/pflag v1.0.5 // indirect
        github.com/stretchr/objx v0.5.2 // indirect
diff --git a/gremlin-go/go.sum b/gremlin-go/go.sum
index 24bf83a7a5..365be7fe1a 100644
--- a/gremlin-go/go.sum
+++ b/gremlin-go/go.sum
@@ -1,5 +1,9 @@
 github.com/BurntSushi/toml v1.4.0 
h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
 github.com/BurntSushi/toml v1.4.0/go.mod 
h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
+github.com/bahlo/generic-list-go v0.2.0 
h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
+github.com/bahlo/generic-list-go v0.2.0/go.mod 
h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
+github.com/buger/jsonparser v1.1.1 
h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
+github.com/buger/jsonparser v1.1.1/go.mod 
h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
 github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod 
h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/cucumber/gherkin/go/v26 v26.2.0 
h1:EgIjePLWiPeslwIWmNQ3XHcypPsWAHoMCz/YEBKP4GI=
 github.com/cucumber/gherkin/go/v26 v26.2.0/go.mod 
h1:t2GAPnB8maCT4lkHL99BDCVNzCh1d7dBhCLt150Nr/0=
@@ -30,11 +34,14 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod 
h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
 github.com/hashicorp/golang-lru v0.5.4 
h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
 github.com/hashicorp/golang-lru v0.5.4/go.mod 
h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod 
h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/josharian/intern v1.0.0/go.mod 
h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
 github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
 github.com/kr/pretty v0.2.1/go.mod 
h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod 
h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/mailru/easyjson v0.7.7 
h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod 
h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 github.com/nicksnyder/go-i18n/v2 v2.4.1 
h1:zwzjtX4uYyiaU02K5Ia3zSkpJZrByARkRB4V3YPrr0g=
 github.com/nicksnyder/go-i18n/v2 v2.4.1/go.mod 
h1:++Pl70FR6Cki7hdzZRnEEqdc2dJt+SAGotyFg/SvZMk=
 github.com/pmezard/go-difflib v1.0.0 
h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -54,6 +61,8 @@ github.com/stretchr/testify v1.8.1/go.mod 
h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
 github.com/stretchr/testify v1.8.2/go.mod 
h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 github.com/stretchr/testify v1.9.0 
h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod 
h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/wk8/go-ordered-map/v2 v2.1.8 
h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
+github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod 
h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
 golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
 golang.org/x/text v0.21.0/go.mod 
h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=


Reply via email to