Compare commits
5 Commits
770f6b05b4
...
0ac26711ac
| Author | SHA1 | Date | |
|---|---|---|---|
| 0ac26711ac | |||
| 8446ae6186 | |||
| c511ebcb15 | |||
| 00b0f13d3e | |||
| 13d35e54f5 |
@ -47,6 +47,15 @@ func canAssign(destination, source tape.Tag) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// boolInt converts a bool to an integer.
|
||||||
|
func boolInt(input bool) int {
|
||||||
|
if input {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
// Generator converts protocols into Go code.
|
// Generator converts protocols into Go code.
|
||||||
@ -315,6 +324,9 @@ func (this *Generator) generateMessage(method uint16, message Message) (n int, e
|
|||||||
// - nn int
|
// - nn int
|
||||||
func (this *Generator) generateEncodeValue(typ Type, valueSource, tagSource string) (n int, err error) {
|
func (this *Generator) generateEncodeValue(typ Type, valueSource, tagSource string) (n int, err error) {
|
||||||
switch typ := typ.(type) {
|
switch typ := typ.(type) {
|
||||||
|
case TypeBool:
|
||||||
|
// SI: (none)
|
||||||
|
// SI stores the value in the tag, so we write nothing here
|
||||||
case TypeInt:
|
case TypeInt:
|
||||||
// SI: (none)
|
// SI: (none)
|
||||||
// LI/LSI: <value: IntN>
|
// LI/LSI: <value: IntN>
|
||||||
@ -518,6 +530,11 @@ func (this *Generator) generateEncodeValue(typ Type, valueSource, tagSource stri
|
|||||||
// for [Generator.generateDecodeBranch].
|
// for [Generator.generateDecodeBranch].
|
||||||
func (this *Generator) generateDecodeValue(typ Type, typeName, valueSource, tagSource string) (n int, err error) {
|
func (this *Generator) generateDecodeValue(typ Type, typeName, valueSource, tagSource string) (n int, err error) {
|
||||||
switch typ := typ.(type) {
|
switch typ := typ.(type) {
|
||||||
|
case TypeBool:
|
||||||
|
// SI: (none)
|
||||||
|
// SI stores the value in the tag
|
||||||
|
nn, err := this.iprintf("*%s = %s.CN() > 0\n", valueSource, tagSource)
|
||||||
|
n += nn; if err != nil { return n, err }
|
||||||
case TypeInt:
|
case TypeInt:
|
||||||
// SI: (none)
|
// SI: (none)
|
||||||
// LI/LSI: <value: IntN>
|
// LI/LSI: <value: IntN>
|
||||||
@ -944,6 +961,9 @@ func (this *Generator) generateBareErrorCheck() (n int, err error) {
|
|||||||
func (this *Generator) generateTag(typ Type, source string) (tagVar string, n int, err error) {
|
func (this *Generator) generateTag(typ Type, source string) (tagVar string, n int, err error) {
|
||||||
tagVar = this.newTemporaryVar("tag")
|
tagVar = this.newTemporaryVar("tag")
|
||||||
switch typ := typ.(type) {
|
switch typ := typ.(type) {
|
||||||
|
case TypeBool:
|
||||||
|
nn, err := this.iprintf("%s := tape.SI.WithCN(boolInt(bool(%s)))\n", tagVar, source)
|
||||||
|
n += nn; if err != nil { return tagVar, n, err }
|
||||||
case TypeInt:
|
case TypeInt:
|
||||||
if typ.Bits <= 5 {
|
if typ.Bits <= 5 {
|
||||||
nn, err := this.iprintf("%s := tape.SI.WithCN(int(%s))\n", tagVar, source)
|
nn, err := this.iprintf("%s := tape.SI.WithCN(int(%s))\n", tagVar, source)
|
||||||
@ -997,6 +1017,9 @@ func (this *Generator) generateTag(typ Type, source string) (tagVar string, n in
|
|||||||
// information is chosen.
|
// information is chosen.
|
||||||
func (this *Generator) generateTN(typ Type) (n int, err error) {
|
func (this *Generator) generateTN(typ Type) (n int, err error) {
|
||||||
switch typ := typ.(type) {
|
switch typ := typ.(type) {
|
||||||
|
case TypeBool:
|
||||||
|
nn, err := this.printf("tape.SI")
|
||||||
|
n += nn; if err != nil { return n, err }
|
||||||
case TypeInt:
|
case TypeInt:
|
||||||
if typ.Bits <= 5 {
|
if typ.Bits <= 5 {
|
||||||
nn, err := this.printf("tape.SI")
|
nn, err := this.printf("tape.SI")
|
||||||
@ -1040,6 +1063,9 @@ func (this *Generator) generateTN(typ Type) (n int, err error) {
|
|||||||
|
|
||||||
func (this *Generator) generateType(typ Type) (n int, err error) {
|
func (this *Generator) generateType(typ Type) (n int, err error) {
|
||||||
switch typ := typ.(type) {
|
switch typ := typ.(type) {
|
||||||
|
case TypeBool:
|
||||||
|
nn, err := this.printf("bool")
|
||||||
|
n += nn; if err != nil { return n, err }
|
||||||
case TypeInt:
|
case TypeInt:
|
||||||
if err := this.validateIntBitSize(typ.Bits); err != nil {
|
if err := this.validateIntBitSize(typ.Bits); err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
|
|||||||
@ -59,6 +59,7 @@ func init() {
|
|||||||
0x000C: Field { Name: "NI16",Type: TypeInt { Bits: 16, Signed: true } },
|
0x000C: Field { Name: "NI16",Type: TypeInt { Bits: 16, Signed: true } },
|
||||||
0x000D: Field { Name: "NI32",Type: TypeInt { Bits: 32, Signed: true } },
|
0x000D: Field { Name: "NI32",Type: TypeInt { Bits: 32, Signed: true } },
|
||||||
0x000E: Field { Name: "NI64",Type: TypeInt { Bits: 64, Signed: true } },
|
0x000E: Field { Name: "NI64",Type: TypeInt { Bits: 64, Signed: true } },
|
||||||
|
0x000F: Field { Name: "Bool",Type: TypeBool { } },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -201,10 +202,11 @@ func TestGenerateRunEncodeDecode(test *testing.T) {
|
|||||||
NI16: -0x34C9,
|
NI16: -0x34C9,
|
||||||
NI32: -0x10E134C9,
|
NI32: -0x10E134C9,
|
||||||
NI64: -0x639109BC10E134C9,
|
NI64: -0x639109BC10E134C9,
|
||||||
|
Bool: true,
|
||||||
}
|
}
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&messageIntegers,
|
&messageIntegers,
|
||||||
tu.S(0xE0, 13).AddVar(
|
tu.S(0xE0, 14).AddVar(
|
||||||
[]byte { 0x00, 0x00, 0x13 },
|
[]byte { 0x00, 0x00, 0x13 },
|
||||||
[]byte { 0x00, 0x01, 0x20, 0xC9 },
|
[]byte { 0x00, 0x01, 0x20, 0xC9 },
|
||||||
[]byte { 0x00, 0x02, 0x21, 0x34, 0xC9 },
|
[]byte { 0x00, 0x02, 0x21, 0x34, 0xC9 },
|
||||||
@ -218,6 +220,7 @@ func TestGenerateRunEncodeDecode(test *testing.T) {
|
|||||||
[]byte { 0x00, 0x0C, 0x41, 0xCB, 0x37 },
|
[]byte { 0x00, 0x0C, 0x41, 0xCB, 0x37 },
|
||||||
[]byte { 0x00, 0x0D, 0x43, 0xEF, 0x1E, 0xCB, 0x37 },
|
[]byte { 0x00, 0x0D, 0x43, 0xEF, 0x1E, 0xCB, 0x37 },
|
||||||
[]byte { 0x00, 0x0E, 0x47, 0x9C, 0x6E, 0xF6, 0x43, 0xEF, 0x1E, 0xCB, 0x37 },
|
[]byte { 0x00, 0x0E, 0x47, 0x9C, 0x6E, 0xF6, 0x43, 0xEF, 0x1E, 0xCB, 0x37 },
|
||||||
|
[]byte { 0x00, 0x0F, 0x01 },
|
||||||
))
|
))
|
||||||
log.Println("MessageDynamic")
|
log.Println("MessageDynamic")
|
||||||
messageDynamic := MessageDynamic {
|
messageDynamic := MessageDynamic {
|
||||||
|
|||||||
@ -59,6 +59,7 @@ func EncodeAny(encoder *Encoder, value any, tag Tag) (n int, err error) {
|
|||||||
case reflect.Uint64: return encoder.WriteUint64(uint64(reflectValue.Uint()))
|
case reflect.Uint64: return encoder.WriteUint64(uint64(reflectValue.Uint()))
|
||||||
case reflect.Float32: return encoder.WriteFloat32(float32(reflectValue.Float()))
|
case reflect.Float32: return encoder.WriteFloat32(float32(reflectValue.Float()))
|
||||||
case reflect.Float64: return encoder.WriteFloat64(float64(reflectValue.Float()))
|
case reflect.Float64: return encoder.WriteFloat64(float64(reflectValue.Float()))
|
||||||
|
case reflect.Bool: return // SI has no payload
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
if reflectValue.Len() > MaxStructureLength {
|
if reflectValue.Len() > MaxStructureLength {
|
||||||
return 0, ErrTooLong
|
return 0, ErrTooLong
|
||||||
@ -298,6 +299,12 @@ func tagAny(reflectValue reflect.Value) (Tag, error) {
|
|||||||
case reflect.Uint64: return LI.WithCN(7), nil
|
case reflect.Uint64: return LI.WithCN(7), nil
|
||||||
case reflect.Float32: return FP.WithCN(3), nil
|
case reflect.Float32: return FP.WithCN(3), nil
|
||||||
case reflect.Float64: return FP.WithCN(7), nil
|
case reflect.Float64: return FP.WithCN(7), nil
|
||||||
|
case reflect.Bool:
|
||||||
|
if reflectValue.Bool() {
|
||||||
|
return SI.WithCN(1), nil
|
||||||
|
} else {
|
||||||
|
return SI.WithCN(0), nil
|
||||||
|
}
|
||||||
case reflect.String: return bufferLenTag(reflectValue.Len()), nil
|
case reflect.String: return bufferLenTag(reflectValue.Len()), nil
|
||||||
}
|
}
|
||||||
if reflectValue.CanConvert(reflect.TypeOf(dummyBuffer)) {
|
if reflectValue.CanConvert(reflect.TypeOf(dummyBuffer)) {
|
||||||
@ -374,7 +381,8 @@ func canSet(destination reflect.Type, tag Tag) error {
|
|||||||
switch destination.Kind() {
|
switch destination.Kind() {
|
||||||
case
|
case
|
||||||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||||
|
reflect.Bool:
|
||||||
default:
|
default:
|
||||||
return errCantAssignf("cannot assign integer to %v", destination)
|
return errCantAssignf("cannot assign integer to %v", destination)
|
||||||
}
|
}
|
||||||
@ -432,6 +440,8 @@ func setInt(destination reflect.Value, value int64, bytes int) {
|
|||||||
// setUint expects a settable destination.
|
// setUint expects a settable destination.
|
||||||
func setUint(destination reflect.Value, value uint64, bytes int) {
|
func setUint(destination reflect.Value, value uint64, bytes int) {
|
||||||
switch {
|
switch {
|
||||||
|
case destination.Kind() == reflect.Bool:
|
||||||
|
destination.Set(reflect.ValueOf(value > 0))
|
||||||
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():
|
||||||
|
|||||||
@ -15,6 +15,8 @@ var samplePayloads = [][]byte {
|
|||||||
/* uint16 */ []byte { byte(LI.WithCN(1)), 0x45, 0x67 },
|
/* uint16 */ []byte { byte(LI.WithCN(1)), 0x45, 0x67 },
|
||||||
/* uint32 */ []byte { byte(LI.WithCN(3)), 0x45, 0x67, 0x89, 0xAB },
|
/* uint32 */ []byte { byte(LI.WithCN(3)), 0x45, 0x67, 0x89, 0xAB },
|
||||||
/* uint64 */ []byte { byte(LI.WithCN(7)), 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 },
|
/* uint64 */ []byte { byte(LI.WithCN(7)), 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 },
|
||||||
|
/* bool */ []byte { byte(SI.WithCN(0)) },
|
||||||
|
/* bool */ []byte { byte(SI.WithCN(1)) },
|
||||||
/* string */ []byte { byte(SBA.WithCN(7)), 'p', 'u', 'p', 'e', 'v', 'e', 'r' },
|
/* string */ []byte { byte(SBA.WithCN(7)), 'p', 'u', 'p', 'e', 'v', 'e', 'r' },
|
||||||
/* []byte */ []byte { byte(SBA.WithCN(5)), 'b', 'l', 'a', 'r', 'g' },
|
/* []byte */ []byte { byte(SBA.WithCN(5)), 'b', 'l', 'a', 'r', 'g' },
|
||||||
/* []string */ []byte {
|
/* []string */ []byte {
|
||||||
@ -45,6 +47,8 @@ var sampleValues = []any {
|
|||||||
/* uint16 */ uint16(0x4567),
|
/* uint16 */ uint16(0x4567),
|
||||||
/* uint32 */ uint32(0x456789AB),
|
/* uint32 */ uint32(0x456789AB),
|
||||||
/* uint64 */ uint64(0x456789ABCDEF0123),
|
/* uint64 */ uint64(0x456789ABCDEF0123),
|
||||||
|
/* bool */ false,
|
||||||
|
/* bool */ true,
|
||||||
/* string */ "pupever",
|
/* string */ "pupever",
|
||||||
/* []byte */ "blarg",
|
/* []byte */ "blarg",
|
||||||
/* []string */ []string {
|
/* []string */ []string {
|
||||||
@ -84,7 +88,9 @@ func TestEncodeAnyTable(test *testing.T) {
|
|||||||
0x3456: userDefinedInteger(0x3921),
|
0x3456: userDefinedInteger(0x3921),
|
||||||
0x1F1F: float32(67.26),
|
0x1F1F: float32(67.26),
|
||||||
0x0F0F: float64(5.3),
|
0x0F0F: float64(5.3),
|
||||||
}, KTV.WithCN(0), tu.S(9).AddVar(
|
0xAAAA: false,
|
||||||
|
0xBBBB: true,
|
||||||
|
}, KTV.WithCN(0), tu.S(11).AddVar(
|
||||||
[]byte {
|
[]byte {
|
||||||
0xF3, 0xB9,
|
0xF3, 0xB9,
|
||||||
byte(LSI.WithCN(3)),
|
byte(LSI.WithCN(3)),
|
||||||
@ -138,6 +144,14 @@ func TestEncodeAnyTable(test *testing.T) {
|
|||||||
byte(FP.WithCN(7)),
|
byte(FP.WithCN(7)),
|
||||||
0x40, 0x15, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
|
0x40, 0x15, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
|
||||||
},
|
},
|
||||||
|
[]byte {
|
||||||
|
0xAA, 0xAA,
|
||||||
|
byte(SI.WithCN(0)),
|
||||||
|
},
|
||||||
|
[]byte {
|
||||||
|
0xBB, 0xBB,
|
||||||
|
byte(SI.WithCN(1)),
|
||||||
|
},
|
||||||
))
|
))
|
||||||
if err != nil { test.Fatal(err) }
|
if err != nil { test.Fatal(err) }
|
||||||
}
|
}
|
||||||
@ -146,7 +160,7 @@ func TestDecodeWrongType(test *testing.T) {
|
|||||||
for index, data := range samplePayloads {
|
for index, data := range samplePayloads {
|
||||||
test.Logf("data %2d %v [%s]", index, Tag(data[0]), tu.HexBytes(data[1:]))
|
test.Logf("data %2d %v [%s]", index, Tag(data[0]), tu.HexBytes(data[1:]))
|
||||||
// integers should only assign to other integers
|
// integers should only assign to other integers
|
||||||
if index > 8 {
|
if index > 10 {
|
||||||
cas := func(destination any) {
|
cas := func(destination any) {
|
||||||
n, err := DecodeAnyInto(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) }
|
if err != nil { test.Fatalf("error: %v | n: %d", err, n) }
|
||||||
@ -155,7 +169,7 @@ func TestDecodeWrongType(test *testing.T) {
|
|||||||
if reflectValue.Int() != 0 {
|
if reflectValue.Int() != 0 {
|
||||||
test.Fatalf("destination not zero: %v", reflectValue.Elem().Interface())
|
test.Fatalf("destination not zero: %v", reflectValue.Elem().Interface())
|
||||||
}
|
}
|
||||||
} else {
|
} else if reflectValue.Kind() != reflect.Bool {
|
||||||
if reflectValue.Uint() != 0 {
|
if reflectValue.Uint() != 0 {
|
||||||
test.Fatalf("destination not zero: %v", reflectValue.Elem().Interface())
|
test.Fatalf("destination not zero: %v", reflectValue.Elem().Interface())
|
||||||
}
|
}
|
||||||
@ -180,6 +194,8 @@ func TestDecodeWrongType(test *testing.T) {
|
|||||||
{ var dest uint32; cas(&dest) }
|
{ var dest uint32; cas(&dest) }
|
||||||
test.Log("- uint64")
|
test.Log("- uint64")
|
||||||
{ var dest uint64; cas(&dest) }
|
{ var dest uint64; cas(&dest) }
|
||||||
|
test.Log("- bool")
|
||||||
|
{ var dest bool; cas(&dest) }
|
||||||
}
|
}
|
||||||
arrayCase := func(destination any) {
|
arrayCase := func(destination any) {
|
||||||
n, err := DecodeAnyInto(NewDecoder(bytes.NewBuffer(data[1:])), destination, Tag(data[0]))
|
n, err := DecodeAnyInto(NewDecoder(bytes.NewBuffer(data[1:])), destination, Tag(data[0]))
|
||||||
@ -194,19 +210,19 @@ func TestDecodeWrongType(test *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// SBA/LBA types should only assign to other SBA/LBA types
|
// SBA/LBA types should only assign to other SBA/LBA types
|
||||||
if index != 9 && index != 10 {
|
if index != 11 && index != 12 {
|
||||||
test.Log("- string")
|
test.Log("- string")
|
||||||
{ var dest string; arrayCase(&dest) }
|
{ var dest string; arrayCase(&dest) }
|
||||||
test.Log("- []byte")
|
test.Log("- []byte")
|
||||||
{ var dest []byte; arrayCase(&dest) }
|
{ var dest []byte; arrayCase(&dest) }
|
||||||
}
|
}
|
||||||
// arrays should only assign to other arrays
|
// arrays should only assign to other arrays
|
||||||
if index != 11 {
|
if index != 13 {
|
||||||
test.Log("- []string")
|
test.Log("- []string")
|
||||||
{ 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 && index != 13 {
|
if index != 14 && index != 15 {
|
||||||
test.Log("- map[uint16] any")
|
test.Log("- map[uint16] any")
|
||||||
{ var dest = map[uint16] any { }; arrayCase(&dest) }
|
{ var dest = map[uint16] any { }; arrayCase(&dest) }
|
||||||
}
|
}
|
||||||
@ -231,6 +247,12 @@ func TestEncodeDecodeAnyTable(test *testing.T) {
|
|||||||
func TestEncodeDecodeAnyDestination(test *testing.T) {
|
func TestEncodeDecodeAnyDestination(test *testing.T) {
|
||||||
var destination any
|
var destination any
|
||||||
for index, data := range samplePayloads {
|
for index, data := range samplePayloads {
|
||||||
|
if _, isBool := sampleValues[index].(bool); isBool {
|
||||||
|
// test is invalid for bools because they are never
|
||||||
|
// created as a skeleton value
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
tag := Tag(data[0])
|
tag := Tag(data[0])
|
||||||
payload := data[1:]
|
payload := data[1:]
|
||||||
test.Logf("data %2d %v [%s]", index, tag, tu.HexBytes(payload))
|
test.Logf("data %2d %v [%s]", index, tag, tu.HexBytes(payload))
|
||||||
@ -349,6 +371,12 @@ func TestTagAny(test *testing.T) {
|
|||||||
|
|
||||||
func TestDecodeAny(test *testing.T) {
|
func TestDecodeAny(test *testing.T) {
|
||||||
for index, payload := range samplePayloads {
|
for index, payload := range samplePayloads {
|
||||||
|
if _, isBool := sampleValues[index].(bool); isBool {
|
||||||
|
// test is invalid for bools because they are never
|
||||||
|
// created as a skeleton value
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
correctValue := sampleValues[index]
|
correctValue := sampleValues[index]
|
||||||
data := payload[1:]
|
data := payload[1:]
|
||||||
decoder := NewDecoder(bytes.NewBuffer(data))
|
decoder := NewDecoder(bytes.NewBuffer(data))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user