// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package vom

import (
	"io"
)

const minBufFree = 1024 // buffers always have at least 1K free after growth

// encbuf manages the write buffer for encoders.  The approach is similar to
// bytes.Buffer, but the implementation is simplified to only deal with many
// writes followed by a read of the whole buffer.
type encbuf struct {
	buf []byte
	end int // [0, end) is data that's already written
}

func newEncbuf() *encbuf {
	return &encbuf{
		buf: make([]byte, minBufFree),
	}
}

// Bytes returns a slice of the bytes written so far.
func (b *encbuf) Bytes() []byte { return b.buf[:b.end] }

// Len returns the number of bytes written so far.
func (b *encbuf) Len() int { return b.end }

// Reset the length to 0 to start a new round of writes.
func (b *encbuf) Reset() { b.end = 0 }

// reserve at least min free bytes in the buffer.
func (b *encbuf) tryReserve(min int) {
	if len(b.buf)-b.end < min {
		newlen := len(b.buf) * 2
		if newlen-b.end < min {
			newlen = b.end + min + minBufFree
		}
		newbuf := make([]byte, newlen)
		copy(newbuf, b.buf[:b.end])
		b.buf = newbuf
	}
}

// Grow the buffer by n bytes, and returns those bytes.
//
// Different from bytes.Buffer.Grow, which doesn't return the bytes.  Although
// this makes expandingEncbuf slightly easier to misuse, it helps to improve performance
// by avoiding unnecessary copying.
func (b *encbuf) Grow(n int) []byte {
	b.tryReserve(n)
	oldend := b.end
	b.end += n
	return b.buf[oldend:b.end]
}

// WriteOneByte writes byte c into the buffer.
func (b *encbuf) WriteOneByte(c byte) {
	b.tryReserve(1)
	b.buf[b.end] = c
	b.end++
}

// Write writes a byte slice to the buffer.
func (b *encbuf) Write(p []byte) {
	b.tryReserve(len(p))
	b.end += copy(b.buf[b.end:], p)
}

// decbuf manages the read buffer for decoders.  The approach is similar to
// bufio.Reader, but the API is better suited for fast decoding.
type decbuf struct {
	buf      []byte
	beg, end int // [beg, end) is data read from reader but unread by the user
	lim      int // number of bytes left in limit, or -1 for no limit
	reader   io.Reader

	// It's faster to hold end than to use the len and cap properties of buf,
	// since end is cheaper to update than buf.
	version Version
}

// newDecbuf returns a new decbuf that fills its internal buffer by reading r.
func newDecbuf(r io.Reader) *decbuf {
	return &decbuf{
		buf:    make([]byte, minBufFree),
		lim:    -1,
		reader: r,
	}
}

// newDecbufFromBytes returns a new decbuf that reads directly from b.
func newDecbufFromBytes(b []byte) *decbuf {
	return &decbuf{
		buf:    b,
		end:    len(b),
		lim:    -1,
		reader: alwaysEOFReader{},
	}
}

type alwaysEOFReader struct{}

func (alwaysEOFReader) Read([]byte) (int, error) { return 0, io.EOF }

// Reset resets the buffer so it has no data.
func (b *decbuf) Reset() {
	b.beg = 0
	b.end = 0
	b.lim = -1
}

// SetLimit sets a limit to the bytes that are returned by decbuf; after a limit
// is set, subsequent reads cannot read past the limit, even if more bytes are
// available.  Attempts to read past the limit return io.EOF.  Call RemoveLimit
// to remove the limit.
//
// REQUIRES: limit >=0,
func (b *decbuf) SetLimit(limit int) {
	b.lim = limit
}

func (b *decbuf) HasDataAvailable() bool {
	return b.lim != 0 // -1 or positive
}

func (b *decbuf) Limit() int {
	return b.lim
}

// RemoveLimit removes the limit, and returns the number of leftover bytes.
// Returns -1 if no limit was set.
func (b *decbuf) RemoveLimit() int {
	leftover := b.lim
	b.lim = -1
	return leftover
}

// fill the buffer with at least min bytes of data.  Returns an error if fewer
// than min bytes could be filled.  Doesn't advance the read position.
func (b *decbuf) fill(min int) error {
	switch avail := b.end - b.beg; {
	case avail >= min:
		// Fastpath - enough bytes are available.
		return nil
	case len(b.buf) < min:
		// The buffer isn't big enough.  Make a new buffer that's big enough and
		// copy existing data to the front.
		newlen := len(b.buf) * 2
		if newlen < min+minBufFree {
			newlen = min + minBufFree
		}
		newbuf := make([]byte, newlen)
		b.end = copy(newbuf, b.buf[b.beg:b.end])
		b.beg = 0
		b.buf = newbuf
	default:
		// The buffer is big enough.  Move existing data to the front.
		b.moveDataToFront()
	}
	// INVARIANT: len(b.buf)-b.beg >= min
	//
	// Fill [b.end:] until min bytes are available.  We must loop since Read may
	// return success with fewer bytes than requested.
	for b.end-b.beg < min {
		switch nread, err := b.reader.Read(b.buf[b.end:]); {
		case nread > 0:
			b.end += nread
		case err != nil:
			return err
		}
	}
	return nil
}

// moveDataToFront moves existing data in buf to the front, so that b.beg is 0.
func (b *decbuf) moveDataToFront() {
	b.end = copy(b.buf, b.buf[b.beg:b.end])
	b.beg = 0
}

// ReadSmall returns a buffer with the next n bytes, and increments the read
// position past those bytes.  Returns an error if fewer than n bytes are
// available.
//
// The returned slice points directly at our internal buffer, and is only valid
// until the next decbuf call.
//
// REQUIRES: n >= 0
func (b *decbuf) ReadSmall(n int) ([]byte, error) {
	if b.lim > -1 {
		if b.lim < n {
			b.lim = 0
			return nil, io.EOF
		}
		b.lim -= n
	}
	if err := b.fill(n); err != nil {
		return nil, err
	}
	buf := b.buf[b.beg : b.beg+n]
	b.beg += n
	return buf, nil
}

// PeekSmall returns a buffer with at least the next n bytes, but possibly
// more.  The read position isn't incremented.  Returns an error if fewer than
// min bytes are available.
//
// The returned slice points directly at our internal buffer, and is only valid
// until the next decbuf call.
//
// REQUIRES: min >= 0
func (b *decbuf) PeekSmall(min int) ([]byte, error) {
	if b.lim > -1 && b.lim < min {
		return nil, io.EOF
	}
	if err := b.fill(min); err != nil {
		return nil, err
	}
	return b.buf[b.beg:b.end], nil
}

// Skip increments the read position past the next n bytes.  Returns an error if
// fewer than n bytes are available.
//
// REQUIRES: n >= 0
func (b *decbuf) Skip(n int) error {
	if b.lim > -1 {
		if b.lim < n {
			n = b.lim
			return io.EOF
		}
		b.lim -= n
	}
	// If enough bytes are available, just update indices.
	avail := b.end - b.beg
	if avail >= n {
		b.beg += n
		return nil
	}
	n -= avail
	// Keep reading into buf until we've read enough bytes.
	for {
		switch nread, err := b.reader.Read(b.buf); {
		case nread > 0:
			if nread >= n {
				b.beg = n
				b.end = nread
				return nil
			}
			n -= nread
		case err != nil:
			return err
		}
	}
}

// ReadByte returns the next byte, and increments the read position.
func (b *decbuf) ReadByte() (byte, error) {
	if b.lim > -1 {
		if b.lim == 0 {
			return 0, io.EOF
		}
		b.lim--
	}
	if err := b.fill(1); err != nil {
		return 0, err
	}
	ret := b.buf[b.beg]
	b.beg++
	return ret, nil
}

// PeekByte returns the next byte, without changing the read position.
func (b *decbuf) PeekByte() (byte, error) {
	if b.lim == 0 {
		return 0, io.EOF
	}
	if err := b.fill(1); err != nil {
		return 0, err
	}
	return b.buf[b.beg], nil
}

// ReadIntoBuf reads the next len(p) bytes into p, and increments the read position
// past those bytes.  Returns an error if fewer than len(p) bytes are available.
func (b *decbuf) ReadIntoBuf(p []byte) error {
	if b.lim > -1 {
		if b.lim < len(p) {
			return io.EOF
		}
		b.lim -= len(p)
	}
	// Copy bytes from the buffer.
	ncopy := copy(p, b.buf[b.beg:b.end])
	b.beg += ncopy
	p = p[ncopy:]
	// Keep reading into p until we've read enough bytes.
	for len(p) > 0 {
		switch nread, err := b.reader.Read(p); {
		case nread > 0:
			p = p[nread:]
		case err != nil:
			return err
		}
	}
	return nil
}
