github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/jsoni/reflect_native.go (about)

     1  package jsoni
     2  
     3  import (
     4  	"context"
     5  	"encoding/base64"
     6  	"reflect"
     7  	"strconv"
     8  	"unsafe"
     9  
    10  	"github.com/modern-go/reflect2"
    11  )
    12  
    13  const ptrSize = 32 << (^uintptr(0) >> 63)
    14  
    15  func createEncoderOfNative(ctx *ctx, typ reflect2.Type) ValEncoder {
    16  	if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 {
    17  		return &base64Codec{sliceDecoder: decoderOfSlice(ctx, typ)}
    18  	}
    19  	typeName := typ.String()
    20  	kind := typ.Kind()
    21  	switch kind {
    22  	case reflect.String:
    23  		if typeName != "string" {
    24  			return encoderOfType(ctx, PtrElem((*string)(nil)))
    25  		}
    26  		return &stringCodec{}
    27  	case reflect.Int:
    28  		if typeName != "int" {
    29  			return encoderOfType(ctx, PtrElem((*int)(nil)))
    30  		}
    31  		if strconv.IntSize == 32 {
    32  			return &int32Codec{}
    33  		}
    34  		return &int64Codec{}
    35  	case reflect.Int8:
    36  		if typeName != "int8" {
    37  			return encoderOfType(ctx, PtrElem((*int8)(nil)))
    38  		}
    39  		return &int8Codec{}
    40  	case reflect.Int16:
    41  		if typeName != "int16" {
    42  			return encoderOfType(ctx, PtrElem((*int16)(nil)))
    43  		}
    44  		return &int16Codec{}
    45  	case reflect.Int32:
    46  		if typeName != "int32" {
    47  			return encoderOfType(ctx, PtrElem((*int32)(nil)))
    48  		}
    49  		return &int32Codec{}
    50  	case reflect.Int64:
    51  		if typeName != "int64" {
    52  			return encoderOfType(ctx, PtrElem((*int64)(nil)))
    53  		}
    54  		if ctx.int64AsString {
    55  			return &stringModeNumberEncoder{&int64Codec{}}
    56  		}
    57  		return &int64Codec{}
    58  	case reflect.Uint:
    59  		if typeName != "uint" {
    60  			return encoderOfType(ctx, PtrElem((*uint)(nil)))
    61  		}
    62  		if strconv.IntSize == 32 {
    63  			return &uint32Codec{}
    64  		}
    65  		return &uint64Codec{}
    66  	case reflect.Uint8:
    67  		if typeName != "uint8" {
    68  			return encoderOfType(ctx, PtrElem((*uint8)(nil)))
    69  		}
    70  		return &uint8Codec{}
    71  	case reflect.Uint16:
    72  		if typeName != "uint16" {
    73  			return encoderOfType(ctx, PtrElem((*uint16)(nil)))
    74  		}
    75  		return &uint16Codec{}
    76  	case reflect.Uint32:
    77  		if typeName != "uint32" {
    78  			return encoderOfType(ctx, PtrElem((*uint32)(nil)))
    79  		}
    80  		return &uint32Codec{}
    81  	case reflect.Uintptr:
    82  		if typeName != "uintptr" {
    83  			return encoderOfType(ctx, PtrElem((*uintptr)(nil)))
    84  		}
    85  		if ptrSize == 32 {
    86  			return &uint32Codec{}
    87  		}
    88  		return &uint64Codec{}
    89  	case reflect.Uint64:
    90  		if typeName != "uint64" {
    91  			return encoderOfType(ctx, PtrElem((*uint64)(nil)))
    92  		}
    93  		if ctx.int64AsString {
    94  			return &stringModeNumberEncoder{&uint64Codec{}}
    95  		}
    96  		return &uint64Codec{}
    97  	case reflect.Float32:
    98  		if typeName != "float32" {
    99  			return encoderOfType(ctx, PtrElem((*float32)(nil)))
   100  		}
   101  		return &float32Codec{}
   102  	case reflect.Float64:
   103  		if typeName != "float64" {
   104  			return encoderOfType(ctx, PtrElem((*float64)(nil)))
   105  		}
   106  		return &float64Codec{}
   107  	case reflect.Bool:
   108  		if typeName != "bool" {
   109  			return encoderOfType(ctx, PtrElem((*bool)(nil)))
   110  		}
   111  		return &boolCodec{}
   112  	}
   113  	return nil
   114  }
   115  
   116  func createDecoderOfNative(ctx *ctx, typ reflect2.Type) ValDecoder {
   117  	if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 {
   118  		return &base64Codec{sliceDecoder: decoderOfSlice(ctx, typ)}
   119  	}
   120  	typeName := typ.String()
   121  	switch typ.Kind() {
   122  	case reflect.String:
   123  		if typeName != "string" {
   124  			return decoderOfType(ctx, PtrElem((*string)(nil)))
   125  		}
   126  		return &stringCodec{}
   127  	case reflect.Int:
   128  		if typeName != "int" {
   129  			return decoderOfType(ctx, PtrElem((*int)(nil)))
   130  		}
   131  		if strconv.IntSize == 32 {
   132  			return &int32Codec{}
   133  		}
   134  		return &int64Codec{}
   135  	case reflect.Int8:
   136  		if typeName != "int8" {
   137  			return decoderOfType(ctx, PtrElem((*int8)(nil)))
   138  		}
   139  		return &int8Codec{}
   140  	case reflect.Int16:
   141  		if typeName != "int16" {
   142  			return decoderOfType(ctx, PtrElem((*int16)(nil)))
   143  		}
   144  		return &int16Codec{}
   145  	case reflect.Int32:
   146  		if typeName != "int32" {
   147  			return decoderOfType(ctx, PtrElem((*int32)(nil)))
   148  		}
   149  		return &int32Codec{}
   150  	case reflect.Int64:
   151  		if typeName != "int64" {
   152  			return decoderOfType(ctx, PtrElem((*int64)(nil)))
   153  		}
   154  		if ctx.int64AsString {
   155  			return &stringModeNumberCompatibleDecoder{&int64Codec{}}
   156  		}
   157  		return &int64Codec{}
   158  	case reflect.Uint:
   159  		if typeName != "uint" {
   160  			return decoderOfType(ctx, PtrElem((*uint)(nil)))
   161  		}
   162  		if strconv.IntSize == 32 {
   163  			return &uint32Codec{}
   164  		}
   165  		return &uint64Codec{}
   166  	case reflect.Uint8:
   167  		if typeName != "uint8" {
   168  			return decoderOfType(ctx, PtrElem((*uint8)(nil)))
   169  		}
   170  		return &uint8Codec{}
   171  	case reflect.Uint16:
   172  		if typeName != "uint16" {
   173  			return decoderOfType(ctx, PtrElem((*uint16)(nil)))
   174  		}
   175  		return &uint16Codec{}
   176  	case reflect.Uint32:
   177  		if typeName != "uint32" {
   178  			return decoderOfType(ctx, PtrElem((*uint32)(nil)))
   179  		}
   180  		return &uint32Codec{}
   181  	case reflect.Uintptr:
   182  		if typeName != "uintptr" {
   183  			return decoderOfType(ctx, PtrElem((*uintptr)(nil)))
   184  		}
   185  		if ptrSize == 32 {
   186  			return &uint32Codec{}
   187  		}
   188  		return &uint64Codec{}
   189  	case reflect.Uint64:
   190  		if typeName != "uint64" {
   191  			return decoderOfType(ctx, PtrElem((*uint64)(nil)))
   192  		}
   193  		if ctx.int64AsString {
   194  			return &stringModeNumberCompatibleDecoder{&int64Codec{}}
   195  		}
   196  		return &uint64Codec{}
   197  	case reflect.Float32:
   198  		if typeName != "float32" {
   199  			return decoderOfType(ctx, PtrElem((*float32)(nil)))
   200  		}
   201  		return &float32Codec{}
   202  	case reflect.Float64:
   203  		if typeName != "float64" {
   204  			return decoderOfType(ctx, PtrElem((*float64)(nil)))
   205  		}
   206  		return &float64Codec{}
   207  	case reflect.Bool:
   208  		if typeName != "bool" {
   209  			return decoderOfType(ctx, PtrElem((*bool)(nil)))
   210  		}
   211  		return &boolCodec{}
   212  	}
   213  	return nil
   214  }
   215  
   216  type stringCodec struct{}
   217  
   218  func (c *stringCodec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) {
   219  	*((*string)(ptr)) = iter.ReadString()
   220  }
   221  
   222  func (c *stringCodec) Encode(ctx context.Context, ptr unsafe.Pointer, stream *Stream) {
   223  	s := *((*string)(ptr))
   224  
   225  	if writeRawBytesIfClearQuotes(ctx, s, stream) {
   226  		return
   227  	}
   228  
   229  	stream.WriteString(s)
   230  }
   231  
   232  func (c *stringCodec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool {
   233  	return *((*string)(p)) == ""
   234  }
   235  
   236  type int8Codec struct{}
   237  
   238  func (c *int8Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) {
   239  	if !iter.ReadNil() {
   240  		*((*int8)(ptr)) = iter.ReadInt8()
   241  	}
   242  }
   243  
   244  func (c *int8Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) {
   245  	stream.WriteInt8(*((*int8)(ptr)))
   246  }
   247  
   248  func (c *int8Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool {
   249  	return *((*int8)(p)) == 0
   250  }
   251  
   252  type int16Codec struct{}
   253  
   254  func (c *int16Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) {
   255  	if !iter.ReadNil() {
   256  		*((*int16)(ptr)) = iter.ReadInt16()
   257  	}
   258  }
   259  
   260  func (c *int16Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) {
   261  	stream.WriteInt16(*((*int16)(ptr)))
   262  }
   263  
   264  func (c *int16Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool {
   265  	return *((*int16)(p)) == 0
   266  }
   267  
   268  type int32Codec struct{}
   269  
   270  func (c *int32Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) {
   271  	if !iter.ReadNil() {
   272  		*((*int32)(ptr)) = iter.ReadInt32()
   273  	}
   274  }
   275  
   276  func (c *int32Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) {
   277  	stream.WriteInt32(*((*int32)(ptr)))
   278  }
   279  
   280  func (c *int32Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool {
   281  	return *((*int32)(p)) == 0
   282  }
   283  
   284  type int64Codec struct{}
   285  
   286  func (c *int64Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) {
   287  	if !iter.ReadNil() {
   288  		*((*int64)(ptr)) = iter.ReadInt64()
   289  	}
   290  }
   291  
   292  func (c *int64Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) {
   293  	stream.WriteInt64(*((*int64)(ptr)))
   294  }
   295  
   296  func (c *int64Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool {
   297  	return *((*int64)(p)) == 0
   298  }
   299  
   300  type uint8Codec struct{}
   301  
   302  func (c *uint8Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) {
   303  	if !iter.ReadNil() {
   304  		*((*uint8)(ptr)) = iter.ReadUint8()
   305  	}
   306  }
   307  
   308  func (c *uint8Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) {
   309  	stream.WriteUint8(*((*uint8)(ptr)))
   310  }
   311  
   312  func (c *uint8Codec) IsEmpty(_ context.Context, ptr unsafe.Pointer, _ bool) bool {
   313  	return *((*uint8)(ptr)) == 0
   314  }
   315  
   316  type uint16Codec struct{}
   317  
   318  func (c *uint16Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) {
   319  	if !iter.ReadNil() {
   320  		*((*uint16)(ptr)) = iter.ReadUint16()
   321  	}
   322  }
   323  
   324  func (c *uint16Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) {
   325  	stream.WriteUint16(*((*uint16)(ptr)))
   326  }
   327  
   328  func (c *uint16Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool {
   329  	return *((*uint16)(p)) == 0
   330  }
   331  
   332  type uint32Codec struct{}
   333  
   334  func (c *uint32Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) {
   335  	if !iter.ReadNil() {
   336  		*((*uint32)(ptr)) = iter.ReadUint32()
   337  	}
   338  }
   339  
   340  func (c *uint32Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) {
   341  	stream.WriteUint32(*((*uint32)(ptr)))
   342  }
   343  
   344  func (c *uint32Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool {
   345  	return *((*uint32)(p)) == 0
   346  }
   347  
   348  type uint64Codec struct{}
   349  
   350  func (c *uint64Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) {
   351  	if !iter.ReadNil() {
   352  		*((*uint64)(ptr)) = iter.ReadUint64()
   353  	}
   354  }
   355  
   356  func (c *uint64Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) {
   357  	stream.WriteUint64(*((*uint64)(ptr)))
   358  }
   359  
   360  func (c *uint64Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool {
   361  	return *((*uint64)(p)) == 0
   362  }
   363  
   364  type float32Codec struct{}
   365  
   366  func (c *float32Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) {
   367  	if !iter.ReadNil() {
   368  		*((*float32)(ptr)) = iter.ReadFloat32()
   369  	}
   370  }
   371  
   372  func (c *float32Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) {
   373  	stream.WriteFloat32(*((*float32)(ptr)))
   374  }
   375  
   376  func (c *float32Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool {
   377  	return *((*float32)(p)) == 0
   378  }
   379  
   380  type float64Codec struct{}
   381  
   382  func (c *float64Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) {
   383  	if !iter.ReadNil() {
   384  		*((*float64)(ptr)) = iter.ReadFloat64()
   385  	}
   386  }
   387  
   388  func (c *float64Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) {
   389  	stream.WriteFloat64(*((*float64)(ptr)))
   390  }
   391  
   392  func (c *float64Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool {
   393  	return *((*float64)(p)) == 0
   394  }
   395  
   396  type boolCodec struct{}
   397  
   398  func (c *boolCodec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) {
   399  	if !iter.ReadNil() {
   400  		*((*bool)(ptr)) = iter.ReadBool()
   401  	}
   402  }
   403  
   404  func (c *boolCodec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) {
   405  	stream.WriteBool(*((*bool)(ptr)))
   406  }
   407  
   408  func (c *boolCodec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool {
   409  	return !(*((*bool)(p)))
   410  }
   411  
   412  type base64Codec struct {
   413  	sliceType    *reflect2.UnsafeSliceType
   414  	sliceDecoder ValDecoder
   415  }
   416  
   417  func (c *base64Codec) Decode(ctx context.Context, ptr unsafe.Pointer, iter *Iterator) {
   418  	if iter.ReadNil() {
   419  		c.sliceType.UnsafeSetNil(ptr)
   420  		return
   421  	}
   422  	switch iter.WhatIsNext() {
   423  	case StringValue:
   424  		src := iter.ReadString()
   425  		dst, err := base64.StdEncoding.DecodeString(src)
   426  		if err != nil {
   427  			iter.ReportError("decode base64", err.Error())
   428  		} else {
   429  			c.sliceType.UnsafeSet(ptr, unsafe.Pointer(&dst))
   430  		}
   431  	case ArrayValue:
   432  		c.sliceDecoder.Decode(ctx, ptr, iter)
   433  	default:
   434  		iter.ReportError("base64Codec", "invalid input")
   435  	}
   436  }
   437  
   438  func (c *base64Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) {
   439  	if c.sliceType.UnsafeIsNil(ptr) {
   440  		stream.WriteNil()
   441  		return
   442  	}
   443  	src := *((*[]byte)(ptr))
   444  	encoding := base64.StdEncoding
   445  	stream.writeByte('"')
   446  	if len(src) > 0 {
   447  		size := encoding.EncodedLen(len(src))
   448  		buf := make([]byte, size)
   449  		encoding.Encode(buf, src)
   450  		stream.buf = append(stream.buf, buf...)
   451  	}
   452  	stream.writeByte('"')
   453  }
   454  
   455  func (c *base64Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool {
   456  	return len(*((*[]byte)(p))) == 0
   457  }