use serde::{Serialize, de::DeserializeOwned};
use crate::codec::{Bytes, Codec};
use crate::error::Error;
use crate::store::Store;
pub struct DequeRef<'a, C: Codec> {
store: &'a Store<C>,
key: &'a str,
}
impl<'a, C: Codec> DequeRef<'a, C> {
pub(crate) fn new(store: &'a Store<C>, key: &'a str) -> Self {
Self { store, key }
}
#[inline]
fn enc<T: Serialize>(&self, v: &T) -> Result<Bytes, Error> {
self.store.codec().encode(v)
}
#[inline]
fn dec<T: DeserializeOwned>(&self, b: &[u8]) -> Result<T, Error> {
self.store.codec().decode(b)
}
pub fn push_front<T: Serialize>(&self, value: &T) -> Result<usize, Error> {
let b = self.enc(value)?;
self.store.with_deque_mut(self.key, |dq| {
dq.push_front(b);
Ok(dq.len())
})
}
pub fn push_back<T: Serialize>(&self, value: &T) -> Result<usize, Error> {
let b = self.enc(value)?;
self.store.with_deque_mut(self.key, |dq| {
dq.push_back(b);
Ok(dq.len())
})
}
pub fn pop_front<T: DeserializeOwned>(&self) -> Result<Option<T>, Error> {
self.store.with_deque_mut(self.key, |dq| {
let Some(b) = dq.pop_front() else {
return Ok(None);
};
Ok(Some(self.dec::<T>(&b)?))
})
}
pub fn pop_back<T: DeserializeOwned>(&self) -> Result<Option<T>, Error> {
self.store.with_deque_mut(self.key, |dq| {
let Some(b) = dq.pop_back() else {
return Ok(None);
};
Ok(Some(self.dec::<T>(&b)?))
})
}
pub fn peek_front<T: DeserializeOwned>(&self) -> Result<Option<T>, Error> {
self.store.with_deque_read(self.key, |opt| {
let Some(dq) = opt else {
return Ok(None);
};
let Some(b) = dq.front() else {
return Ok(None);
};
Ok(Some(self.dec::<T>(b)?))
})
}
pub fn peek_back<T: DeserializeOwned>(&self) -> Result<Option<T>, Error> {
self.store.with_deque_read(self.key, |opt| {
let Some(dq) = opt else {
return Ok(None);
};
let Some(b) = dq.back() else {
return Ok(None);
};
Ok(Some(self.dec::<T>(b)?))
})
}
pub fn pop_at<T: DeserializeOwned>(&self, index: usize) -> Result<Option<T>, Error> {
self.store.with_deque_mut(self.key, |dq| {
let Some(b) = dq.remove(index) else {
return Ok(None);
};
Ok(Some(self.dec::<T>(&b)?))
})
}
pub fn peek_at<T: DeserializeOwned>(&self, index: usize) -> Result<Option<T>, Error> {
self.store.with_deque_read(self.key, |opt| {
let Some(dq) = opt else {
return Ok(None);
};
let Some(b) = dq.get(index) else {
return Ok(None);
};
Ok(Some(self.dec::<T>(b)?))
})
}
pub fn truncate(&self, len: usize) -> Result<(), Error> {
self.store.with_deque_mut(self.key, |dq| {
dq.truncate(len);
Ok(())
})
}
pub fn len(&self) -> Result<usize, Error> {
self.store
.with_deque_read(self.key, |opt| Ok(opt.map(|d| d.len()).unwrap_or(0)))
}
pub fn is_empty(&self) -> Result<bool, Error> {
Ok(self.len()? == 0)
}
pub fn clear(&self) -> Result<(), Error> {
self.store.with_deque_mut(self.key, |dq| {
dq.clear();
Ok(())
})
}
}
#[cfg(test)]
mod tests {
use crate::Store;
#[test]
fn deque_basic_ops() {
let store = Store::new();
let d = store.deque("d");
d.push_back(&1_i64).unwrap();
d.push_front(&0_i64).unwrap();
assert_eq!(d.len().unwrap(), 2);
assert!(!d.is_empty().unwrap());
let a: Option<i64> = d.peek_front().unwrap();
assert_eq!(a, Some(0));
let x: Option<i64> = d.pop_at(1).unwrap();
assert_eq!(x, Some(1));
assert_eq!(d.len().unwrap(), 1);
d.clear().unwrap();
assert_eq!(d.len().unwrap(), 0);
assert!(d.is_empty().unwrap());
}
#[test]
fn deque_cover_more_paths() {
let store = Store::new();
let d = store.deque("d2");
d.push_front(&"a").unwrap();
d.push_back(&"b").unwrap();
let back: Option<String> = d.peek_back().unwrap();
assert_eq!(back.as_deref(), Some("b"));
let x: Option<String> = d.pop_back().unwrap();
assert_eq!(x.as_deref(), Some("b"));
d.push_back(&"c").unwrap();
d.push_back(&"d").unwrap();
d.truncate(1).unwrap();
assert_eq!(d.len().unwrap(), 1);
let y: Option<String> = d.peek_at(0).unwrap();
assert!(y.is_some());
}
}