Compare commits
No commits in common. "21941986939cbb6d0289bd5513fbb7d68d7315db" and "f5de450c39df3b495e452c8b200396da3bfede07" have entirely different histories.
2194198693
...
f5de450c39
@ -75,16 +75,16 @@ connection. Thus, the value may range from 0 to 31 if unsigned, and from -16 to
|
|||||||
17 if signed.
|
17 if signed.
|
||||||
|
|
||||||
#### Large Integer (LI)
|
#### Large Integer (LI)
|
||||||
LI encodes an integer of up to 256 bits, which are stored in the payload. The
|
LI encodes an integer of up to 256 bits, which are stored in the payload. The CN
|
||||||
length of the payload (in bytes) is CN + 1. The integer is big-endian. Whether
|
determine the length of the payload in bytes. The integer is big-endian. Whether
|
||||||
the payload is interpreted as unsigned or as signed two's complement is semantic
|
the payload is interpreted as unsigned or as signed two's complement is semantic
|
||||||
information and must be agreed upon by both sides of the connection. Thus, the
|
information and must be agreed upon by both sides of the connection. Thus, the
|
||||||
value may range from 0 to 31 if unsigned, and from -16 to 17 if signed.
|
value may range from 0 to 31 if unsigned, and from -16 to 17 if signed.
|
||||||
|
|
||||||
#### Floating Point (FP)
|
#### Floating Point (FP)
|
||||||
FP encodes an IEEE 754 floating point number of up to 256 bits, which are stored
|
FP encodes an IEEE 754 floating point number of up to 256 bits, which are stored
|
||||||
in the payload. The length of the payload (in bytes) is CN + 1. The only
|
in the payload. The CN determines the length of the payload in bytes, and it may
|
||||||
supported bit widths for floats are as follows: 16, 32, 64, 128, and 256.
|
only be one of these values: 16, 32, 64, 128, or 256.
|
||||||
|
|
||||||
#### Small Byte Array (SBA)
|
#### Small Byte Array (SBA)
|
||||||
SBA encodes an array of up to 32 bytes, which are stored in the paylod. The
|
SBA encodes an array of up to 32 bytes, which are stored in the paylod. The
|
||||||
@ -98,16 +98,15 @@ in bytes is determined by the CN.
|
|||||||
#### One-Tag Array (OTA)
|
#### One-Tag Array (OTA)
|
||||||
OTA encodes an array of up to 2^256 items, which are stored in the payload after
|
OTA encodes an array of up to 2^256 items, which are stored in the payload after
|
||||||
the length field and the item tag, where the length field comes first. Each item
|
the length field and the item tag, where the length field comes first. Each item
|
||||||
must be the same length, as they all share the same tag. The length of the
|
must be the same length, as they all share the same tag. The length of the data
|
||||||
length field (in bytes) is CN + 1.
|
length field in bytes is determined by the CN.
|
||||||
|
|
||||||
#### Key-Tag-Value Table (KTV)
|
#### Key-Tag-Value Table (KTV)
|
||||||
KTV encodes a table of up to 2^256 key/value pairs, which are stored in the
|
KTV encodes a table of up to 2^256 key/value pairs, which are stored in the
|
||||||
payload after the length field. The pairs themselves consist of a 16-bit
|
payload after the length field. The pairs themselves consist of a 16-bit
|
||||||
unsigned big-endian key followed by a tag and then the payload. Pair values can
|
unsigned big-endian key followed by a tag and then the payload. Pair values can
|
||||||
be of different types and sizes. The order of the pairs is not significant and
|
be of different types and sizes. The order of the pairs is not significant and
|
||||||
should never be treated as such. The length of the length field (in bytes) is
|
should never be treated as such.
|
||||||
CN + 1.
|
|
||||||
|
|
||||||
## Transports
|
## Transports
|
||||||
A transport is a protocol that HOPP connections can run on top of. HOPP
|
A transport is a protocol that HOPP connections can run on top of. HOPP
|
||||||
|
|||||||
@ -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 {
|
||||||
@ -372,7 +372,7 @@ func (this *Generator) generateEncodeValue(typ Type, valueSource, tagSource stri
|
|||||||
nn, err = this.iprintf("}\n")
|
nn, err = this.iprintf("}\n")
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
nn, err = this.iprintf(
|
nn, err = this.iprintf(
|
||||||
"nn, err = encoder.WriteUintN(uint64(len(%s)), %s.CN() + 1)\n",
|
"nn, err = encoder.WriteUintN(uint64(len(%s)), %s.CN())\n",
|
||||||
valueSource, tagSource)
|
valueSource, tagSource)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
nn, err = this.generateErrorCheck()
|
nn, err = this.generateErrorCheck()
|
||||||
@ -407,8 +407,8 @@ func (this *Generator) generateEncodeValue(typ Type, valueSource, tagSource stri
|
|||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
nn, err = this.iprintf("nn, err = encoder.WriteTag(itemTag)\n")
|
nn, err = this.iprintf("nn, err = encoder.WriteTag(itemTag)\n")
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
nn, err = this.generateErrorCheck()
|
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
|
nn, err = this.generateErrorCheck()
|
||||||
nn, err = this.iprintf("for _, item := range %s {\n", valueSource)
|
nn, err = this.iprintf("for _, item := range %s {\n", valueSource)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
this.push()
|
this.push()
|
||||||
@ -445,7 +445,7 @@ func (this *Generator) generateEncodeValue(typ Type, valueSource, tagSource stri
|
|||||||
nn, err = this.iprintf("}\n")
|
nn, err = this.iprintf("}\n")
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
nn, err = this.iprintf(
|
nn, err = this.iprintf(
|
||||||
"nn, err = encoder.WriteUintN(%d, %s.CN() + 1)\n",
|
"nn, err = encoder.WriteUintN(%d, %s.CN())\n",
|
||||||
len(typ.Fields), tagSource)
|
len(typ.Fields), tagSource)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
nn, err = this.generateErrorCheck()
|
nn, err = this.generateErrorCheck()
|
||||||
@ -709,7 +709,7 @@ func (this *Generator) generateDecodeBranch(hash [16]byte, typ Type, typeName st
|
|||||||
this.pop()
|
this.pop()
|
||||||
nn, err = this.iprintf("}\n")
|
nn, err = this.iprintf("}\n")
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
nn, err = this.iprintf("%s, nn, err = decoder.ReadUintN(int(tag.CN()) + 1)\n", lengthVar)
|
nn, err = this.iprintf("%s, nn, err = decoder.ReadUintN(int(tag.CN()))\n", lengthVar)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
nn, err = this.generateErrorCheck()
|
nn, err = this.generateErrorCheck()
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
@ -785,7 +785,7 @@ func (this *Generator) generateDecodeBranch(hash [16]byte, typ Type, typeName st
|
|||||||
this.pop()
|
this.pop()
|
||||||
nn, err = this.iprintf("}\n")
|
nn, err = this.iprintf("}\n")
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
nn, err = this.iprintf("%s, nn, err = decoder.ReadUintN(int(tag.CN()) + 1)\n", lengthVar)
|
nn, err = this.iprintf("%s, nn, err = decoder.ReadUintN(int(tag.CN()))\n", lengthVar)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
nn, err = this.generateErrorCheck()
|
nn, err = this.generateErrorCheck()
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
@ -952,13 +952,13 @@ func (this *Generator) generateTag(typ Type, source string) (tagVar string, n in
|
|||||||
nn, err := this.iprintf("%s := tape.BufferTag([]byte(%s))\n", tagVar, source)
|
nn, err := this.iprintf("%s := tape.BufferTag([]byte(%s))\n", tagVar, source)
|
||||||
n += nn; if err != nil { return tagVar, n, err }
|
n += nn; if err != nil { return tagVar, n, err }
|
||||||
case TypeArray:
|
case TypeArray:
|
||||||
nn, err := this.iprintf("%s := tape.OTA.WithCN(tape.IntBytes(uint64(len(%s))) - 1)\n", tagVar, source)
|
nn, err := this.iprintf("%s := tape.OTA.WithCN(tape.IntBytes(uint64(len(%s))))\n", tagVar, source)
|
||||||
n += nn; if err != nil { return tagVar, n, err }
|
n += nn; if err != nil { return tagVar, n, err }
|
||||||
case TypeTable:
|
case TypeTable:
|
||||||
nn, err := this.iprintf("%s := tape.KTV.WithCN(tape.IntBytes(uint64(len(%s))) - 1)\n", tagVar, source)
|
nn, err := this.iprintf("%s := tape.KTV.WithCN(tape.IntBytes(uint64(len(%s))))\n", tagVar, source)
|
||||||
n += nn; if err != nil { return tagVar, n, err }
|
n += nn; if err != nil { return tagVar, n, err }
|
||||||
case TypeTableDefined:
|
case TypeTableDefined:
|
||||||
nn, err := this.iprintf("%s := tape.KTV.WithCN(%d)\n", tagVar, tape.IntBytes(uint64(len(typ.Fields))) - 1)
|
nn, err := this.iprintf("%s := tape.KTV.WithCN(%d)\n", tagVar, tape.IntBytes(uint64(len(typ.Fields))))
|
||||||
n += nn; if err != nil { return tagVar, n, err }
|
n += nn; if err != nil { return tagVar, n, err }
|
||||||
case TypeNamed:
|
case TypeNamed:
|
||||||
resolved, err := this.resolveTypeName(typ.Name)
|
resolved, err := this.resolveTypeName(typ.Name)
|
||||||
|
|||||||
@ -103,7 +103,7 @@ func TestGenerateRunEncodeDecode(test *testing.T) {
|
|||||||
}
|
}
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&messageConnect,
|
&messageConnect,
|
||||||
tu.S(0xE0, 0x02).AddVar(
|
tu.S(0xE1, 0x02).AddVar(
|
||||||
[]byte { 0x00, 0x00, 0x86, 'r', 'a', 'r', 'i', 't', 'y' },
|
[]byte { 0x00, 0x00, 0x86, 'r', 'a', 'r', 'i', 't', 'y' },
|
||||||
[]byte { 0x00, 0x01, 0x84, 'g', 'e', 'm', 's' },
|
[]byte { 0x00, 0x01, 0x84, 'g', 'e', 'm', 's' },
|
||||||
))
|
))
|
||||||
@ -129,8 +129,8 @@ func TestGenerateRunEncodeDecode(test *testing.T) {
|
|||||||
}
|
}
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&messageUserList,
|
&messageUserList,
|
||||||
tu.S(0xE0, 0x01, 0x00, 0x00,
|
tu.S(0xE1, 0x01, 0x00, 0x00,
|
||||||
0xC0, 0x03, 0xE0,
|
0xC1, 0x03, 0xE1,
|
||||||
).Add(0x03).AddVar(
|
).Add(0x03).AddVar(
|
||||||
[]byte { 0x00, 0x00, 0x86, 'r', 'a', 'r', 'i', 't', 'y' },
|
[]byte { 0x00, 0x00, 0x86, 'r', 'a', 'r', 'i', 't', 'y' },
|
||||||
[]byte { 0x00, 0x01, 0x87, 'a', 's', 'd', 'j', 'a', 'd', 's' },
|
[]byte { 0x00, 0x01, 0x87, 'a', 's', 'd', 'j', 'a', 'd', 's' },
|
||||||
@ -155,7 +155,7 @@ func TestGenerateRunEncodeDecode(test *testing.T) {
|
|||||||
}
|
}
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&messagePulse,
|
&messagePulse,
|
||||||
tu.S(0xE0, 0x05).AddVar(
|
tu.S(0xE1, 0x05).AddVar(
|
||||||
[]byte { 0x00, 0x00, 0x09 },
|
[]byte { 0x00, 0x00, 0x09 },
|
||||||
[]byte { 0x00, 0x01, 0x41, 0xCA, 0xDF },
|
[]byte { 0x00, 0x01, 0x41, 0xCA, 0xDF },
|
||||||
[]byte { 0x00, 0x02, 0x61, 0x51, 0xAC },
|
[]byte { 0x00, 0x02, 0x61, 0x51, 0xAC },
|
||||||
@ -176,7 +176,7 @@ func TestGenerateRunEncodeDecode(test *testing.T) {
|
|||||||
}
|
}
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&messageNestedArray,
|
&messageNestedArray,
|
||||||
tu.S(0xC0, 0x02, 0xC0,
|
tu.S(0xC1, 0x02, 0xC1,
|
||||||
0x06, 0x20, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
|
0x06, 0x20, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
|
||||||
35, 0x20, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
|
35, 0x20, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
|
||||||
0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC,
|
0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC,
|
||||||
@ -202,7 +202,7 @@ func TestGenerateRunEncodeDecode(test *testing.T) {
|
|||||||
}
|
}
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&messageIntegers,
|
&messageIntegers,
|
||||||
tu.S(0xE0, 13).AddVar(
|
tu.S(0xE1, 13).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 },
|
||||||
@ -243,7 +243,7 @@ func TestGenerateRunEncodeDecode(test *testing.T) {
|
|||||||
}
|
}
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&messageDynamic,
|
&messageDynamic,
|
||||||
tu.S(0xE0, 14).AddVar(
|
tu.S(0xE1, 14).AddVar(
|
||||||
[]byte { 0x00, 0x00, 0x20, 0x23 },
|
[]byte { 0x00, 0x00, 0x20, 0x23 },
|
||||||
[]byte { 0x00, 0x01, 0x21, 0x32, 0x47 },
|
[]byte { 0x00, 0x01, 0x21, 0x32, 0x47 },
|
||||||
[]byte { 0x00, 0x02, 0x23, 0x87, 0x32, 0x45, 0x23 },
|
[]byte { 0x00, 0x02, 0x23, 0x87, 0x32, 0x45, 0x23 },
|
||||||
@ -255,15 +255,11 @@ func TestGenerateRunEncodeDecode(test *testing.T) {
|
|||||||
[]byte { 0x00, 0x08, 0x63, 0x45, 0x12, 0x63, 0xCE },
|
[]byte { 0x00, 0x08, 0x63, 0x45, 0x12, 0x63, 0xCE },
|
||||||
[]byte { 0x00, 0x09, 0x67, 0x40, 0x74, 0x4E, 0x3D, 0x6F, 0xCD, 0x17, 0x75 },
|
[]byte { 0x00, 0x09, 0x67, 0x40, 0x74, 0x4E, 0x3D, 0x6F, 0xCD, 0x17, 0x75 },
|
||||||
[]byte { 0x00, 0x0A, 0x87, 'f', 'o', 'x', ' ', 'b', 'e', 'd' },
|
[]byte { 0x00, 0x0A, 0x87, 'f', 'o', 'x', ' ', 'b', 'e', 'd' },
|
||||||
[]byte { 0x00, 0x0B, 0xC0, 0x04, 0x41,
|
[]byte { 0x00, 0x0B, 0xC4, 0x00, 0x07, 0x00, 0x06, 0x00, 0x05, 0x00, 0x04 },
|
||||||
0x00, 0x07,
|
[]byte { 0x00, 0x0C, 0xE1, 0x02,
|
||||||
0x00, 0x06,
|
0x00, 0x01, 0x20, 0x08,
|
||||||
0x00, 0x05,
|
|
||||||
0x00, 0x04 },
|
|
||||||
[]byte { 0x00, 0x0C, 0xE0, 0x02,
|
|
||||||
0x00, 0x01, 0x40, 0x08,
|
|
||||||
0x00, 0x02, 0x67, 0x40, 0x11, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9A },
|
0x00, 0x02, 0x67, 0x40, 0x11, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9A },
|
||||||
[]byte { 0x00, 0x0D, 0xE0, 0x03, // ERR
|
[]byte { 0x00, 0x0D, 0xE1, 0x03,
|
||||||
0x00, 0x01, 0x63, 0x43, 0xF4, 0xC0, 0x00,
|
0x00, 0x01, 0x63, 0x43, 0xF4, 0xC0, 0x00,
|
||||||
0x00, 0x02, 0x82, 'h', 'i',
|
0x00, 0x02, 0x82, 'h', 'i',
|
||||||
0x00, 0x03, 0x21, 0x39, 0x92 },
|
0x00, 0x03, 0x21, 0x39, 0x92 },
|
||||||
|
|||||||
@ -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: ", tu.Describe(destination))
|
log.Println("before: ", 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: ", tu.Describe(destination))
|
log.Println("got: ", destination)
|
||||||
log.Println("correct:", tu.Describe(message))
|
log.Println("correct:", 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,9 +2,8 @@ package testutil
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "slices"
|
import "slices"
|
||||||
import "reflect"
|
|
||||||
import "strings"
|
import "strings"
|
||||||
import "unicode"
|
import "reflect"
|
||||||
|
|
||||||
// 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
|
||||||
@ -125,10 +124,6 @@ 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")
|
||||||
@ -146,20 +141,12 @@ 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 }
|
||||||
field := typ.Field(index)
|
this.iprintf("%s: ", typ.Field(index).Name)
|
||||||
this.iprintf("%s: ", field.Name)
|
this.describe(value.FieldByIndex(indexBuffer[:]))
|
||||||
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("}")
|
this.iprintf("}\n")
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
this.printf("map {\n")
|
this.printf("map {\n")
|
||||||
this.indent += 1
|
this.indent += 1
|
||||||
@ -172,7 +159,7 @@ func (this *describer) describe(value reflect.Value) {
|
|||||||
this.iprintf("\n")
|
this.iprintf("\n")
|
||||||
}
|
}
|
||||||
this.indent -= 1
|
this.indent -= 1
|
||||||
this.iprintf("}")
|
this.iprintf("}\n")
|
||||||
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 := decodeAny(decoder, destination.Elem(), tag)
|
nn, err := DecodeAnyInto(decoder, destination, tag)
|
||||||
n += nn; if err != nil { return nil, n, err }
|
n += nn; if err != nil { return nil, n, err }
|
||||||
return destination.Elem().Interface(), n, err
|
return destination, n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// unknownSlicePlaceholder is inserted by skeletonValue and informs the program
|
// unknownSlicePlaceholder is inserted by skeletonValue and informs the program
|
||||||
@ -242,22 +242,12 @@ 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()) {
|
||||||
// im fucking so done dude. im so fucking done. this was
|
// need a skeleton value if we are assigning to any.
|
||||||
// supposed to only run when we need it but i guess it runs all
|
value := reflect.MakeMapWithSize(reflect.TypeOf(dummyMap), lengthCast)
|
||||||
// the time, because when we get a map destination (a valid,
|
destination.Set(value)
|
||||||
// allocated one) we break apart on SetMapIndex because of a nil
|
destination = value
|
||||||
// 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()
|
||||||
@ -397,11 +387,7 @@ 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:
|
||||||
cantAssign :=
|
if destination != reflect.TypeOf(dummyMap) {
|
||||||
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:
|
||||||
@ -510,8 +496,7 @@ 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 }
|
||||||
value := reflect.New(typ)
|
return reflect.New(typ), nil
|
||||||
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,12 +27,6 @@ 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 {
|
||||||
@ -55,11 +49,6 @@ 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
|
||||||
@ -206,7 +195,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 && index != 13 {
|
if index != 12 {
|
||||||
test.Log("- map[uint16] any")
|
test.Log("- map[uint16] any")
|
||||||
{ var dest = map[uint16] any { }; arrayCase(&dest) }
|
{ var dest = map[uint16] any { }; arrayCase(&dest) }
|
||||||
}
|
}
|
||||||
@ -307,63 +296,3 @@ func TestPeekSliceOnce(test *testing.T) {
|
|||||||
test.Fatalf("wrong n: %d != %d", got, correct)
|
test.Fatalf("wrong n: %d != %d", got, correct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTagAny(test *testing.T) {
|
|
||||||
cases := [][2]any {
|
|
||||||
[2]any { LSI.WithCN(3), int(9) },
|
|
||||||
[2]any { LSI.WithCN(0), int8(9) },
|
|
||||||
[2]any { LSI.WithCN(1), int16(9) },
|
|
||||||
[2]any { LSI.WithCN(3), int32(9) },
|
|
||||||
[2]any { LSI.WithCN(7), int64(9) },
|
|
||||||
[2]any { LI.WithCN(3), uint(9) },
|
|
||||||
[2]any { LI.WithCN(0), uint8(9) },
|
|
||||||
[2]any { LI.WithCN(1), uint16(9) },
|
|
||||||
[2]any { LI.WithCN(3), uint32(9) },
|
|
||||||
[2]any { LI.WithCN(7), uint64(9) },
|
|
||||||
[2]any { FP.WithCN(3), float32(9) },
|
|
||||||
[2]any { FP.WithCN(7), float64(9) },
|
|
||||||
[2]any { SBA.WithCN(12), "small string" },
|
|
||||||
[2]any { SBA.WithCN(12), []byte("small string") },
|
|
||||||
[2]any { LBA.WithCN(0), "this is a very long string that is long" },
|
|
||||||
[2]any { LBA.WithCN(0), []byte("this is a very long string that is long") },
|
|
||||||
[2]any { LBA.WithCN(1), lipsum },
|
|
||||||
[2]any { OTA.WithCN(0), []int { 1, 2, 3, 4, 5 } },
|
|
||||||
[2]any { OTA.WithCN(0), []string { "1, 2, 3, 4, 5" } },
|
|
||||||
[2]any { KTV.WithCN(0), map[uint16] any {
|
|
||||||
0: 1,
|
|
||||||
1: "wow",
|
|
||||||
2: 10.238,
|
|
||||||
45: -9,
|
|
||||||
9: map[uint16] any { },
|
|
||||||
}},
|
|
||||||
}
|
|
||||||
for _, cas := range cases {
|
|
||||||
test.Log(cas)
|
|
||||||
got, err := TagAny(cas[1])
|
|
||||||
if err != nil { test.Fatal(err) }
|
|
||||||
if correct := cas[0].(Tag); correct != got {
|
|
||||||
test.Fatalf("wrong tag: %v != %v", got, correct)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,11 +0,0 @@
|
|||||||
package tape
|
|
||||||
|
|
||||||
const lipsum = `Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.
|
|
||||||
|
|
||||||
Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.
|
|
||||||
|
|
||||||
Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.
|
|
||||||
|
|
||||||
Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.
|
|
||||||
|
|
||||||
Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.`
|
|
||||||
13
tape/tag.go
13
tape/tag.go
@ -18,17 +18,6 @@ type Tag byte; const (
|
|||||||
CNLimit Tag = 32 // All valid CNs are < CNLimit
|
CNLimit Tag = 32 // All valid CNs are < CNLimit
|
||||||
)
|
)
|
||||||
|
|
||||||
// what the first nybble of a tag means:
|
|
||||||
//
|
|
||||||
// 0-1 : SI
|
|
||||||
// 2-3 : LI
|
|
||||||
// 4-5 : LSI
|
|
||||||
// 6-7 : FP
|
|
||||||
// 8-9 : SBA
|
|
||||||
// A-B : LBA
|
|
||||||
// C-D : OTA
|
|
||||||
// E-F : KTV
|
|
||||||
|
|
||||||
func (tag Tag) TN() int {
|
func (tag Tag) TN() int {
|
||||||
return int(tag >> 5)
|
return int(tag >> 5)
|
||||||
}
|
}
|
||||||
@ -78,6 +67,6 @@ func bufferLenTag(length int) Tag {
|
|||||||
if length < int(CNLimit) {
|
if length < int(CNLimit) {
|
||||||
return SBA.WithCN(length)
|
return SBA.WithCN(length)
|
||||||
} else {
|
} else {
|
||||||
return LBA.WithCN(IntBytes(uint64(length)) - 1)
|
return LBA.WithCN(IntBytes(uint64(length)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user