github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/val_encoder.go (about) 1 package jzon 2 3 import ( 4 "encoding" 5 "encoding/json" 6 "reflect" 7 "strconv" 8 "unsafe" 9 ) 10 11 var ( 12 globalValEncoders = map[rtype]ValEncoder{} 13 encoderKindMap = [numKinds]rtype{} 14 kindEncoders = [numKinds]ValEncoder{} 15 keyEncoders = [numKinds]keyEncoder{} 16 ) 17 18 func createGlobalValEncoder(ptr interface{}, enc ValEncoder) { 19 typ := reflect.TypeOf(ptr).Elem() 20 rType := rtypeOfType(typ) 21 if !ifaceIndir(rType) { 22 panic("not supported") 23 } 24 globalValEncoders[rType] = enc 25 } 26 27 func mapEncoderKind(ptr interface{}, enc ValEncoder) { 28 elem := reflect.TypeOf(ptr).Elem() 29 kind := elem.Kind() 30 elemRType := rtypeOfType(elem) 31 if !ifaceIndir(elemRType) { 32 panic("not supported") 33 } 34 encoderKindMap[kind] = elemRType 35 kindEncoders[kind] = enc 36 } 37 38 func mapKeyEncoder(ptr interface{}, enc keyEncoder) { 39 ptrType := reflect.TypeOf(ptr) 40 kind := ptrType.Elem().Kind() 41 keyEncoders[kind] = enc 42 } 43 44 func init() { 45 // standard json library types 46 createGlobalValEncoder((*json.Number)(nil), (*jsonNumberEncoder)(nil)) 47 createGlobalValEncoder((*json.RawMessage)(nil), (*jsonRawMessageEncoder)(nil)) 48 createGlobalValEncoder((*json.Marshaler)(nil), (*dynamicJSONMarshalerEncoder)(nil)) 49 createGlobalValEncoder((*encoding.TextMarshaler)(nil), (*dynamicTextMarshalerEncoder)(nil)) 50 51 // kind mapping 52 mapEncoderKind((*bool)(nil), (*boolEncoder)(nil)) 53 mapEncoderKind((*string)(nil), (*stringEncoder)(nil)) 54 if strconv.IntSize == 32 { 55 mapEncoderKind((*int)(nil), (*int32Encoder)(nil)) 56 mapEncoderKind((*uint)(nil), (*uint32Encoder)(nil)) 57 } else { 58 mapEncoderKind((*int)(nil), (*int64Encoder)(nil)) 59 mapEncoderKind((*uint)(nil), (*uint64Encoder)(nil)) 60 } 61 if unsafe.Sizeof(uintptr(0)) == 4 { 62 mapEncoderKind((*uintptr)(nil), (*uint32Encoder)(nil)) 63 } else { 64 mapEncoderKind((*uintptr)(nil), (*uint64Encoder)(nil)) 65 } 66 mapEncoderKind((*int8)(nil), (*int8Encoder)(nil)) 67 mapEncoderKind((*int16)(nil), (*int16Encoder)(nil)) 68 mapEncoderKind((*int32)(nil), (*int32Encoder)(nil)) 69 mapEncoderKind((*int64)(nil), (*int64Encoder)(nil)) 70 mapEncoderKind((*uint8)(nil), (*uint8Encoder)(nil)) 71 mapEncoderKind((*uint16)(nil), (*uint16Encoder)(nil)) 72 mapEncoderKind((*uint32)(nil), (*uint32Encoder)(nil)) 73 mapEncoderKind((*uint64)(nil), (*uint64Encoder)(nil)) 74 mapEncoderKind((*float32)(nil), (*float32Encoder)(nil)) 75 mapEncoderKind((*float64)(nil), (*float64Encoder)(nil)) 76 77 // object key encoders 78 mapKeyEncoder((*string)(nil), (*stringKeyEncoder)(nil)) 79 if strconv.IntSize == 32 { 80 mapKeyEncoder((*int)(nil), (*int32KeyEncoder)(nil)) 81 mapKeyEncoder((*uint)(nil), (*uint32KeyEncoder)(nil)) 82 } else { 83 mapKeyEncoder((*int)(nil), (*int64KeyEncoder)(nil)) 84 mapKeyEncoder((*uint)(nil), (*uint64KeyEncoder)(nil)) 85 } 86 mapKeyEncoder((*int8)(nil), (*int8KeyEncoder)(nil)) 87 mapKeyEncoder((*int16)(nil), (*int16KeyEncoder)(nil)) 88 mapKeyEncoder((*int32)(nil), (*int32KeyEncoder)(nil)) 89 mapKeyEncoder((*int64)(nil), (*int64KeyEncoder)(nil)) 90 mapKeyEncoder((*uint8)(nil), (*uint8KeyEncoder)(nil)) 91 mapKeyEncoder((*uint16)(nil), (*uint16KeyEncoder)(nil)) 92 mapKeyEncoder((*uint32)(nil), (*uint32KeyEncoder)(nil)) 93 mapKeyEncoder((*uint64)(nil), (*uint64KeyEncoder)(nil)) 94 if unsafe.Sizeof(uintptr(0)) == 4 { 95 mapKeyEncoder((*uintptr)(nil), (*uint32KeyEncoder)(nil)) 96 } else { 97 mapKeyEncoder((*uintptr)(nil), (*uint64KeyEncoder)(nil)) 98 } 99 } 100 101 // EncOpts is the context related encoding option of the object 102 type EncOpts struct { 103 Quoted bool 104 } 105 106 func (opts *EncOpts) noescape() *EncOpts { 107 return (*EncOpts)(noescape(unsafe.Pointer(opts))) 108 } 109 110 type keyEncoder interface { 111 Encode(ptr unsafe.Pointer, s *Streamer) 112 } 113 114 // ValEncoder is the interface to be implemented for custom encoder 115 type ValEncoder interface { 116 IsEmpty(ptr unsafe.Pointer) bool 117 118 Encode(ptr unsafe.Pointer, s *Streamer, opts *EncOpts) 119 } 120 121 type notSupportedEncoder string 122 123 func (enc notSupportedEncoder) IsEmpty(ptr unsafe.Pointer) bool { 124 return false 125 } 126 127 func (enc notSupportedEncoder) Encode(ptr unsafe.Pointer, s *Streamer, opts *EncOpts) { 128 if s.Error != nil { 129 return 130 } 131 s.Error = TypeNotSupportedError(enc) 132 }