multi_structs/lib.rs
1//! A macro for generating a merged struct from multiple sub-structs.
2//!
3//! # Example
4//!
5//! ```
6//! use multi_structs::multi_structs;
7//!
8//! multi_structs! {
9//! /// The merged struct.
10//! #[derive(Debug)]
11//! pub struct Merged {
12//! /// Foo
13//! #[derive(Debug)]
14//! pub foo: struct Foo {
15//! /// a
16//! pub a: i32,
17//! /// b
18//! pub b: i64,
19//! }
20//! /// Bar
21//! #[derive(Debug)]
22//! pub bar: struct Bar {
23//! /// c
24//! pub c: usize,
25//! /// d
26//! pub d: String,
27//! }
28//! }
29//! }
30//!
31//! fn main() {
32//! let foo = Foo { a: 1, b: 2 };
33//! let bar = Bar { c: 3, d: "aaa".to_string() };
34//! println!("{:?}, {:?}", foo, bar);
35//! let merged = Merged::new(foo, bar);
36//! println!("{:?}", merged);
37//! let (foo, bar) = merged.split();
38//! println!("{:?}, {:?}", foo, bar);
39//! }
40//! ```
41//!
42//! See [`example_generated`](./example_generated/index.html) for
43//! documentation of code generated by the above `multi_structs!`
44//! expansion.
45//!
46//! # Attributes
47//!
48//! Attributes can be attached to any struct and field involved.
49//!
50//! # Methods
51//!
52//! The following methods are defined for the merged struct:
53//!
54//! - `new`: create the new merged struct from multiple sub-structs.
55//! - `split`: split the merged struct into the sub-structs.
56//!
57//! # Visibility
58//!
59//! The visibility of structs and fields is taken directly from their definitions. For the
60//! generated methods `new` and `split`, the visibility of the merged struct is assumed.
61
62#![no_std]
63
64#[cfg(feature = "example_generated")]
65extern crate std;
66
67#[macro_export]
68macro_rules! multi_structs {
69 {
70 $(#[$($meta:tt)+])*
71 $multi_vis:vis struct $name:ident {
72 $(
73 $(#[$($sub_meta:tt)+])*
74 $sub_vis:vis $var:ident: struct $sub:ident {
75 $(
76 $(#[$($field_meta:tt)+])*
77 $field_vis:vis $field:ident: $ty:ty
78 ),+ $(,)?
79 }
80 )+
81 }
82 } => {
83 $(
84 $(#[$($sub_meta)+])*
85 $sub_vis struct $sub {
86 $(
87 $(#[$($field_meta)+])*
88 $field_vis $field: $ty,
89 )+
90 }
91 )+
92
93 $(#[$($meta)+])*
94 $multi_vis struct $name {
95 $(
96 $(
97 $(#[$($field_meta)+])*
98 $field_vis $field: $ty,
99 )+
100 )+
101 }
102
103 impl $name {
104 /// Create this struct from sub-structs.
105 $multi_vis fn new(
106 $($var: $sub,)+
107 ) -> Self {
108 Self {
109 $(
110 $($field: $var.$field,)+
111 )+
112 }
113 }
114
115 /// Split this struct into its sub-structs.
116 $multi_vis fn split(self) -> ($($sub,)+) {
117 (
118 $(
119 $sub {
120 $($field: self.$field,)+
121 },
122 )+
123 )
124 }
125 }
126 }
127}
128
129#[cfg(feature = "example_generated")]
130pub mod example_generated;