specta_util/
selection.rs

1// TODO: Should `specta-util` rexport `specta` for these macros???
2
3/// Specta compatible selection of struct fields.
4///
5/// ```rust
6/// use specta::{selection, ts::inline_ref};
7///
8/// #[derive(Clone)]
9/// struct MyStruct {
10///     name: String,
11///     age: i32,
12///     is_verified: bool,
13///     password: String,
14/// }
15///
16/// let person = MyStruct {
17///     name: "Monty".into(),
18///     age: 7,
19///     is_verified: true,
20///     password: "password".into(),
21/// };
22/// let people = vec![person.clone(), person.clone()];
23///
24/// // Selection creates an anonymous struct with the subset of fields you want.
25/// assert_eq!(inline_ref(&selection!(person, {
26///     name,
27///     age
28/// }), &Default::default()).unwrap(), "{ name: string; age: number }");
29///
30/// // You can apply the selection to an array.
31/// assert_eq!(inline_ref(&selection!(people, [{
32///     name,
33///     age
34/// }]), &Default::default()).unwrap(), "{ name: string; age: number }[]");
35/// ```
36// TODO: better docs w/ example
37#[macro_export]
38macro_rules! selection {
39    ( $s:expr, { $($n:ident),+ $(,)? } ) => {{
40        #[allow(non_camel_case_types)]
41        mod selection {
42            #[derive(serde::Serialize, specta::Type)]
43            #[specta(inline)]
44            pub struct Selection<$($n,)*> {
45                $(pub $n: $n),*
46            }
47        }
48        use selection::Selection;
49        #[allow(non_camel_case_types)]
50        Selection { $($n: $s.$n,)* }
51    }};
52    ( $s:expr, [{ $($n:ident),+ $(,)? }] ) => {{
53        #[allow(non_camel_case_types)]
54        mod selection {
55            #[derive(serde::Serialize, specta::Type)]
56            #[specta(inline)]
57            pub struct Selection<$($n,)*> {
58                $(pub $n: $n,)*
59            }
60        }
61        use selection::Selection;
62        #[allow(non_camel_case_types)]
63        $s.into_iter().map(|v| Selection { $($n: v.$n,)* }).collect::<Vec<_>>()
64    }};
65}
66
67// Tests in `src/tests/selection.rs` due to `$crate` issues