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
35pub trait Extension: Send + 'static {
41 fn as_mut_any(&mut self) -> &mut dyn Any;
45
46 fn type_id(&self) -> TypeId;
48}
49
50impl Extension for Box<dyn Extension> {
51 fn as_mut_any(&mut self) -> &mut dyn Any {
52 (**self).as_mut_any()
53 }
54
55 fn type_id(&self) -> TypeId {
56 (**self).type_id()
57 }
58}
59
60#[macro_export]
74macro_rules! decl_extension {
75 (
76 $( #[ $attr:meta ] )*
77 $vis:vis struct $ext_name:ident ($inner:ty);
78 ) => {
79 $( #[ $attr ] )*
80 $vis struct $ext_name (pub $inner);
81
82 impl $crate::Extension for $ext_name {
83 fn as_mut_any(&mut self) -> &mut dyn core::any::Any {
84 self
85 }
86
87 fn type_id(&self) -> core::any::TypeId {
88 core::any::Any::type_id(self)
89 }
90 }
91
92 impl core::ops::Deref for $ext_name {
93 type Target = $inner;
94
95 fn deref(&self) -> &Self::Target {
96 &self.0
97 }
98 }
99
100 impl core::ops::DerefMut for $ext_name {
101 fn deref_mut(&mut self) -> &mut Self::Target {
102 &mut self.0
103 }
104 }
105
106 impl From<$inner> for $ext_name {
107 fn from(inner: $inner) -> Self {
108 Self(inner)
109 }
110 }
111 };
112 (
113 $( #[ $attr:meta ] )*
114 $vis:vis struct $ext_name:ident;
115 ) => {
116 $( #[ $attr ] )*
117 $vis struct $ext_name;
118
119 impl $crate::Extension for $ext_name {
120 fn as_mut_any(&mut self) -> &mut dyn core::any::Any {
121 self
122 }
123
124 fn type_id(&self) -> core::any::TypeId {
125 core::any::Any::type_id(self)
126 }
127 }
128 }
129}
130
131pub trait ExtensionStore {
135 fn extension_by_type_id(&mut self, type_id: TypeId) -> Option<&mut dyn Any>;
141
142 fn register_extension_with_type_id(
146 &mut self,
147 type_id: TypeId,
148 extension: Box<dyn Extension>,
149 ) -> Result<(), Error>;
150
151 fn deregister_extension_by_type_id(&mut self, type_id: TypeId) -> Result<(), Error>;
155}
156
157#[derive(Default)]
159pub struct Extensions {
160 extensions: BTreeMap<TypeId, Box<dyn Extension>>,
161}
162
163impl core::fmt::Debug for Extensions {
164 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
165 write!(f, "Extensions: ({})", self.extensions.len())
166 }
167}
168
169impl Extensions {
170 pub fn new() -> Self {
172 Self::default()
173 }
174
175 pub fn register<E: Extension>(&mut self, ext: E) {
177 let type_id = ext.type_id();
178 self.extensions.insert(type_id, Box::new(ext));
179 }
180
181 pub fn register_with_type_id(
183 &mut self,
184 type_id: TypeId,
185 extension: Box<dyn Extension>,
186 ) -> Result<(), Error> {
187 match self.extensions.entry(type_id) {
188 Entry::Vacant(vacant) => {
189 vacant.insert(extension);
190 Ok(())
191 },
192 Entry::Occupied(_) => Err(Error::ExtensionAlreadyRegistered),
193 }
194 }
195
196 pub fn get_mut(&mut self, ext_type_id: TypeId) -> Option<&mut dyn Any> {
198 self.extensions
199 .get_mut(&ext_type_id)
200 .map(DerefMut::deref_mut)
201 .map(Extension::as_mut_any)
202 }
203
204 pub fn deregister(&mut self, type_id: TypeId) -> bool {
208 self.extensions.remove(&type_id).is_some()
209 }
210
211 pub fn iter_mut(&mut self) -> impl Iterator<Item = (&TypeId, &mut Box<dyn Extension>)> {
213 self.extensions.iter_mut()
214 }
215
216 pub fn merge(&mut self, other: Self) {
221 self.extensions.extend(other.extensions);
222 }
223}
224
225impl Extend<Extensions> for Extensions {
226 fn extend<T: IntoIterator<Item = Extensions>>(&mut self, iter: T) {
227 iter.into_iter()
228 .for_each(|ext| self.extensions.extend(ext.extensions.into_iter()));
229 }
230}
231
232#[cfg(test)]
233mod tests {
234 use super::*;
235
236 decl_extension! {
237 struct DummyExt(u32);
238 }
239 decl_extension! {
240 struct DummyExt2(u32);
241 }
242
243 #[test]
244 fn register_and_retrieve_extension() {
245 let mut exts = Extensions::new();
246 exts.register(DummyExt(1));
247 exts.register(DummyExt2(2));
248
249 let ext = exts.get_mut(TypeId::of::<DummyExt>()).expect("Extension is registered");
250 let ext_ty = ext.downcast_mut::<DummyExt>().expect("Downcasting works");
251
252 assert_eq!(ext_ty.0, 1);
253 }
254
255 #[test]
256 fn register_box_extension() {
257 let mut exts = Extensions::new();
258 let box1: Box<dyn Extension> = Box::new(DummyExt(1));
259 let box2: Box<dyn Extension> = Box::new(DummyExt2(2));
260 exts.register(box1);
261 exts.register(box2);
262
263 {
264 let ext = exts.get_mut(TypeId::of::<DummyExt>()).expect("Extension 1 is registered");
265 let ext_ty = ext.downcast_mut::<DummyExt>().expect("Downcasting works for Extension 1");
266 assert_eq!(ext_ty.0, 1);
267 }
268 {
269 let ext2 = exts.get_mut(TypeId::of::<DummyExt2>()).expect("Extension 2 is registered");
270 let ext_ty2 =
271 ext2.downcast_mut::<DummyExt2>().expect("Downcasting works for Extension 2");
272 assert_eq!(ext_ty2.0, 2);
273 }
274 }
275}