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