You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by xi...@apache.org on 2025/01/23 23:34:10 UTC

(tinkerpop) branch go-type-ser created (now 3735d7eb61)

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

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


      at 3735d7eb61 update graph binary serializer to 4.0.0 spec

This branch includes the following new commits:

     new 3735d7eb61 update graph binary serializer to 4.0.0 spec

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(tinkerpop) 01/01: update graph binary serializer to 4.0.0 spec

Posted by xi...@apache.org.
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 <55...@users.noreply.github.com>
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=