1use super::storage::Footprint;
21use codec::{Decode, DecodeWithMemTracking, Encode, FullCodec, MaxEncodedLen};
22use core::{fmt::Debug, marker::PhantomData};
23use scale_info::TypeInfo;
24use sp_core::{ConstU32, Get, TypedGet};
25use sp_runtime::{traits::Convert, BoundedSlice, RuntimeDebug};
26use sp_weights::{Weight, WeightMeter};
27
28#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, TypeInfo, Debug)]
31pub enum ProcessMessageError {
32 BadFormat,
34 Corrupt,
36 Unsupported,
38 Overweight(Weight),
42 Yield,
49 StackLimitReached,
51}
52
53pub trait ProcessMessage {
55 type Origin: FullCodec + MaxEncodedLen + Clone + Eq + PartialEq + TypeInfo + Debug;
57
58 fn process_message(
62 message: &[u8],
63 origin: Self::Origin,
64 meter: &mut WeightMeter,
65 id: &mut [u8; 32],
66 ) -> Result<bool, ProcessMessageError>;
67}
68
69#[derive(Eq, PartialEq, RuntimeDebug)]
72pub enum ExecuteOverweightError {
73 NotFound,
75 AlreadyProcessed,
79 InsufficientWeight,
81 QueuePaused,
85 Other,
87 RecursiveDisallowed,
89}
90
91pub trait ServiceQueues {
93 type OverweightMessageAddress;
95
96 fn service_queues(weight_limit: Weight) -> Weight;
104
105 fn execute_overweight(
108 _weight_limit: Weight,
109 _address: Self::OverweightMessageAddress,
110 ) -> Result<Weight, ExecuteOverweightError> {
111 Err(ExecuteOverweightError::NotFound)
112 }
113}
114
115pub struct NoopServiceQueues<OverweightAddr>(PhantomData<OverweightAddr>);
117impl<OverweightAddr> ServiceQueues for NoopServiceQueues<OverweightAddr> {
118 type OverweightMessageAddress = OverweightAddr;
119
120 fn service_queues(_: Weight) -> Weight {
121 Weight::zero()
122 }
123}
124
125#[derive(Default, Copy, Clone, Eq, PartialEq, RuntimeDebug)]
127pub struct QueueFootprint {
128 pub pages: u32,
130 pub ready_pages: u32,
132 pub storage: Footprint,
134}
135
136pub trait EnqueueMessage<Origin: MaxEncodedLen> {
138 type MaxMessageLen: Get<u32>;
140
141 fn enqueue_message(message: BoundedSlice<u8, Self::MaxMessageLen>, origin: Origin);
143
144 fn enqueue_messages<'a>(
146 messages: impl Iterator<Item = BoundedSlice<'a, u8, Self::MaxMessageLen>>,
147 origin: Origin,
148 );
149
150 fn sweep_queue(origin: Origin);
152
153 fn footprint(origin: Origin) -> QueueFootprint;
155}
156
157impl<Origin: MaxEncodedLen> EnqueueMessage<Origin> for () {
158 type MaxMessageLen = ConstU32<0>;
159 fn enqueue_message(_: BoundedSlice<u8, Self::MaxMessageLen>, _: Origin) {}
160 fn enqueue_messages<'a>(
161 _: impl Iterator<Item = BoundedSlice<'a, u8, Self::MaxMessageLen>>,
162 _: Origin,
163 ) {
164 }
165 fn sweep_queue(_: Origin) {}
166 fn footprint(_: Origin) -> QueueFootprint {
167 QueueFootprint::default()
168 }
169}
170
171pub struct TransformOrigin<E, O, N, C>(PhantomData<(E, O, N, C)>);
173impl<E: EnqueueMessage<O>, O: MaxEncodedLen, N: MaxEncodedLen, C: Convert<N, O>> EnqueueMessage<N>
174 for TransformOrigin<E, O, N, C>
175{
176 type MaxMessageLen = E::MaxMessageLen;
177
178 fn enqueue_message(message: BoundedSlice<u8, Self::MaxMessageLen>, origin: N) {
179 E::enqueue_message(message, C::convert(origin));
180 }
181
182 fn enqueue_messages<'a>(
183 messages: impl Iterator<Item = BoundedSlice<'a, u8, Self::MaxMessageLen>>,
184 origin: N,
185 ) {
186 E::enqueue_messages(messages, C::convert(origin));
187 }
188
189 fn sweep_queue(origin: N) {
190 E::sweep_queue(C::convert(origin));
191 }
192
193 fn footprint(origin: N) -> QueueFootprint {
194 E::footprint(C::convert(origin))
195 }
196}
197
198pub trait HandleMessage {
200 type MaxMessageLen: Get<u32>;
202
203 fn handle_message(message: BoundedSlice<u8, Self::MaxMessageLen>);
205
206 fn handle_messages<'a>(
208 messages: impl Iterator<Item = BoundedSlice<'a, u8, Self::MaxMessageLen>>,
209 );
210
211 fn sweep_queue();
213
214 fn footprint() -> QueueFootprint;
216}
217
218pub struct EnqueueWithOrigin<E, O>(PhantomData<(E, O)>);
220impl<E: EnqueueMessage<O::Type>, O: TypedGet> HandleMessage for EnqueueWithOrigin<E, O>
221where
222 O::Type: MaxEncodedLen,
223{
224 type MaxMessageLen = E::MaxMessageLen;
225
226 fn handle_message(message: BoundedSlice<u8, Self::MaxMessageLen>) {
227 E::enqueue_message(message, O::get());
228 }
229
230 fn handle_messages<'a>(
231 messages: impl Iterator<Item = BoundedSlice<'a, u8, Self::MaxMessageLen>>,
232 ) {
233 E::enqueue_messages(messages, O::get());
234 }
235
236 fn sweep_queue() {
237 E::sweep_queue(O::get());
238 }
239
240 fn footprint() -> QueueFootprint {
241 E::footprint(O::get())
242 }
243}
244
245pub trait QueuePausedQuery<Origin> {
247 fn is_paused(origin: &Origin) -> bool;
249}
250
251#[impl_trait_for_tuples::impl_for_tuples(8)]
252impl<Origin> QueuePausedQuery<Origin> for Tuple {
253 fn is_paused(origin: &Origin) -> bool {
254 for_tuples!( #(
255 if Tuple::is_paused(origin) {
256 return true;
257 }
258 )* );
259 false
260 }
261}