postmoogle/vendor/go.mau.fi/util/exslices/stack.go
2025-12-09 10:58:52 +00:00

80 lines
1.5 KiB
Go

// Copyright (c) 2024 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package exslices
import (
"iter"
)
type Stack[T comparable] []T
func (s *Stack[T]) Push(v ...T) {
*s = append(*s, v...)
}
// Peek returns the top item from the stack without removing it.
func (s *Stack[T]) Peek() (v T, ok bool) {
return s.PeekN(1)
}
// PeekN returns the nth item from the top of the stack (1-based).
func (s *Stack[T]) PeekN(n int) (v T, ok bool) {
if len(*s) < n {
return
}
v = (*s)[len(*s)-n]
ok = true
return
}
// Pop removes and returns the top item from the stack.
func (s *Stack[T]) Pop() (v T, ok bool) {
v, ok = s.Peek()
if ok {
*s = (*s)[:len(*s)-1]
}
return
}
func (s *Stack[T]) PeekValue() T {
v, _ := s.Peek()
return v
}
func (s *Stack[T]) PopValue() T {
v, _ := s.Pop()
return v
}
// Index returns the highest index of the given value in the stack, or -1 if not found.
func (s *Stack[T]) Index(val T) int {
for i := len(*s) - 1; i >= 0; i-- {
if (*s)[i] == val {
return i
}
}
return -1
}
// Has returns whether the given value is in the stack.
func (s *Stack[T]) Has(val T) bool {
return s.Index(val) != -1
}
func (s *Stack[T]) PopIter() iter.Seq[T] {
return func(yield func(T) bool) {
for {
v, ok := s.Pop()
if !ok {
return
}
if !yield(v) {
return
}
}
}
}