internal/buffer/buffer.go (142 lines of code) (raw):

package buffer import ( "encoding/binary" "io" ) // Buffer is similar to bytes.Buffer but specialized for this module. // The zero-value is an empty buffer ready for use. type Buffer struct { b []byte i int } // New creates a new Buffer with b as its initial contents. // Use this to start reading from b. func New(b []byte) *Buffer { return &Buffer{b: b} } // Next returns a slice containing the next n bytes from the buffer and advances the buffer. // If there are fewer than n bytes in the buffer, Next returns the remaining contents, false. // The slice is only valid until the next call to a read or write method. func (b *Buffer) Next(n int64) ([]byte, bool) { if b.readCheck(n) { buf := b.b[b.i:len(b.b)] b.i = len(b.b) return buf, false } buf := b.b[b.i : b.i+int(n)] b.i += int(n) return buf, true } // Skip advances the buffer by n bytes. func (b *Buffer) Skip(n int) { b.i += n } // Reset resets the buffer to be empty but retains // the underlying storage for use by future writes. func (b *Buffer) Reset() { b.b = b.b[:0] b.i = 0 } // Reclaim moves the unread portion of the buffer to the // beginning of the underlying slice and resets the index. func (b *Buffer) Reclaim() { l := b.Len() copy(b.b[:l], b.b[b.i:]) b.b = b.b[:l] b.i = 0 } // returns true if n is larger than the unread portion of the buffer func (b *Buffer) readCheck(n int64) bool { return int64(b.i)+n > int64(len(b.b)) } // ReadByte reads one byte from the buffer and advances the buffer. // If there are insufficient bytes, an error is returned. func (b *Buffer) ReadByte() (byte, error) { if b.readCheck(1) { return 0, io.EOF } byte_ := b.b[b.i] b.i++ return byte_, nil } // PeekByte returns the next byte in the buffer without advancing the buffer. // If there are insufficient bytes, an error is returned. func (b *Buffer) PeekByte() (byte, error) { if b.readCheck(1) { return 0, io.EOF } return b.b[b.i], nil } // ReadUint16 reads two bytes from the buffer and decodes them // as big-endian into a uint16. Advances the buffer by two. // If there are insufficient bytes, an error is returned. func (b *Buffer) ReadUint16() (uint16, error) { if b.readCheck(2) { return 0, io.EOF } n := binary.BigEndian.Uint16(b.b[b.i:]) b.i += 2 return n, nil } // ReadUint32 reads four bytes from the buffer and decodes them // as big-endian into a uint32. Advances the buffer by four. // If there are insufficient bytes, an error is returned. func (b *Buffer) ReadUint32() (uint32, error) { if b.readCheck(4) { return 0, io.EOF } n := binary.BigEndian.Uint32(b.b[b.i:]) b.i += 4 return n, nil } // ReadUint64 reads eight bytes from the buffer and decodes them // as big-endian into a uint64. Advances the buffer by eight. // If there are insufficient bytes, an error is returned. func (b *Buffer) ReadUint64() (uint64, error) { if b.readCheck(8) { return 0, io.EOF } n := binary.BigEndian.Uint64(b.b[b.i : b.i+8]) b.i += 8 return n, nil } // ReadFromOnce reads from r to populate the buffer. // Reads up to cap - len of the underlying slice. func (b *Buffer) ReadFromOnce(r io.Reader) error { const minRead = 512 l := len(b.b) if cap(b.b)-l < minRead { total := l * 2 if total == 0 { total = minRead } new := make([]byte, l, total) copy(new, b.b) b.b = new } n, err := r.Read(b.b[l:cap(b.b)]) b.b = b.b[:l+n] return err } // Append appends p to the existing buffer. func (b *Buffer) Append(p []byte) { b.b = append(b.b, p...) } // AppendByte appends bb to the existing buffer. func (b *Buffer) AppendByte(bb byte) { b.b = append(b.b, bb) } // AppendString appends s to the existing buffer. func (b *Buffer) AppendString(s string) { b.b = append(b.b, s...) } // Len returns the number of bytes of the unread portion of the buffer. func (b *Buffer) Len() int { return len(b.b) - b.i } // Size returns the number of bytes that have been read from this buffer. // This implies a minimum size of the underlying buffer. func (b *Buffer) Size() int { return b.i } // Bytes returns a slice containing the unread portion of the buffer. func (b *Buffer) Bytes() []byte { return b.b[b.i:] } // Detach returns the underlying byte slice, disassociating it from the buffer. func (b *Buffer) Detach() []byte { temp := b.b b.b = nil b.i = 0 return temp } // AppendUint16 appends n as two bytes in big-endian encoding. func (b *Buffer) AppendUint16(n uint16) { b.b = append(b.b, byte(n>>8), byte(n), ) } // AppendUint32 appends n as four bytes in big-endian encoding. func (b *Buffer) AppendUint32(n uint32) { b.b = append(b.b, byte(n>>24), byte(n>>16), byte(n>>8), byte(n), ) } // AppendUint64 appends n as eight bytes in big-endian encoding. func (b *Buffer) AppendUint64(n uint64) { b.b = append(b.b, byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32), byte(n>>24), byte(n>>16), byte(n>>8), byte(n), ) }