// Package circ implements a circular FIFO buffer. package circ // B is a circular FIFO buffer. type B[T any] struct { buf []T len int head int tail int } // Make creates a new buffer. func Make[T any](cap int) B[T] { buf := make([]T, cap) return B[T]{buf: buf} } // Capacity returns the total capacity of the buffer. func (b *B[T]) Capacity() int { return cap(b.buf) } // Len returns the number of items in the buffer. func (b *B[T]) Len() int { return b.len } // CanPush returns true if the buffer has space for new items. func (b *B[T]) CanPush() bool { return cap(b.buf)-b.len != 0 } // CanPop returns true if the buffer has one or more items. func (b *B[T]) CanPop() bool { return b.len != 0 } // PopFront returns the front-most item from the buffer. // // If the buffer is empty, it panics. func (b *B[T]) PopFront() T { if !b.CanPop() { panic("cannot pop from empty buffer") } item := b.buf[b.head] // clear buffer slot so as not to hold on to garbage var empty T b.buf[b.head] = empty b.len-- b.head++ if b.head == cap(b.buf) { b.head = 0 } return item } // PushBack adds an item to the end of the buffer. // // If the buffer is full, it panics. func (b *B[T]) PushBack(value T) { if !b.CanPush() { panic("cannot push back to full buffer") } b.buf[b.tail] = value b.len++ b.tail++ if b.tail == cap(b.buf) { b.tail = 0 } }