#![allow(missing_docs)]
use crate::*;
use alloc::vec::Vec;
use frame_support::traits::Defensive;
pub trait IntoWeight {
fn into_weight(self) -> Weight;
}
impl IntoWeight for u64 {
fn into_weight(self) -> Weight {
Weight::from_parts(self, self)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, MaxEncodedLen, TypeInfo, Debug)]
pub enum MessageOrigin {
Here,
There,
Everywhere(u32),
}
impl From<u32> for MessageOrigin {
fn from(i: u32) -> Self {
Self::Everywhere(i)
}
}
pub struct NoopMessageProcessor<Origin, const REQUIRED_WEIGHT: u64 = 1>(PhantomData<Origin>);
impl<Origin, const REQUIRED_WEIGHT: u64> ProcessMessage
for NoopMessageProcessor<Origin, REQUIRED_WEIGHT>
where
Origin: codec::FullCodec + MaxEncodedLen + Clone + Eq + PartialEq + TypeInfo + Debug,
{
type Origin = Origin;
fn process_message(
_message: &[u8],
_origin: Self::Origin,
meter: &mut WeightMeter,
_id: &mut [u8; 32],
) -> Result<bool, ProcessMessageError> {
let required = Weight::from_parts(REQUIRED_WEIGHT, REQUIRED_WEIGHT);
if meter.try_consume(required).is_ok() {
Ok(true)
} else {
Err(ProcessMessageError::Overweight(required))
}
}
}
pub fn msg<N: Get<u32>>(x: &str) -> BoundedSlice<u8, N> {
BoundedSlice::defensive_truncate_from(x.as_bytes())
}
pub fn vmsg(x: &str) -> Vec<u8> {
x.as_bytes().to_vec()
}
pub fn page<T: Config>(msg: &[u8]) -> PageOf<T> {
PageOf::<T>::from_message::<T>(msg.try_into().unwrap())
}
pub fn single_page_book<T: Config>() -> BookStateOf<T> {
BookState { begin: 0, end: 1, count: 1, message_count: 1, size: 1, ..Default::default() }
}
pub fn empty_book<T: Config>() -> BookStateOf<T> {
BookState { begin: 0, end: 1, count: 1, ..Default::default() }
}
pub fn full_page<T: Config>() -> (PageOf<T>, usize) {
let mut msgs = 0;
let mut page = PageOf::<T>::default();
for i in 0..u32::MAX {
let r = i.using_encoded(|d| page.try_append_message::<T>(d.try_into().unwrap()));
if r.is_err() {
break
} else {
msgs += 1;
}
}
assert!(msgs > 0, "page must hold at least one message");
(page, msgs)
}
pub fn book_for<T: Config>(page: &PageOf<T>) -> BookStateOf<T> {
BookState {
count: 1,
begin: 0,
end: 1,
message_count: page.remaining.into() as u64,
size: page.remaining_size.into() as u64,
..Default::default()
}
}
#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
pub fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
assert!(
!frame_system::Pallet::<T>::block_number().is_zero(),
"The genesis block has n o events"
);
frame_system::Pallet::<T>::assert_last_event(generic_event.into());
}
pub fn setup_bump_service_head<T: Config>(
current: <<T as Config>::MessageProcessor as ProcessMessage>::Origin,
next: <<T as Config>::MessageProcessor as ProcessMessage>::Origin,
) {
crate::Pallet::<T>::enqueue_message(msg("1"), current);
crate::Pallet::<T>::enqueue_message(msg("1"), next);
}
pub fn knit<T: Config>(o: &<<T as Config>::MessageProcessor as ProcessMessage>::Origin) {
let mut b = BookStateFor::<T>::get(o);
b.ready_neighbours = crate::Pallet::<T>::ready_ring_knit(o).ok().defensive();
BookStateFor::<T>::insert(o, b);
}
pub fn unknit<T: Config>(o: &<<T as Config>::MessageProcessor as ProcessMessage>::Origin) {
let mut b = BookStateFor::<T>::get(o);
crate::Pallet::<T>::ready_ring_unknit(o, b.ready_neighbours.unwrap());
b.ready_neighbours = None;
BookStateFor::<T>::insert(o, b);
}
pub fn build_ring<T: Config>(
queues: &[<<T as Config>::MessageProcessor as ProcessMessage>::Origin],
) {
for queue in queues.iter() {
crate::Pallet::<T>::enqueue_message(msg("1"), queue.clone());
}
assert_ring::<T>(queues);
}
pub fn assert_ring<T: Config>(
queues: &[<<T as Config>::MessageProcessor as ProcessMessage>::Origin],
) {
for (i, origin) in queues.iter().enumerate() {
let book = BookStateFor::<T>::get(origin);
assert_eq!(
book.ready_neighbours,
Some(Neighbours {
prev: queues[(i + queues.len() - 1) % queues.len()].clone(),
next: queues[(i + 1) % queues.len()].clone(),
})
);
}
assert_eq!(ServiceHead::<T>::get(), queues.first().cloned());
}