|
@@ -0,0 +1,111 @@
|
|
|
+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
|
|
|
+}
|