From a0950f4c29b0b72fc1df867dcfb4d4ad86ec3ca4 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 1 Aug 2022 21:55:34 -0600 Subject: wip --- lib/lowmemjson/decode.go | 50 +++++++++++++++++++++++++++++++++--------------- 1 file 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)}) } } -- cgit v1.2.3-2-g168b