use crate::{
Codec, Encoding, Item, IterableStorage, KeySerde, Map, Order, StorageError, StorageMut,
};
use std::ops::Bound;
pub struct PriorityQueue<'a, K: KeySerde + Ord + Clone, V: Codec<Enc>, Enc: Encoding> {
map: Map<'a, K, Item<'a, V, Enc>>,
}
impl<'a, K: KeySerde + Ord + Clone, V: Codec<Enc>, Enc: Encoding> PriorityQueue<'a, K, V, Enc> {
pub const fn new(prefix: &'static [u8]) -> Self {
Self {
map: Map::new(prefix),
}
}
pub fn push<S: StorageMut>(
&self,
storage: &mut S,
priority: K,
value: &V,
) -> Result<(), StorageError<Enc>> {
self.map.at(priority)?.save(storage, value)
}
pub fn peek<S: IterableStorage>(
&self,
storage: &S,
order: Order,
) -> Result<Option<(K, V)>, StorageError<Enc>> {
let mut iter = self
.map
.range(storage, Bound::Unbounded, Bound::Unbounded, order)?;
let item = iter.next();
match item {
Some(Ok((key, value))) => Ok(Some((key.0, value))),
Some(Err(e)) => Err(e),
None => Ok(None),
}
}
pub fn pop<S: StorageMut + IterableStorage>(
&self,
storage: &mut S,
order: Order,
) -> Result<Option<(K, V)>, StorageError<Enc>> {
if let Some((key, value)) = self.peek(storage, order)? {
self.map.at(key.clone())?.delete(storage)?;
Ok(Some((key, value)))
} else {
Ok(None)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::mock::DisplayEncoding;
use std::collections::BTreeMap;
#[test]
fn test_priority_queue() {
let mut storage = BTreeMap::new();
let pq: PriorityQueue<i32, String, DisplayEncoding> = PriorityQueue::new(b"test_pq");
pq.push(&mut storage, 3, &"third".to_string()).unwrap();
pq.push(&mut storage, 1, &"first".to_string()).unwrap();
pq.push(&mut storage, 2, &"second".to_string()).unwrap();
assert_eq!(
pq.peek(&storage, Order::Ascending).unwrap(),
Some((1, "first".to_string()))
);
assert_eq!(
pq.peek(&storage, Order::Descending).unwrap(),
Some((3, "third".to_string()))
);
assert_eq!(
pq.pop(&mut storage, Order::Ascending).unwrap(),
Some((1, "first".to_string()))
);
assert_eq!(
pq.pop(&mut storage, Order::Ascending).unwrap(),
Some((2, "second".to_string()))
);
assert_eq!(
pq.pop(&mut storage, Order::Ascending).unwrap(),
Some((3, "third".to_string()))
);
assert_eq!(pq.pop(&mut storage, Order::Ascending).unwrap(), None);
}
}