// KEKS -- Go KEKS codec implementation
// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, version 3 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program.  If not, see <http://www.gnu.org/licenses/>.

package keks

import (
	"io"
	"unsafe"
)

func (ctx *Decoder) getByte() (b byte, err error) {
	if ctx.B == nil {
		var buf [1]byte
		_, err = ctx.R.Read(buf[:])
		b = buf[0]
		ctx.Read++
		return
	}
	if len(ctx.B) < 1 {
		err = io.ErrUnexpectedEOF
		return
	}
	b, ctx.B = ctx.B[0], ctx.B[1:]
	ctx.Read++
	return
}

// Read n bytes from the data source. If data source is R, then buf is
// allocated for each new read. If data source is B, then buf is a slice
// of the original B buffer.
func (ctx *Decoder) getBytes(n int) (s string, err error) {
	var read int
	if ctx.B == nil {
		var buf []byte
		if ctx.readBuf == nil {
			buf = make([]byte, n)
		} else {
			buf = ctx.readBuf[:n]
			if len(ctx.readBuf) < n {
				panic("readBuf is smaller")
			}
		}
		read, err = io.ReadFull(ctx.R, buf)
		ctx.Read += int64(read)
		if err != nil {
			return
		}
		s = unsafe.String(unsafe.SliceData(buf), len(buf))
		return
	}
	if len(ctx.B) < n {
		err = io.ErrUnexpectedEOF
		return
	}
	s = unsafe.String(unsafe.SliceData(ctx.B[:n]), n)
	ctx.B = ctx.B[n:]
	ctx.Read += int64(n)
	return
}
