Pool: documenation

This commit is contained in:
kayos@tcp.direct 2023-02-05 19:32:59 -08:00
parent 02695f44bd
commit 1a3c4cefc4
Signed by: kayos
GPG Key ID: 4B841471B4BEE979

View File

@ -6,10 +6,13 @@ import (
"sync"
)
// BufferFactory is a factory for creating and reusing bytes.Buffers.
// BufferFactory tries to be safer than using a sync.Pool directly by ensuring that the buffer is not returned twice.
type BufferFactory struct {
pool *sync.Pool
}
// NewBufferFactory creates a new BufferFactory that creates new buffers on demand.
func NewBufferFactory() BufferFactory {
return BufferFactory{
pool: &sync.Pool{
@ -18,6 +21,7 @@ func NewBufferFactory() BufferFactory {
}
}
// NewSizedBufferFactory creates a new BufferFactory that creates new buffers of the given size on demand.
func NewSizedBufferFactory(size int) BufferFactory {
return BufferFactory{
pool: &sync.Pool{
@ -26,6 +30,7 @@ func NewSizedBufferFactory(size int) BufferFactory {
}
}
// Put returns the buffer to the pool. It returns an error if the buffer has already been returned to the pool.
func (cf BufferFactory) Put(buf *Buffer) error {
var err = ErrBufferReturned
buf.o.Do(func() {
@ -37,12 +42,14 @@ func (cf BufferFactory) Put(buf *Buffer) error {
return err
}
// MustPut is the same as Put but panics if the buffer has already been returned to the pool.
func (cf BufferFactory) MustPut(buf *Buffer) {
if err := cf.Put(buf); err != nil {
panic(err)
}
}
// Get returns a buffer from the pool.
func (cf BufferFactory) Get() *Buffer {
return &Buffer{
cf.pool.Get().(*bytes.Buffer),
@ -50,11 +57,19 @@ func (cf BufferFactory) Get() *Buffer {
}
}
// Buffer is a wrapper around bytes.Buffer that can only be returned to a pool once.
type Buffer struct {
*bytes.Buffer
o *sync.Once
}
// Bytes returns a slice of length b.Len() holding the unread portion of the buffer.
// The slice is valid for use only until the next buffer modification (that is,
// only until the next call to a method like Read, Write, Reset, or Truncate).
// The slice aliases the buffer content at least until the next buffer modification,
// so immediate changes to the slice will affect the result of future reads.
//
// *This is from the bytes.Buffer docs.*
func (c Buffer) Bytes() []byte {
if c.Buffer == nil {
return nil
@ -62,6 +77,7 @@ func (c Buffer) Bytes() []byte {
return c.Buffer.Bytes()
}
// MustBytes is the same as Bytes but panics if the buffer has already been returned to the pool.
func (c Buffer) MustBytes() []byte {
if c.Buffer == nil {
panic(ErrBufferReturned)
@ -69,6 +85,12 @@ func (c Buffer) MustBytes() []byte {
return c.Buffer.Bytes()
}
// String returns the contents of the unread portion of the buffer
// as a string. If the Buffer is a nil pointer, it returns "<nil>".
//
// To build strings more efficiently, see the strings.Builder type.
//
// *This is from the bytes.Buffer docs.*
func (c Buffer) String() string {
if c.Buffer == nil {
return ""
@ -76,6 +98,7 @@ func (c Buffer) String() string {
return c.Buffer.String()
}
// MustString is the same as String but panics if the buffer has already been returned to the pool.
func (c Buffer) MustString() string {
if c.Buffer == nil {
panic(ErrBufferReturned)
@ -83,6 +106,12 @@ func (c Buffer) MustString() string {
return c.Buffer.String()
}
// Reset resets the buffer to be empty,
// but it retains the underlying storage for use by future writes.
// Reset is the same as Truncate(0).
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) Reset() error {
if c.Buffer == nil {
return ErrBufferReturned
@ -91,6 +120,7 @@ func (c Buffer) Reset() error {
return nil
}
// MustReset is the same as Reset but panics if the buffer has already been returned to the pool.
func (c Buffer) MustReset() {
if err := c.Reset(); err != nil {
panic(err)
@ -98,6 +128,11 @@ func (c Buffer) MustReset() {
c.Buffer.Reset()
}
// Len returns the number of bytes of the unread portion of the buffer;
// b.Len() == len(b.Bytes()).
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns 0 if the buffer has already been returned to the pool.
func (c Buffer) Len() int {
if c.Buffer == nil {
return 0
@ -105,6 +140,7 @@ func (c Buffer) Len() int {
return c.Buffer.Len()
}
// MustLen is the same as Len but panics if the buffer has already been returned to the pool.
func (c Buffer) MustLen() int {
if c.Buffer == nil {
panic(ErrBufferReturned)
@ -112,6 +148,12 @@ func (c Buffer) MustLen() int {
return c.Buffer.Len()
}
// Write appends the contents of p to the buffer, growing the buffer as
// needed. The return value n is the length of p; err is always nil. If the
// buffer becomes too large, Write will panic with ErrTooLarge.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) Write(p []byte) (int, error) {
if c.Buffer == nil {
return 0, ErrBufferReturned
@ -119,12 +161,20 @@ func (c Buffer) Write(p []byte) (int, error) {
return c.Buffer.Write(p)
}
// MustWrite is the same as Write but panics if the buffer has already been returned to the pool.
func (c Buffer) MustWrite(p []byte) {
if _, err := c.Write(p); err != nil {
panic(err)
}
}
// WriteRune appends the UTF-8 encoding of Unicode code point r to the
// buffer, returning its length and an error, which is always nil but is
// included to match bufio.Writer's WriteRune. The buffer is grown as needed;
// if it becomes too large, WriteRune will panic with ErrTooLarge.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) WriteRune(r rune) (int, error) {
if c.Buffer == nil {
return 0, ErrBufferReturned
@ -132,12 +182,20 @@ func (c Buffer) WriteRune(r rune) (int, error) {
return c.Buffer.WriteRune(r)
}
// MustWriteRune is the same as WriteRune but panics if the buffer has already been returned to the pool.
func (c Buffer) MustWriteRune(r rune) {
if _, err := c.WriteRune(r); err != nil {
panic(err)
}
}
// WriteByte appends the byte c to the buffer, growing the buffer as needed.
// The returned error is always nil, but is included to match bufio.Writer's
// WriteByte. If the buffer becomes too large, WriteByte will panic with
// ErrTooLarge.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) WriteByte(cyte byte) error {
if c.Buffer == nil {
return ErrBufferReturned
@ -145,12 +203,19 @@ func (c Buffer) WriteByte(cyte byte) error {
return c.Buffer.WriteByte(cyte)
}
// MustWriteByte is the same as WriteByte but panics if the buffer has already been returned to the pool.
func (c Buffer) MustWriteByte(cyte byte) {
if err := c.WriteByte(cyte); err != nil {
panic(err)
}
}
// WriteString appends the contents of s to the buffer, growing the buffer as
// needed. The return value n is the length of s; err is always nil. If the
// buffer becomes too large, WriteString will panic with ErrTooLarge.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) WriteString(str string) (int, error) {
if c.Buffer == nil {
return 0, ErrBufferReturned
@ -160,6 +225,9 @@ func (c Buffer) WriteString(str string) (int, error) {
// Grow grows the buffer's capacity, if necessary, to guarantee space for another n bytes. After Grow(n), at least n bytes can be written to the buffer without another allocation. If n is negative, Grow will panic. If the buffer can't grow it will panic with ErrTooLarge.
// If the buffer has already been returned to the pool, Grow will return ErrBufferReturned.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) Grow(n int) error {
if c.Buffer == nil {
return ErrBufferReturned
@ -168,6 +236,11 @@ func (c Buffer) Grow(n int) error {
return nil
}
// Cap returns the capacity of the buffer's underlying byte slice, that is, the
// total space allocated for the buffer's data.
//
// *This is from the bytes.Buffer docs.*
// If the buffer has already been returned to the pool, Cap will return 0.
func (c Buffer) Cap() int {
if c.Buffer == nil {
return 0
@ -175,6 +248,12 @@ func (c Buffer) Cap() int {
return c.Buffer.Cap()
}
// Truncate discards all but the first n unread bytes from the buffer
// but continues to use the same allocated storage.
// It panics if n is negative or greater than the length of the buffer.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) Truncate(n int) error {
if c.Buffer == nil {
return ErrBufferReturned
@ -183,12 +262,20 @@ func (c Buffer) Truncate(n int) error {
return nil
}
// MustTruncate is the same as Truncate but panics if the buffer has already been returned to the pool.
func (c Buffer) MustTruncate(n int) {
if err := c.Truncate(n); err != nil {
panic(err)
}
}
// ReadFrom reads data from r until EOF and appends it to the buffer, growing
// the buffer as needed. The return value n is the number of bytes read. Any
// error except io.EOF encountered during the read is also returned. If the
// buffer becomes too large, ReadFrom will panic with ErrTooLarge.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) ReadFrom(r io.Reader) (int64, error) {
if c.Buffer == nil {
return 0, ErrBufferReturned
@ -196,12 +283,20 @@ func (c Buffer) ReadFrom(r io.Reader) (int64, error) {
return c.Buffer.ReadFrom(r)
}
// MustReadFrom is the same as ReadFrom but panics if the buffer has already been returned to the pool.
func (c Buffer) MustReadFrom(r io.Reader) {
if _, err := c.ReadFrom(r); err != nil {
panic(err)
}
}
// WriteTo writes data to w until the buffer is drained or an error occurs.
// The return value n is the number of bytes written; it always fits into an
// int, but it is int64 to match the io.WriterTo interface. Any error
// encountered during the write is also returned.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) WriteTo(w io.Writer) (int64, error) {
if c.Buffer == nil {
return 0, ErrBufferReturned
@ -209,12 +304,20 @@ func (c Buffer) WriteTo(w io.Writer) (int64, error) {
return c.Buffer.WriteTo(w)
}
// MustWriteTo is the same as WriteTo but panics if the buffer has already been returned to the pool.
func (c Buffer) MustWriteTo(w io.Writer) {
if _, err := c.WriteTo(w); err != nil {
panic(err)
}
}
// Read reads the next len(p) bytes from the buffer or until the buffer
// is drained. The return value n is the number of bytes read. If the
// buffer has no data to return, err is io.EOF (unless len(p) is zero);
// otherwise it is nil.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) Read(p []byte) (int, error) {
if c.Buffer == nil {
return 0, ErrBufferReturned
@ -222,6 +325,11 @@ func (c Buffer) Read(p []byte) (int, error) {
return c.Buffer.Read(p)
}
// ReadByte reads and returns the next byte from the buffer.
// If no byte is available, it returns error io.EOF.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) ReadByte() (byte, error) {
if c.Buffer == nil {
return 0, ErrBufferReturned
@ -229,6 +337,14 @@ func (c Buffer) ReadByte() (byte, error) {
return c.Buffer.ReadByte()
}
// ReadRune reads and returns the next UTF-8-encoded
// Unicode code point from the buffer.
// If no bytes are available, the error returned is io.EOF.
// If the bytes are an erroneous UTF-8 encoding, it
// consumes one byte and returns U+FFFD, 1.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) ReadRune() (rune, int, error) {
if c.Buffer == nil {
return 0, 0, ErrBufferReturned
@ -236,6 +352,13 @@ func (c Buffer) ReadRune() (rune, int, error) {
return c.Buffer.ReadRune()
}
// UnreadByte unreads the last byte returned by the most recent successful
// read operation that read at least one byte. If a write has happened since
// the last read, if the last read returned an error, or if the read read zero
// bytes, UnreadByte returns an error.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) UnreadByte() error {
if c.Buffer == nil {
return ErrBufferReturned
@ -243,6 +366,14 @@ func (c Buffer) UnreadByte() error {
return c.Buffer.UnreadByte()
}
// UnreadRune unreads the last rune returned by ReadRune.
// If the most recent read or write operation on the buffer was
// not a successful ReadRune, UnreadRune returns an error. (In this regard
// it is stricter than UnreadByte, which will unread the last byte
// from any read operation.)
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) UnreadRune() error {
if c.Buffer == nil {
return ErrBufferReturned
@ -250,6 +381,15 @@ func (c Buffer) UnreadRune() error {
return c.Buffer.UnreadRune()
}
// ReadBytes reads until the first occurrence of delim in the input,
// returning a slice containing the data up to and including the delimiter.
// If ReadBytes encounters an error before finding a delimiter,
// it returns the data read before the error and the error itself (often io.EOF).
// ReadBytes returns err != nil if and only if the returned data does not end in
// delim.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns an error if the buffer has already been returned to the pool.
func (c Buffer) ReadBytes(delim byte) ([]byte, error) {
if c.Buffer == nil {
return nil, ErrBufferReturned
@ -257,6 +397,13 @@ func (c Buffer) ReadBytes(delim byte) ([]byte, error) {
return c.Buffer.ReadBytes(delim)
}
// Next returns a slice containing the next n bytes from the buffer,
// advancing the buffer as if the bytes had been returned by Read.
// If there are fewer than n bytes in the buffer, Next returns the entire buffer.
// The slice is only valid until the next call to a read or write method.
//
// *This is from the bytes.Buffer docs.*
// This wrapper returns nil if the buffer has already been returned to the pool.
func (c Buffer) Next(n int) []byte {
if c.Buffer == nil {
return nil