package hopp import "fmt" import "encoding" import "git.tebibyte.media/sashakoshka/hopp/tape" // Message is any object that can be sent or received over a HOPP connection. type Message interface { // Method returns the method number of the message. This must be unique // within the protocol, and should not change between calls. Method() uint16 encoding.BinaryMarshaler encoding.BinaryUnmarshaler } var _ Message = new(MessageData) // MessageData represents a message that organizes its data into table pairs. It // can be used to alter a protocol at runtime, transmit data with arbitrary // keys, etc. Bear in mind that is less performant than generating code because // it has to make extra memory allocations and such. type MessageData struct { // Methd holds the method number. This should only be set once. Methd uint16 // Pairs maps tags to values. Pairs map[uint16] []byte } // Method returns the message's method field. func (this *MessageData) Method() uint16 { return this.Methd } // MarshalBinary implements the [encoding.BinaryMarshaler] interface. The // message is encoded using TAPE (Table Pair Encoding). func (this *MessageData) MarshalBinary() ([]byte, error) { buffer, err := tape.EncodePairs(this.Pairs) if err != nil { return nil, fmt.Errorf("marshaling MessageData: %w", err) } return buffer, nil } // UnmarshalBinary implements the [encoding.BinaryUnmarshaler] interface. The // message is decoded using TAPE (Table Pair Encoding). func (this *MessageData) UnmarshalBinary(buffer []byte) error { this.Pairs = make(map[uint16] []byte) pairs, err := tape.DecodePairs(buffer) if err != nil { return fmt.Errorf("unmarshaling MessageData: %w", err) } for key, value := range pairs { this.Pairs[key] = value } return nil }