generate: Implement decoding (untested)
This commit is contained in:
parent
d3d7b07a74
commit
b73f9fa7ce
@ -190,7 +190,7 @@ func (this *Generator) generateMessage(method uint16, message Message) (n int, e
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.println()
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("nn, err := encoder.WriteUint8(uint8(tag))\n")
|
||||
nn, err = this.iprintf("nn, err := encoder.WriteTag(tag)\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateErrorCheck()
|
||||
n += nn; if err != nil { return n, err }
|
||||
@ -210,7 +210,12 @@ func (this *Generator) generateMessage(method uint16, message Message) (n int, e
|
||||
this.resolveMessageName(message.Name))
|
||||
n += nn; if err != nil { return n, err }
|
||||
this.push()
|
||||
// TODO this is a stub
|
||||
nn, err = this.iprintf("tag, nn, err := decoder.ReadTag()\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateErrorCheck()
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateDecodeValue(message.Type, "this", "tag")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("return n, nil\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
this.pop()
|
||||
@ -377,8 +382,10 @@ func (this *Generator) generateEncodeValue(typ Type, valueSource, tagSource stri
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateErrorCheck()
|
||||
n += nn; if err != nil { return n, err }
|
||||
default:
|
||||
panic(fmt.Errorf("unknown type: %T", typ))
|
||||
}
|
||||
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
@ -393,10 +400,180 @@ func (this *Generator) generateEncodeValue(typ Type, valueSource, tagSource stri
|
||||
// - err error
|
||||
// - nn int
|
||||
func (this *Generator) generateDecodeValue(typ Type, valueSource, tagSource string) (n int, err error) {
|
||||
// TODO generate stub so the code runs and we can test encoding at least+
|
||||
|
||||
switch typ := typ.(type) {
|
||||
case TypeInt:
|
||||
// SI: (none)
|
||||
// LI: <value: IntN>
|
||||
if typ.Bits <= 5 {
|
||||
// SI stores the value in the tag, so we write nothing here
|
||||
break
|
||||
}
|
||||
prefix := "ReadUint"
|
||||
if typ.Signed {
|
||||
prefix = "ReadInt"
|
||||
}
|
||||
nn, err := this.iprintf("*%s, nn, err = encoder.%s%d()\n", valueSource, prefix, typ.Bits)
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateErrorCheck()
|
||||
n += nn; if err != nil { return n, err }
|
||||
case TypeFloat:
|
||||
// FP: <value: FloatN>
|
||||
nn, err := this.iprintf("%s, nn, err = encoder.ReadFloat%d(%s)\n", valueSource, typ.Bits)
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateErrorCheck()
|
||||
n += nn; if err != nil { return n, err }
|
||||
case TypeString, TypeBuffer:
|
||||
// SBA: <data: U8>*
|
||||
// LBA: <length: UN> <data: U8>*
|
||||
nn, err := this.iprintf("{\n")
|
||||
this.push()
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("var length uint64\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("if %s.Is(tape.LBA) {\n", tagSource)
|
||||
n += nn; if err != nil { return n, err }
|
||||
this.push()
|
||||
nn, err = this.iprintf(
|
||||
"length, nn, err = encoder.ReadUintN(uint64(%s.CN()))\n",
|
||||
tagSource)
|
||||
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("} else {\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
this.push()
|
||||
nn, err = this.iprintf("length = uint64(%s.CN())\n", tagSource)
|
||||
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("buffer := make([]byte, int(length))\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("nn, err = encoder.Read(buffer)\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateErrorCheck()
|
||||
n += nn; if err != nil { return n, err }
|
||||
if _, ok := typ.(TypeString); ok {
|
||||
nn, err = this.iprintf("*%s = string(buffer)\n", valueSource)
|
||||
n += nn; if err != nil { return n, err }
|
||||
} else {
|
||||
nn, err = this.iprintf("*%s = buffer\n", valueSource)
|
||||
n += nn; if err != nil { return n, err }
|
||||
}
|
||||
this.pop()
|
||||
nn, err = this.iprintf("}\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
case TypeArray:
|
||||
// OTA: <length: UN> <elementTag: tape.Tag> <values>*
|
||||
nn, err := this.iprintf("{\n")
|
||||
this.push()
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("var length uint64\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf(
|
||||
"length, nn, err = encoder.ReadUintN(uint64(%s.CN()))\n",
|
||||
tagSource)
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateErrorCheck()
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("*%s = make(", valueSource)
|
||||
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(", int(length))\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("var itemTag tape.Tag\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("itemTag, nn, err = encoder.ReadTag()\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateErrorCheck()
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("for index := range length {\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
this.push()
|
||||
nn, err = this.generateDecodeValue(
|
||||
typ.Element,
|
||||
fmt.Sprintf("(&(*%s)[index])", valueSource),
|
||||
"itemTag")
|
||||
n += nn; if err != nil { return n, err }
|
||||
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 }
|
||||
case TypeTable:
|
||||
// KTV: <length: UN> (<key: U16> <tag: Tag> <value>)*
|
||||
nn, err := this.iprintf(
|
||||
"nn, err = tape.DecodeAny(decoder, %s, %s)\n",
|
||||
valueSource, tagSource)
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateErrorCheck()
|
||||
n += nn; if err != nil { return n, err }
|
||||
case TypeTableDefined:
|
||||
// KTV: <length: UN> (<key: U16> <tag: Tag> <value>)*
|
||||
nn, err := this.iprintf("{\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
this.push()
|
||||
nn, err = this.iprintf("var length uint64\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf(
|
||||
"length, nn, err = encoder.ReadUintN(uint64(%s.CN()))\n",
|
||||
tagSource)
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateErrorCheck()
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("for _ = range length {\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
this.push()
|
||||
nn, err = this.iprintf("var key uint16\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("key, nn, err = decoder.ReadUint16()\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateErrorCheck()
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("var itemTag tape.Tag\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("itemTag, nn, err = decoder.ReadTag()\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateErrorCheck()
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.iprintf("switch key {\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
keys := slices.Collect(maps.Keys(typ.Fields))
|
||||
slices.Sort(keys)
|
||||
for _, key := range keys {
|
||||
field := typ.Fields[key]
|
||||
nn, err = this.iprintf("case 0x%04X:\n", key)
|
||||
n += nn; if err != nil { return n, err }
|
||||
this.push()
|
||||
nn, err = this.generateDecodeValue(
|
||||
field.Type,
|
||||
fmt.Sprintf("(&%s.%s)", valueSource, field.Name),
|
||||
"itemTag")
|
||||
n += nn; if err != nil { return n, err }
|
||||
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 }
|
||||
this.pop()
|
||||
nn, err = this.iprintf("}\n")
|
||||
n += nn; if err != nil { return n, err }
|
||||
case TypeNamed:
|
||||
// WHATEVER: [WHATEVER]
|
||||
nn, err := this.iprintf("nn, err = %s.DecodeValue(encoder, %s)\n", valueSource, tagSource)
|
||||
n += nn; if err != nil { return n, err }
|
||||
nn, err = this.generateErrorCheck()
|
||||
n += nn; if err != nil { return n, err }
|
||||
default:
|
||||
panic(fmt.Errorf("unknown type: %T", typ))
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (this *Generator) generateErrorCheck() (n int, err error) {
|
||||
@ -438,6 +615,8 @@ func (this *Generator) generateTag(typ Type, source string) (n int, err error) {
|
||||
if err != nil { return n, err }
|
||||
nn, err := this.generateTag(resolved, source)
|
||||
n += nn; if err != nil { return n, err }
|
||||
default:
|
||||
panic(fmt.Errorf("unknown type: %T", typ))
|
||||
}
|
||||
|
||||
return n, nil
|
||||
|
Loading…
Reference in New Issue
Block a user