github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/api/types/plugins/logdriver/io.go (about)

     1  package logdriver // import "github.com/docker/docker/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  }