package linkedbuffer

import (
	
)

var ErrEOF = errors.New("EOF")

// buffer implements a generic buffer that can store any type of data.
// It is not thread-safe and should be used with a mutex.
// It is used by LinkedBuffer to store data and is not intended to be used directly.
type buffer[ any] struct {
	data           []
	nextWriteIndex int
	nextReadIndex  int
	next           *buffer[]
	zero           
}

func newBuffer[ any]( int) *buffer[] {
	return &buffer[]{
		data: make([], ),
	}
}

// Cap returns the capacity of the buffer.
func ( *buffer[]) () int {
	return cap(.data)
}

// Len returns the number of elements in the buffer.
func ( *buffer[]) () int {
	return .nextWriteIndex - .nextReadIndex
}

// Write writes a value to the buffer.
// If the buffer is full, it returns an EOF error.
func ( *buffer[]) ( ) error {
	if .nextWriteIndex >= .Cap() {
		// Buffer is full
		return ErrEOF
	}

	.data[.nextWriteIndex] = 
	.nextWriteIndex++
	return nil
}

// Read reads a value from the buffer.
// If the buffer is empty, it returns an EOF error.
// If the buffer has been read completely, it returns an EOF error.
func ( *buffer[]) () ( ,  error) {
	if .nextReadIndex >= .Cap() || (.next == nil && .nextReadIndex >= .nextWriteIndex) {
		// Buffer read completely, return EOF error
		 = ErrEOF
		return
	}

	 = .data[.nextReadIndex]

	// Remove reference to read value to prevent memory leaks caused by
	// holding references to submitted tasks.
	// See https://github.com/alitto/pond/issues/110
	.data[.nextReadIndex] = .zero

	.nextReadIndex++
	return
}