github.com/night-codes/go-json@v0.9.15/decode.go (about) 1 package json 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "reflect" 8 "unsafe" 9 10 "github.com/night-codes/go-json/internal/decoder" 11 "github.com/night-codes/go-json/internal/errors" 12 "github.com/night-codes/go-json/internal/runtime" 13 ) 14 15 type Decoder struct { 16 s *decoder.Stream 17 } 18 19 const ( 20 nul = '\000' 21 ) 22 23 type emptyInterface struct { 24 typ *runtime.Type 25 ptr unsafe.Pointer 26 } 27 28 func unmarshal(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error { 29 src := make([]byte, len(data)+1) // append nul byte to the end 30 copy(src, data) 31 32 header := (*emptyInterface)(unsafe.Pointer(&v)) 33 34 if err := validateType(header.typ, uintptr(header.ptr)); err != nil { 35 return err 36 } 37 dec, err := decoder.CompileToGetDecoder(header.typ) 38 if err != nil { 39 return err 40 } 41 ctx := decoder.TakeRuntimeContext() 42 ctx.Buf = src 43 ctx.Option.Flags = 0 44 for _, optFunc := range optFuncs { 45 optFunc(ctx.Option) 46 } 47 cursor, err := dec.Decode(ctx, 0, 0, header.ptr) 48 if err != nil { 49 decoder.ReleaseRuntimeContext(ctx) 50 return err 51 } 52 decoder.ReleaseRuntimeContext(ctx) 53 return validateEndBuf(src, cursor) 54 } 55 56 func unmarshalContext(ctx context.Context, data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error { 57 src := make([]byte, len(data)+1) // append nul byte to the end 58 copy(src, data) 59 60 header := (*emptyInterface)(unsafe.Pointer(&v)) 61 62 if err := validateType(header.typ, uintptr(header.ptr)); err != nil { 63 return err 64 } 65 dec, err := decoder.CompileToGetDecoder(header.typ) 66 if err != nil { 67 return err 68 } 69 rctx := decoder.TakeRuntimeContext() 70 rctx.Buf = src 71 rctx.Option.Flags = 0 72 rctx.Option.Flags |= decoder.ContextOption 73 rctx.Option.Context = ctx 74 for _, optFunc := range optFuncs { 75 optFunc(rctx.Option) 76 } 77 cursor, err := dec.Decode(rctx, 0, 0, header.ptr) 78 if err != nil { 79 decoder.ReleaseRuntimeContext(rctx) 80 return err 81 } 82 decoder.ReleaseRuntimeContext(rctx) 83 return validateEndBuf(src, cursor) 84 } 85 86 func unmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error { 87 src := make([]byte, len(data)+1) // append nul byte to the end 88 copy(src, data) 89 90 header := (*emptyInterface)(unsafe.Pointer(&v)) 91 92 if err := validateType(header.typ, uintptr(header.ptr)); err != nil { 93 return err 94 } 95 dec, err := decoder.CompileToGetDecoder(header.typ) 96 if err != nil { 97 return err 98 } 99 100 ctx := decoder.TakeRuntimeContext() 101 ctx.Buf = src 102 ctx.Option.Flags = 0 103 for _, optFunc := range optFuncs { 104 optFunc(ctx.Option) 105 } 106 cursor, err := dec.Decode(ctx, 0, 0, noescape(header.ptr)) 107 if err != nil { 108 decoder.ReleaseRuntimeContext(ctx) 109 return err 110 } 111 decoder.ReleaseRuntimeContext(ctx) 112 return validateEndBuf(src, cursor) 113 } 114 115 func validateEndBuf(src []byte, cursor int64) error { 116 for { 117 switch src[cursor] { 118 case ' ', '\t', '\n', '\r': 119 cursor++ 120 continue 121 case nul: 122 return nil 123 } 124 return errors.ErrSyntax( 125 fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]), 126 cursor+1, 127 ) 128 } 129 } 130 131 //nolint:staticcheck 132 //go:nosplit 133 func noescape(p unsafe.Pointer) unsafe.Pointer { 134 x := uintptr(p) 135 return unsafe.Pointer(x ^ 0) 136 } 137 138 func validateType(typ *runtime.Type, p uintptr) error { 139 if typ == nil || typ.Kind() != reflect.Ptr || p == 0 { 140 return &InvalidUnmarshalError{Type: runtime.RType2Type(typ)} 141 } 142 return nil 143 } 144 145 // NewDecoder returns a new decoder that reads from r. 146 // 147 // The decoder introduces its own buffering and may 148 // read data from r beyond the JSON values requested. 149 func NewDecoder(r io.Reader) *Decoder { 150 s := decoder.NewStream(r) 151 return &Decoder{ 152 s: s, 153 } 154 } 155 156 // Buffered returns a reader of the data remaining in the Decoder's 157 // buffer. The reader is valid until the next call to Decode. 158 func (d *Decoder) Buffered() io.Reader { 159 return d.s.Buffered() 160 } 161 162 // Decode reads the next JSON-encoded value from its 163 // input and stores it in the value pointed to by v. 164 // 165 // See the documentation for Unmarshal for details about 166 // the conversion of JSON into a Go value. 167 func (d *Decoder) Decode(v interface{}) error { 168 return d.DecodeWithOption(v) 169 } 170 171 // DecodeContext reads the next JSON-encoded value from its 172 // input and stores it in the value pointed to by v with context.Context. 173 func (d *Decoder) DecodeContext(ctx context.Context, v interface{}) error { 174 d.s.Option.Flags |= decoder.ContextOption 175 d.s.Option.Context = ctx 176 return d.DecodeWithOption(v) 177 } 178 179 func (d *Decoder) DecodeWithOption(v interface{}, optFuncs ...DecodeOptionFunc) error { 180 header := (*emptyInterface)(unsafe.Pointer(&v)) 181 typ := header.typ 182 ptr := uintptr(header.ptr) 183 typeptr := uintptr(unsafe.Pointer(typ)) 184 // noescape trick for header.typ ( reflect.*rtype ) 185 copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr)) 186 187 if err := validateType(copiedType, ptr); err != nil { 188 return err 189 } 190 191 dec, err := decoder.CompileToGetDecoder(typ) 192 if err != nil { 193 return err 194 } 195 if err := d.s.PrepareForDecode(); err != nil { 196 return err 197 } 198 s := d.s 199 for _, optFunc := range optFuncs { 200 optFunc(s.Option) 201 } 202 if err := dec.DecodeStream(s, 0, header.ptr); err != nil { 203 return err 204 } 205 s.Reset() 206 return nil 207 } 208 209 func (d *Decoder) More() bool { 210 return d.s.More() 211 } 212 213 func (d *Decoder) Token() (Token, error) { 214 return d.s.Token() 215 } 216 217 // DisallowUnknownFields causes the Decoder to return an error when the destination 218 // is a struct and the input contains object keys which do not match any 219 // non-ignored, exported fields in the destination. 220 func (d *Decoder) DisallowUnknownFields() { 221 d.s.DisallowUnknownFields = true 222 } 223 224 func (d *Decoder) InputOffset() int64 { 225 return d.s.TotalOffset() 226 } 227 228 // UseNumber causes the Decoder to unmarshal a number into an interface{} as a 229 // Number instead of as a float64. 230 func (d *Decoder) UseNumber() { 231 d.s.UseNumber = true 232 }