ankurah_core/util/cast.rs
1//! Macros for ergonomic entity creation.
2
3/// Macro for ergonomic entity creation with automatic `.into()` on fields.
4///
5/// Transforms struct initialization to call `.into()` on each field value:
6/// ```rust,ignore
7/// use ankurah::into;
8///
9/// // This:
10/// into!(ConnectionEvent { &user, session: &session_view, timestamp: ts })
11///
12/// // Expands to:
13/// ConnectionEvent { user: (&user).into(), session: (&session_view).into(), timestamp: ts.into() }
14/// ```
15///
16/// This works because:
17/// - Views implement `From<&View> for Ref<Model>` (blanket impl in entity_ref.rs)
18/// - All types implement `Into<Self>` (reflexive impl)
19#[macro_export]
20macro_rules! into {
21 ($ty:ident { $($tt:tt)* }) => {
22 $crate::into!(@expand $ty {} $($tt)*)
23 };
24 (@expand $ty:ident { $($out:tt)* }) => { $ty { $($out)* } };
25 (@expand $ty:ident { $($out:tt)* } ,) => { $ty { $($out)* } };
26 // Shorthand ref: &field, ...
27 (@expand $ty:ident { $($out:tt)* } & $field:ident, $($rest:tt)*) => {
28 $crate::into!(@expand $ty { $($out)* $field: (&$field).into(), } $($rest)*)
29 };
30 (@expand $ty:ident { $($out:tt)* } & $field:ident) => {
31 $crate::into!(@expand $ty { $($out)* $field: (&$field).into(), })
32 };
33 // Shorthand: field, ...
34 (@expand $ty:ident { $($out:tt)* } $field:ident, $($rest:tt)*) => {
35 $crate::into!(@expand $ty { $($out)* $field: ($field).into(), } $($rest)*)
36 };
37 (@expand $ty:ident { $($out:tt)* } $field:ident) => {
38 $crate::into!(@expand $ty { $($out)* $field: ($field).into(), })
39 };
40 // Explicit: field: expr, ...
41 (@expand $ty:ident { $($out:tt)* } $field:ident : $value:expr, $($rest:tt)*) => {
42 $crate::into!(@expand $ty { $($out)* $field: ($value).into(), } $($rest)*)
43 };
44 (@expand $ty:ident { $($out:tt)* } $field:ident : $value:expr) => {
45 $crate::into!(@expand $ty { $($out)* $field: ($value).into(), })
46 };
47}
48
49/// Macro for creating entities with automatic `.into()` on fields.
50///
51/// Combines a transaction's `create` call with the `into!` macro:
52/// ```rust,ignore
53/// use ankurah::create;
54///
55/// // This:
56/// create!(trx, ConnectionEvent { &user, session: &session_view, timestamp: ts })
57///
58/// // Expands to:
59/// trx.create(&into!(ConnectionEvent { &user, session: &session_view, timestamp: ts }))
60/// ```
61#[macro_export]
62macro_rules! create {
63 ($trx:expr, $ty:ident { $($tt:tt)* }) => {
64 $trx.create(&$crate::into!($ty { $($tt)* }))
65 };
66}