package main import ( "bytes" "encoding/binary" "io" "time" ) type StorableMessage interface { Write(w io.Writer) error } type Message struct { Type uint16 TimeStamp *int64 Content interface{} } type MessageWriter struct { io.Writer } type StorableMessageHeader struct { Version uint16 Type uint16 TimeStamp int64 DataLength uint64 } func GetData(fn func(w io.Writer) error) ([]byte, error) { var buf bytes.Buffer err := fn(&buf) if err != nil { return nil, err } b := buf.Bytes() return b, nil } func (m Message) Write(w io.Writer) error { h, err := GetMessageHandler(m.Type) if err != nil { return err } data, err := GetData(func(w io.Writer) error { return h.Write(&m, w) }) if err != nil { return err } ts := time.Now().Unix() if m.TimeStamp != nil { ts = *m.TimeStamp } err = binary.Write(w, binary.LittleEndian, StorableMessageHeader{ Version: 1, Type: m.Type, TimeStamp: ts, DataLength: uint64(len(data)), }) w.Write(data) return err } func ReadMessage(reader io.Reader, m *Message) error { h, err := GetMessageHandler(m.Type) if err != nil { return err } header := StorableMessageHeader{} err = binary.Read(reader, binary.LittleEndian, &header) if err != nil { return err } messageBytes := make([]byte, header.DataLength) _, err = reader.Read(messageBytes) if err != nil { return err } content, err := h.Read(messageBytes) if err != nil { return err } m.Content = content m.Type = header.Type m.TimeStamp = &header.TimeStamp return nil }