generate: Decode arrays (but don't validate their length yet)

This commit is contained in:
Sasha Koshka 2025-08-05 06:22:27 -04:00
parent 7dcfc08678
commit 2cbf58d558

View File

@ -555,17 +555,88 @@ func (this *Generator) generateDecodeBranch(hash [16]byte, typ Type) (n int, err
n += nn; if err != nil { return n, err } n += nn; if err != nil { return n, err }
nn, err = this.printf(" decoder *tape.Decoder, tag tape.Tag) (nn int, err error) \n{") nn, err = this.printf(" decoder *tape.Decoder, tag tape.Tag) (nn int, err error) \n{")
n += nn; if err != nil { return n, err } n += nn; if err != nil { return n, err }
this.push()
switch typ := typ.(type) { nn, err = this.iprintf("var nn int\n")
case TypeArray: n += nn; if err != nil { return n, err }
// OTA: <length: UN> <elementTag: tape.Tag> <values>*
case TypeTableDefined: switch typ := typ.(type) {
// KTV: <length: UN> (<key: U16> <tag: Tag> <value>)* case TypeArray:
// TODO // OTA: <length: UN> <elementTag: tape.Tag> <values>*
default: return n, fmt.Errorf("unexpected type: %T", typ) // 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 }
elementTagVar := this.newTemporaryVar("elementTag")
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.ReadTag()\n", elementTagVar)
n += nn; if err != nil { return n, err }
nn, err = this.generateErrorCheck()
n += nn; if err != nil { return n, err }
// abort macro
abort := func() (n int, err error) {
// skim entire array
nn, err = this.iprintf("for _ = range %s {\n", lengthVar)
n += nn; if err != nil { return n, err }
this.push()
nn, err = this.iprintf("nn, err = tape.Skim(decoder, tag)")
n += nn; if err != nil { return n, err }
nn, err = this.generateErrorCheck()
n += nn; if err != nil { return n, err }
this.pop()
nn, err = this.iprintf("}\n")
n += nn; if err != nil { return n, err }
nn, err = this.iprintf("return n, nil")
n += nn; if err != nil { return n, err }
return n, nil
}
// validate header
// TODO: here, validate that length is less than the
// max, whatever that is configured to be. the reason we
// want to read it here is that we would have to skip
// the tag anyway so why not.
nn, err = this.iprintf("if %s != ", elementTagVar)
n += nn; if err != nil { return n, err }
nn, err = this.generateTag(typ.Element, "(*this)")
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 = abort()
n += nn; if err != nil { return n, err }
this.pop()
nn, err = this.iprintf("}\n")
n += nn; if err != nil { return n, err }
// decode payloads
nn, err = this.iprintf("*this = make(")
n += nn; if err != nil { return n, err }
nn, err = this.generateType(typ)
n += nn; if err != nil { return n, err }
nn, err = this.printf(", %s)\n", lengthVar)
n += nn; if err != nil { return n, err }
nn, err = this.iprintf("for index := range %s {\n", lengthVar)
n += nn; if err != nil { return n, err }
this.push()
nn, err = this.generateDecodeValue(typ.Element, "(*this)[index]", elementTagVar)
n += nn; if err != nil { return n, err }
this.pop()
nn, err = this.iprintf("}\n")
n += nn; if err != nil { return n, err }
case TypeTableDefined:
// KTV: <length: UN> (<key: U16> <tag: Tag> <value>)*
// TODO
default: return n, fmt.Errorf("unexpected type: %T", typ)
}
this.pop()
nn, err = this.iprintf("}") nn, err = this.iprintf("}")
n += nn; if err != nil { return n, err } n += nn; if err != nil { return n, err }
return n, nil return n, nil