Files
ent/dialect/gremlin/encoding/graphson/native.go
Ariel Mashraki bd07c86b60 all: add license header to all go files
Summary:
Used addlicense to generate this:
 addlicense -c "Facebook Inc" -f license_header .

example was taken from: https://github.com/facebook/litho/blob/master/lib/soloader/BUCK

Reviewed By: alexsn

Differential Revision: D17070152

fbshipit-source-id: e7b91398d7f6181727be3400c1872ad5f28e38ed
2019-08-27 04:48:28 -07:00

138 lines
3.6 KiB
Go

// 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 (
"fmt"
"io"
"math"
"reflect"
"unsafe"
"github.com/json-iterator/go"
"github.com/modern-go/reflect2"
)
// EncoderOfNative returns a value encoder of a native type.
func (encodeExtension) EncoderOfNative(typ reflect2.Type) jsoniter.ValEncoder {
switch typ.Kind() {
case reflect.Float64:
return float64Encoder{typ}
default:
return nil
}
}
// DecoratorOfNative decorates a value encoder of a native type.
func (encodeExtension) DecoratorOfNative(typ reflect2.Type, enc jsoniter.ValEncoder) jsoniter.ValEncoder {
switch typ.Kind() {
case reflect.Bool, reflect.String:
return enc
case reflect.Int64, reflect.Int, reflect.Uint32:
return typeEncoder{enc, int64Type}
case reflect.Int32, reflect.Int8, reflect.Uint16:
return typeEncoder{enc, int32Type}
case reflect.Int16:
return typeEncoder{enc, int16Type}
case reflect.Uint64, reflect.Uint:
return typeEncoder{enc, bigIntegerType}
case reflect.Uint8:
return typeEncoder{enc, byteType}
case reflect.Float32:
return typeEncoder{enc, floatType}
case reflect.Float64:
return typeEncoder{enc, doubleType}
default:
return nil
}
}
// DecoderOfNative returns a value decoder of a native type.
func (decodeExtension) DecoderOfNative(typ reflect2.Type) jsoniter.ValDecoder {
switch typ.Kind() {
case reflect.Float64:
return float64Decoder{typ}
default:
return nil
}
}
// DecoratorOfNative decorates a value decoder of a native type.
func (decodeExtension) DecoratorOfNative(typ reflect2.Type, dec jsoniter.ValDecoder) jsoniter.ValDecoder {
switch typ.Kind() {
case reflect.Bool:
return dec
case reflect.String:
return typeDecoder{dec, typeCheckerFunc(func(Type) error { return nil })}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return typeDecoder{dec, integerTypes}
case reflect.Float32:
return typeDecoder{dec, floatTypes}
case reflect.Float64:
return typeDecoder{dec, doubleTypes}
default:
return nil
}
}
type float64Encoder struct {
reflect2.Type
}
func (enc float64Encoder) IsEmpty(ptr unsafe.Pointer) bool {
return enc.UnsafeIndirect(ptr).(float64) == 0
}
func (enc float64Encoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
f := enc.UnsafeIndirect(ptr).(float64)
switch {
case math.IsNaN(f):
stream.WriteString("NaN")
case math.IsInf(f, 1):
stream.WriteString("Infinity")
case math.IsInf(f, -1):
stream.WriteString("-Infinity")
default:
stream.WriteFloat64(f)
}
}
type float64Decoder struct {
reflect2.Type
}
var (
integerTypes = Types{byteType, int16Type, int32Type, int64Type, bigIntegerType}
floatTypes = append(integerTypes, floatType, bigDecimal)
doubleTypes = append(floatTypes, doubleType)
)
func (dec float64Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
var val float64
switch next := iter.WhatIsNext(); next {
case jsoniter.NumberValue:
val = iter.ReadFloat64()
case jsoniter.StringValue:
switch str := iter.ReadString(); str {
case "NaN":
val = math.NaN()
case "Infinity":
val = math.Inf(1)
case "-Infinity":
val = math.Inf(-1)
default:
iter.ReportError("decode float64", "invalid value "+str)
}
default:
iter.ReportError("decode float64", fmt.Sprintf("unexpected value type: %d", next))
}
if iter.Error == nil || iter.Error == io.EOF {
// nolint: gas
dec.UnsafeSet(ptr, unsafe.Pointer(&val))
}
}