github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/api/types/plugins/logdriver/io.go (about) 1 package logdriver // import "github.com/demonoid81/moby/api/types/plugins/logdriver" 2 3 import ( 4 "encoding/binary" 5 "io" 6 ) 7 8 const binaryEncodeLen = 4 9 10 // LogEntryEncoder encodes a LogEntry to a protobuf stream 11 // The stream should look like: 12 // 13 // [uint32 binary encoded message size][protobuf message] 14 // 15 // To decode an entry, read the first 4 bytes to get the size of the entry, 16 // then read `size` bytes from the stream. 17 type LogEntryEncoder interface { 18 Encode(*LogEntry) error 19 } 20 21 // NewLogEntryEncoder creates a protobuf stream encoder for log entries. 22 // This is used to write out log entries to a stream. 23 func NewLogEntryEncoder(w io.Writer) LogEntryEncoder { 24 return &logEntryEncoder{ 25 w: w, 26 buf: make([]byte, 1024), 27 } 28 } 29 30 type logEntryEncoder struct { 31 buf []byte 32 w io.Writer 33 } 34 35 func (e *logEntryEncoder) Encode(l *LogEntry) error { 36 n := l.Size() 37 38 total := n + binaryEncodeLen 39 if total > len(e.buf) { 40 e.buf = make([]byte, total) 41 } 42 binary.BigEndian.PutUint32(e.buf, uint32(n)) 43 44 if _, err := l.MarshalTo(e.buf[binaryEncodeLen:]); err != nil { 45 return err 46 } 47 _, err := e.w.Write(e.buf[:total]) 48 return err 49 } 50 51 // LogEntryDecoder decodes log entries from a stream 52 // It is expected that the wire format is as defined by LogEntryEncoder. 53 type LogEntryDecoder interface { 54 Decode(*LogEntry) error 55 } 56 57 // NewLogEntryDecoder creates a new stream decoder for log entries 58 func NewLogEntryDecoder(r io.Reader) LogEntryDecoder { 59 return &logEntryDecoder{ 60 lenBuf: make([]byte, binaryEncodeLen), 61 buf: make([]byte, 1024), 62 r: r, 63 } 64 } 65 66 type logEntryDecoder struct { 67 r io.Reader 68 lenBuf []byte 69 buf []byte 70 } 71 72 func (d *logEntryDecoder) Decode(l *LogEntry) error { 73 _, err := io.ReadFull(d.r, d.lenBuf) 74 if err != nil { 75 return err 76 } 77 78 size := int(binary.BigEndian.Uint32(d.lenBuf)) 79 if len(d.buf) < size { 80 d.buf = make([]byte, size) 81 } 82 83 if _, err := io.ReadFull(d.r, d.buf[:size]); err != nil { 84 return err 85 } 86 return l.Unmarshal(d.buf[:size]) 87 }