// This is a derivitive work of Go's bytes.Buffer implementation.
//
// Originally copyright 2009 The Go Authors. All rights reserved.
//
// Modifications copyright 2018 Steven Allen. All rights reserved.
//
// Use of this source code is governed by both a BSD-style and an MIT-style
// license that can be found in the LICENSE_BSD and LICENSE files.

package pool

import (
	
)

// Buffer is a buffer like bytes.Buffer that:
//
// 1. Uses a buffer pool.
// 2. Frees memory on read.
//
// If you only have a few buffers and read/write at a steady rate, *don't* use
// this package, it'll be slower.
//
// However:
//
// 1. If you frequently create/destroy buffers, this implementation will be
//    significantly nicer to the allocator.
// 2. If you have many buffers with bursty traffic, this implementation will use
//    significantly less memory.
type Buffer struct {
	// Pool is the buffer pool to use. If nil, this Buffer will use the
	// global buffer pool.
	Pool *BufferPool

	buf  []byte
	rOff int

	// Preallocated slice for samll reads/writes.
	// This is *really* important for performance and only costs 8 words.
	bootstrap [64]byte
}

// NewBuffer constructs a new buffer initialized to `buf`.
// Unlike `bytes.Buffer`, we *copy* the buffer but don't reuse it (to ensure
// that we *only* use buffers from the pool).
func ( []byte) *Buffer {
	 := new(Buffer)
	if len() > 0 {
		.buf = .getBuf(len())
		copy(.buf, )
	}
	return 
}

// NewBufferString is identical to NewBuffer *except* that it allows one to
// initialize the buffer from a string (without having to allocate an
// intermediate bytes slice).
func ( string) *Buffer {
	 := new(Buffer)
	if len() > 0 {
		.buf = .getBuf(len())
		copy(.buf, )
	}
	return 
}

func ( *Buffer) ( int) int {
	 := len(.buf)
	 := cap(.buf)

	if  >= + {
		.buf = .buf[:+]
		return 
	}

	 := .Len()

	 := 2* + 

	// Slide if cap >= minCap.
	// Reallocate otherwise.
	if  >=  {
		copy(.buf, .buf[.rOff:])
	} else {
		// Needs new buffer.
		 := .getBuf()
		copy(, .buf[.rOff:])
		.returnBuf()
		.buf = 
	}

	.rOff = 0
	.buf = .buf[:+]
	return 
}

func ( *Buffer) () *BufferPool {
	if .Pool == nil {
		return GlobalPool
	}
	return .Pool
}

func ( *Buffer) () {
	if cap(.buf) > len(.bootstrap) {
		.getPool().Put(.buf)
	}
	.buf = nil
}

func ( *Buffer) ( int) []byte {
	if  <= len(.bootstrap) {
		return .bootstrap[:]
	}
	return .getPool().Get()
}

// Len returns the number of bytes that can be read from this buffer.
func ( *Buffer) () int {
	return len(.buf) - .rOff
}

// Cap returns the current capacity of the buffer.
//
// Note: Buffer *may* re-allocate when writing (or growing by) `n` bytes even if
// `Cap() < Len() + n` to avoid excessive copying.
func ( *Buffer) () int {
	return cap(.buf)
}

// Bytes returns the slice of bytes currently buffered in the Buffer.
//
// The buffer returned by Bytes is valid until the next call grow, truncate,
// read, or write. Really, just don't touch the Buffer until you're done with
// the return value of this function.
func ( *Buffer) () []byte {
	return .buf[.rOff:]
}

// String returns the string representation of the buffer.
//
// It returns `<nil>` the buffer is a nil pointer.
func ( *Buffer) () string {
	if  == nil {
		return "<nil>"
	}
	return string(.buf[.rOff:])
}

// WriteString writes a string to the buffer.
//
// This function is identical to Write except that it allows one to write a
// string directly without allocating an intermediate byte slice.
func ( *Buffer) ( string) (int, error) {
	 := .grow(len())
	return copy(.buf[:], ), nil
}

// Truncate truncates the Buffer.
//
// Panics if `n > b.Len()`.
//
// This function may free memory by shrinking the internal buffer.
func ( *Buffer) ( int) {
	if  < 0 ||  > .Len() {
		panic("truncation out of range")
	}
	.buf = .buf[:.rOff+]
	.shrink()
}

// Reset is equivalent to Truncate(0).
func ( *Buffer) () {
	.returnBuf()
	.rOff = 0
}

// ReadByte reads a single byte from the Buffer.
func ( *Buffer) () (byte, error) {
	if .rOff >= len(.buf) {
		return 0, io.EOF
	}
	 := .buf[.rOff]
	.rOff++
	return , nil
}

// WriteByte writes a single byte to the Buffer.
func ( *Buffer) ( byte) error {
	 := .grow(1)
	.buf[] = 
	return nil
}

// Grow grows the internal buffer such that `n` bytes can be written without
// reallocating.
func ( *Buffer) ( int) {
	 := .grow()
	.buf = .buf[:]
}

// Next is an alternative to `Read` that returns a byte slice instead of taking
// one.
//
// The returned byte slice is valid until the next read, write, grow, or
// truncate.
func ( *Buffer) ( int) []byte {
	 := .Len()
	if  <  {
		 = 
	}
	 := .buf[.rOff : .rOff+]
	.rOff += 
	return 
}

// Write writes the byte slice to the buffer.
func ( *Buffer) ( []byte) (int, error) {
	 := .grow(len())
	return copy(.buf[:], ), nil
}

// WriteTo copies from the buffer into the given writer until the buffer is
// empty.
func ( *Buffer) ( io.Writer) (int64, error) {
	if .rOff < len(.buf) {
		,  := .Write(.buf[.rOff:])
		.rOff += 
		if .rOff > len(.buf) {
			panic("invalid write count")
		}
		.shrink()
		return int64(), 
	}
	return 0, nil
}

// MinRead is the minimum slice size passed to a Read call by
// Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond
// what is required to hold the contents of r, ReadFrom will not grow the
// underlying buffer.
const MinRead = 512

// ReadFrom reads from the given reader into the buffer.
func ( *Buffer) ( io.Reader) (int64, error) {
	 := int64(0)
	for {
		 := .grow(MinRead)
		// Use *entire* buffer.
		.buf = .buf[:cap(.buf)]

		,  := .Read(.buf[:])
		.buf = .buf[:+]
		 += int64()
		switch  {
		case nil:
		case io.EOF:
			 = nil
			fallthrough
		default:
			.shrink()
			return , 
		}
	}
}

// Read reads at most `len(buf)` bytes from the internal buffer into the given
// buffer.
func ( *Buffer) ( []byte) (int, error) {
	if len() == 0 {
		return 0, nil
	}
	if .rOff >= len(.buf) {
		return 0, io.EOF
	}
	 := copy(, .buf[.rOff:])
	.rOff += 
	.shrink()
	return , nil
}

func ( *Buffer) () {
	 := .Cap()
	// Either nil or bootstrap.
	if  <= len(.bootstrap) {
		return
	}

	 := .Len()
	if  == 0 {
		// Shortcut if empty.
		.returnBuf()
		.rOff = 0
	} else if *8 <  {
		// Only shrink when capacity > 8x length. Avoids shrinking too aggressively.
		 := .getBuf()
		copy(, .buf[.rOff:])
		.returnBuf()
		.rOff = 0
		.buf = [:]
	}
}