1
0
buffer/lib.go

105 lines
3.0 KiB
Go
Raw Normal View History

2026-02-17 16:58:00 +01:00
// alternative to bufio
// meant to be used with buffer from pool
package buffer
import (
"io"
"errors"
)
type Pool interface {
Get() ([]byte, error)
Put([]byte)
}
type ContentWriter interface {
WriteTo(io.WriteCloser) (int, error)
}
type Options struct {
// defaults to new instance created by DefaultPool()
Pool Pool
// may differ, default 512
ReadSize int
}
// initialize with NewReader or ReaderFrom
// uninitialized reader panics
// reads from the underlying reader until the first error, but only returns an error when the buffer is empty
// once the underlying reader returned an error, it doesn't attempt to read from it anymore
// the pool yes, the reader does not support concurrent access
type Reader struct {
reader *reader
}
var ErrZeroAllocation = errors.New("zero allocation")
func DefaultPool() Pool {
return newPool()
}
func NoPool(allocSize int) Pool {
return noPool{allocSize: allocSize}
}
func ReaderFrom(in io.Reader, o Options) Reader {
if o.Pool == nil {
o.Pool = DefaultPool()
}
if o.ReadSize <= 0 {
o.ReadSize = 1 << 9
}
return Reader{reader: &reader{options: o, in: in}}
}
func ReaderFromContent(w ContentWriter, o Options) Reader {
return Reader{}
}
// - it returns an error only when the underlying reader returned an error and the internal buffer is empty
// - if the underlying reader returns zero read length and nil error, and the buffer is empty, it returns zero
// read length and nil error. It's up the calling code to decide how to proceed in such cases
func (r Reader) Read(p []byte) (int, error) {
return r.reader.read(p)
}
// copy
// data and err when no delimiter found
// - when found the delimiter within max, consumes until and including the delimiter, and returns the consumed
// bytes, true, and nil error. If the underlying reader returned meanwhile a non-nil error, including EOF, it
// will be returned on subsequent reads after the internal buffer was consumed
// - when not found the delimiter within max, and the underlying reader didn't return an error, it returns zero
// length bytes, false and nil error
// - when not found the delimiter within max, and the underlying reader returned an error, it returns the
// buffered bytes, false and a nil error
// - when the buffer is empty, and the underlying reader previously returned an error, it returns zero length
// bytes, false, and the error
func (r Reader) ReadBytes(delimiter []byte, max int) ([]byte, bool, error) {
return r.reader.readBytes(delimiter, max)
}
// only returns an error when the underlying reader returned an error, or the used pool returned an error
func (r Reader) ReadUTF8(max int) ([]rune, int, error) {
return r.reader.readUTF8(max)
}
// not a copy
func (r Reader) Peek(max int) ([]byte, error) {
return r.reader.peek(max)
}
// not a copy
// can be wrong after error
func (r Reader) Buffered() []byte {
return r.reader.buffered()
}
// important that the writer must not modify the slice data, as defined in the io.Writer interface
func (r Reader) WriteTo(w io.Writer) (int64, error) {
return r.reader.writeTo(w)
}