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