sp_externalities/
extensions.rs1use crate::Error;
26use alloc::{
27 boxed::Box,
28 collections::btree_map::{BTreeMap, Entry},
29};
30use core::{
31 any::{Any, TypeId},
32 ops::DerefMut,
33};
34
35#[derive(Clone, Copy, Debug, PartialEq, Eq)]
37pub enum TransactionType {
38 Host,
40 Runtime,
42}
43
44impl TransactionType {
45 pub fn is_host(self) -> bool {
47 matches!(self, Self::Host)
48 }
49
50 pub fn is_runtime(self) -> bool {
52 matches!(self, Self::Runtime)
53 }
54}
55
56pub trait Extension: Send + 'static {
62 fn as_mut_any(&mut self) -> &mut dyn Any;
66
67 fn type_id(&self) -> TypeId;
69
70 fn start_transaction(&mut self, ty: TransactionType) {
72 let _ty = ty;
73 }
74
75 fn commit_transaction(&mut self, ty: TransactionType) {
77 let _ty = ty;
78 }
79
80 fn rollback_transaction(&mut self, ty: TransactionType) {
82 let _ty = ty;
83 }
84}
85
86impl Extension for Box<dyn Extension> {
87 fn as_mut_any(&mut self) -> &mut dyn Any {
88 (**self).as_mut_any()
89 }
90
91 fn type_id(&self) -> TypeId {
92 (**self).type_id()
93 }
94
95 fn start_transaction(&mut self, ty: TransactionType) {
96 (**self).start_transaction(ty);
97 }
98
99 fn commit_transaction(&mut self, ty: TransactionType) {
100 (**self).commit_transaction(ty);
101 }
102
103 fn rollback_transaction(&mut self, ty: TransactionType) {
104 (**self).rollback_transaction(ty);
105 }
106}
107
108#[macro_export]
141macro_rules! decl_extension {
142 (
143 $( #[ $attr:meta ] )*
144 $vis:vis struct $ext_name:ident ($inner:ty);
145 $(
146 impl $ext_name_impl:ident {
147 $(
148 $impls:tt
149 )*
150 }
151 )*
152 ) => {
153 $( #[ $attr ] )*
154 $vis struct $ext_name (pub $inner);
155
156 impl $crate::Extension for $ext_name {
157 fn as_mut_any(&mut self) -> &mut dyn core::any::Any {
158 self
159 }
160
161 fn type_id(&self) -> core::any::TypeId {
162 core::any::Any::type_id(self)
163 }
164
165 $(
166 $(
167 $impls
168 )*
169 )*
170 }
171
172 impl core::ops::Deref for $ext_name {
173 type Target = $inner;
174
175 fn deref(&self) -> &Self::Target {
176 &self.0
177 }
178 }
179
180 impl core::ops::DerefMut for $ext_name {
181 fn deref_mut(&mut self) -> &mut Self::Target {
182 &mut self.0
183 }
184 }
185
186 impl From<$inner> for $ext_name {
187 fn from(inner: $inner) -> Self {
188 Self(inner)
189 }
190 }
191 };
192 (
193 $( #[ $attr:meta ] )*
194 $vis:vis struct $ext_name:ident;
195 ) => {
196 $( #[ $attr ] )*
197 $vis struct $ext_name;
198
199 impl $crate::Extension for $ext_name {
200 fn as_mut_any(&mut self) -> &mut dyn core::any::Any {
201 self
202 }
203
204 fn type_id(&self) -> core::any::TypeId {
205 core::any::Any::type_id(self)
206 }
207 }
208 }
209}
210
211pub trait ExtensionStore {
215 fn extension_by_type_id(&mut self, type_id: TypeId) -> Option<&mut dyn Any>;
221
222 fn register_extension_with_type_id(
226 &mut self,
227 type_id: TypeId,
228 extension: Box<dyn Extension>,
229 ) -> Result<(), Error>;
230
231 fn deregister_extension_by_type_id(&mut self, type_id: TypeId) -> Result<(), Error>;
235}
236
237#[derive(Default)]
239pub struct Extensions {
240 extensions: BTreeMap<TypeId, Box<dyn Extension>>,
241}
242
243impl core::fmt::Debug for Extensions {
244 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
245 write!(f, "Extensions: ({})", self.extensions.len())
246 }
247}
248
249impl Extensions {
250 pub fn new() -> Self {
252 Self::default()
253 }
254
255 pub fn register<E: Extension>(&mut self, ext: E) {
257 let type_id = ext.type_id();
258 self.extensions.insert(type_id, Box::new(ext));
259 }
260
261 pub fn register_with_type_id(
263 &mut self,
264 type_id: TypeId,
265 extension: Box<dyn Extension>,
266 ) -> Result<(), Error> {
267 match self.extensions.entry(type_id) {
268 Entry::Vacant(vacant) => {
269 vacant.insert(extension);
270 Ok(())
271 },
272 Entry::Occupied(_) => Err(Error::ExtensionAlreadyRegistered),
273 }
274 }
275
276 pub fn get_mut(&mut self, ext_type_id: TypeId) -> Option<&mut dyn Any> {
278 self.extensions
279 .get_mut(&ext_type_id)
280 .map(DerefMut::deref_mut)
281 .map(Extension::as_mut_any)
282 }
283
284 pub fn deregister(&mut self, type_id: TypeId) -> bool {
288 self.extensions.remove(&type_id).is_some()
289 }
290
291 pub fn iter_mut(&mut self) -> impl Iterator<Item = (&TypeId, &mut Box<dyn Extension>)> {
293 self.extensions.iter_mut()
294 }
295
296 pub fn merge(&mut self, other: Self) {
301 self.extensions.extend(other.extensions);
302 }
303
304 pub fn start_transaction(&mut self, ty: TransactionType) {
306 self.extensions.values_mut().for_each(|e| e.start_transaction(ty));
307 }
308
309 pub fn commit_transaction(&mut self, ty: TransactionType) {
311 self.extensions.values_mut().for_each(|e| e.commit_transaction(ty));
312 }
313
314 pub fn rollback_transaction(&mut self, ty: TransactionType) {
316 self.extensions.values_mut().for_each(|e| e.rollback_transaction(ty));
317 }
318}
319
320impl Extend<Extensions> for Extensions {
321 fn extend<T: IntoIterator<Item = Extensions>>(&mut self, iter: T) {
322 iter.into_iter()
323 .for_each(|ext| self.extensions.extend(ext.extensions.into_iter()));
324 }
325}
326
327#[cfg(test)]
328mod tests {
329 use super::*;
330
331 decl_extension! {
332 struct DummyExt(u32);
333 }
334 decl_extension! {
335 struct DummyExt2(u32);
336 }
337
338 #[test]
339 fn register_and_retrieve_extension() {
340 let mut exts = Extensions::new();
341 exts.register(DummyExt(1));
342 exts.register(DummyExt2(2));
343
344 let ext = exts.get_mut(TypeId::of::<DummyExt>()).expect("Extension is registered");
345 let ext_ty = ext.downcast_mut::<DummyExt>().expect("Downcasting works");
346
347 assert_eq!(ext_ty.0, 1);
348 }
349
350 #[test]
351 fn register_box_extension() {
352 let mut exts = Extensions::new();
353 let box1: Box<dyn Extension> = Box::new(DummyExt(1));
354 let box2: Box<dyn Extension> = Box::new(DummyExt2(2));
355 exts.register(box1);
356 exts.register(box2);
357
358 {
359 let ext = exts.get_mut(TypeId::of::<DummyExt>()).expect("Extension 1 is registered");
360 let ext_ty = ext.downcast_mut::<DummyExt>().expect("Downcasting works for Extension 1");
361 assert_eq!(ext_ty.0, 1);
362 }
363 {
364 let ext2 = exts.get_mut(TypeId::of::<DummyExt2>()).expect("Extension 2 is registered");
365 let ext_ty2 =
366 ext2.downcast_mut::<DummyExt2>().expect("Downcasting works for Extension 2");
367 assert_eq!(ext_ty2.0, 2);
368 }
369 }
370}