go-json/internal/decoder/bytes.go

177 lines
4.0 KiB
Go
Raw Permalink Normal View History

2021-06-03 12:49:01 +03:00
package decoder
2020-11-21 20:47:18 +03:00
import (
"encoding/base64"
"unsafe"
2021-06-03 12:49:01 +03:00
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
2020-11-21 20:47:18 +03:00
)
type bytesDecoder struct {
2021-06-03 12:49:01 +03:00
typ *runtime.Type
2021-06-03 13:10:17 +03:00
sliceDecoder Decoder
2020-12-24 08:26:18 +03:00
structName string
fieldName string
}
2020-11-21 20:47:18 +03:00
2021-06-03 13:10:17 +03:00
func byteUnmarshalerSliceDecoder(typ *runtime.Type, structName string, fieldName string) Decoder {
var unmarshalDecoder Decoder
2020-12-24 08:26:18 +03:00
switch {
2021-06-03 12:49:01 +03:00
case runtime.PtrTo(typ).Implements(unmarshalJSONType):
unmarshalDecoder = newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName)
case runtime.PtrTo(typ).Implements(unmarshalTextType):
unmarshalDecoder = newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName)
2020-12-24 08:26:18 +03:00
}
if unmarshalDecoder == nil {
return nil
}
return newSliceDecoder(unmarshalDecoder, typ, 1, structName, fieldName)
}
2021-06-03 12:49:01 +03:00
func newBytesDecoder(typ *runtime.Type, structName string, fieldName string) *bytesDecoder {
2020-12-24 08:26:18 +03:00
return &bytesDecoder{
typ: typ,
sliceDecoder: byteUnmarshalerSliceDecoder(typ, structName, fieldName),
structName: structName,
fieldName: fieldName,
}
2020-11-21 20:47:18 +03:00
}
2021-06-03 12:49:01 +03:00
func (d *bytesDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.decodeStreamBinary(s, depth, p)
2020-11-21 20:47:18 +03:00
if err != nil {
return err
}
2020-12-05 16:27:33 +03:00
if bytes == nil {
s.reset()
return nil
}
2020-11-21 20:47:18 +03:00
decodedLen := base64.StdEncoding.DecodedLen(len(bytes))
buf := make([]byte, decodedLen)
if _, err := base64.StdEncoding.Decode(buf, bytes); err != nil {
return err
}
*(*[]byte)(p) = buf
2020-12-05 16:27:33 +03:00
s.reset()
2020-11-21 20:47:18 +03:00
return nil
}
2021-06-04 19:08:27 +03:00
func (d *bytesDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.decodeBinary(ctx, cursor, depth, p)
2020-11-21 20:47:18 +03:00
if err != nil {
return 0, err
}
2020-12-24 08:26:18 +03:00
if bytes == nil {
return c, nil
}
2020-11-21 20:47:18 +03:00
cursor = c
decodedLen := base64.StdEncoding.DecodedLen(len(bytes))
b := make([]byte, decodedLen)
2020-12-24 13:36:49 +03:00
n, err := base64.StdEncoding.Decode(b, bytes)
if err != nil {
2020-11-21 20:47:18 +03:00
return 0, err
}
2020-12-24 13:36:49 +03:00
*(*[]byte)(p) = b[:n]
2020-11-21 20:47:18 +03:00
return cursor, nil
}
2021-06-03 12:49:01 +03:00
func binaryBytes(s *Stream) ([]byte, error) {
2020-11-21 20:47:18 +03:00
s.cursor++
start := s.cursor
for {
switch s.char() {
case '"':
literal := s.buf[start:s.cursor]
s.cursor++
return literal, nil
case nul:
if s.read() {
continue
}
goto ERROR
}
s.cursor++
}
ERROR:
2021-06-03 12:49:01 +03:00
return nil, errors.ErrUnexpectedEndOfJSON("[]byte", s.totalOffset())
2020-11-21 20:47:18 +03:00
}
2021-06-03 12:49:01 +03:00
func (d *bytesDecoder) decodeStreamBinary(s *Stream, depth int64, p unsafe.Pointer) ([]byte, error) {
2020-11-21 20:47:18 +03:00
for {
switch s.char() {
case ' ', '\n', '\t', '\r':
s.cursor++
continue
case '"':
return binaryBytes(s)
case 'n':
if err := nullBytes(s); err != nil {
return nil, err
}
2020-12-05 16:27:33 +03:00
return nil, nil
2020-12-24 08:26:18 +03:00
case '[':
if d.sliceDecoder == nil {
2021-06-03 12:49:01 +03:00
return nil, &errors.UnmarshalTypeError{
Type: runtime.RType2Type(d.typ),
2020-12-24 08:26:18 +03:00
Offset: s.totalOffset(),
}
}
2021-06-03 12:49:01 +03:00
if err := d.sliceDecoder.DecodeStream(s, depth, p); err != nil {
2020-12-24 08:26:18 +03:00
return nil, err
}
return nil, nil
2020-11-21 20:47:18 +03:00
case nul:
if s.read() {
continue
}
}
break
}
2021-06-03 12:49:01 +03:00
return nil, errors.ErrNotAtBeginningOfValue(s.totalOffset())
2020-11-21 20:47:18 +03:00
}
2021-06-04 19:08:27 +03:00
func (d *bytesDecoder) decodeBinary(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) ([]byte, int64, error) {
buf := ctx.Buf
2020-11-21 20:47:18 +03:00
for {
switch buf[cursor] {
case ' ', '\n', '\t', '\r':
cursor++
case '"':
cursor++
start := cursor
for {
switch buf[cursor] {
case '"':
literal := buf[start:cursor]
cursor++
return literal, cursor, nil
case nul:
2021-06-03 12:49:01 +03:00
return nil, 0, errors.ErrUnexpectedEndOfJSON("[]byte", cursor)
2020-11-21 20:47:18 +03:00
}
cursor++
}
2020-12-24 08:26:18 +03:00
case '[':
if d.sliceDecoder == nil {
2021-06-03 12:49:01 +03:00
return nil, 0, &errors.UnmarshalTypeError{
Type: runtime.RType2Type(d.typ),
2020-12-24 08:26:18 +03:00
Offset: cursor,
}
}
2021-06-04 19:08:27 +03:00
c, err := d.sliceDecoder.Decode(ctx, cursor, depth, p)
2020-12-24 08:26:18 +03:00
if err != nil {
return nil, 0, err
}
return nil, c, nil
2020-11-21 20:47:18 +03:00
case 'n':
if err := validateNull(buf, cursor); err != nil {
return nil, 0, err
2020-11-21 20:47:18 +03:00
}
cursor += 4
return nil, cursor, nil
2020-11-21 20:47:18 +03:00
default:
2021-06-03 12:49:01 +03:00
return nil, 0, errors.ErrNotAtBeginningOfValue(cursor)
2020-11-21 20:47:18 +03:00
}
}
}