subsoil/externalities/
extensions.rs1use super::Error;
15use alloc::{
16 boxed::Box,
17 collections::btree_map::{BTreeMap, Entry},
18};
19use core::{
20 any::{Any, TypeId},
21 iter::FromIterator,
22 ops::DerefMut,
23};
24
25#[derive(Clone, Copy, Debug, PartialEq, Eq)]
27pub enum TransactionType {
28 Host,
30 Runtime,
32}
33
34impl TransactionType {
35 pub fn is_host(self) -> bool {
37 matches!(self, Self::Host)
38 }
39
40 pub fn is_runtime(self) -> bool {
42 matches!(self, Self::Runtime)
43 }
44}
45
46pub trait Extension: Send + 'static {
52 fn as_mut_any(&mut self) -> &mut dyn Any;
56
57 fn type_id(&self) -> TypeId;
59
60 fn start_transaction(&mut self, ty: TransactionType) {
62 let _ty = ty;
63 }
64
65 fn commit_transaction(&mut self, ty: TransactionType) {
67 let _ty = ty;
68 }
69
70 fn rollback_transaction(&mut self, ty: TransactionType) {
72 let _ty = ty;
73 }
74}
75
76impl Extension for Box<dyn Extension> {
77 fn as_mut_any(&mut self) -> &mut dyn Any {
78 (**self).as_mut_any()
79 }
80
81 fn type_id(&self) -> TypeId {
82 (**self).type_id()
83 }
84
85 fn start_transaction(&mut self, ty: TransactionType) {
86 (**self).start_transaction(ty);
87 }
88
89 fn commit_transaction(&mut self, ty: TransactionType) {
90 (**self).commit_transaction(ty);
91 }
92
93 fn rollback_transaction(&mut self, ty: TransactionType) {
94 (**self).rollback_transaction(ty);
95 }
96}
97
98#[macro_export]
131macro_rules! decl_extension {
132 (
133 $( #[ $attr:meta ] )*
134 $vis:vis struct $ext_name:ident ($inner:ty);
135 $(
136 impl $ext_name_impl:ident {
137 $(
138 $impls:tt
139 )*
140 }
141 )*
142 ) => {
143 $( #[ $attr ] )*
144 $vis struct $ext_name (pub $inner);
145
146 impl $crate::externalities::Extension for $ext_name {
147 fn as_mut_any(&mut self) -> &mut dyn core::any::Any {
148 self
149 }
150
151 fn type_id(&self) -> core::any::TypeId {
152 core::any::Any::type_id(self)
153 }
154
155 $(
156 $(
157 $impls
158 )*
159 )*
160 }
161
162 impl $ext_name {
163 #[allow(dead_code)]
165 pub fn type_id() -> core::any::TypeId {
166 core::any::TypeId::of::<Self>()
167 }
168 }
169
170 impl core::ops::Deref for $ext_name {
171 type Target = $inner;
172
173 fn deref(&self) -> &Self::Target {
174 &self.0
175 }
176 }
177
178 impl core::ops::DerefMut for $ext_name {
179 fn deref_mut(&mut self) -> &mut Self::Target {
180 &mut self.0
181 }
182 }
183
184 impl From<$inner> for $ext_name {
185 fn from(inner: $inner) -> Self {
186 Self(inner)
187 }
188 }
189 };
190 (
191 $( #[ $attr:meta ] )*
192 $vis:vis struct $ext_name:ident;
193 ) => {
194 $( #[ $attr ] )*
195 $vis struct $ext_name;
196
197 impl $crate::externalities::Extension for $ext_name {
198 fn as_mut_any(&mut self) -> &mut dyn core::any::Any {
199 self
200 }
201
202 fn type_id(&self) -> core::any::TypeId {
203 core::any::Any::type_id(self)
204 }
205 }
206
207 impl $ext_name {
208 #[allow(dead_code)]
210 pub fn type_id() -> core::any::TypeId {
211 core::any::TypeId::of::<Self>()
212 }
213 }
214 }
215}
216
217pub trait ExtensionStore {
221 fn extension_by_type_id(&mut self, type_id: TypeId) -> Option<&mut dyn Any>;
227
228 fn register_extension_with_type_id(
232 &mut self,
233 type_id: TypeId,
234 extension: Box<dyn Extension>,
235 ) -> Result<(), Error>;
236
237 fn deregister_extension_by_type_id(&mut self, type_id: TypeId) -> Result<(), Error>;
241}
242
243#[derive(Default)]
245pub struct Extensions {
246 extensions: BTreeMap<TypeId, Box<dyn Extension>>,
247}
248
249impl core::fmt::Debug for Extensions {
250 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
251 write!(f, "Extensions: ({})", self.extensions.len())
252 }
253}
254
255impl Extensions {
256 pub fn new() -> Self {
258 Self::default()
259 }
260
261 pub fn register<E: Extension>(&mut self, ext: E) {
263 let type_id = ext.type_id();
264 self.extensions.insert(type_id, Box::new(ext));
265 }
266
267 pub fn is_registered(&self, type_id: TypeId) -> bool {
269 self.extensions.contains_key(&type_id)
270 }
271
272 pub fn register_with_type_id(
274 &mut self,
275 type_id: TypeId,
276 extension: Box<dyn Extension>,
277 ) -> Result<(), Error> {
278 match self.extensions.entry(type_id) {
279 Entry::Vacant(vacant) => {
280 vacant.insert(extension);
281 Ok(())
282 },
283 Entry::Occupied(_) => Err(Error::ExtensionAlreadyRegistered),
284 }
285 }
286
287 pub fn get_mut(&mut self, ext_type_id: TypeId) -> Option<&mut dyn Any> {
289 self.extensions
290 .get_mut(&ext_type_id)
291 .map(DerefMut::deref_mut)
292 .map(Extension::as_mut_any)
293 }
294
295 pub fn deregister(&mut self, type_id: TypeId) -> bool {
299 self.extensions.remove(&type_id).is_some()
300 }
301
302 pub fn iter_mut(&mut self) -> impl Iterator<Item = (&TypeId, &mut Box<dyn Extension>)> {
304 self.extensions.iter_mut()
305 }
306
307 pub fn merge(&mut self, other: Self) {
312 self.extensions.extend(other.extensions);
313 }
314
315 pub fn start_transaction(&mut self, ty: TransactionType) {
317 self.extensions.values_mut().for_each(|e| e.start_transaction(ty));
318 }
319
320 pub fn commit_transaction(&mut self, ty: TransactionType) {
322 self.extensions.values_mut().for_each(|e| e.commit_transaction(ty));
323 }
324
325 pub fn rollback_transaction(&mut self, ty: TransactionType) {
327 self.extensions.values_mut().for_each(|e| e.rollback_transaction(ty));
328 }
329
330 pub fn into_extensions(self) -> impl Iterator<Item = Box<dyn Extension>> {
332 self.extensions.into_values()
333 }
334}
335
336impl Extend<Extensions> for Extensions {
337 fn extend<T: IntoIterator<Item = Extensions>>(&mut self, iter: T) {
338 iter.into_iter()
339 .for_each(|ext| self.extensions.extend(ext.extensions.into_iter()));
340 }
341}
342
343impl<A: Extension> From<A> for Extensions {
344 fn from(ext: A) -> Self {
345 Self {
346 extensions: FromIterator::from_iter(
347 [(Extension::type_id(&ext), Box::new(ext) as Box<dyn Extension>)].into_iter(),
348 ),
349 }
350 }
351}
352
353impl<A: Extension, B: Extension> From<(A, B)> for Extensions {
354 fn from((ext, ext2): (A, B)) -> Self {
355 Self {
356 extensions: FromIterator::from_iter(
357 [
358 (Extension::type_id(&ext), Box::new(ext) as Box<dyn Extension>),
359 (Extension::type_id(&ext2), Box::new(ext2) as Box<dyn Extension>),
360 ]
361 .into_iter(),
362 ),
363 }
364 }
365}
366
367impl<A: Extension, B: Extension, C: Extension> From<(A, B, C)> for Extensions {
368 fn from((ext, ext2, ext3): (A, B, C)) -> Self {
369 Self {
370 extensions: FromIterator::from_iter(
371 [
372 (Extension::type_id(&ext), Box::new(ext) as Box<dyn Extension>),
373 (Extension::type_id(&ext2), Box::new(ext2) as Box<dyn Extension>),
374 (Extension::type_id(&ext3), Box::new(ext3) as Box<dyn Extension>),
375 ]
376 .into_iter(),
377 ),
378 }
379 }
380}
381
382#[cfg(test)]
383mod tests {
384 use super::*;
385
386 decl_extension! {
387 struct DummyExt(u32);
388 }
389 decl_extension! {
390 struct DummyExt2(u32);
391 }
392
393 #[test]
394 fn register_and_retrieve_extension() {
395 let mut exts = Extensions::new();
396 exts.register(DummyExt(1));
397 exts.register(DummyExt2(2));
398
399 let ext = exts.get_mut(TypeId::of::<DummyExt>()).expect("Extension is registered");
400 let ext_ty = ext.downcast_mut::<DummyExt>().expect("Downcasting works");
401
402 assert_eq!(ext_ty.0, 1);
403 }
404
405 #[test]
406 fn register_box_extension() {
407 let mut exts = Extensions::new();
408 let box1: Box<dyn Extension> = Box::new(DummyExt(1));
409 let box2: Box<dyn Extension> = Box::new(DummyExt2(2));
410 exts.register(box1);
411 exts.register(box2);
412
413 {
414 let ext = exts.get_mut(TypeId::of::<DummyExt>()).expect("Extension 1 is registered");
415 let ext_ty = ext.downcast_mut::<DummyExt>().expect("Downcasting works for Extension 1");
416 assert_eq!(ext_ty.0, 1);
417 }
418 {
419 let ext2 = exts.get_mut(TypeId::of::<DummyExt2>()).expect("Extension 2 is registered");
420 let ext_ty2 =
421 ext2.downcast_mut::<DummyExt2>().expect("Downcasting works for Extension 2");
422 assert_eq!(ext_ty2.0, 2);
423 }
424 }
425
426 #[test]
427 fn from_boxed_extensions() {
428 let exts = Extensions::from((DummyExt(1), DummyExt2(2)));
429
430 assert!(exts.is_registered(DummyExt::type_id()));
431 assert!(exts.is_registered(DummyExt2::type_id()));
432 }
433}