use crate::storage::{
Callback, CountedByKey, DoubleMapStorage, GetCallback, Interval, IterableByKeyMap, IterableMap,
KeyFor,
};
use core::marker::PhantomData;
pub type ValueWithInterval<T, B> = (T, Interval<B>);
pub trait Waitlist {
type Key1;
type Key2;
type Value;
type BlockNumber;
type Error: WaitlistError;
type OutputError: From<Self::Error>;
fn contains(key1: &Self::Key1, key2: &Self::Key2) -> bool;
fn insert(value: Self::Value, bn: Self::BlockNumber) -> Result<(), Self::OutputError>;
fn remove(
key1: Self::Key1,
key2: Self::Key2,
) -> Result<ValueWithInterval<Self::Value, Self::BlockNumber>, Self::OutputError>;
fn clear();
}
pub trait WaitlistCallbacks {
type Value;
type BlockNumber;
type GetBlockNumber: GetCallback<Self::BlockNumber>;
type OnInsert: Callback<ValueWithInterval<Self::Value, Self::BlockNumber>>;
type OnRemove: Callback<ValueWithInterval<Self::Value, Self::BlockNumber>>;
}
pub trait WaitlistError {
fn duplicate_key() -> Self;
fn element_not_found() -> Self;
}
pub struct WaitlistImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>(
PhantomData<(T, Error, OutputError, Callbacks, KeyGen)>,
)
where
T: DoubleMapStorage<Value = (Value, Interval<BlockNumber>)>,
Error: WaitlistError,
OutputError: From<Error>,
Callbacks: WaitlistCallbacks<Value = Value, BlockNumber = BlockNumber>,
KeyGen: KeyFor<Key = (T::Key1, T::Key2), Value = Value>;
impl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen> Waitlist
for WaitlistImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>
where
T: DoubleMapStorage<Value = (Value, Interval<BlockNumber>)>,
Error: WaitlistError,
OutputError: From<Error>,
Callbacks: WaitlistCallbacks<Value = Value, BlockNumber = BlockNumber>,
KeyGen: KeyFor<Key = (T::Key1, T::Key2), Value = Value>,
{
type Key1 = T::Key1;
type Key2 = T::Key2;
type Value = Value;
type BlockNumber = BlockNumber;
type Error = Error;
type OutputError = OutputError;
fn contains(program_id: &Self::Key1, message_id: &Self::Key2) -> bool {
T::contains_keys(program_id, message_id)
}
fn insert(
message: Self::Value,
scheduled_at: Self::BlockNumber,
) -> Result<(), Self::OutputError> {
let (key1, key2) = KeyGen::key_for(&message);
if Self::contains(&key1, &key2) {
return Err(Self::Error::duplicate_key().into());
}
let block_number = Callbacks::GetBlockNumber::call();
let message_with_bn = (
message,
Interval {
start: block_number,
finish: scheduled_at,
},
);
Callbacks::OnInsert::call(&message_with_bn);
T::insert(key1, key2, message_with_bn);
Ok(())
}
fn remove(
program_id: Self::Key1,
message_id: Self::Key2,
) -> Result<ValueWithInterval<Self::Value, Self::BlockNumber>, Self::OutputError> {
if let Some(message_with_bn) = T::take(program_id, message_id) {
Callbacks::OnRemove::call(&message_with_bn);
Ok(message_with_bn)
} else {
Err(Self::Error::element_not_found().into())
}
}
fn clear() {
T::clear()
}
}
impl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen> CountedByKey
for WaitlistImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>
where
T: DoubleMapStorage<Value = (Value, Interval<BlockNumber>)> + CountedByKey<Key = T::Key1>,
Error: WaitlistError,
OutputError: From<Error>,
Callbacks: WaitlistCallbacks<Value = Value, BlockNumber = BlockNumber>,
KeyGen: KeyFor<Key = (T::Key1, T::Key2), Value = Value>,
{
type Key = T::Key1;
type Length = T::Length;
fn len(key: &Self::Key) -> Self::Length {
T::len(key)
}
}
impl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen> IterableByKeyMap<T::Value>
for WaitlistImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>
where
T: DoubleMapStorage<Value = (Value, Interval<BlockNumber>)>
+ IterableByKeyMap<T::Value, Key = T::Key1>,
Error: WaitlistError,
OutputError: From<Error>,
Callbacks: WaitlistCallbacks<Value = Value, BlockNumber = BlockNumber>,
KeyGen: KeyFor<Key = (T::Key1, T::Key2), Value = Value>,
{
type Key = T::Key1;
type DrainIter = T::DrainIter;
type Iter = T::Iter;
fn drain_key(key: Self::Key) -> Self::DrainIter {
T::drain_key(key)
}
fn iter_key(key: Self::Key) -> Self::Iter {
T::iter_key(key)
}
}
impl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen> IterableMap<T::Value>
for WaitlistImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>
where
T: DoubleMapStorage<Value = (Value, Interval<BlockNumber>)> + IterableMap<T::Value>,
Error: WaitlistError,
OutputError: From<Error>,
Callbacks: WaitlistCallbacks<Value = Value, BlockNumber = BlockNumber>,
KeyGen: KeyFor<Key = (T::Key1, T::Key2), Value = Value>,
{
type DrainIter = T::DrainIter;
type Iter = T::Iter;
fn drain() -> Self::DrainIter {
T::drain()
}
fn iter() -> Self::Iter {
T::iter()
}
}