message-size-increase #3

Open
sashakoshka wants to merge 209 commits from message-size-increase into main
Showing only changes of commit c4dd129fc5 - Show all commits

View File

@ -34,6 +34,19 @@ type Message interface {
// Method returns the method code of the message.
Method() uint16
}
// canAssign determines if data from the given source tag can be assigned to
// a Go type represented by destination. It is designed to receive destination
// values from [generate.Generator.generateCanAssign]. The eventual Go type and
// the destination tag must come from the same (or hash-equivalent) PDL type.
func canAssign(destination, source tape.Tag) bool {
if destination.Is(source) { return true }
if (destination == tape.SBA || destination == tape.LBA) &&
(source == tape.SBA || source == tape.LBA) {
return true
}
return false
}
`
// Generator converts protocols into Go code.
@ -585,6 +598,7 @@ func (this *Generator) generateDecodeBranch(hash [16]byte, typ Type) (n int, err
nn, err = this.iprintf("for _ = range %s {\n", lengthVar)
n += nn; if err != nil { return n, err }
this.push()
// FIXME: wrong tag var
nn, err = this.iprintf("nn, err = tape.Skim(decoder, tag)")
n += nn; if err != nil { return n, err }
nn, err = this.generateErrorCheck()
@ -597,6 +611,12 @@ func (this *Generator) generateDecodeBranch(hash [16]byte, typ Type) (n int, err
return n, nil
}
// FIXME: the tag is validated improperly, the result of
// generateTag means basically nothing here because
// there is no data in the destination, we need another
// function that checks if a tag can be assigned to a
// PDL type
// validate header
// TODO: here, validate that length is less than the
// max, whatever that is configured to be. the reason we
@ -632,7 +652,102 @@ func (this *Generator) generateDecodeBranch(hash [16]byte, typ Type) (n int, err
n += nn; if err != nil { return n, err }
case TypeTableDefined:
// KTV: <length: UN> (<key: U16> <tag: Tag> <value>)*
// TODO
// read header
lengthVar := this.newTemporaryVar("length")
nn, err := this.iprintf("var %s uint64\n", lengthVar)
n += nn; if err != nil { return n, err }
nn, err = this.iprintf("%s, nn, err = decoder.ReadUintN(int(tag.CN()))\n", lengthVar)
n += nn; if err != nil { return n, err }
nn, err = this.generateErrorCheck()
n += nn; if err != nil { return n, err }
indexVar := this.newTemporaryVar("index")
nn, err = this.iprintf("%s := 0\n", indexVar)
n += nn; if err != nil { return n, err }
// validate header
// TODO: here, validate that length is less than the
// max, whatever that is configured to be. if not, stop
// ALL decoding. skimming huge big ass data could cause
// problems
// read fields
nn, err = this.iprintf("for index = range %s {\n", lengthVar)
n += nn; if err != nil { return n, err }
this.push()
// read field header
fieldKeyVar := this.newTemporaryVar("fieldKey")
nn, err = this.iprintf("var %s uint16\n", fieldKeyVar)
n += nn; if err != nil { return n, err }
nn, err = this.iprintf("%s, nn, err = decoder.ReadUint16()\n", fieldKeyVar)
n += nn; if err != nil { return n, err }
nn, err = this.generateErrorCheck()
n += nn; if err != nil { return n, err }
fieldTagVar := this.newTemporaryVar("fieldTag")
nn, err = this.iprintf("var %s tape.Tag\n", fieldTagVar)
n += nn; if err != nil { return n, err }
nn, err = this.iprintf("%s, nn, err = decoder.ReadTag()\n", fieldTagVar)
n += nn; if err != nil { return n, err }
nn, err = this.generateErrorCheck()
n += nn; if err != nil { return n, err }
// abort field macro
abortField := func() (n int, err error) {
nn, err = this.iprintf("tape.Skim(decoder, %s)", fieldTagVar)
n += nn; if err != nil { return n, err }
nn, err = this.iprintf("continue")
n += nn; if err != nil { return n, err }
return n, nil
}
// switch on tag
nn, err = this.iprintf("switch %s {\n", fieldTagVar)
n += nn; if err != nil { return n, err }
this.push()
for _, key := range slices.Sorted(maps.Keys(typ.Fields)) {
field := typ.Fields[key]
nn, err = this.iprintf("case %s:\n", fieldTagVar)
n += nn; if err != nil { return n, err }
this.push()
// validate field header
nn, err = this.iprintf("if !(")
n += nn; if err != nil { return n, err }
nn, err = this.generateCanAssign(field.Type, fieldTagVar)
n += nn; if err != nil { return n, err }
nn, err = this.printf(") {\n")
n += nn; if err != nil { return n, err }
this.push()
nn, err = abortField()
n += nn; if err != nil { return n, err }
this.pop()
nn, err = this.iprintf("}\n")
n += nn; if err != nil { return n, err }
// decode payload
nn, err = this.generateDecodeValue(field.Type, fmt.Sprintf("&(this.%s)", field.Name), fieldTagVar)
n += nn; if err != nil { return n, err }
this.pop()
}
nn, err = this.iprintf("default:\n")
n += nn; if err != nil { return n, err }
this.push()
abortField()
this.pop()
nn, err = this.iprintf("}\n")
n += nn; if err != nil { return n, err }
this.pop()
nn, err = this.iprintf("}\n")
n += nn; if err != nil { return n, err }
// TODO once options are implemented, have a set of
// bools for each non-optional field, and check here
// that they are all true. a counter will not work
// because if someone specifies a non-optional field
// twice, they can neglect to specify another
// non-optional field and we won't even know because the
// count will still be even. we shouldn't use a map
// either because its an allocation and its way more
// memory than just, like 5 bools (on the stack no less)
default: return n, fmt.Errorf("unexpected type: %T", typ)
}
@ -831,6 +946,19 @@ func (this *Generator) generateTypeTableDefined(typ TypeTableDefined) (n int, er
return n, nil
}
// generateCanAssign generates an expression which checks if the tag specified
// by tagSource can be assigned to a Go destination generated from typ. The
// generated code is INLINE.
func (this *Generator) generateCanAssign(typ Type, tagSource string) (n int, err error) {
nn, err := this.printf("canAssign(")
n += nn; if err != nil { return n, err }
nn, err = this.generateTN(typ)
n += nn; if err != nil { return n, err }
nn, err = this.printf(", %s)", tagSource)
n += nn; if err != nil { return n, err }
return n, nil
}
func (this *Generator) validateIntBitSize(size int) error {
switch size {
case 5, 8, 16, 32, 64: return nil