Compare commits
10 Commits
f6b12d43fb
...
unify-byte
| Author | SHA1 | Date | |
|---|---|---|---|
| 5c2b8a0582 | |||
| 4575fa229b | |||
| cbfb513933 | |||
| f10327356e | |||
| f402b46b1c | |||
| c3d0f33700 | |||
| ba2dc6b53f | |||
| 2e03867c66 | |||
| 7a03d8d6b5 | |||
| b2504cda2d |
@@ -24,7 +24,7 @@ const preamble = `
|
|||||||
|
|
||||||
const static = `
|
const static = `
|
||||||
// Table is a KTV table with an undefined schema.
|
// Table is a KTV table with an undefined schema.
|
||||||
type Table map[uint16] any
|
type Table = map[uint16] any
|
||||||
|
|
||||||
// Message is any message that can be sent along this protocol.
|
// Message is any message that can be sent along this protocol.
|
||||||
type Message interface {
|
type Message interface {
|
||||||
|
|||||||
@@ -100,12 +100,12 @@ func testGenerateRun(test *testing.T, protocol *Protocol, title, imports, testCa
|
|||||||
log.Println("decoding:")
|
log.Println("decoding:")
|
||||||
destination := reflect.New(reflect.ValueOf(message).Elem().Type()).Interface().(Message)
|
destination := reflect.New(reflect.ValueOf(message).Elem().Type()).Interface().(Message)
|
||||||
flat := data.Flatten()
|
flat := data.Flatten()
|
||||||
log.Println("before: ", destination)
|
log.Println("before: ", tu.Describe(destination))
|
||||||
decoder := tape.NewDecoder(bytes.NewBuffer(flat))
|
decoder := tape.NewDecoder(bytes.NewBuffer(flat))
|
||||||
n, err = destination.Decode(decoder)
|
n, err = destination.Decode(decoder)
|
||||||
if err != nil { log.Fatalf("at %d: %v\n", n, err) }
|
if err != nil { log.Fatalf("at %d: %v\n", n, err) }
|
||||||
log.Println("got: ", destination)
|
log.Println("got: ", tu.Describe(destination))
|
||||||
log.Println("correct:", message)
|
log.Println("correct:", tu.Describe(message))
|
||||||
if n != len(flat) {
|
if n != len(flat) {
|
||||||
log.Fatalf("n incorrect: %d != %d\n", n, len(flat))
|
log.Fatalf("n incorrect: %d != %d\n", n, len(flat))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ package testutil
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "slices"
|
import "slices"
|
||||||
import "strings"
|
|
||||||
import "reflect"
|
import "reflect"
|
||||||
|
import "strings"
|
||||||
|
import "unicode"
|
||||||
|
|
||||||
// Snake lets you compare blocks of data where the ordering of certain parts may
|
// Snake lets you compare blocks of data where the ordering of certain parts may
|
||||||
// be swapped every which way. It is designed for comparing the encoding of
|
// be swapped every which way. It is designed for comparing the encoding of
|
||||||
@@ -124,6 +125,10 @@ func (this *describer) describe(value reflect.Value) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
value = reflect.ValueOf(value.Interface())
|
value = reflect.ValueOf(value.Interface())
|
||||||
|
if !value.IsValid() {
|
||||||
|
this.printf("<invalid>")
|
||||||
|
return
|
||||||
|
}
|
||||||
switch value.Kind() {
|
switch value.Kind() {
|
||||||
case reflect.Array, reflect.Slice:
|
case reflect.Array, reflect.Slice:
|
||||||
this.printf("[\n")
|
this.printf("[\n")
|
||||||
@@ -141,12 +146,20 @@ func (this *describer) describe(value reflect.Value) {
|
|||||||
typ := value.Type()
|
typ := value.Type()
|
||||||
for index := range typ.NumField() {
|
for index := range typ.NumField() {
|
||||||
indexBuffer := [1]int { index }
|
indexBuffer := [1]int { index }
|
||||||
this.iprintf("%s: ", typ.Field(index).Name)
|
field := typ.Field(index)
|
||||||
this.describe(value.FieldByIndex(indexBuffer[:]))
|
this.iprintf("%s: ", field.Name)
|
||||||
|
for _, char := range field.Name {
|
||||||
|
if unicode.IsUpper(char) {
|
||||||
|
this.describe(value.FieldByIndex(indexBuffer[:]))
|
||||||
|
} else {
|
||||||
|
this.printf("<private>")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
this.iprintf("\n")
|
this.iprintf("\n")
|
||||||
}
|
}
|
||||||
this.indent -= 1
|
this.indent -= 1
|
||||||
this.iprintf("}\n")
|
this.iprintf("}")
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
this.printf("map {\n")
|
this.printf("map {\n")
|
||||||
this.indent += 1
|
this.indent += 1
|
||||||
@@ -159,7 +172,7 @@ func (this *describer) describe(value reflect.Value) {
|
|||||||
this.iprintf("\n")
|
this.iprintf("\n")
|
||||||
}
|
}
|
||||||
this.indent -= 1
|
this.indent -= 1
|
||||||
this.iprintf("}\n")
|
this.iprintf("}")
|
||||||
case reflect.Pointer:
|
case reflect.Pointer:
|
||||||
this.printf("& ")
|
this.printf("& ")
|
||||||
this.describe(value.Elem())
|
this.describe(value.Elem())
|
||||||
|
|||||||
@@ -116,9 +116,9 @@ func DecodeAnyInto(decoder *Decoder, destination any, tag Tag) (n int, err error
|
|||||||
func DecodeAny(decoder *Decoder, tag Tag) (value any, n int, err error) {
|
func DecodeAny(decoder *Decoder, tag Tag) (value any, n int, err error) {
|
||||||
destination, err := skeletonPointer(decoder, tag)
|
destination, err := skeletonPointer(decoder, tag)
|
||||||
if err != nil { return nil, n, err }
|
if err != nil { return nil, n, err }
|
||||||
nn, err := DecodeAnyInto(decoder, destination, tag)
|
nn, err := decodeAny(decoder, destination.Elem(), tag)
|
||||||
n += nn; if err != nil { return nil, n, err }
|
n += nn; if err != nil { return nil, n, err }
|
||||||
return destination, n, err
|
return destination.Elem().Interface(), n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// unknownSlicePlaceholder is inserted by skeletonValue and informs the program
|
// unknownSlicePlaceholder is inserted by skeletonValue and informs the program
|
||||||
@@ -242,12 +242,22 @@ func decodeAnyOrError(decoder *Decoder, destination reflect.Value, tag Tag) (n i
|
|||||||
}
|
}
|
||||||
lengthCast, err := Uint64ToIntSafe(length)
|
lengthCast, err := Uint64ToIntSafe(length)
|
||||||
if err != nil { return n, err }
|
if err != nil { return n, err }
|
||||||
if isTypeAny(destination.Type()) {
|
|
||||||
// need a skeleton value if we are assigning to any.
|
// im fucking so done dude. im so fucking done. this was
|
||||||
value := reflect.MakeMapWithSize(reflect.TypeOf(dummyMap), lengthCast)
|
// supposed to only run when we need it but i guess it runs all
|
||||||
destination.Set(value)
|
// the time, because when we get a map destination (a valid,
|
||||||
destination = value
|
// allocated one) we break apart on SetMapIndex because of a nil
|
||||||
}
|
// map. yeah thats right. a fucking nil map panic. on the map we
|
||||||
|
// just allocated. but running this unconditionally (whether or
|
||||||
|
// not we receive an empty any value) actually makes it fucking
|
||||||
|
// work. go figure().
|
||||||
|
//
|
||||||
|
// (the map allocation functionality in skeletonPointer has been
|
||||||
|
// removed)
|
||||||
|
value := reflect.MakeMapWithSize(reflect.TypeOf(dummyMap), lengthCast)
|
||||||
|
destination.Set(value)
|
||||||
|
destination = value
|
||||||
|
|
||||||
destination.Clear()
|
destination.Clear()
|
||||||
for _ = range lengthCast {
|
for _ = range lengthCast {
|
||||||
key, nn, err := decoder.ReadUint16()
|
key, nn, err := decoder.ReadUint16()
|
||||||
@@ -387,7 +397,11 @@ func canSet(destination reflect.Type, tag Tag) error {
|
|||||||
return errCantAssignf("cannot assign array to %v", destination)
|
return errCantAssignf("cannot assign array to %v", destination)
|
||||||
}
|
}
|
||||||
case KTV:
|
case KTV:
|
||||||
if destination != reflect.TypeOf(dummyMap) {
|
cantAssign :=
|
||||||
|
destination.Kind() != reflect.Map ||
|
||||||
|
destination.Key().Kind() != reflect.Uint16 ||
|
||||||
|
!isTypeAny(destination.Elem())
|
||||||
|
if cantAssign {
|
||||||
return errCantAssignf("cannot assign table to %v", destination)
|
return errCantAssignf("cannot assign table to %v", destination)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -496,7 +510,8 @@ func skeletonValue(decoder *Decoder, tag Tag) (reflect.Value, error) {
|
|||||||
func skeletonPointer(decoder *Decoder, tag Tag) (reflect.Value, error) {
|
func skeletonPointer(decoder *Decoder, tag Tag) (reflect.Value, error) {
|
||||||
typ, err := typeOf(decoder, tag)
|
typ, err := typeOf(decoder, tag)
|
||||||
if err != nil { return reflect.Value { }, err }
|
if err != nil { return reflect.Value { }, err }
|
||||||
return reflect.New(typ), nil
|
value := reflect.New(typ)
|
||||||
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// typeOf returns the type of the current tag being decoded. It does not use up
|
// typeOf returns the type of the current tag being decoded. It does not use up
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ var samplePayloads = [][]byte {
|
|||||||
0x02, 0x23, byte(LSI.WithCN(1)), 0x45, 0x67,
|
0x02, 0x23, byte(LSI.WithCN(1)), 0x45, 0x67,
|
||||||
0x02, 0x24, byte(LI.WithCN(3)), 0x45, 0x67, 0x89, 0xAB,
|
0x02, 0x24, byte(LI.WithCN(3)), 0x45, 0x67, 0x89, 0xAB,
|
||||||
},
|
},
|
||||||
|
/* map[uint16] any */ []byte {
|
||||||
|
byte(KTV.WithCN(0)), 3,
|
||||||
|
0x00, 0x01, 0x63, 0x43, 0xF4, 0xC0, 0x00,
|
||||||
|
0x00, 0x02, 0x82, 'h', 'i',
|
||||||
|
0x00, 0x03, 0x21, 0x39, 0x92,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var sampleValues = []any {
|
var sampleValues = []any {
|
||||||
@@ -49,6 +55,11 @@ var sampleValues = []any {
|
|||||||
0x0223: int16(0x4567),
|
0x0223: int16(0x4567),
|
||||||
0x0224: uint32(0x456789AB),
|
0x0224: uint32(0x456789AB),
|
||||||
},
|
},
|
||||||
|
/* map[uint16] any */ map[uint16] any {
|
||||||
|
0x0001: float32(489.5),
|
||||||
|
0x0002: "hi",
|
||||||
|
0x0003: uint16(0x3992),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
type userDefinedInteger int16
|
type userDefinedInteger int16
|
||||||
@@ -195,7 +206,7 @@ func TestDecodeWrongType(test *testing.T) {
|
|||||||
{ var dest []string; arrayCase(&dest) }
|
{ var dest []string; arrayCase(&dest) }
|
||||||
}
|
}
|
||||||
// tables should only assign to other tables
|
// tables should only assign to other tables
|
||||||
if index != 12 {
|
if index != 12 && index != 13 {
|
||||||
test.Log("- map[uint16] any")
|
test.Log("- map[uint16] any")
|
||||||
{ var dest = map[uint16] any { }; arrayCase(&dest) }
|
{ var dest = map[uint16] any { }; arrayCase(&dest) }
|
||||||
}
|
}
|
||||||
@@ -335,3 +346,24 @@ func TestTagAny(test *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDecodeAny(test *testing.T) {
|
||||||
|
for index, payload := range samplePayloads {
|
||||||
|
correctValue := sampleValues[index]
|
||||||
|
data := payload[1:]
|
||||||
|
decoder := NewDecoder(bytes.NewBuffer(data))
|
||||||
|
tag := Tag(payload[0])
|
||||||
|
decoded, n, err := DecodeAny(decoder, tag)
|
||||||
|
test.Log("n: ", n)
|
||||||
|
test.Log("tag: ", tag)
|
||||||
|
test.Log("got: ", tu.Describe(decoded))
|
||||||
|
test.Log("correct:", tu.Describe(correctValue))
|
||||||
|
if err != nil { test.Fatal(err) }
|
||||||
|
if !reflect.DeepEqual(decoded, correctValue) {
|
||||||
|
test.Fatal("values not equal")
|
||||||
|
}
|
||||||
|
if n != len(data) {
|
||||||
|
test.Fatalf("n not equal: %d != %d", n, len(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user