diff --git a/generate/generate.go b/generate/generate.go index e6d8eea..3180957 100644 --- a/generate/generate.go +++ b/generate/generate.go @@ -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: + 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: + 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: * + // LBA: * + 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: * + 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: ( )* + 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: ( )* + 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