Skip to main content

sov_universal_wallet/schema/
schema_impls.rs

1#[doc(hidden)]
2// This module contains the implementations of the `UniversalWallet` trait for all primitive types
3mod primitive_type_impls {
4    extern crate alloc;
5    use std::any::TypeId;
6    use std::cell::{Cell, RefCell, UnsafeCell};
7    use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
8    use std::marker::PhantomData;
9    use std::ops::Range;
10    use std::rc::Rc;
11    use std::sync::{Arc, Mutex, RwLock};
12
13    use crate::schema::container::{Container, StructWithSerde};
14    use crate::schema::{
15        IndexLinking, Item, Link, OverrideSchema, Primitive, Schema, UniversalWallet,
16    };
17    use crate::ty::{
18        macro_for_ints, ByteDisplay, ContainerSerdeMetadata, FieldOrVariantSerdeMetadata,
19        IntegerDisplay, IntegerType, NamedField, Struct, Tuple, UnnamedField,
20    };
21
22    macro_rules! impl_for_int {
23        ($t:ident) => {
24            impl UniversalWallet for $t {
25                fn scaffold() -> Item<IndexLinking> {
26                    Item::Atom(Primitive::Integer(IntegerType::$t, IntegerDisplay::Decimal))
27                }
28                fn get_child_links(_schema: &mut Schema) -> Vec<Link> {
29                    Vec::new()
30                }
31            }
32        };
33    }
34    macro_for_ints!(impl_for_int);
35
36    impl OverrideSchema for usize {
37        type Output = u32;
38    }
39
40    impl OverrideSchema for isize {
41        type Output = u32;
42    }
43
44    impl UniversalWallet for bool {
45        fn scaffold() -> Item<IndexLinking> {
46            Item::Atom(Primitive::Boolean)
47        }
48        fn get_child_links(_schema: &mut Schema) -> Vec<Link> {
49            Vec::new()
50        }
51    }
52
53    impl UniversalWallet for f32 {
54        fn scaffold() -> Item<IndexLinking> {
55            Item::Atom(Primitive::Float32)
56        }
57        fn get_child_links(_schema: &mut Schema) -> Vec<Link> {
58            Vec::new()
59        }
60    }
61
62    impl UniversalWallet for f64 {
63        fn scaffold() -> Item<IndexLinking> {
64            Item::Atom(Primitive::Float64)
65        }
66        fn get_child_links(_schema: &mut Schema) -> Vec<Link> {
67            Vec::new()
68        }
69    }
70
71    impl UniversalWallet for () {
72        fn scaffold() -> Item<IndexLinking> {
73            Item::Atom(Primitive::Skip { len: 0 })
74        }
75        fn get_child_links(_schema: &mut Schema) -> Vec<Link> {
76            Vec::new()
77        }
78    }
79
80    impl<T: 'static> UniversalWallet for PhantomData<T> {
81        fn scaffold() -> Item<IndexLinking> {
82            Item::Atom(Primitive::Skip { len: 0 })
83        }
84        fn get_child_links(_schema: &mut Schema) -> Vec<Link> {
85            Vec::new()
86        }
87    }
88
89    impl<T: UniversalWallet> UniversalWallet for Vec<T> {
90        fn get_child_links(schema: &mut Schema) -> Vec<Link> {
91            vec![T::make_linkable(schema)]
92        }
93
94        fn scaffold() -> Item<IndexLinking> {
95            if TypeId::of::<T>() == TypeId::of::<u8>() {
96                Item::Atom(Primitive::ByteVec {
97                    display: ByteDisplay::Hex,
98                })
99            } else {
100                Item::Container(Container::Vec {
101                    value: Link::Placeholder,
102                })
103            }
104        }
105    }
106
107    impl<T: UniversalWallet> OverrideSchema for HashSet<T> {
108        type Output = Vec<T>;
109    }
110
111    impl<T: UniversalWallet> OverrideSchema for BTreeSet<T> {
112        type Output = Vec<T>;
113    }
114
115    impl<const N: usize, T: UniversalWallet> UniversalWallet for [T; N] {
116        fn get_child_links(schema: &mut Schema) -> Vec<Link> {
117            vec![T::make_linkable(schema)]
118        }
119
120        fn scaffold() -> Item<IndexLinking> {
121            if TypeId::of::<T>() == TypeId::of::<u8>() {
122                Item::Atom(Primitive::ByteArray {
123                    len: N,
124                    display: ByteDisplay::Hex,
125                })
126            } else {
127                Item::Container(Container::Array {
128                    len: N,
129                    value: Link::Placeholder,
130                })
131            }
132        }
133    }
134
135    macro_rules! impl_container_type {
136        ($t:ident) => {
137            impl<T: UniversalWallet> OverrideSchema for $t<T> {
138                type Output = T;
139            }
140        };
141    }
142    impl_container_type!(Box);
143    impl_container_type!(Arc);
144    impl_container_type!(Rc);
145    impl_container_type!(Cell);
146    impl_container_type!(RefCell);
147    impl_container_type!(UnsafeCell);
148    impl_container_type!(Mutex);
149    impl_container_type!(RwLock);
150
151    /// Helper macro, used for counting repetition without actually using the type
152    macro_rules! type_to_placeholder {
153        ($t: tt) => {
154            Link::Placeholder
155        };
156    }
157    macro_rules! impl_tuple_type {
158        ($($tts:tt),*) => {
159            impl<$($tts: UniversalWallet + 'static,)*> UniversalWallet for ($($tts,)*) {
160                fn scaffold() -> Item<IndexLinking> {
161                    Item::Container(Container::Tuple(Tuple {
162                        template: None,
163                        peekable: false,
164                        fields: vec![
165                            $(UnnamedField {
166                                value: type_to_placeholder!($tts),
167                                silent: false,
168                                doc: "".to_string()
169                            }),*
170                        ]
171                    }))
172                }
173
174                fn get_child_links(schema: &mut Schema) -> Vec<Link> {
175                    vec![$($tts::make_linkable(schema)),*]
176                }
177            }
178        };
179    }
180    // This is purely a convenience - any higher amount of tuples can simply be handled by the
181    // derive macro.
182    impl_tuple_type!(T1, T2);
183    impl_tuple_type!(T1, T2, T3);
184    impl_tuple_type!(T1, T2, T3, T4);
185    impl_tuple_type!(T1, T2, T3, T4, T5);
186    impl_tuple_type!(T1, T2, T3, T4, T5, T6);
187    impl_tuple_type!(T1, T2, T3, T4, T5, T6, T7);
188    impl_tuple_type!(T1, T2, T3, T4, T5, T6, T7, T8);
189
190    impl<T: UniversalWallet> UniversalWallet for Option<T> {
191        fn scaffold() -> Item<IndexLinking> {
192            Item::Container(Container::Option {
193                value: Link::Placeholder,
194            })
195        }
196
197        fn get_child_links(schema: &mut Schema) -> Vec<Link> {
198            vec![T::make_linkable(schema)]
199        }
200    }
201
202    impl<K: UniversalWallet, V: UniversalWallet> UniversalWallet for HashMap<K, V> {
203        fn scaffold() -> Item<IndexLinking> {
204            Item::Container(Container::Map {
205                key: Link::Placeholder,
206                value: Link::Placeholder,
207            })
208        }
209
210        fn get_child_links(schema: &mut Schema) -> Vec<Link> {
211            vec![K::make_linkable(schema), V::make_linkable(schema)]
212        }
213    }
214
215    impl<K: UniversalWallet, V: UniversalWallet> OverrideSchema for BTreeMap<K, V> {
216        type Output = HashMap<K, V>;
217    }
218
219    impl<T: UniversalWallet> UniversalWallet for Range<T> {
220        fn scaffold() -> Item<IndexLinking> {
221            Item::Container(Container::Struct(StructWithSerde {
222                ty: Struct {
223                    type_name: "Range".to_string(),
224                    template: Some("{}..{}".to_string()),
225                    peekable: false,
226                    fields: vec![
227                        NamedField {
228                            value: Link::Placeholder,
229                            doc: "".to_string(),
230                            silent: false,
231                            display_name: "start".to_string(),
232                        },
233                        NamedField {
234                            value: Link::Placeholder,
235                            doc: "".to_string(),
236                            silent: false,
237                            display_name: "end".to_string(),
238                        },
239                    ],
240                },
241                serde: ContainerSerdeMetadata {
242                    name: "Range".to_string(),
243                    fields_or_variants: vec![
244                        FieldOrVariantSerdeMetadata {
245                            name: "start".to_string(),
246                        },
247                        FieldOrVariantSerdeMetadata {
248                            name: "end".to_string(),
249                        },
250                    ],
251                },
252            }))
253        }
254
255        fn get_child_links(schema: &mut Schema) -> Vec<Link> {
256            vec![T::make_linkable(schema), T::make_linkable(schema)]
257        }
258    }
259
260    #[cfg(feature = "arrayvec")]
261    impl<T: UniversalWallet, const N: usize> OverrideSchema for arrayvec::ArrayVec<T, N> {
262        type Output = Vec<T>;
263    }
264}