app_frame/
util.rs

1use regex::Regex;
2
3pub use private::Never;
4mod private {
5    use std::process::{ExitCode, Termination};
6    /// A type that cannot be constructed. Use as a return type for functions
7    /// that never return.
8    pub struct Never(());
9    impl Termination for Never {
10        fn report(self) -> ExitCode {
11            ExitCode::FAILURE
12        }
13    }
14}
15
16pub trait ToError<E> {
17    fn to_error(self) -> E;
18}
19
20impl<E> ToError<E> for Result<Never, E> {
21    fn to_error(self) -> E {
22        match self {
23            Ok(_) => unsafe { std::hint::unreachable_unchecked() },
24            Err(e) => e,
25        }
26    }
27}
28
29#[macro_export]
30macro_rules! newtype {
31    (
32        $(#[$outer:meta])*
33        $viz:vis $Name:ident $(<$($G:ident),+>)? ($iviz:vis $Inner:ty)
34    ) => {
35        $(#[$outer])*
36        $viz struct $Name $(<$($G),+>)? ($iviz $Inner);
37        impl$(<$($G),+>)? $Name$(<$($G),+>)? {
38            pub fn new(inner: $Inner) -> Self {
39                Self(inner)
40            }
41        }
42        impl $(<$($G),+>)? std::ops::Deref for $Name $(<$($G),+>)? {
43            type Target = $Inner;
44            fn deref(&self) -> &Self::Target {
45                &self.0
46            }
47        }
48    };
49    (
50        $(#[$outer:meta])*
51        $viz:vis mut $Name:ident $(<$($G:ident),+>)? ($iviz:vis $Inner:ty)
52    ) => {
53        $crate::newtype!($(#[$outer])*$viz $Name $(<$($G),+>)? ($iviz $Inner));
54        impl$(<$($G),+>)? std::ops::DerefMut for $Name $(<$($G),+>)? {
55            fn deref_mut(&mut self) -> &mut Self::Target {
56                &mut self.0
57            }
58        }
59    };
60}
61
62/// Clone the item and move it into the async closure.
63#[macro_export]
64macro_rules! clone_to_async {
65    (
66        ($($to_move:ident $(= $orig_name:expr)?),*)
67        |$(mut $arg:ident),*|
68        $blk:expr
69    ) => {{
70        $(
71            $(let $to_move = $orig_name.clone();)?
72            let $to_move = $to_move.clone();
73        )*
74        move |$(mut $arg),*| {
75            $(let $to_move = $to_move.clone();)*
76            async move { $blk }
77        }
78    }};
79    (
80        ($($to_move:ident $(= $orig_name:expr)?),*)
81        |$($arg:ident),*|
82        $blk:expr
83    ) => {{
84        $(
85            $(let $to_move = $orig_name.clone();)?
86            let $to_move = $to_move.clone();
87        )*
88        move |$($arg),*| {
89            $(let $to_move = $to_move.clone();)*
90            async move { $blk }
91        }
92    }};
93}
94
95pub fn short_name<T: ?Sized>() -> String {
96    abs_to_rel_paths(std::any::type_name::<T>())
97}
98
99fn abs_to_rel_paths(s: &str) -> String {
100    let re = Regex::new("[_a-zA-Z0-9]*::").unwrap();
101    re.replace_all(s, "").into()
102}
103
104#[test]
105fn abs_to_rel_paths_works() {
106    assert_eq!(
107        "GenericStruct<UserConfig, Getter<UserConfig>, UserConfigIndex, UserId>", 
108        abs_to_rel_paths("some::path::to::GenericStruct<whatever::state::config::UserConfig, my_crate::state::generic::getter::Getter<whatever::state::config::UserConfig>, my_crate::state::caches::UserConfigIndex, lib::user::UserId>")
109    );
110    assert_eq!(
111        "GenericStruct<Repository, RepositoryProvider, Metadata, UserId>",
112        abs_to_rel_paths("some::path::to::GenericStruct<jwt::state::Repository, my_crate::state::account_providers::mint::RepositoryProvider, my_crate::state::generic::meta::Metadata, lib::user::UserId>",)
113    );
114    assert_eq!(
115        "GenericStruct<Market, Getter<Market>, MarketIndex, UserId>",
116        abs_to_rel_paths("some::path::to::GenericStruct<the_app::control::state::Market, my_crate::state::generic::getter::Getter<the_app::control::state::Market>, my_crate::state::caches::MarketIndex, lib::user::UserId>",)
117    );
118    assert_eq!(
119        "GenericStruct<UserItem, UserItemProvider, Metadata, UserId>",
120        abs_to_rel_paths("some::path::to::GenericStruct<whatever_crate::state::UserItem, my_crate::state::account_providers::manager_crate::UserItemProvider, my_crate::state::generic::meta::Metadata, lib::user::UserId>",)
121    );
122    assert_eq!(
123        "GenericStruct<UserAccount, Getter<UserAccount>, Metadata, UserId>",
124        abs_to_rel_paths("some::path::to::GenericStruct<whatever::state::account::UserAccount, my_crate::state::generic::getter::Getter<whatever::state::account::UserAccount>, my_crate::state::generic::meta::Metadata, lib::user::UserId>",)
125    );
126    assert_eq!(
127        "GenericStruct<User, Arc<dyn HttpClient>, UserIndex, UserId>", 
128        abs_to_rel_paths("some::path::to::GenericStruct<the_app::manager::state::User, alloc::sync::Arc<dyn clients::http::HttpClient>, my_crate::state::caches::UserIndex, lib::user::UserId>",)
129    );
130    assert_eq!(
131        "GenericStruct<BTreeSet<Entry>, PurchaseProvider, Metadata, UserId>", 
132        abs_to_rel_paths("some::path::to::GenericStruct<alloc::collections::btree::set::BTreeSet<my_crate::state::Entry>, my_crate::state::account_providers::thing::PurchaseProvider, my_crate::state::generic::meta::Metadata, lib::user::UserId>",)
133    );
134    assert_eq!(
135        "GenericStruct<ExtSvc, ExtProvider, Metadata, UserId>", 
136        abs_to_rel_paths("some::path::to::GenericStruct<ext_sdk::ExtSvc, my_crate::state::account_providers::oracle::ExtProvider, my_crate::state::generic::meta::Metadata, lib::user::UserId>",)
137    );
138    assert_eq!(
139        "GenericStruct<MyItem, UserItemProvider, Metadata, (UserId, UserId)>", 
140        abs_to_rel_paths("some::path::to::GenericStruct<whatever_sdk::access::jwt_access::MyItem, my_crate::state::account_providers::access::UserItemProvider, my_crate::state::generic::meta::Metadata, (lib::user::UserId, lib::user::UserId)>",)
141    );
142    assert_eq!(
143        "InstantiatableProvider",
144        abs_to_rel_paths("my_crate::service::provider::InstantiatableProvider"),
145    );
146    assert_eq!(
147        "StaleProvider",
148        abs_to_rel_paths("my_crate::service::provider::StaleProvider"),
149    );
150    assert_eq!(
151        "InstantiationService",
152        abs_to_rel_paths("my_crate::service::dispatch::InstantiationService"),
153    );
154    assert_eq!("DataSync", abs_to_rel_paths("my_crate::init::DataSync"),);
155}