mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-01-23 14:50:21 +00:00
225 lines
4.2 KiB
Go
225 lines
4.2 KiB
Go
|
package optdec
|
||
|
|
||
|
import (
|
||
|
"reflect"
|
||
|
"unsafe"
|
||
|
|
||
|
"github.com/bytedance/sonic/internal/rt"
|
||
|
)
|
||
|
|
||
|
type sliceDecoder struct {
|
||
|
elemType *rt.GoType
|
||
|
elemDec decFunc
|
||
|
typ reflect.Type
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
emptyPtr = &struct{}{}
|
||
|
)
|
||
|
|
||
|
func (d *sliceDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||
|
if node.IsNull() {
|
||
|
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
arr, ok := node.AsArr()
|
||
|
if !ok {
|
||
|
return error_mismatch(node, ctx, d.typ)
|
||
|
}
|
||
|
|
||
|
slice := rt.MakeSlice(vp, d.elemType, arr.Len())
|
||
|
elems := slice.Ptr
|
||
|
next := arr.Children()
|
||
|
|
||
|
var gerr error
|
||
|
for i := 0; i < arr.Len(); i++ {
|
||
|
val := NewNode(next)
|
||
|
elem := unsafe.Pointer(uintptr(elems) + uintptr(i)*d.elemType.Size)
|
||
|
err := d.elemDec.FromDom(elem, val, ctx)
|
||
|
if gerr == nil && err != nil {
|
||
|
gerr = err
|
||
|
}
|
||
|
next = val.Next()
|
||
|
}
|
||
|
|
||
|
*(*rt.GoSlice)(vp) = *slice
|
||
|
return gerr
|
||
|
}
|
||
|
|
||
|
type arrayDecoder struct {
|
||
|
len int
|
||
|
elemType *rt.GoType
|
||
|
elemDec decFunc
|
||
|
typ reflect.Type
|
||
|
}
|
||
|
|
||
|
//go:nocheckptr
|
||
|
func (d *arrayDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||
|
if node.IsNull() {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
arr, ok := node.AsArr()
|
||
|
if !ok {
|
||
|
return error_mismatch(node, ctx, d.typ)
|
||
|
}
|
||
|
|
||
|
next := arr.Children()
|
||
|
i := 0
|
||
|
|
||
|
var gerr error
|
||
|
for ; i < d.len && i < arr.Len(); i++ {
|
||
|
elem := unsafe.Pointer(uintptr(vp) + uintptr(i)*d.elemType.Size)
|
||
|
val := NewNode(next)
|
||
|
err := d.elemDec.FromDom(elem, val, ctx)
|
||
|
if gerr == nil && err != nil {
|
||
|
gerr = err
|
||
|
}
|
||
|
next = val.Next()
|
||
|
}
|
||
|
|
||
|
/* zero rest of array */
|
||
|
ptr := unsafe.Pointer(uintptr(vp) + uintptr(i)*d.elemType.Size)
|
||
|
n := uintptr(d.len-i) * d.elemType.Size
|
||
|
rt.ClearMemory(d.elemType, ptr, n)
|
||
|
return gerr
|
||
|
}
|
||
|
|
||
|
type sliceEfaceDecoder struct {
|
||
|
}
|
||
|
|
||
|
func (d *sliceEfaceDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||
|
if node.IsNull() {
|
||
|
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return node.AsSliceEface(ctx, vp)
|
||
|
}
|
||
|
|
||
|
type sliceI32Decoder struct {
|
||
|
}
|
||
|
|
||
|
func (d *sliceI32Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||
|
if node.IsNull() {
|
||
|
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return node.AsSliceI32(ctx, vp)
|
||
|
}
|
||
|
|
||
|
type sliceI64Decoder struct {
|
||
|
}
|
||
|
|
||
|
func (d *sliceI64Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||
|
if node.IsNull() {
|
||
|
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return node.AsSliceI64(ctx, vp)
|
||
|
}
|
||
|
|
||
|
type sliceU32Decoder struct {
|
||
|
}
|
||
|
|
||
|
func (d *sliceU32Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||
|
if node.IsNull() {
|
||
|
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return node.AsSliceU32(ctx, vp)
|
||
|
}
|
||
|
|
||
|
type sliceU64Decoder struct {
|
||
|
}
|
||
|
|
||
|
func (d *sliceU64Decoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||
|
if node.IsNull() {
|
||
|
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return node.AsSliceU64(ctx, vp)
|
||
|
}
|
||
|
|
||
|
type sliceStringDecoder struct {
|
||
|
}
|
||
|
|
||
|
func (d *sliceStringDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||
|
if node.IsNull() {
|
||
|
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return node.AsSliceString(ctx, vp)
|
||
|
}
|
||
|
|
||
|
type sliceBytesDecoder struct {
|
||
|
}
|
||
|
|
||
|
func (d *sliceBytesDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||
|
if node.IsNull() {
|
||
|
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
s, err := node.AsSliceBytes(ctx)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
*(*[]byte)(vp) = s
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
type sliceBytesUnmarshalerDecoder struct {
|
||
|
elemType *rt.GoType
|
||
|
elemDec decFunc
|
||
|
typ reflect.Type
|
||
|
}
|
||
|
|
||
|
func (d *sliceBytesUnmarshalerDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
|
||
|
if node.IsNull() {
|
||
|
*(*rt.GoSlice)(vp) = rt.GoSlice{}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
/* parse JSON string into `[]byte` */
|
||
|
if node.IsStr() {
|
||
|
slice, err := node.AsSliceBytes(ctx)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
*(*[]byte)(vp) = slice
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
/* parse JSON array into `[]byte` */
|
||
|
arr, ok := node.AsArr()
|
||
|
if !ok {
|
||
|
return error_mismatch(node, ctx, d.typ)
|
||
|
}
|
||
|
|
||
|
slice := rt.MakeSlice(vp, d.elemType, arr.Len())
|
||
|
elems := slice.Ptr
|
||
|
|
||
|
var gerr error
|
||
|
next := arr.Children()
|
||
|
for i := 0; i < arr.Len(); i++ {
|
||
|
child := NewNode(next)
|
||
|
elem := unsafe.Pointer(uintptr(elems) + uintptr(i)*d.elemType.Size)
|
||
|
err := d.elemDec.FromDom(elem, child, ctx)
|
||
|
if gerr == nil && err != nil {
|
||
|
gerr = err
|
||
|
}
|
||
|
next = child.Next()
|
||
|
}
|
||
|
|
||
|
*(*rt.GoSlice)(vp) = *slice
|
||
|
return gerr
|
||
|
}
|