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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user