gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

encoder.go (14403B)


      1 package encoder
      2 
      3 import (
      4 	"bytes"
      5 	"encoding"
      6 	"encoding/base64"
      7 	"encoding/json"
      8 	"fmt"
      9 	"math"
     10 	"reflect"
     11 	"strconv"
     12 	"strings"
     13 	"sync"
     14 	"unsafe"
     15 
     16 	"github.com/goccy/go-json/internal/errors"
     17 	"github.com/goccy/go-json/internal/runtime"
     18 )
     19 
     20 func (t OpType) IsMultipleOpHead() bool {
     21 	switch t {
     22 	case OpStructHead:
     23 		return true
     24 	case OpStructHeadSlice:
     25 		return true
     26 	case OpStructHeadArray:
     27 		return true
     28 	case OpStructHeadMap:
     29 		return true
     30 	case OpStructHeadStruct:
     31 		return true
     32 	case OpStructHeadOmitEmpty:
     33 		return true
     34 	case OpStructHeadOmitEmptySlice:
     35 		return true
     36 	case OpStructHeadOmitEmptyArray:
     37 		return true
     38 	case OpStructHeadOmitEmptyMap:
     39 		return true
     40 	case OpStructHeadOmitEmptyStruct:
     41 		return true
     42 	case OpStructHeadSlicePtr:
     43 		return true
     44 	case OpStructHeadOmitEmptySlicePtr:
     45 		return true
     46 	case OpStructHeadArrayPtr:
     47 		return true
     48 	case OpStructHeadOmitEmptyArrayPtr:
     49 		return true
     50 	case OpStructHeadMapPtr:
     51 		return true
     52 	case OpStructHeadOmitEmptyMapPtr:
     53 		return true
     54 	}
     55 	return false
     56 }
     57 
     58 func (t OpType) IsMultipleOpField() bool {
     59 	switch t {
     60 	case OpStructField:
     61 		return true
     62 	case OpStructFieldSlice:
     63 		return true
     64 	case OpStructFieldArray:
     65 		return true
     66 	case OpStructFieldMap:
     67 		return true
     68 	case OpStructFieldStruct:
     69 		return true
     70 	case OpStructFieldOmitEmpty:
     71 		return true
     72 	case OpStructFieldOmitEmptySlice:
     73 		return true
     74 	case OpStructFieldOmitEmptyArray:
     75 		return true
     76 	case OpStructFieldOmitEmptyMap:
     77 		return true
     78 	case OpStructFieldOmitEmptyStruct:
     79 		return true
     80 	case OpStructFieldSlicePtr:
     81 		return true
     82 	case OpStructFieldOmitEmptySlicePtr:
     83 		return true
     84 	case OpStructFieldArrayPtr:
     85 		return true
     86 	case OpStructFieldOmitEmptyArrayPtr:
     87 		return true
     88 	case OpStructFieldMapPtr:
     89 		return true
     90 	case OpStructFieldOmitEmptyMapPtr:
     91 		return true
     92 	}
     93 	return false
     94 }
     95 
     96 type OpcodeSet struct {
     97 	Type                     *runtime.Type
     98 	NoescapeKeyCode          *Opcode
     99 	EscapeKeyCode            *Opcode
    100 	InterfaceNoescapeKeyCode *Opcode
    101 	InterfaceEscapeKeyCode   *Opcode
    102 	CodeLength               int
    103 	EndCode                  *Opcode
    104 	Code                     Code
    105 	QueryCache               map[string]*OpcodeSet
    106 	cacheMu                  sync.RWMutex
    107 }
    108 
    109 func (s *OpcodeSet) getQueryCache(hash string) *OpcodeSet {
    110 	s.cacheMu.RLock()
    111 	codeSet := s.QueryCache[hash]
    112 	s.cacheMu.RUnlock()
    113 	return codeSet
    114 }
    115 
    116 func (s *OpcodeSet) setQueryCache(hash string, codeSet *OpcodeSet) {
    117 	s.cacheMu.Lock()
    118 	s.QueryCache[hash] = codeSet
    119 	s.cacheMu.Unlock()
    120 }
    121 
    122 type CompiledCode struct {
    123 	Code    *Opcode
    124 	Linked  bool // whether recursive code already have linked
    125 	CurLen  uintptr
    126 	NextLen uintptr
    127 }
    128 
    129 const StartDetectingCyclesAfter = 1000
    130 
    131 func Load(base uintptr, idx uintptr) uintptr {
    132 	addr := base + idx
    133 	return **(**uintptr)(unsafe.Pointer(&addr))
    134 }
    135 
    136 func Store(base uintptr, idx uintptr, p uintptr) {
    137 	addr := base + idx
    138 	**(**uintptr)(unsafe.Pointer(&addr)) = p
    139 }
    140 
    141 func LoadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr {
    142 	addr := base + idx
    143 	p := **(**uintptr)(unsafe.Pointer(&addr))
    144 	if p == 0 {
    145 		return 0
    146 	}
    147 	return PtrToPtr(p)
    148 	/*
    149 		for i := 0; i < ptrNum; i++ {
    150 			if p == 0 {
    151 				return p
    152 			}
    153 			p = PtrToPtr(p)
    154 		}
    155 		return p
    156 	*/
    157 }
    158 
    159 func PtrToUint64(p uintptr) uint64              { return **(**uint64)(unsafe.Pointer(&p)) }
    160 func PtrToFloat32(p uintptr) float32            { return **(**float32)(unsafe.Pointer(&p)) }
    161 func PtrToFloat64(p uintptr) float64            { return **(**float64)(unsafe.Pointer(&p)) }
    162 func PtrToBool(p uintptr) bool                  { return **(**bool)(unsafe.Pointer(&p)) }
    163 func PtrToBytes(p uintptr) []byte               { return **(**[]byte)(unsafe.Pointer(&p)) }
    164 func PtrToNumber(p uintptr) json.Number         { return **(**json.Number)(unsafe.Pointer(&p)) }
    165 func PtrToString(p uintptr) string              { return **(**string)(unsafe.Pointer(&p)) }
    166 func PtrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) }
    167 func PtrToPtr(p uintptr) uintptr {
    168 	return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
    169 }
    170 func PtrToNPtr(p uintptr, ptrNum int) uintptr {
    171 	for i := 0; i < ptrNum; i++ {
    172 		if p == 0 {
    173 			return 0
    174 		}
    175 		p = PtrToPtr(p)
    176 	}
    177 	return p
    178 }
    179 
    180 func PtrToUnsafePtr(p uintptr) unsafe.Pointer {
    181 	return *(*unsafe.Pointer)(unsafe.Pointer(&p))
    182 }
    183 func PtrToInterface(code *Opcode, p uintptr) interface{} {
    184 	return *(*interface{})(unsafe.Pointer(&emptyInterface{
    185 		typ: code.Type,
    186 		ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)),
    187 	}))
    188 }
    189 
    190 func ErrUnsupportedValue(code *Opcode, ptr uintptr) *errors.UnsupportedValueError {
    191 	v := *(*interface{})(unsafe.Pointer(&emptyInterface{
    192 		typ: code.Type,
    193 		ptr: *(*unsafe.Pointer)(unsafe.Pointer(&ptr)),
    194 	}))
    195 	return &errors.UnsupportedValueError{
    196 		Value: reflect.ValueOf(v),
    197 		Str:   fmt.Sprintf("encountered a cycle via %s", code.Type),
    198 	}
    199 }
    200 
    201 func ErrUnsupportedFloat(v float64) *errors.UnsupportedValueError {
    202 	return &errors.UnsupportedValueError{
    203 		Value: reflect.ValueOf(v),
    204 		Str:   strconv.FormatFloat(v, 'g', -1, 64),
    205 	}
    206 }
    207 
    208 func ErrMarshalerWithCode(code *Opcode, err error) *errors.MarshalerError {
    209 	return &errors.MarshalerError{
    210 		Type: runtime.RType2Type(code.Type),
    211 		Err:  err,
    212 	}
    213 }
    214 
    215 type emptyInterface struct {
    216 	typ *runtime.Type
    217 	ptr unsafe.Pointer
    218 }
    219 
    220 type MapItem struct {
    221 	Key   []byte
    222 	Value []byte
    223 }
    224 
    225 type Mapslice struct {
    226 	Items []MapItem
    227 }
    228 
    229 func (m *Mapslice) Len() int {
    230 	return len(m.Items)
    231 }
    232 
    233 func (m *Mapslice) Less(i, j int) bool {
    234 	return bytes.Compare(m.Items[i].Key, m.Items[j].Key) < 0
    235 }
    236 
    237 func (m *Mapslice) Swap(i, j int) {
    238 	m.Items[i], m.Items[j] = m.Items[j], m.Items[i]
    239 }
    240 
    241 //nolint:structcheck,unused
    242 type mapIter struct {
    243 	key         unsafe.Pointer
    244 	elem        unsafe.Pointer
    245 	t           unsafe.Pointer
    246 	h           unsafe.Pointer
    247 	buckets     unsafe.Pointer
    248 	bptr        unsafe.Pointer
    249 	overflow    unsafe.Pointer
    250 	oldoverflow unsafe.Pointer
    251 	startBucket uintptr
    252 	offset      uint8
    253 	wrapped     bool
    254 	B           uint8
    255 	i           uint8
    256 	bucket      uintptr
    257 	checkBucket uintptr
    258 }
    259 
    260 type MapContext struct {
    261 	Start int
    262 	First int
    263 	Idx   int
    264 	Slice *Mapslice
    265 	Buf   []byte
    266 	Len   int
    267 	Iter  mapIter
    268 }
    269 
    270 var mapContextPool = sync.Pool{
    271 	New: func() interface{} {
    272 		return &MapContext{
    273 			Slice: &Mapslice{},
    274 		}
    275 	},
    276 }
    277 
    278 func NewMapContext(mapLen int, unorderedMap bool) *MapContext {
    279 	ctx := mapContextPool.Get().(*MapContext)
    280 	if !unorderedMap {
    281 		if len(ctx.Slice.Items) < mapLen {
    282 			ctx.Slice.Items = make([]MapItem, mapLen)
    283 		} else {
    284 			ctx.Slice.Items = ctx.Slice.Items[:mapLen]
    285 		}
    286 	}
    287 	ctx.Buf = ctx.Buf[:0]
    288 	ctx.Iter = mapIter{}
    289 	ctx.Idx = 0
    290 	ctx.Len = mapLen
    291 	return ctx
    292 }
    293 
    294 func ReleaseMapContext(c *MapContext) {
    295 	mapContextPool.Put(c)
    296 }
    297 
    298 //go:linkname MapIterInit runtime.mapiterinit
    299 //go:noescape
    300 func MapIterInit(mapType *runtime.Type, m unsafe.Pointer, it *mapIter)
    301 
    302 //go:linkname MapIterKey reflect.mapiterkey
    303 //go:noescape
    304 func MapIterKey(it *mapIter) unsafe.Pointer
    305 
    306 //go:linkname MapIterNext reflect.mapiternext
    307 //go:noescape
    308 func MapIterNext(it *mapIter)
    309 
    310 //go:linkname MapLen reflect.maplen
    311 //go:noescape
    312 func MapLen(m unsafe.Pointer) int
    313 
    314 func AppendByteSlice(_ *RuntimeContext, b []byte, src []byte) []byte {
    315 	if src == nil {
    316 		return append(b, `null`...)
    317 	}
    318 	encodedLen := base64.StdEncoding.EncodedLen(len(src))
    319 	b = append(b, '"')
    320 	pos := len(b)
    321 	remainLen := cap(b[pos:])
    322 	var buf []byte
    323 	if remainLen > encodedLen {
    324 		buf = b[pos : pos+encodedLen]
    325 	} else {
    326 		buf = make([]byte, encodedLen)
    327 	}
    328 	base64.StdEncoding.Encode(buf, src)
    329 	return append(append(b, buf...), '"')
    330 }
    331 
    332 func AppendFloat32(_ *RuntimeContext, b []byte, v float32) []byte {
    333 	f64 := float64(v)
    334 	abs := math.Abs(f64)
    335 	fmt := byte('f')
    336 	// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
    337 	if abs != 0 {
    338 		f32 := float32(abs)
    339 		if f32 < 1e-6 || f32 >= 1e21 {
    340 			fmt = 'e'
    341 		}
    342 	}
    343 	return strconv.AppendFloat(b, f64, fmt, -1, 32)
    344 }
    345 
    346 func AppendFloat64(_ *RuntimeContext, b []byte, v float64) []byte {
    347 	abs := math.Abs(v)
    348 	fmt := byte('f')
    349 	// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
    350 	if abs != 0 {
    351 		if abs < 1e-6 || abs >= 1e21 {
    352 			fmt = 'e'
    353 		}
    354 	}
    355 	return strconv.AppendFloat(b, v, fmt, -1, 64)
    356 }
    357 
    358 func AppendBool(_ *RuntimeContext, b []byte, v bool) []byte {
    359 	if v {
    360 		return append(b, "true"...)
    361 	}
    362 	return append(b, "false"...)
    363 }
    364 
    365 var (
    366 	floatTable = [256]bool{
    367 		'0': true,
    368 		'1': true,
    369 		'2': true,
    370 		'3': true,
    371 		'4': true,
    372 		'5': true,
    373 		'6': true,
    374 		'7': true,
    375 		'8': true,
    376 		'9': true,
    377 		'.': true,
    378 		'e': true,
    379 		'E': true,
    380 		'+': true,
    381 		'-': true,
    382 	}
    383 )
    384 
    385 func AppendNumber(_ *RuntimeContext, b []byte, n json.Number) ([]byte, error) {
    386 	if len(n) == 0 {
    387 		return append(b, '0'), nil
    388 	}
    389 	for i := 0; i < len(n); i++ {
    390 		if !floatTable[n[i]] {
    391 			return nil, fmt.Errorf("json: invalid number literal %q", n)
    392 		}
    393 	}
    394 	b = append(b, n...)
    395 	return b, nil
    396 }
    397 
    398 func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
    399 	rv := reflect.ValueOf(v) // convert by dynamic interface type
    400 	if (code.Flags & AddrForMarshalerFlags) != 0 {
    401 		if rv.CanAddr() {
    402 			rv = rv.Addr()
    403 		} else {
    404 			newV := reflect.New(rv.Type())
    405 			newV.Elem().Set(rv)
    406 			rv = newV
    407 		}
    408 	}
    409 	v = rv.Interface()
    410 	var bb []byte
    411 	if (code.Flags & MarshalerContextFlags) != 0 {
    412 		marshaler, ok := v.(marshalerContext)
    413 		if !ok {
    414 			return AppendNull(ctx, b), nil
    415 		}
    416 		stdctx := ctx.Option.Context
    417 		if ctx.Option.Flag&FieldQueryOption != 0 {
    418 			stdctx = SetFieldQueryToContext(stdctx, code.FieldQuery)
    419 		}
    420 		b, err := marshaler.MarshalJSON(stdctx)
    421 		if err != nil {
    422 			return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
    423 		}
    424 		bb = b
    425 	} else {
    426 		marshaler, ok := v.(json.Marshaler)
    427 		if !ok {
    428 			return AppendNull(ctx, b), nil
    429 		}
    430 		b, err := marshaler.MarshalJSON()
    431 		if err != nil {
    432 			return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
    433 		}
    434 		bb = b
    435 	}
    436 	marshalBuf := ctx.MarshalBuf[:0]
    437 	marshalBuf = append(append(marshalBuf, bb...), nul)
    438 	compactedBuf, err := compact(b, marshalBuf, (ctx.Option.Flag&HTMLEscapeOption) != 0)
    439 	if err != nil {
    440 		return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
    441 	}
    442 	ctx.MarshalBuf = marshalBuf
    443 	return compactedBuf, nil
    444 }
    445 
    446 func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
    447 	rv := reflect.ValueOf(v) // convert by dynamic interface type
    448 	if (code.Flags & AddrForMarshalerFlags) != 0 {
    449 		if rv.CanAddr() {
    450 			rv = rv.Addr()
    451 		} else {
    452 			newV := reflect.New(rv.Type())
    453 			newV.Elem().Set(rv)
    454 			rv = newV
    455 		}
    456 	}
    457 	v = rv.Interface()
    458 	var bb []byte
    459 	if (code.Flags & MarshalerContextFlags) != 0 {
    460 		marshaler, ok := v.(marshalerContext)
    461 		if !ok {
    462 			return AppendNull(ctx, b), nil
    463 		}
    464 		b, err := marshaler.MarshalJSON(ctx.Option.Context)
    465 		if err != nil {
    466 			return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
    467 		}
    468 		bb = b
    469 	} else {
    470 		marshaler, ok := v.(json.Marshaler)
    471 		if !ok {
    472 			return AppendNull(ctx, b), nil
    473 		}
    474 		b, err := marshaler.MarshalJSON()
    475 		if err != nil {
    476 			return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
    477 		}
    478 		bb = b
    479 	}
    480 	marshalBuf := ctx.MarshalBuf[:0]
    481 	marshalBuf = append(append(marshalBuf, bb...), nul)
    482 	indentedBuf, err := doIndent(
    483 		b,
    484 		marshalBuf,
    485 		string(ctx.Prefix)+strings.Repeat(string(ctx.IndentStr), int(ctx.BaseIndent+code.Indent)),
    486 		string(ctx.IndentStr),
    487 		(ctx.Option.Flag&HTMLEscapeOption) != 0,
    488 	)
    489 	if err != nil {
    490 		return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
    491 	}
    492 	ctx.MarshalBuf = marshalBuf
    493 	return indentedBuf, nil
    494 }
    495 
    496 func AppendMarshalText(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
    497 	rv := reflect.ValueOf(v) // convert by dynamic interface type
    498 	if (code.Flags & AddrForMarshalerFlags) != 0 {
    499 		if rv.CanAddr() {
    500 			rv = rv.Addr()
    501 		} else {
    502 			newV := reflect.New(rv.Type())
    503 			newV.Elem().Set(rv)
    504 			rv = newV
    505 		}
    506 	}
    507 	v = rv.Interface()
    508 	marshaler, ok := v.(encoding.TextMarshaler)
    509 	if !ok {
    510 		return AppendNull(ctx, b), nil
    511 	}
    512 	bytes, err := marshaler.MarshalText()
    513 	if err != nil {
    514 		return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
    515 	}
    516 	return AppendString(ctx, b, *(*string)(unsafe.Pointer(&bytes))), nil
    517 }
    518 
    519 func AppendMarshalTextIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
    520 	rv := reflect.ValueOf(v) // convert by dynamic interface type
    521 	if (code.Flags & AddrForMarshalerFlags) != 0 {
    522 		if rv.CanAddr() {
    523 			rv = rv.Addr()
    524 		} else {
    525 			newV := reflect.New(rv.Type())
    526 			newV.Elem().Set(rv)
    527 			rv = newV
    528 		}
    529 	}
    530 	v = rv.Interface()
    531 	marshaler, ok := v.(encoding.TextMarshaler)
    532 	if !ok {
    533 		return AppendNull(ctx, b), nil
    534 	}
    535 	bytes, err := marshaler.MarshalText()
    536 	if err != nil {
    537 		return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
    538 	}
    539 	return AppendString(ctx, b, *(*string)(unsafe.Pointer(&bytes))), nil
    540 }
    541 
    542 func AppendNull(_ *RuntimeContext, b []byte) []byte {
    543 	return append(b, "null"...)
    544 }
    545 
    546 func AppendComma(_ *RuntimeContext, b []byte) []byte {
    547 	return append(b, ',')
    548 }
    549 
    550 func AppendCommaIndent(_ *RuntimeContext, b []byte) []byte {
    551 	return append(b, ',', '\n')
    552 }
    553 
    554 func AppendStructEnd(_ *RuntimeContext, b []byte) []byte {
    555 	return append(b, '}', ',')
    556 }
    557 
    558 func AppendStructEndIndent(ctx *RuntimeContext, code *Opcode, b []byte) []byte {
    559 	b = append(b, '\n')
    560 	b = append(b, ctx.Prefix...)
    561 	indentNum := ctx.BaseIndent + code.Indent - 1
    562 	for i := uint32(0); i < indentNum; i++ {
    563 		b = append(b, ctx.IndentStr...)
    564 	}
    565 	return append(b, '}', ',', '\n')
    566 }
    567 
    568 func AppendIndent(ctx *RuntimeContext, b []byte, indent uint32) []byte {
    569 	b = append(b, ctx.Prefix...)
    570 	indentNum := ctx.BaseIndent + indent
    571 	for i := uint32(0); i < indentNum; i++ {
    572 		b = append(b, ctx.IndentStr...)
    573 	}
    574 	return b
    575 }
    576 
    577 func IsNilForMarshaler(v interface{}) bool {
    578 	rv := reflect.ValueOf(v)
    579 	switch rv.Kind() {
    580 	case reflect.Bool:
    581 		return !rv.Bool()
    582 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    583 		return rv.Int() == 0
    584 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
    585 		return rv.Uint() == 0
    586 	case reflect.Float32, reflect.Float64:
    587 		return math.Float64bits(rv.Float()) == 0
    588 	case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Func:
    589 		return rv.IsNil()
    590 	case reflect.Slice:
    591 		return rv.IsNil() || rv.Len() == 0
    592 	case reflect.String:
    593 		return rv.Len() == 0
    594 	}
    595 	return false
    596 }