package extypes import ( "errors" "sync" ) // QueueFullErr is returned when Enqueue is called on a full queue. var QueueFullErr = errors.New("queue full") // QueueEmptyErr is returned when Peak or Dequeue is called on an empty queue. var QueueEmptyErr = errors.New("queue empty") // Queue is a fixed-size FIFO queue protected by a mutex. type Queue[T any] struct { size uint64 mu sync.RWMutex queue Slice[T] } // CreateQueue creates a queue with the provided maximum size. func CreateQueue[T any](size uint64) *Queue[T] { return &Queue[T]{queue: make(Slice[T], 0, size), size: size} } // Len returns the current number of queued elements. func (q *Queue[T]) Len() uint64 { q.mu.RLock() defer q.mu.RUnlock() return uint64(q.queue.Len()) } // IsEmpty reports whether the queue currently holds no elements. func (q *Queue[T]) IsEmpty() bool { return q.Len() == 0 } // IsFull reports whether the queue has reached its configured size. func (q *Queue[T]) IsFull() bool { return q.Len() == q.size } // Size returns the configured queue capacity. func (q *Queue[T]) Size() uint64 { return q.size } // Enqueue appends el to the queue or returns QueueFullErr. func (q *Queue[T]) Enqueue(el T) error { q.mu.Lock() defer q.mu.Unlock() if uint64(len(q.queue)) == q.size { return QueueFullErr } q.queue = q.queue.Push(el) return nil } // Dequeue removes and returns the head element or QueueEmptyErr. func (q *Queue[T]) Dequeue() (T, error) { q.mu.Lock() defer q.mu.Unlock() var zero T if len(q.queue) == 0 { return zero, QueueEmptyErr } el := q.queue[0] copy(q.queue, q.queue[1:]) q.queue[len(q.queue)-1] = zero q.queue = q.queue[:len(q.queue)-1] return el, nil } // Peak returns the head element without removing it or QueueEmptyErr when the // queue is empty. func (q *Queue[T]) Peak() (T, error) { q.mu.RLock() defer q.mu.RUnlock() var zero T if len(q.queue) == 0 { return zero, QueueEmptyErr } return q.queue[0], nil } // Raw returns a copy of the queue contents from head to tail. func (q *Queue[T]) Raw() Slice[T] { q.mu.RLock() defer q.mu.RUnlock() return NewSliceFrom(q.queue) }