tape: Assorted changes i forgor
This commit is contained in:
parent
84b96ed8f3
commit
7df18f7d26
@ -8,6 +8,17 @@ package tape
|
|||||||
|
|
||||||
// TODO: test all of these smaller functions individually
|
// TODO: test all of these smaller functions individually
|
||||||
|
|
||||||
|
// For an explanation as to why this package always treats LBA/SBA as strings,
|
||||||
|
// refer to https://go.dev/blog/strings:
|
||||||
|
//
|
||||||
|
// It’s important to state right up front that a string holds arbitrary
|
||||||
|
// bytes. It is not required to hold Unicode text, UTF-8 text, or any other
|
||||||
|
// predefined format. As far as the content of a string is concerned, it is
|
||||||
|
// exactly equivalent to a slice of bytes.
|
||||||
|
//
|
||||||
|
// Arbitrary byte slices and blobs won't be as common of a use case as text
|
||||||
|
// data, and if you need that anyway you can just cast it to a byte slice.
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "reflect"
|
import "reflect"
|
||||||
|
|
||||||
@ -142,7 +153,7 @@ func decodeAnyOrError(decoder *Decoder, destination reflect.Value, tag Tag) (n i
|
|||||||
switch tag.WithoutCN() {
|
switch tag.WithoutCN() {
|
||||||
case SI:
|
case SI:
|
||||||
// SI: (none)
|
// SI: (none)
|
||||||
setInt(destination, uint64(tag.CN()))
|
setUint(destination, uint64(tag.CN()), 1)
|
||||||
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)
|
||||||
@ -164,7 +175,7 @@ func decodeAnyOrError(decoder *Decoder, destination reflect.Value, tag Tag) (n i
|
|||||||
buffer := make([]byte, length)
|
buffer := make([]byte, length)
|
||||||
nn, err := decoder.Read(buffer)
|
nn, err := decoder.Read(buffer)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
setByteArray(destination, buffer)
|
setString(destination, string(buffer))
|
||||||
case LBA:
|
case LBA:
|
||||||
// LBA: <length: UN> <data: U8>*
|
// LBA: <length: UN> <data: U8>*
|
||||||
length, nn, err := decoder.ReadUintN(tag.CN() + 1)
|
length, nn, err := decoder.ReadUintN(tag.CN() + 1)
|
||||||
@ -175,7 +186,7 @@ func decodeAnyOrError(decoder *Decoder, destination reflect.Value, tag Tag) (n i
|
|||||||
buffer := make([]byte, length)
|
buffer := make([]byte, length)
|
||||||
nn, err = decoder.Read(buffer)
|
nn, err = decoder.Read(buffer)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
setByteArray(destination, buffer)
|
setString(destination, string(buffer))
|
||||||
case OTA:
|
case OTA:
|
||||||
// OTA: <length: UN> <elementTag: tape.Tag> <values>*
|
// OTA: <length: UN> <elementTag: tape.Tag> <values>*
|
||||||
length, nn, err := decoder.ReadUintN(tag.CN() + 1)
|
length, nn, err := decoder.ReadUintN(tag.CN() + 1)
|
||||||
@ -325,6 +336,10 @@ func encodeAnyMap(encoder *Encoder, value any, tag Tag) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func canSet(destination reflect.Type, tag Tag) error {
|
func canSet(destination reflect.Type, tag Tag) error {
|
||||||
|
// anything can be assigned to `any`
|
||||||
|
if isTypeAny(destination) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
switch tag.WithoutCN() {
|
switch tag.WithoutCN() {
|
||||||
case SI, LI, LSI:
|
case SI, LI, LSI:
|
||||||
switch destination.Kind() {
|
switch destination.Kind() {
|
||||||
@ -362,17 +377,43 @@ func canSet(destination reflect.Type, tag Tag) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setInt expects a settable destination.
|
// setInt expects a settable destination.
|
||||||
func setInt[T int64 | uint64](destination reflect.Value, value T) {
|
func setInt(destination reflect.Value, value int64, bytes int) {
|
||||||
switch {
|
switch {
|
||||||
case destination.CanInt():
|
case destination.CanInt():
|
||||||
destination.Set(reflect.ValueOf(int64(value)).Convert(destination.Type()))
|
destination.Set(reflect.ValueOf(int64(value)).Convert(destination.Type()))
|
||||||
case destination.CanUint():
|
case destination.CanUint():
|
||||||
destination.Set(reflect.ValueOf(value).Convert(destination.Type()))
|
destination.Set(reflect.ValueOf(value).Convert(destination.Type()))
|
||||||
|
case isTypeAny(destination.Type()):
|
||||||
|
switch {
|
||||||
|
case bytes > 4: destination.Set(reflect.ValueOf(int64(value)))
|
||||||
|
case bytes > 2: destination.Set(reflect.ValueOf(int32(value)))
|
||||||
|
case bytes > 1: destination.Set(reflect.ValueOf(int16(value)))
|
||||||
|
default: destination.Set(reflect.ValueOf(int8(value)))
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
panic("setInt called on an unsupported type")
|
panic("setInt called on an unsupported type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setUint expects a settable destination.
|
||||||
|
func setUint(destination reflect.Value, value uint64, bytes int) {
|
||||||
|
switch {
|
||||||
|
case destination.CanInt():
|
||||||
|
destination.Set(reflect.ValueOf(int64(value)).Convert(destination.Type()))
|
||||||
|
case destination.CanUint():
|
||||||
|
destination.Set(reflect.ValueOf(value).Convert(destination.Type()))
|
||||||
|
case isTypeAny(destination.Type()):
|
||||||
|
switch {
|
||||||
|
case bytes > 4: destination.Set(reflect.ValueOf(uint64(value)))
|
||||||
|
case bytes > 2: destination.Set(reflect.ValueOf(uint32(value)))
|
||||||
|
case bytes > 1: destination.Set(reflect.ValueOf(uint16(value)))
|
||||||
|
default: destination.Set(reflect.ValueOf(uint8(value)))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("setUint called on an unsupported type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// setFloat expects a settable destination.
|
// setFloat expects a settable destination.
|
||||||
func setFloat(destination reflect.Value, value float64) {
|
func setFloat(destination reflect.Value, value float64) {
|
||||||
destination.Set(reflect.ValueOf(value).Convert(destination.Type()))
|
destination.Set(reflect.ValueOf(value).Convert(destination.Type()))
|
||||||
@ -387,7 +428,7 @@ func setByteArray(destination reflect.Value, value []byte) {
|
|||||||
func decodeAndSetInt(decoder *Decoder, destination reflect.Value, bytes int) (n int, err error) {
|
func decodeAndSetInt(decoder *Decoder, destination reflect.Value, bytes int) (n int, err error) {
|
||||||
value, nn, err := decoder.ReadIntN(bytes)
|
value, nn, err := decoder.ReadIntN(bytes)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
setInt(destination, value)
|
setInt(destination, value, bytes)
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,7 +436,7 @@ func decodeAndSetInt(decoder *Decoder, destination reflect.Value, bytes int) (n
|
|||||||
func decodeAndSetUint(decoder *Decoder, destination reflect.Value, bytes int) (n int, err error) {
|
func decodeAndSetUint(decoder *Decoder, destination reflect.Value, bytes int) (n int, err error) {
|
||||||
value, nn, err := decoder.ReadUintN(bytes)
|
value, nn, err := decoder.ReadUintN(bytes)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
setInt(destination, value)
|
setUint(destination, value, bytes)
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,8 +493,8 @@ func typeOf(decoder *Decoder, tag Tag) (reflect.Type, error) {
|
|||||||
case 7: return reflect.TypeOf(float64(0)), nil
|
case 7: return reflect.TypeOf(float64(0)), nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("unknown CN %d for FP", tag.CN())
|
return nil, fmt.Errorf("unknown CN %d for FP", tag.CN())
|
||||||
case SBA: return reflect.SliceOf(reflect.TypeOf(byte(0))), nil
|
case SBA: return reflect.TypeOf(""), nil
|
||||||
case LBA: return reflect.SliceOf(reflect.TypeOf(byte(0))), nil
|
case LBA: return reflect.TypeOf(""), nil
|
||||||
case OTA:
|
case OTA:
|
||||||
elemTag, dimension, err := peekSlice(decoder, tag)
|
elemTag, dimension, err := peekSlice(decoder, tag)
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
@ -469,6 +510,12 @@ func typeOf(decoder *Decoder, tag Tag) (reflect.Type, error) {
|
|||||||
return nil, fmt.Errorf("unknown TN %d", tag.TN())
|
return nil, fmt.Errorf("unknown TN %d", tag.TN())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isTypeAny returns whether the given reflect.Type is an interface with no
|
||||||
|
// methods.
|
||||||
|
func isTypeAny(typ reflect.Type) bool {
|
||||||
|
return typ.Kind() == reflect.Interface && typ.NumMethod() == 0
|
||||||
|
}
|
||||||
|
|
||||||
// peekSlice returns the element tag and dimension count of the OTA currently
|
// peekSlice returns the element tag and dimension count of the OTA currently
|
||||||
// being decoded. It does not use up the decoder, it only peeks.
|
// being decoded. It does not use up the decoder, it only peeks.
|
||||||
func peekSlice(decoder *Decoder, tag Tag) (Tag, int, error) {
|
func peekSlice(decoder *Decoder, tag Tag) (Tag, int, error) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user