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 Mailbox {
type Key1;
type Key2;
type Value;
type BlockNumber;
type Error: MailboxError;
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 peek(key1: &Self::Key1, key2: &Self::Key2) -> Option<Self::Value>;
fn clear();
}
pub trait MailboxCallbacks<OutputError> {
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 MailboxError {
fn duplicate_key() -> Self;
fn element_not_found() -> Self;
}
impl MailboxError for () {
fn duplicate_key() -> Self {}
fn element_not_found() -> Self {}
}
pub struct MailboxImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>(
PhantomData<(T, Error, OutputError, Callbacks, KeyGen)>,
)
where
T: DoubleMapStorage<Value = ValueWithInterval<Value, BlockNumber>>,
Error: MailboxError,
OutputError: From<Error>,
Callbacks: MailboxCallbacks<OutputError, Value = Value, BlockNumber = BlockNumber>,
KeyGen: KeyFor<Key = (T::Key1, T::Key2), Value = Value>;
impl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen> Mailbox
for MailboxImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>
where
T: DoubleMapStorage<Value = ValueWithInterval<Value, BlockNumber>>,
Error: MailboxError,
OutputError: From<Error>,
Callbacks: MailboxCallbacks<OutputError, 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(user_id: &Self::Key1, message_id: &Self::Key2) -> bool {
T::contains_keys(user_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(
user_id: Self::Key1,
message_id: Self::Key2,
) -> Result<ValueWithInterval<Self::Value, Self::BlockNumber>, Self::OutputError> {
if let Some(message_with_bn) = T::take(user_id, message_id) {
Callbacks::OnRemove::call(&message_with_bn);
Ok(message_with_bn)
} else {
Err(Self::Error::element_not_found().into())
}
}
fn peek(user_id: &Self::Key1, message_id: &Self::Key2) -> Option<Self::Value> {
T::get(user_id, message_id).map(|(stored, _)| stored)
}
fn clear() {
T::clear()
}
}
impl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen> CountedByKey
for MailboxImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>
where
T: DoubleMapStorage<Value = ValueWithInterval<Value, BlockNumber>>
+ CountedByKey<Key = T::Key1>,
Error: MailboxError,
OutputError: From<Error>,
Callbacks: MailboxCallbacks<OutputError, 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 MailboxImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>
where
T: DoubleMapStorage<Value = ValueWithInterval<Value, BlockNumber>>
+ IterableByKeyMap<T::Value, Key = T::Key1>,
Error: MailboxError,
OutputError: From<Error>,
Callbacks: MailboxCallbacks<OutputError, 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 MailboxImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>
where
T: DoubleMapStorage<Value = ValueWithInterval<Value, BlockNumber>> + IterableMap<T::Value>,
Error: MailboxError,
OutputError: From<Error>,
Callbacks: MailboxCallbacks<OutputError, 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()
}
}