snapshot of https://github.com/ent/ent.git (master, 2026-09-15; blobs > 131072B omitted)
This commit is contained in:
116
dialect/gremlin/encoding/graphson/map.go
Normal file
116
dialect/gremlin/encoding/graphson/map.go
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright 2019-present Facebook Inc. All rights reserved.
|
||||
// This source code is licensed under the Apache 2.0 license found
|
||||
// in the LICENSE file in the root directory of this source tree.
|
||||
|
||||
package graphson
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
// EncoderOfMap returns a value encoder of a map type.
|
||||
func (ext encodeExtension) EncoderOfMap(typ reflect2.Type) jsoniter.ValEncoder {
|
||||
mapType := typ.(reflect2.MapType)
|
||||
return &mapEncoder{
|
||||
mapType: mapType,
|
||||
keyEnc: ext.LazyEncoderOf(mapType.Key()),
|
||||
elemEnc: ext.LazyEncoderOf(mapType.Elem()),
|
||||
}
|
||||
}
|
||||
|
||||
// DecoratorOfMap decorates a value encoder of a map type.
|
||||
func (encodeExtension) DecoratorOfMap(enc jsoniter.ValEncoder) jsoniter.ValEncoder {
|
||||
return typeEncoder{enc, mapType}
|
||||
}
|
||||
|
||||
type mapEncoder struct {
|
||||
mapType reflect2.MapType
|
||||
keyEnc jsoniter.ValEncoder
|
||||
elemEnc jsoniter.ValEncoder
|
||||
}
|
||||
|
||||
func (enc *mapEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
||||
iter := enc.mapType.UnsafeIterate(ptr)
|
||||
if !iter.HasNext() {
|
||||
stream.WriteEmptyArray()
|
||||
return
|
||||
}
|
||||
|
||||
stream.WriteArrayStart()
|
||||
for {
|
||||
key, elem := iter.UnsafeNext()
|
||||
enc.keyEnc.Encode(key, stream)
|
||||
stream.WriteMore()
|
||||
enc.elemEnc.Encode(elem, stream)
|
||||
if !iter.HasNext() {
|
||||
break
|
||||
}
|
||||
stream.WriteMore()
|
||||
}
|
||||
stream.WriteArrayEnd()
|
||||
}
|
||||
|
||||
func (enc *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return !enc.mapType.UnsafeIterate(ptr).HasNext()
|
||||
}
|
||||
|
||||
// DecoderOfMap returns a value decoder of a map type.
|
||||
func (ext decodeExtension) DecoderOfMap(typ reflect2.Type) jsoniter.ValDecoder {
|
||||
mapType := typ.(reflect2.MapType)
|
||||
keyType, elemType := mapType.Key(), mapType.Elem()
|
||||
return &mapDecoder{
|
||||
mapType: mapType,
|
||||
keyType: keyType,
|
||||
elemType: elemType,
|
||||
keyDec: ext.LazyDecoderOf(keyType),
|
||||
elemDec: ext.LazyDecoderOf(elemType),
|
||||
}
|
||||
}
|
||||
|
||||
// DecoratorOfMap decorates a value decoder of a map type.
|
||||
func (decodeExtension) DecoratorOfMap(dec jsoniter.ValDecoder) jsoniter.ValDecoder {
|
||||
return typeDecoder{dec, mapType}
|
||||
}
|
||||
|
||||
type mapDecoder struct {
|
||||
mapType reflect2.MapType
|
||||
keyType reflect2.Type
|
||||
elemType reflect2.Type
|
||||
keyDec jsoniter.ValDecoder
|
||||
elemDec jsoniter.ValDecoder
|
||||
}
|
||||
|
||||
func (dec *mapDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
mapType := dec.mapType
|
||||
if mapType.UnsafeIsNil(ptr) {
|
||||
mapType.UnsafeSet(ptr, mapType.UnsafeMakeMap(0))
|
||||
}
|
||||
|
||||
var key unsafe.Pointer
|
||||
if !iter.ReadArrayCB(func(iter *jsoniter.Iterator) bool {
|
||||
if key == nil {
|
||||
key = dec.keyType.UnsafeNew()
|
||||
dec.keyDec.Decode(key, iter)
|
||||
return iter.Error == nil
|
||||
}
|
||||
|
||||
elem := dec.elemType.UnsafeNew()
|
||||
dec.elemDec.Decode(elem, iter)
|
||||
if iter.Error != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
mapType.UnsafeSetIndex(ptr, key, elem)
|
||||
key = nil
|
||||
return true
|
||||
}) {
|
||||
return
|
||||
}
|
||||
|
||||
if key != nil {
|
||||
iter.ReportError("decode map", "odd number of map items")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user