message-size-increase #3
145
tape/dynamic.go
145
tape/dynamic.go
@ -14,6 +14,14 @@ import "reflect"
|
|||||||
var dummyMap map[uint16] any
|
var dummyMap map[uint16] any
|
||||||
var dummyBuffer []byte
|
var dummyBuffer []byte
|
||||||
|
|
||||||
|
type errCantAssign string
|
||||||
|
func (err errCantAssign) Error() string {
|
||||||
|
return string(err)
|
||||||
|
}
|
||||||
|
func errCantAssignf(format string, v ...any) errCantAssign {
|
||||||
|
return errCantAssign(fmt.Sprintf(format, v...))
|
||||||
|
}
|
||||||
|
|
||||||
// EncodeAny encodes an "any" value. Returns an error if the underlying type is
|
// EncodeAny encodes an "any" value. Returns an error if the underlying type is
|
||||||
// unsupported. Supported types are:
|
// unsupported. Supported types are:
|
||||||
//
|
//
|
||||||
@ -83,20 +91,34 @@ type unknownSlicePlaceholder struct { }
|
|||||||
var unknownSlicePlaceholderType = reflect.TypeOf(unknownSlicePlaceholder { })
|
var unknownSlicePlaceholderType = reflect.TypeOf(unknownSlicePlaceholder { })
|
||||||
|
|
||||||
// decodeAny is internal to [DecodeAny]. It takes in an addressable
|
// decodeAny is internal to [DecodeAny]. It takes in an addressable
|
||||||
// [reflect.Value] as the destination.
|
// [reflect.Value] as the destination. If the decoded value cannot fit in the
|
||||||
|
// destination, it skims over the payload, leaves the destination empty, and
|
||||||
|
// returns without an error.
|
||||||
func decodeAny(decoder *Decoder, destination reflect.Value, tag Tag) (n int, err error) {
|
func decodeAny(decoder *Decoder, destination reflect.Value, tag Tag) (n int, err error) {
|
||||||
errWrongDestinationType := func(expected string) error {
|
n, err = decodeAnyOrError(decoder, destination, tag)
|
||||||
panic(fmt.Errorf(
|
if _, ok := err.(errCantAssign); ok {
|
||||||
// return fmt.Errorf(
|
if n > 0 { panic(fmt.Sprintf("decodeAnyOrError decoded more than it should: %d", n)) }
|
||||||
"expected %s destination, not %v",
|
nn, err := Skim(decoder, tag)
|
||||||
expected, destination))
|
n += nn; if err != nil { return n, err }
|
||||||
|
return n, nil
|
||||||
}
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeAnyOrError is internal to [decodeAny]. It takes in an addressable
|
||||||
|
// [reflect.Value] as the destination. If the decoded value cannot fit in the
|
||||||
|
// destination, it decodes nothing and returns an error of type errCantAssign,
|
||||||
|
// except for the case of a mismatched OTA element tag, wherein it will skim
|
||||||
|
// over the rest of the payload, leave the destination empty, and return without
|
||||||
|
// an error.
|
||||||
|
func decodeAnyOrError(decoder *Decoder, destination reflect.Value, tag Tag) (n int, err error) {
|
||||||
|
err = canSet(destination.Type(), tag)
|
||||||
|
if err != nil { return n, err }
|
||||||
|
|
||||||
switch tag.WithoutCN() {
|
switch tag.WithoutCN() {
|
||||||
case SI:
|
case SI:
|
||||||
// SI: (none)
|
// SI: (none)
|
||||||
err = setInt(destination, uint64(tag.CN()))
|
setInt(destination, uint64(tag.CN()))
|
||||||
if err != nil { return n, err }
|
|
||||||
case LI:
|
case LI:
|
||||||
// LI: <value: IntN>
|
// LI: <value: IntN>
|
||||||
nn, err := decodeAndSetUint(decoder, destination, tag.CN() + 1)
|
nn, err := decodeAndSetUint(decoder, destination, tag.CN() + 1)
|
||||||