use smallvec::SmallVec;
#[derive(Debug, Clone)]
pub struct PriorityStack<T> {
stacks: Vec<SmallVec<[T; 1]>>,
}
impl<T> PriorityStack<T> {
pub fn new() -> Self {
Self {
stacks: Vec::default(),
}
}
pub fn with_priority_capacity(priority: usize) -> Self {
Self {
stacks: Vec::with_capacity(priority),
}
}
pub fn push(&mut self, priority: usize, item: T) {
if priority >= self.stacks.len() {
self.stacks.resize_with(priority + 1, Default::default);
}
self.stacks[priority].push(item);
}
pub fn pop(&mut self) -> Option<T> {
self.stacks
.iter_mut()
.rev()
.filter_map(SmallVec::pop)
.next()
}
pub fn pop_prio(&mut self) -> Option<(usize, T)> {
self.stacks
.iter_mut()
.enumerate()
.rev()
.filter_map(|(i, stack)| stack.pop().map(|x| (i, x)))
.next()
}
pub fn peek(&self) -> Option<&T> {
self.stacks
.iter()
.rev()
.filter_map(|stack| stack.last())
.next()
}
pub fn peek_prio(&self) -> Option<(usize, &T)> {
self.stacks
.iter()
.enumerate()
.rev()
.filter_map(|(i, stack)| stack.last().map(|x| (i, x)))
.next()
}
pub fn len(&self) -> usize {
self.stacks.iter().map(SmallVec::len).sum()
}
pub fn is_empty(&self) -> bool {
self.stacks.is_empty()
}
}
impl<T> Default for PriorityStack<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Extend<(usize, T)> for PriorityStack<T> {
fn extend<I: IntoIterator<Item = (usize, T)>>(&mut self, iter: I) {
for (priority, item) in iter {
self.push(priority, item);
}
}
}