From e5d7ad0702a6f7e72b27faeca25b33ba97b0f1b9 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 19 Oct 2025 13:16:59 -0400 Subject: [PATCH] generate: Emit Send/Receive functions --- generate/generate.go | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/generate/generate.go b/generate/generate.go index 97f73bf..ea2762b 100644 --- a/generate/generate.go +++ b/generate/generate.go @@ -35,6 +35,15 @@ type Message interface { Method() uint16 } +// Send encodes a message and sends it along a transaction. +func Send(trans hopp.Trans, message Message) (n int, err error) { + writer, err := trans.SendWriter(message.Method()) + if err != nil { return n, err } + defer writer.Close() + encoder := tape.NewEncoder(writer) + return message.Encode(encoder) +} + // 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 @@ -121,6 +130,10 @@ func (this *Generator) Generate(protocol *Protocol) (n int, err error) { n += nn; if err != nil { return n, err } } + // receive + nn, err = this.generateReceive() + n += nn; if err != nil { return n, err } + return n, nil } @@ -1184,6 +1197,51 @@ func (this *Generator) generateCanAssign(typ Type, tagSource string) (n int, err return n, nil } +// generateReceive generates a function Receive(hopp.Trans) (Message, int, error) +func (this *Generator) generateReceive() (n int, err error) { + nn, err := this.iprintf( + "\n// Receive decodes a message from a transaction and returns it as a value.\n" + + "// Use a type switch to determine what type of message it is.\n") + n += nn; if err != nil { return n, err } + nn, err = this.iprintf( + "func Receive(trans hopp.Trans) (message any, n int, err error) {\n") + n += nn; if err != nil { return n, err } + this.push() + nn, err = this.iprintf("method, reader, err := trans.ReceiveReader()\n") + n += nn; if err != nil { return n, err } + nn, err = this.iprintf("decoder := tape.NewDecoder(reader)\n") + n += nn; if err != nil { return n, err } + nn, err = this.iprintf("if err != nil { return nil, n, err }\n") + n += nn; if err != nil { return n, err } + nn, err = this.iprintf("switch method {\n") + n += nn; if err != nil { return n, err } + for method, message := range this.protocol.Messages { + nn, err = this.iprintf("case %04X:\n", method) + n += nn; if err != nil { return n, err } + this.push() + nn, err = this.iprintf( + "var message %s\n", + this.resolveMessageName(message.Name)) + n += nn; if err != nil { return n, err } + nn, err := this.iprintf( + "nn, err := message.Decode(decoder)\n") + n += nn; if err != nil { return n, err } + nn, err = this.iprintf("n += nn; if err != nil { return nil, n, err }\n") + n += nn; if err != nil { return n, err } + nn, err = this.iprintf("return message, n, nil\n") + n += nn; if err != nil { return n, err } + this.pop() + } + nn, err = this.iprint("}\n") + n += nn; if err != nil { return n, err } + nn, err = this.iprintf("return nil, n, hopp.ErrUnknownMethod\n") + n += nn; if err != nil { return n, err } + this.pop() + nn, err = this.iprint("}\n") + 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