diff --git a/mempool/src/lib.rs b/mempool/src/lib.rs index d12d785..b9469d3 100644 --- a/mempool/src/lib.rs +++ b/mempool/src/lib.rs @@ -1 +1,169 @@ -//ToDo: Add mempool module +use std::collections::VecDeque; + +use mempoolitem::MemPoolItem; + +pub mod mempoolitem; + +pub struct MemPool { + items: VecDeque, +} + +impl MemPool { + pub fn new() -> Self { + Self { + items: VecDeque::new(), + } + } + + pub fn pop_last(&mut self) -> Option { + self.items.pop_front() + } + + pub fn peek_last(&self) -> Option<&Item> { + self.items.front() + } + + pub fn push_item(&mut self, item: Item) { + self.items.push_back(item); + } + + pub fn len(&self) -> usize { + self.items.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn pop_size(&mut self, size: usize) -> Vec { + let mut ret_vec = vec![]; + + for _ in 0..size { + let item = self.pop_last(); + + match item { + Some(item) => ret_vec.push(item), + None => break, + } + } + + ret_vec + } + + pub fn drain_size(&mut self, remainder: usize) -> Vec { + self.pop_size(self.len().saturating_sub(remainder)) + } +} + +impl Default for MemPool { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +mod tests { + use std::vec; + + use super::*; + + pub type ItemId = u64; + + #[derive(Debug, PartialEq, Eq)] + pub struct TestItem { + id: ItemId, + } + + impl MemPoolItem for TestItem { + type Identifier = ItemId; + + fn identifier(&self) -> Self::Identifier { + self.id + } + } + + fn test_item_with_id(id: u64) -> TestItem { + TestItem { id } + } + + #[test] + fn test_create_empty_mempool() { + let _: MemPool = MemPool::new(); + } + + #[test] + fn test_push_pop() { + let mut mempool: MemPool = MemPool::new(); + + let items = vec![ + test_item_with_id(1), + test_item_with_id(2), + test_item_with_id(3), + ]; + + for item in items { + mempool.push_item(item); + } + assert_eq!(mempool.len(), 3); + + let item = mempool.pop_last(); + + assert_eq!(item, Some(TestItem { id: 1 })); + assert_eq!(mempool.len(), 2); + + let item = mempool.pop_last(); + + assert_eq!(item, Some(TestItem { id: 2 })); + assert_eq!(mempool.len(), 1); + + let item = mempool.pop_last(); + + assert_eq!(item, Some(TestItem { id: 3 })); + assert_eq!(mempool.len(), 0); + + let item = mempool.pop_last(); + + assert_eq!(item, None); + } + + #[test] + fn test_pop_many() { + let mut mempool: MemPool = MemPool::new(); + + let mut items = vec![]; + + for i in 1..11 { + items.push(test_item_with_id(i)); + } + + for item in items { + mempool.push_item(item); + } + + assert_eq!(mempool.len(), 10); + + let items1 = mempool.pop_size(4); + assert_eq!( + items1, + vec![ + test_item_with_id(1), + test_item_with_id(2), + test_item_with_id(3), + test_item_with_id(4) + ] + ); + assert_eq!(mempool.len(), 6); + + let items2 = mempool.drain_size(2); + assert_eq!( + items2, + vec![ + test_item_with_id(5), + test_item_with_id(6), + test_item_with_id(7), + test_item_with_id(8) + ] + ); + assert_eq!(mempool.len(), 2); + } +} diff --git a/mempool/src/mempoolitem.rs b/mempool/src/mempoolitem.rs new file mode 100644 index 0000000..b3e3530 --- /dev/null +++ b/mempool/src/mempoolitem.rs @@ -0,0 +1,4 @@ +pub trait MemPoolItem { + type Identifier; + fn identifier(&self) -> Self::Identifier; +}