From b7bdaba69418ba0e7e169f697d5d47bde6c3cd2e Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Mon, 8 Sep 2025 09:42:39 -0400 Subject: [PATCH] tape: Split DecodeAny into two funcs, one autocreates skeleton value --- tape/dynamic.go | 14 ++++++++++++-- tape/dynamic_test.go | 6 +++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/tape/dynamic.go b/tape/dynamic.go index 501ed63..abe9742 100644 --- a/tape/dynamic.go +++ b/tape/dynamic.go @@ -86,9 +86,9 @@ func EncodeAny(encoder *Encoder, value any, tag Tag) (n int, err error) { return n, fmt.Errorf("cannot encode type %T", value) } -// DecodeAny decodes data and places it into destination, which must be a +// DecodeAnyInto decodes data and places it into destination, which must be a // pointer to a supported type. See [EncodeAny] for a list of supported types. -func DecodeAny(decoder *Decoder, destination any, tag Tag) (n int, err error) { +func DecodeAnyInto(decoder *Decoder, destination any, tag Tag) (n int, err error) { reflectDestination := reflect.ValueOf(destination) if reflectDestination.Kind() != reflect.Pointer { return n, fmt.Errorf("expected pointer destination, not %v", destination) @@ -96,6 +96,16 @@ func DecodeAny(decoder *Decoder, destination any, tag Tag) (n int, err error) { return decodeAny(decoder, reflectDestination.Elem(), tag) } +// DecodeAny is like [DecodeAnyInto], but it automatically creates the +// destination from the tag and data. +func DecodeAny(decoder *Decoder, tag Tag) (value any, n int, err error) { + destination, err := skeletonValue(decoder, tag) + if err != nil { return nil, n, err } + nn, err := DecodeAnyInto(decoder, destination, tag) + n += nn; if err != nil { return nil, n, err } + return destination, n, err +} + // unknownSlicePlaceholder is inserted by skeletonValue and informs the program // that the destination for the slice needs to be generated based on the item // tag in the OTA. diff --git a/tape/dynamic_test.go b/tape/dynamic_test.go index 7e7bab7..bf3b66e 100644 --- a/tape/dynamic_test.go +++ b/tape/dynamic_test.go @@ -104,7 +104,7 @@ func TestDecodeWrongType(test *testing.T) { // integers should only assign to other integers if index > 8 { cas := func(destination any) { - n, err := DecodeAny(NewDecoder(bytes.NewBuffer(data[1:])), destination, Tag(data[0])) + n, err := DecodeAnyInto(NewDecoder(bytes.NewBuffer(data[1:])), destination, Tag(data[0])) if err != nil { test.Fatalf("error: %v | n: %d", err, n) } reflectValue := reflect.ValueOf(destination).Elem() if reflectValue.CanInt() { @@ -138,7 +138,7 @@ func TestDecodeWrongType(test *testing.T) { { var dest uint64; cas(&dest) } } arrayCase := func(destination any) { - n, err := DecodeAny(NewDecoder(bytes.NewBuffer(data[1:])), destination, Tag(data[0])) + n, err := DecodeAnyInto(NewDecoder(bytes.NewBuffer(data[1:])), destination, Tag(data[0])) if err != nil { test.Fatalf("error: %v | n: %d", err, n) } reflectDestination := reflect.ValueOf(destination) reflectValue := reflectDestination.Elem() @@ -256,7 +256,7 @@ func decAny(data []byte) (Tag, any, int, error) { destination := map[uint16] any { } tag, err := TagAny(destination) if err != nil { return 0, nil, 0, err } - n, err := DecodeAny(NewDecoder(bytes.NewBuffer(data)), &destination, tag) + n, err := DecodeAnyInto(NewDecoder(bytes.NewBuffer(data)), &destination, tag) if err != nil { return 0, nil, n, err } return tag, destination, n, nil }