optfield_lite/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3#![deny(missing_docs)]
4
5/// A macro to generate a new struct with fields wrapped in `Option`.
6#[macro_export]
7macro_rules! optfield {(
8    $(#[$attr:meta])*
9    $vis:vis struct $name:ident {
10        $(
11            $(#[$field_attr:meta])*
12            $field_vis:vis
13            $field:ident : $ty:ty
14        ),* $(,)?
15    }
16    ($new:ident)
17) => {
18    // Original struct
19    $(#[$attr])*
20    $vis struct $name {
21        $(
22            $(#[$field_attr])*
23            $field_vis
24            $field: $ty,
25        )*
26    }
27    // Generated struct
28    $(#[$attr])*
29    $vis struct $new {
30        $(
31            $(#[$field_attr])*
32            $field_vis
33            $field: ::core::option::Option<$ty>,
34        )*
35    }
36}}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41    use macro_rules_attr::apply;
42
43    #[apply(optfield(OptTest))]
44    /// My test struct
45    struct Test {
46        pub a: u32,
47        b: u32,
48    }
49
50    #[test]
51    fn test_original_struct() {
52        let test = Test { a: 1, b: 2 };
53        assert_eq!(test.a, 1);
54        assert_eq!(test.b, 2);
55    }
56
57    #[test]
58    fn test_generated_struct() {
59        let opt_test = OptTest {
60            a: Some(1),
61            b: None,
62        };
63        assert_eq!(opt_test.a.unwrap(), 1);
64        assert!(opt_test.b.is_none());
65    }
66}