use crate::block_storage::BlockStorage;
use serde::{Deserialize, Serialize};
use std::error::Error;
use std::fs::File;
use std::marker::PhantomData;
pub struct Queue<T> {
store: BlockStorage,
header: Header,
data_type: PhantomData<T>,
}
impl<T> Queue<T>
where
T: Serialize,
for<'de> T: Deserialize<'de>,
{
pub fn new(file: File) -> Result<Self, Box<dyn Error>> {
let mut store = BlockStorage::new(file)?;
let header = Self::read_header(&mut store)?;
let data_type = PhantomData;
let mut queue = Self {
store,
header,
data_type,
};
queue.save_header()?;
Ok(queue)
}
pub fn len(&self) -> usize {
self.header.elements_count
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
fn read_header(store: &mut BlockStorage) -> Result<Header, Box<dyn Error>> {
let bytes = store.read(0)?;
if store.is_empty() {
let header = Header::default();
let bytes: Vec<u8> = bincode::serialize(&header)?;
store.create(bytes.as_slice())?;
Ok(header)
} else {
let header = bincode::deserialize_from(bytes.as_slice())?;
Ok(header)
}
}
fn save_header(&mut self) -> Result<(), Box<dyn Error>> {
let bytes: Vec<u8> = bincode::serialize(&self.header)?;
self.store.update(0, bytes.as_slice())
}
pub fn enqueue(&mut self, data: T) -> Result<(), Box<dyn Error>> {
let mut element = Element {
body: data,
next: 0,
prev: 0,
};
if self.header.first_element != 0 {
element.next = self.header.first_element;
}
let bytes: Vec<u8> = bincode::serialize(&element)?;
let index = self.store.create(bytes.as_slice())?;
if self.header.first_element != 0 {
let first_index = self.header.first_element;
let first_bytes = self.store.read(first_index)?;
let mut first: Element<T> = bincode::deserialize_from(first_bytes.as_slice())?;
first.prev = index;
let first_bytes: Vec<u8> = bincode::serialize(&first)?;
self.store.update(first_index, first_bytes.as_slice())?;
}
if self.header.last_element == 0 {
self.header.last_element = index;
}
self.header.first_element = index;
self.header.elements_count += 1;
self.save_header()?;
Ok(())
}
pub fn dequeue(&mut self) -> Result<Option<T>, Box<dyn Error>> {
if self.header.elements_count == 0 {
return Ok(None);
}
let index = self.header.last_element;
let bytes = self.store.read(index)?;
let element: Element<T> = bincode::deserialize_from(bytes.as_slice())?;
self.store.delete(index)?;
self.header.last_element = element.prev;
self.header.elements_count -= 1;
self.save_header()?;
Ok(Some(element.body))
}
}
impl<T> Iterator for Queue<T>
where
T: Serialize,
for<'de> T: Deserialize<'de>,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.dequeue().unwrap_or(None)
}
}
#[derive(Serialize, Deserialize, Debug, Default)]
struct Header {
first_element: usize,
last_element: usize,
elements_count: usize,
}
#[derive(Serialize, Deserialize, Debug)]
struct Element<T> {
next: usize,
prev: usize,
body: T,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn works() {
let file = tempfile::tempfile().expect("could not create tempfile");
let mut queue = Queue::<i32>::new(file).expect("could not create");
assert_eq!(queue.len(), 0);
queue.enqueue(1).expect("could not enqueue");
queue.enqueue(2).expect("could not enqueue");
assert_eq!(queue.len(), 2);
let data = queue.dequeue().expect("could not dequeue");
assert_eq!(data, Some(1));
assert_eq!(queue.len(), 1);
let data = queue.dequeue().expect("could not dequeue");
assert_eq!(data, Some(2));
assert_eq!(queue.len(), 0);
let data = queue.dequeue().expect("could not dequeue");
assert_eq!(data, None);
}
#[test]
fn iteration() {
let file = tempfile::tempfile().expect("could not create tempfile");
let mut queue = Queue::<i32>::new(file).expect("could not create");
queue.enqueue(1).expect("could not enqueue");
queue.enqueue(2).expect("could not enqueue");
assert_eq!(queue.len(), 2);
let vec: Vec<i32> = queue.collect();
assert_eq!(vec, vec![1, 2]);
}
}