safecoin_frozen_abi/
abi_example.rs

1use {
2    crate::abi_digester::{AbiDigester, DigestError, DigestResult},
3    lazy_static::lazy_static,
4    log::*,
5    serde::Serialize,
6    std::any::type_name,
7};
8
9pub trait AbiExample: Sized {
10    fn example() -> Self;
11}
12
13// Following code snippets are copied and adapted from the official rustc implementation to
14// implement AbiExample trait for most of basic types.
15// These are licensed under Apache-2.0 + MIT (compatible because we're Apache-2.0)
16
17// Source: https://github.com/rust-lang/rust/blob/ba18875557aabffe386a2534a1aa6118efb6ab88/src/libcore/tuple.rs#L7
18macro_rules! tuple_example_impls {
19    ($(
20        $Tuple:ident {
21            $(($idx:tt) -> $T:ident)+
22        }
23    )+) => {
24        $(
25            impl<$($T:AbiExample),+> AbiExample for ($($T,)+) {
26                fn example() -> Self {
27                        ($({ let x: $T = AbiExample::example(); x},)+)
28                }
29            }
30        )+
31    }
32}
33
34// Source: https://github.com/rust-lang/rust/blob/ba18875557aabffe386a2534a1aa6118efb6ab88/src/libcore/tuple.rs#L110
35tuple_example_impls! {
36    Tuple1 {
37        (0) -> A
38    }
39    Tuple2 {
40        (0) -> A
41        (1) -> B
42    }
43    Tuple3 {
44        (0) -> A
45        (1) -> B
46        (2) -> C
47    }
48    Tuple4 {
49        (0) -> A
50        (1) -> B
51        (2) -> C
52        (3) -> D
53    }
54    Tuple5 {
55        (0) -> A
56        (1) -> B
57        (2) -> C
58        (3) -> D
59        (4) -> E
60    }
61    Tuple6 {
62        (0) -> A
63        (1) -> B
64        (2) -> C
65        (3) -> D
66        (4) -> E
67        (5) -> F
68    }
69    Tuple7 {
70        (0) -> A
71        (1) -> B
72        (2) -> C
73        (3) -> D
74        (4) -> E
75        (5) -> F
76        (6) -> G
77    }
78    Tuple8 {
79        (0) -> A
80        (1) -> B
81        (2) -> C
82        (3) -> D
83        (4) -> E
84        (5) -> F
85        (6) -> G
86        (7) -> H
87    }
88    Tuple9 {
89        (0) -> A
90        (1) -> B
91        (2) -> C
92        (3) -> D
93        (4) -> E
94        (5) -> F
95        (6) -> G
96        (7) -> H
97        (8) -> I
98    }
99    Tuple10 {
100        (0) -> A
101        (1) -> B
102        (2) -> C
103        (3) -> D
104        (4) -> E
105        (5) -> F
106        (6) -> G
107        (7) -> H
108        (8) -> I
109        (9) -> J
110    }
111    Tuple11 {
112        (0) -> A
113        (1) -> B
114        (2) -> C
115        (3) -> D
116        (4) -> E
117        (5) -> F
118        (6) -> G
119        (7) -> H
120        (8) -> I
121        (9) -> J
122        (10) -> K
123    }
124    Tuple12 {
125        (0) -> A
126        (1) -> B
127        (2) -> C
128        (3) -> D
129        (4) -> E
130        (5) -> F
131        (6) -> G
132        (7) -> H
133        (8) -> I
134        (9) -> J
135        (10) -> K
136        (11) -> L
137    }
138}
139
140// Source: https://github.com/rust-lang/rust/blob/ba18875557aabffe386a2534a1aa6118efb6ab88/src/libcore/array/mod.rs#L417
141macro_rules! array_example_impls {
142    {$n:expr, $t:ident $($ts:ident)*} => {
143        impl<T> AbiExample for [T; $n] where T: AbiExample {
144            fn example() -> Self {
145                [$t::example(), $($ts::example()),*]
146            }
147        }
148        array_example_impls!{($n - 1), $($ts)*}
149    };
150    {$n:expr,} => {
151        impl<T> AbiExample for [T; $n] {
152        fn example() -> Self { [] }
153        }
154    };
155}
156
157array_example_impls! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
158
159// Source: https://github.com/rust-lang/rust/blob/ba18875557aabffe386a2534a1aa6118efb6ab88/src/libcore/default.rs#L137
160macro_rules! example_impls {
161    ($t:ty, $v:expr) => {
162        impl AbiExample for $t {
163            fn example() -> Self {
164                $v
165            }
166        }
167    };
168}
169
170example_impls! { (), () }
171example_impls! { bool, false }
172example_impls! { char, '\x00' }
173
174example_impls! { usize, 0 }
175example_impls! { u8, 0 }
176example_impls! { u16, 0 }
177example_impls! { u32, 0 }
178example_impls! { u64, 0 }
179example_impls! { u128, 0 }
180
181example_impls! { isize, 0 }
182example_impls! { i8, 0 }
183example_impls! { i16, 0 }
184example_impls! { i32, 0 }
185example_impls! { i64, 0 }
186example_impls! { i128, 0 }
187
188example_impls! { f32, 0.0f32 }
189example_impls! { f64, 0.0f64 }
190example_impls! { String, String::new() }
191example_impls! { std::time::Duration, std::time::Duration::from_secs(0) }
192example_impls! { std::sync::Once, std::sync::Once::new() }
193
194use std::sync::atomic::*;
195
196// Source: https://github.com/rust-lang/rust/blob/ba18875557aabffe386a2534a1aa6118efb6ab88/src/libcore/sync/atomic.rs#L1199
197macro_rules! atomic_example_impls {
198    ($atomic_type: ident) => {
199        impl AbiExample for $atomic_type {
200            fn example() -> Self {
201                Self::new(AbiExample::example())
202            }
203        }
204    };
205}
206atomic_example_impls! { AtomicU8 }
207atomic_example_impls! { AtomicU16 }
208atomic_example_impls! { AtomicU32 }
209atomic_example_impls! { AtomicU64 }
210atomic_example_impls! { AtomicUsize }
211atomic_example_impls! { AtomicI8 }
212atomic_example_impls! { AtomicI16 }
213atomic_example_impls! { AtomicI32 }
214atomic_example_impls! { AtomicI64 }
215atomic_example_impls! { AtomicIsize }
216atomic_example_impls! { AtomicBool }
217
218#[cfg(not(target_os = "solana"))]
219use generic_array::{ArrayLength, GenericArray};
220#[cfg(not(target_os = "solana"))]
221impl<T: Default, U: ArrayLength<T>> AbiExample for GenericArray<T, U> {
222    fn example() -> Self {
223        Self::default()
224    }
225}
226
227use bv::{BitVec, BlockType};
228impl<T: BlockType> AbiExample for BitVec<T> {
229    fn example() -> Self {
230        Self::default()
231    }
232}
233
234impl<T: BlockType> IgnoreAsHelper for BitVec<T> {}
235impl<T: BlockType> EvenAsOpaque for BitVec<T> {}
236
237pub(crate) fn normalize_type_name(type_name: &str) -> String {
238    type_name.chars().filter(|c| *c != '&').collect()
239}
240
241type Placeholder = ();
242
243impl<T: Sized> AbiExample for T {
244    default fn example() -> Self {
245        <Placeholder>::type_erased_example()
246    }
247}
248
249// this works like a type erasure and a hatch to escape type error to runtime error
250trait TypeErasedExample<T> {
251    fn type_erased_example() -> T;
252}
253
254impl<T: Sized> TypeErasedExample<T> for Placeholder {
255    default fn type_erased_example() -> T {
256        panic!(
257            "derive or implement AbiExample/AbiEnumVisitor for {}",
258            type_name::<T>()
259        );
260    }
261}
262
263impl<T: Default + Serialize> TypeErasedExample<T> for Placeholder {
264    default fn type_erased_example() -> T {
265        let original_type_name = type_name::<T>();
266        let normalized_type_name = normalize_type_name(original_type_name);
267
268        if normalized_type_name.starts_with("solana") {
269            panic!(
270                "derive or implement AbiExample/AbiEnumVisitor for {}",
271                original_type_name
272            );
273        } else {
274            panic!(
275                "new unrecognized type for ABI digest!: {}",
276                original_type_name
277            )
278        }
279    }
280}
281
282impl<T: AbiExample> AbiExample for Option<T> {
283    fn example() -> Self {
284        info!("AbiExample for (Option<T>): {}", type_name::<Self>());
285        Some(T::example())
286    }
287}
288
289impl<O: AbiExample, E: AbiExample> AbiExample for Result<O, E> {
290    fn example() -> Self {
291        info!("AbiExample for (Result<O, E>): {}", type_name::<Self>());
292        Ok(O::example())
293    }
294}
295
296impl<T: AbiExample> AbiExample for Box<T> {
297    fn example() -> Self {
298        info!("AbiExample for (Box<T>): {}", type_name::<Self>());
299        Box::new(T::example())
300    }
301}
302
303impl<T> AbiExample for Box<dyn Fn(&mut T) + Sync + Send> {
304    fn example() -> Self {
305        info!("AbiExample for (Box<T>): {}", type_name::<Self>());
306        Box::new(move |_t: &mut T| {})
307    }
308}
309
310impl<T, U> AbiExample for Box<dyn Fn(&mut T, U) + Sync + Send> {
311    fn example() -> Self {
312        info!("AbiExample for (Box<T, U>): {}", type_name::<Self>());
313        Box::new(move |_t: &mut T, _u: U| {})
314    }
315}
316
317impl<T: AbiExample> AbiExample for Box<[T]> {
318    fn example() -> Self {
319        info!("AbiExample for (Box<[T]>): {}", type_name::<Self>());
320        Box::new([T::example()])
321    }
322}
323
324impl<T: AbiExample> AbiExample for std::marker::PhantomData<T> {
325    fn example() -> Self {
326        info!("AbiExample for (PhantomData<T>): {}", type_name::<Self>());
327        <std::marker::PhantomData<T>>::default()
328    }
329}
330
331impl<T: AbiExample> AbiExample for std::sync::Arc<T> {
332    fn example() -> Self {
333        info!("AbiExample for (Arc<T>): {}", type_name::<Self>());
334        std::sync::Arc::new(T::example())
335    }
336}
337
338impl<T: AbiExample> AbiExample for std::rc::Rc<T> {
339    fn example() -> Self {
340        info!("AbiExample for (Rc<T>): {}", type_name::<Self>());
341        std::rc::Rc::new(T::example())
342    }
343}
344
345impl<T: AbiExample> AbiExample for std::sync::Mutex<T> {
346    fn example() -> Self {
347        info!("AbiExample for (Mutex<T>): {}", type_name::<Self>());
348        std::sync::Mutex::new(T::example())
349    }
350}
351
352impl<T: AbiExample> AbiExample for std::sync::RwLock<T> {
353    fn example() -> Self {
354        info!("AbiExample for (RwLock<T>): {}", type_name::<Self>());
355        std::sync::RwLock::new(T::example())
356    }
357}
358
359use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
360
361impl<
362        T: std::cmp::Eq + std::hash::Hash + AbiExample,
363        S: AbiExample,
364        H: std::hash::BuildHasher + Default,
365    > AbiExample for HashMap<T, S, H>
366{
367    fn example() -> Self {
368        info!("AbiExample for (HashMap<T, S, H>): {}", type_name::<Self>());
369        let mut map = HashMap::default();
370        map.insert(T::example(), S::example());
371        map
372    }
373}
374
375#[cfg(not(target_os = "solana"))]
376impl<
377        T: Clone + std::cmp::Eq + std::hash::Hash + AbiExample,
378        S: Clone + AbiExample,
379        H: std::hash::BuildHasher + Default,
380    > AbiExample for im::HashMap<T, S, H>
381{
382    fn example() -> Self {
383        info!("AbiExample for (HashMap<T, S, H>): {}", type_name::<Self>());
384        let mut map = im::HashMap::default();
385        map.insert(T::example(), S::example());
386        map
387    }
388}
389
390impl<T: std::cmp::Ord + AbiExample, S: AbiExample> AbiExample for BTreeMap<T, S> {
391    fn example() -> Self {
392        info!("AbiExample for (BTreeMap<T, S>): {}", type_name::<Self>());
393        let mut map = BTreeMap::default();
394        map.insert(T::example(), S::example());
395        map
396    }
397}
398
399impl<T: AbiExample> AbiExample for Vec<T> {
400    fn example() -> Self {
401        info!("AbiExample for (Vec<T>): {}", type_name::<Self>());
402        vec![T::example()]
403    }
404}
405
406lazy_static! {
407    /// we need &Vec<u8>, so we need something with a static lifetime
408    static ref VEC_U8: Vec<u8> = vec![u8::default()];
409}
410
411impl AbiExample for &Vec<u8> {
412    fn example() -> Self {
413        info!("AbiExample for (&Vec<u8>): {}", type_name::<Self>());
414        &*VEC_U8
415    }
416}
417
418impl AbiExample for &[u8] {
419    fn example() -> Self {
420        info!("AbiExample for (&[u8]): {}", type_name::<Self>());
421        &VEC_U8[..]
422    }
423}
424
425impl<T: AbiExample> AbiExample for VecDeque<T> {
426    fn example() -> Self {
427        info!("AbiExample for (Vec<T>): {}", type_name::<Self>());
428        VecDeque::from(vec![T::example()])
429    }
430}
431
432impl<T: std::cmp::Eq + std::hash::Hash + AbiExample, H: std::hash::BuildHasher + Default> AbiExample
433    for HashSet<T, H>
434{
435    fn example() -> Self {
436        info!("AbiExample for (HashSet<T, H>): {}", type_name::<Self>());
437        let mut set: HashSet<T, H> = HashSet::default();
438        set.insert(T::example());
439        set
440    }
441}
442
443impl<T: std::cmp::Ord + AbiExample> AbiExample for BTreeSet<T> {
444    fn example() -> Self {
445        info!("AbiExample for (BTreeSet<T>): {}", type_name::<Self>());
446        let mut set: BTreeSet<T> = BTreeSet::default();
447        set.insert(T::example());
448        set
449    }
450}
451
452#[cfg(not(target_os = "solana"))]
453impl AbiExample for memmap2::MmapMut {
454    fn example() -> Self {
455        memmap2::MmapMut::map_anon(1).expect("failed to map the data file")
456    }
457}
458
459#[cfg(not(target_os = "solana"))]
460impl AbiExample for std::path::PathBuf {
461    fn example() -> Self {
462        std::path::PathBuf::from(String::example())
463    }
464}
465
466use std::net::{IpAddr, Ipv4Addr, SocketAddr};
467impl AbiExample for SocketAddr {
468    fn example() -> Self {
469        SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0)
470    }
471}
472
473// This is a control flow indirection needed for digesting all variants of an enum
474pub trait AbiEnumVisitor: Serialize {
475    fn visit_for_abi(&self, digester: &mut AbiDigester) -> DigestResult;
476}
477
478pub trait IgnoreAsHelper {}
479pub trait EvenAsOpaque {}
480
481impl<T: Serialize + ?Sized> AbiEnumVisitor for T {
482    default fn visit_for_abi(&self, _digester: &mut AbiDigester) -> DigestResult {
483        unreachable!(
484            "AbiEnumVisitor must be implemented for {}",
485            type_name::<T>()
486        );
487    }
488}
489
490impl<T: Serialize + ?Sized + AbiExample> AbiEnumVisitor for T {
491    default fn visit_for_abi(&self, digester: &mut AbiDigester) -> DigestResult {
492        info!("AbiEnumVisitor for (default): {}", type_name::<T>());
493        T::example()
494            .serialize(digester.create_new())
495            .map_err(DigestError::wrap_by_type::<T>)
496    }
497}
498
499// even (experimental) rust specialization isn't enough for us, resort to
500// the autoref hack: https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md
501// relevant test: TestVecEnum
502impl<T: Serialize + ?Sized + AbiEnumVisitor> AbiEnumVisitor for &T {
503    default fn visit_for_abi(&self, digester: &mut AbiDigester) -> DigestResult {
504        info!("AbiEnumVisitor for (&default): {}", type_name::<T>());
505        // Don't call self.visit_for_abi(...) to avoid the infinite recursion!
506        T::visit_for_abi(self, digester)
507    }
508}
509
510// force to call self.serialize instead of T::visit_for_abi() for serialization
511// helper structs like ad-hoc iterator `struct`s
512impl<T: Serialize + IgnoreAsHelper> AbiEnumVisitor for &T {
513    default fn visit_for_abi(&self, digester: &mut AbiDigester) -> DigestResult {
514        info!("AbiEnumVisitor for (IgnoreAsHelper): {}", type_name::<T>());
515        self.serialize(digester.create_new())
516            .map_err(DigestError::wrap_by_type::<T>)
517    }
518}
519
520// force to call self.serialize instead of T::visit_for_abi() to work around the
521// inability of implementing AbiExample for private structs from other crates
522impl<T: Serialize + IgnoreAsHelper + EvenAsOpaque> AbiEnumVisitor for &T {
523    default fn visit_for_abi(&self, digester: &mut AbiDigester) -> DigestResult {
524        info!("AbiEnumVisitor for (IgnoreAsOpaque): {}", type_name::<T>());
525        let top_scope = type_name::<T>().split("::").next().unwrap();
526        self.serialize(digester.create_new_opaque(top_scope))
527            .map_err(DigestError::wrap_by_type::<T>)
528    }
529}
530
531// Because Option and Result enums are so common enums, provide generic trait implementations
532// The digesting pattern must match with what is derived from #[derive(AbiEnumVisitor)]
533impl<T: AbiEnumVisitor> AbiEnumVisitor for Option<T> {
534    fn visit_for_abi(&self, digester: &mut AbiDigester) -> DigestResult {
535        info!("AbiEnumVisitor for (Option<T>): {}", type_name::<Self>());
536
537        let variant: Self = Option::Some(T::example());
538        // serde calls serialize_some(); not serialize_variant();
539        // so create_new is correct, not create_enum_child or create_enum_new
540        variant.serialize(digester.create_new())
541    }
542}
543
544impl<O: AbiEnumVisitor, E: AbiEnumVisitor> AbiEnumVisitor for Result<O, E> {
545    fn visit_for_abi(&self, digester: &mut AbiDigester) -> DigestResult {
546        info!("AbiEnumVisitor for (Result<O, E>): {}", type_name::<Self>());
547
548        digester.update(&["enum Result (variants = 2)"]);
549        let variant: Self = Result::Ok(O::example());
550        variant.serialize(digester.create_enum_child()?)?;
551
552        let variant: Self = Result::Err(E::example());
553        variant.serialize(digester.create_enum_child()?)?;
554
555        digester.create_child()
556    }
557}
558
559impl<T: AbiExample> AbiExample for once_cell::sync::OnceCell<T> {
560    fn example() -> Self {
561        Self::with_value(T::example())
562    }
563}