summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-08-01 21:55:34 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-08-01 21:55:34 -0600
commita0950f4c29b0b72fc1df867dcfb4d4ad86ec3ca4 (patch)
tree3d61781fd7b158ba0bbf991f2af7dec2ecc9a8be
parent8ac23f9c53d4dd6878e2f5814ee7ffd48524f67c (diff)
wip
-rw-r--r--lib/lowmemjson/decode.go50
1 files changed, 35 insertions, 15 deletions
diff --git a/lib/lowmemjson/decode.go b/lib/lowmemjson/decode.go
index c2e7ab1..aeca291 100644
--- a/lib/lowmemjson/decode.go
+++ b/lib/lowmemjson/decode.go
@@ -108,7 +108,6 @@ func _Decode(r io.RuneScanner, ptr any, cfg decodeConfig) (err error) {
var (
rawMessagePtrType = reflect.TypeOf((*json.RawMessage)(nil))
- anyType = reflect.TypeOf((*any)(nil)).Elem()
decoderType = reflect.TypeOf((*Decoder)(nil)).Elem()
jsonUnmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
@@ -200,16 +199,27 @@ func decode(r io.RuneScanner, val reflect.Value, cfg decodeConfig) {
val.SetString(buf.String())
}
case reflect.Interface:
- if val.IsNil() {
- if typ == anyType {
- val.Set(reflect.ValueOf(decodeAny(r, cfg)))
+ if typ.NumMethod() > 0 {
+ panic(decodeError{&json.UnsupportedTypeError{
+ Type: typ,
+ }})
+ }
+ switch peekRune(r) {
+ case 'n':
+ if !val.IsNil() && val.Elem().Kind() == reflect.Pointer && val.Elem().Elem().Kind() == reflect.Pointer {
+ // XXX: I can't justify this case, other than "it's what encoding/json does, but
+ // I don't understand their rationale".
+ decode(r, val.Elem(), cfg)
} else {
- panic(decodeError{&json.UnsupportedTypeError{
- Type: typ,
- }})
+ decodeNull(r)
+ val.Set(reflect.Zero(typ))
+ }
+ default:
+ if !val.IsNil() && val.Elem().Kind() == reflect.Pointer {
+ decode(r, val.Elem(), cfg)
+ } else {
+ val.Set(reflect.ValueOf(decodeAny(r, cfg)))
}
- } else {
- decode(r, val.Elem(), cfg)
}
case reflect.Struct:
index := indexStruct(typ)
@@ -244,8 +254,8 @@ func decode(r io.RuneScanner, val reflect.Value, cfg decodeConfig) {
case 'n':
decodeNull(r)
switch fVal.Kind() {
- // I can't justify this list, other than that it's what encoding/json
- // does. I don't understand their rationale.
+ // XXX: I can't justify this list, other than "it's what encoding/json
+ // does, but I don't understand their rationale".
case reflect.Interface, reflect.Pointer, reflect.Map, reflect.Slice:
fVal.Set(reflect.Zero(fVal.Type()))
}
@@ -341,10 +351,20 @@ func decode(r io.RuneScanner, val reflect.Value, cfg decodeConfig) {
i++
})
case reflect.Pointer:
- if val.IsNil() {
- val.Set(reflect.New(typ.Elem()))
+ switch peekRune(r) {
+ case 'n':
+ decodeNull(r)
+ for val.IsNil() && typ.Elem().Kind() == reflect.Pointer {
+ val.Set(reflect.New(typ.Elem()))
+ val = val.Elem()
+ }
+ val.Elem().Set(reflect.Zero(val.Type().Elem()))
+ default:
+ if val.IsNil() {
+ val.Set(reflect.New(typ.Elem()))
+ }
+ decode(r, val.Elem(), cfg)
}
- decode(r, val.Elem(), cfg)
default:
panic(decodeError{&json.UnsupportedTypeError{
Type: typ,
@@ -409,7 +429,7 @@ func scanNumber(r io.RuneScanner, out io.Writer) {
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
scan(r, out)
default:
- panic(decodeError{fmt.Errorf("expected a nubmer but got %c", c)})
+ panic(decodeError{fmt.Errorf("expected a number but got %c", c)})
}
}