package b1 import ( "encoding/binary" "fmt" "io" ) type Wire struct { Len uint8 Text [127]rune } func MakeWire(s string) Wire { l := len(s) ss := Wire{} if l > len(ss.Text) { l = len(ss.Text) } ss.Len = uint8(l) copy(ss.Text[:], ([]rune(s))[0:l]) return ss } func (ss Wire) String() string { return string(ss.Text[:ss.Len]) } type Attr struct { Name Wire Value Wire } type MessageHeader struct { Kind int64 From int64 To int64 Method Wire AttrCount int8 BodyLength int64 } type Message struct { MessageHeader attrs []Attr body []byte } func (m Message) MarshalTo(w io.Writer) error { err := binary.Write(w, binary.LittleEndian, m.MessageHeader) if err != nil { return err } for i := 0; i < int(m.AttrCount) && i < len(m.attrs); i++ { attr := m.attrs[i] err = binary.Write(w, binary.LittleEndian, attr) if err != nil { return err } } if m.BodyLength > 0 { l, err := w.Write(m.body[0:m.BodyLength]) if l != int(m.BodyLength) { return fmt.Errorf("Message partial write: %d %d", l, m.BodyLength) } return err } return nil } func (m *Message) UnmarshalFrom(w io.Reader) error { err := binary.Read(w, binary.LittleEndian, &m.MessageHeader) if err != nil { return err } if m.AttrCount < 0 { return fmt.Errorf("Negative attr count.") } if m.BodyLength > (2 << 16) { return fmt.Errorf("Body too long.") } m.attrs = make([]Attr, m.AttrCount) m.body = make([]byte, m.BodyLength) for i := 0; i < int(m.AttrCount); i++ { err = binary.Read(w, binary.LittleEndian, &m.attrs[i]) if err != nil { return err } } if m.BodyLength > 0 { l, err := w.Read(m.body) if l != int(m.BodyLength) { return fmt.Errorf("Message partial read: %d %d", l, m.BodyLength) } return err } return nil } func MakeMessage(kind, from, to int64, method string, body []byte, attrs ...string) Message { mh := MessageHeader{kind, from, to, MakeWire(method), int8(len(attrs) / 2), int64(len(body))} mm := Message{} mm.MessageHeader = mh mm.attrs = make([]Attr, len(attrs)/2) for i := 1; i < len(attrs); i += 2 { mm.attrs[i/2] = Attr{MakeWire(attrs[i-1]), MakeWire(attrs[i])} } mm.body = body return mm }