From 54bbd1e59317a6e9658eb8098657078cc8e81979 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 14 Aug 2022 20:52:06 -0600 Subject: wip: Reduce test differences [ci-skip] - Handle UTF-16 surrogate pairs - Handle cycles in values - Handle cycles in types - Better errors - Handle case-folding of struct field names - Allow []byteTypeWithMethods - Fix struct field-order - Fix handling of interfaces storing pointers - Enforce a maximum decode depth - Validate struct tags --- compat/json/compat.go | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) (limited to 'compat/json/compat.go') diff --git a/compat/json/compat.go b/compat/json/compat.go index 78a9d5f..b26914b 100644 --- a/compat/json/compat.go +++ b/compat/json/compat.go @@ -8,7 +8,9 @@ import ( "bufio" "bytes" "encoding/json" + "errors" "io" + "strconv" "git.lukeshu.com/go/lowmemjson" ) @@ -19,7 +21,7 @@ type ( RawMessage = json.RawMessage // low-level decode errors - SyntaxError = lowmemjson.SyntaxError + //SyntaxError = lowmemjson.DecodeSyntaxError // expose a field UnmarshalFieldError = json.UnmarshalFieldError UnmarshalTypeError = json.UnmarshalTypeError // lowmemjson.DecodeTypeError @@ -28,7 +30,7 @@ type ( // marshal errors InvalidUTF8Error = json.InvalidUTF8Error - MarshalerError = json.MarshalerError + MarshalerError = lowmemjson.EncodeMethodError // expose a field UnsupportedTypeError = json.UnsupportedTypeError UnsupportedValueError = json.UnsupportedValueError ) @@ -92,7 +94,7 @@ func Valid(data []byte) bool { } func Unmarshal(data []byte, ptr any) error { - return lowmemjson.Decode(bytes.NewReader(data), ptr) + return NewDecoder(bytes.NewReader(data)).Decode(ptr) } ///////////////////////////////////////////////////////////////////// @@ -113,6 +115,43 @@ func NewDecoder(r io.Reader) *Decoder { } } +func (dec *Decoder) Decode(ptr any) error { + err := dec.Decoder.Decode(ptr) + if derr, ok := err.(*lowmemjson.DecodeError); ok { + switch terr := derr.Err.(type) { + case *lowmemjson.DecodeSyntaxError: + err = &SyntaxError{ + msg: terr.Err.Error(), + Offset: terr.Offset, + } + case *lowmemjson.DecodeTypeError: + if typeErr, ok := terr.Err.(*json.UnmarshalTypeError); ok { + err = &UnmarshalTypeError{ + Value: typeErr.Value, + Type: typeErr.Type, + Offset: typeErr.Offset, + Struct: derr.FieldParent, + Field: derr.FieldName, + } + } else if _, isArgErr := terr.Err.(*lowmemjson.DecodeArgumentError); terr.Err != nil && + !isArgErr && + !errors.Is(terr.Err, strconv.ErrSyntax) && + !errors.Is(terr.Err, strconv.ErrRange) { + err = terr.Err + } else { + err = &UnmarshalTypeError{ + Value: terr.JSONType, + Type: terr.GoType, + Offset: terr.Offset, + Struct: derr.FieldParent, + Field: derr.FieldName, + } + } + } + } + return err +} + func (dec *Decoder) Buffered() io.Reader { dat, _ := dec.buf.Peek(dec.buf.Buffered()) return bytes.NewReader(dat) -- cgit v1.2.3-2-g168b