use crate::Environment;
#[doc(hidden)]
pub trait TopicsBuilderBackend<E>
where
E: Environment,
{
type Output;
fn expect(&mut self, expected_topics: usize);
fn push_topic<T>(&mut self, topic_value: &T)
where
T: scale::Encode;
fn output(self) -> Self::Output;
}
#[doc(hidden)]
pub struct TopicsBuilder<S, E, B> {
backend: B,
state: core::marker::PhantomData<fn() -> (S, E)>,
}
impl<E, B> From<B> for TopicsBuilder<state::Uninit, E, B>
where
E: Environment,
B: TopicsBuilderBackend<E>,
{
fn from(backend: B) -> Self {
Self {
backend,
state: Default::default(),
}
}
}
#[doc(hidden)]
pub mod state {
pub enum Uninit {}
pub enum HasRemainingTopics {}
pub enum NoRemainingTopics {}
}
impl<E, B> TopicsBuilder<state::Uninit, E, B>
where
E: Environment,
B: TopicsBuilderBackend<E>,
{
pub fn build<Event: Topics>(
mut self,
) -> TopicsBuilder<<Event as Topics>::RemainingTopics, E, B> {
self.backend
.expect(<<Event as Topics>::RemainingTopics as EventTopicsAmount>::AMOUNT);
TopicsBuilder {
backend: self.backend,
state: Default::default(),
}
}
}
impl<E, S, B> TopicsBuilder<S, E, B>
where
E: Environment,
S: SomeRemainingTopics,
B: TopicsBuilderBackend<E>,
{
pub fn push_topic<T>(
mut self,
value: &T,
) -> TopicsBuilder<<S as SomeRemainingTopics>::Next, E, B>
where
T: scale::Encode,
{
self.backend.push_topic(value);
TopicsBuilder {
backend: self.backend,
state: Default::default(),
}
}
}
impl<E, B> TopicsBuilder<state::NoRemainingTopics, E, B>
where
E: Environment,
B: TopicsBuilderBackend<E>,
{
pub fn finish(self) -> <B as TopicsBuilderBackend<E>>::Output
where
B: TopicsBuilderBackend<E>,
{
self.backend.output()
}
}
#[doc(hidden)]
pub trait SomeRemainingTopics {
type Next;
}
#[doc(hidden)]
pub trait EventTopicsAmount {
const AMOUNT: usize;
}
macro_rules! impl_some_remaining_for {
( $( $n:literal ),* $(,)? ) => {
$(
impl SomeRemainingTopics for [state::HasRemainingTopics; $n] {
type Next = [state::HasRemainingTopics; $n - 1];
}
impl EventTopicsAmount for [state::HasRemainingTopics; $n] {
const AMOUNT: usize = $n;
}
)*
};
}
#[rustfmt::skip]
impl_some_remaining_for!(
2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32,
);
impl SomeRemainingTopics for [state::HasRemainingTopics; 1] {
type Next = state::NoRemainingTopics;
}
impl EventTopicsAmount for [state::HasRemainingTopics; 1] {
const AMOUNT: usize = 1;
}
impl EventTopicsAmount for state::NoRemainingTopics {
const AMOUNT: usize = 0;
}
pub trait Topics {
type RemainingTopics: EventTopicsAmount;
fn topics<E, B>(
&self,
builder: TopicsBuilder<state::Uninit, E, B>,
) -> <B as TopicsBuilderBackend<E>>::Output
where
E: Environment,
B: TopicsBuilderBackend<E>;
}
#[doc(hidden)]
pub struct PrefixedValue<'a, 'b, T> {
pub prefix: &'a [u8],
pub value: &'b T,
}
impl<X> scale::Encode for PrefixedValue<'_, '_, X>
where
X: scale::Encode,
{
#[inline]
fn size_hint(&self) -> usize {
self.prefix.size_hint() + self.value.size_hint()
}
#[inline]
fn encode_to<T: scale::Output + ?Sized>(&self, dest: &mut T) {
self.prefix.encode_to(dest);
self.value.encode_to(dest);
}
}