use crate::storage::{Callback, Counted, EmptyCallback, IterableMap, MapStorage, ValueStorage};
use core::marker::PhantomData;
use sp_runtime::{
codec::{self, Decode, Encode},
scale_info::{self, TypeInfo},
};
pub trait Dequeue {
type Key;
type Value;
type Error;
fn mutate_values<F: FnMut(Self::Value) -> Self::Value>(f: F);
fn pop_back() -> Result<Option<Self::Value>, Self::Error>;
fn pop_front() -> Result<Option<Self::Value>, Self::Error>;
fn push_back(key: Self::Key, value: Self::Value) -> Result<(), Self::Error>;
fn push_front(key: Self::Key, value: Self::Value) -> Result<(), Self::Error>;
fn clear();
}
pub trait DequeueCallbacks {
type Value;
type OnPopBack: Callback<Self::Value>;
type OnPopFront: Callback<Self::Value>;
type OnPushBack: Callback<Self::Value>;
type OnPushFront: Callback<Self::Value>;
type OnClear: EmptyCallback;
}
pub trait DequeueError {
fn duplicate_key() -> Self;
fn element_not_found() -> Self;
fn head_should_be_set() -> Self;
fn head_should_not_be_set() -> Self;
fn tail_has_next_key() -> Self;
fn tail_parent_not_found() -> Self;
fn tail_should_be_set() -> Self;
fn tail_should_not_be_set() -> Self;
}
pub struct DequeueImpl<Key, Value, Error, HVS, TVS, MS, Callbacks>(
PhantomData<(Error, HVS, TVS, MS, Callbacks)>,
)
where
Key: Clone + PartialEq,
Error: DequeueError,
HVS: ValueStorage<Value = Key>,
TVS: ValueStorage<Value = Key>,
MS: MapStorage<Key = Key, Value = LinkedNode<Key, Value>>,
Callbacks: DequeueCallbacks<Value = Value>;
#[derive(Encode, Decode, TypeInfo)]
#[codec(crate = codec)]
#[scale_info(crate = scale_info)]
pub struct LinkedNode<K, V> {
pub next: Option<K>,
pub value: V,
}
impl<Key, Value, Error, HVS, TVS, MS, Callbacks> Counted
for DequeueImpl<Key, Value, Error, HVS, TVS, MS, Callbacks>
where
Key: Clone + PartialEq,
Error: DequeueError,
HVS: ValueStorage<Value = Key>,
TVS: ValueStorage<Value = Key>,
MS: MapStorage<Key = Key, Value = LinkedNode<Key, Value>> + Counted,
Callbacks: DequeueCallbacks<Value = Value>,
{
type Length = MS::Length;
fn len() -> Self::Length {
MS::len()
}
}
impl<Key, Value, Error, HVS, TVS, MS, Callbacks> Dequeue
for DequeueImpl<Key, Value, Error, HVS, TVS, MS, Callbacks>
where
Key: Clone + PartialEq,
Error: DequeueError,
HVS: ValueStorage<Value = Key>,
TVS: ValueStorage<Value = Key>,
MS: MapStorage<Key = Key, Value = LinkedNode<Key, Value>>,
Callbacks: DequeueCallbacks<Value = Value>,
{
type Key = Key;
type Value = Value;
type Error = Error;
fn mutate_values<F: FnMut(Self::Value) -> Self::Value>(mut f: F) {
MS::mutate_values(|n| LinkedNode {
next: n.next,
value: f(n.value),
})
}
fn pop_back() -> Result<Option<Self::Value>, Self::Error> {
if let Some(head_key) = HVS::get() {
let tail_key = TVS::take().ok_or_else(Self::Error::tail_should_be_set)?;
let tail = MS::take(tail_key.clone()).ok_or_else(Self::Error::element_not_found)?;
let mut next_key = head_key;
loop {
let node = MS::get(&next_key).ok_or_else(Self::Error::element_not_found)?;
if let Some(nodes_next) = node.next {
if nodes_next == tail_key {
break;
}
next_key = nodes_next;
} else {
return Err(Self::Error::tail_parent_not_found());
}
}
let mut node = MS::take(next_key.clone()).ok_or_else(Self::Error::element_not_found)?;
TVS::put(next_key.clone());
node.next = None;
MS::insert(next_key, node);
Callbacks::OnPopBack::call(&tail.value);
Ok(Some(tail.value))
} else if TVS::exists() {
Err(Self::Error::tail_should_not_be_set())
} else {
Ok(None)
}
}
fn pop_front() -> Result<Option<Self::Value>, Self::Error> {
if let Some(head_key) = HVS::take() {
let LinkedNode { next, value } =
MS::take(head_key).ok_or_else(Self::Error::element_not_found)?;
if let Some(next) = next {
HVS::put(next)
} else if TVS::take().is_none() {
return Err(Self::Error::tail_should_be_set());
}
Callbacks::OnPopFront::call(&value);
Ok(Some(value))
} else if TVS::exists() {
Err(Self::Error::tail_should_not_be_set())
} else {
Ok(None)
}
}
fn push_back(key: Self::Key, value: Self::Value) -> Result<(), Self::Error> {
if MS::contains_key(&key) {
Err(Self::Error::duplicate_key())
} else if let Some(tail_key) = TVS::take() {
if let Some(mut tail) = MS::take(tail_key.clone()) {
if tail.next.is_some() {
Err(Self::Error::tail_has_next_key())
} else {
TVS::put(key.clone());
tail.next = Some(key.clone());
MS::insert(tail_key, tail);
Callbacks::OnPushBack::call(&value);
MS::insert(key, LinkedNode { next: None, value });
Ok(())
}
} else {
Err(Self::Error::element_not_found())
}
} else if HVS::exists() {
Err(Self::Error::head_should_not_be_set())
} else {
HVS::put(key.clone());
TVS::put(key.clone());
Callbacks::OnPushBack::call(&value);
MS::insert(key, LinkedNode { next: None, value });
Ok(())
}
}
fn push_front(key: Self::Key, value: Self::Value) -> Result<(), Self::Error> {
if MS::contains_key(&key) {
Err(Self::Error::duplicate_key())
} else if let Some(head_key) = HVS::take() {
HVS::put(key.clone());
Callbacks::OnPushFront::call(&value);
MS::insert(
key,
LinkedNode {
next: Some(head_key),
value,
},
);
Ok(())
} else if TVS::exists() {
Err(Self::Error::tail_should_not_be_set())
} else {
HVS::put(key.clone());
TVS::put(key.clone());
Callbacks::OnPushFront::call(&value);
MS::insert(key, LinkedNode { next: None, value });
Ok(())
}
}
fn clear() {
HVS::kill();
TVS::kill();
MS::clear();
Callbacks::OnClear::call();
}
}
pub struct DequeueDrainIter<Key, Value, Error, HVS, TVS, MS, Callbacks>(
Option<Key>,
PhantomData<(Error, HVS, TVS, MS, Callbacks)>,
)
where
Key: Clone + PartialEq,
Error: DequeueError,
HVS: ValueStorage<Value = Key>,
TVS: ValueStorage<Value = Key>,
MS: MapStorage<Key = Key, Value = LinkedNode<Key, Value>>,
Callbacks: DequeueCallbacks<Value = Value>;
impl<Key, Value, Error, HVS, TVS, MS, Callbacks> Iterator
for DequeueDrainIter<Key, Value, Error, HVS, TVS, MS, Callbacks>
where
Key: Clone + PartialEq,
Error: DequeueError,
HVS: ValueStorage<Value = Key>,
TVS: ValueStorage<Value = Key>,
MS: MapStorage<Key = Key, Value = LinkedNode<Key, Value>>,
Callbacks: DequeueCallbacks<Value = Value>,
{
type Item = Result<Value, Error>;
fn next(&mut self) -> Option<Self::Item> {
let current = self.0.take()?;
if let Some(node) = MS::take(current) {
if let Some(k) = node.next.as_ref() {
HVS::put(k.clone())
}
self.0 = node.next;
Callbacks::OnPopFront::call(&node.value);
Some(Ok(node.value))
} else {
HVS::kill();
TVS::kill();
self.0 = None;
Some(Err(Error::element_not_found()))
}
}
}
pub struct DequeueIter<Key, Value, Error, HVS, TVS, MS>(
Option<Key>,
PhantomData<(Error, HVS, TVS, MS)>,
)
where
Key: Clone + PartialEq,
Error: DequeueError,
HVS: ValueStorage<Value = Key>,
TVS: ValueStorage<Value = Key>,
MS: MapStorage<Key = Key, Value = LinkedNode<Key, Value>>;
impl<Key, Value, Error, HVS, TVS, MS> Iterator for DequeueIter<Key, Value, Error, HVS, TVS, MS>
where
Key: Clone + PartialEq,
Error: DequeueError,
HVS: ValueStorage<Value = Key>,
TVS: ValueStorage<Value = Key>,
MS: MapStorage<Key = Key, Value = LinkedNode<Key, Value>>,
{
type Item = Result<Value, Error>;
fn next(&mut self) -> Option<Self::Item> {
let current = self.0.take()?;
if let Some(node) = MS::get(¤t) {
self.0 = node.next;
Some(Ok(node.value))
} else {
self.0 = None;
Some(Err(Error::element_not_found()))
}
}
}
impl<Key, Value, Error, HVS, TVS, MS, Callbacks> IterableMap<Result<Value, Error>>
for DequeueImpl<Key, Value, Error, HVS, TVS, MS, Callbacks>
where
Key: Clone + PartialEq,
Error: DequeueError,
HVS: ValueStorage<Value = Key>,
TVS: ValueStorage<Value = Key>,
MS: MapStorage<Key = Key, Value = LinkedNode<Key, Value>>,
Callbacks: DequeueCallbacks<Value = Value>,
{
type DrainIter = DequeueDrainIter<Key, Value, Error, HVS, TVS, MS, Callbacks>;
type Iter = DequeueIter<Key, Value, Error, HVS, TVS, MS>;
fn drain() -> Self::DrainIter {
DequeueDrainIter(HVS::get(), PhantomData::<(Error, HVS, TVS, MS, Callbacks)>)
}
fn iter() -> Self::Iter {
DequeueIter(HVS::get(), PhantomData::<(Error, HVS, TVS, MS)>)
}
}