tape: Split DecodeAny into two funcs, one autocreates skeleton value

This commit is contained in:
Sasha Koshka 2025-09-08 09:42:39 -04:00
parent 45dfdb255e
commit b7bdaba694
2 changed files with 15 additions and 5 deletions

View File

@ -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.

View File

@ -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
}