extruct_macros/lib.rs
1use proc_macro::TokenStream;
2
3#[cfg(any(feature = "extruct_from", doc))]
4mod extruct_from;
5#[cfg(any(feature = "fields", doc))]
6mod fields;
7mod utils;
8
9/// A derive macro implements the [`Fields`](trait.Fields.html) trait for a struct.
10///
11/// [`Fields`] can annotate a named struct, a unit struct or an empty unnamed
12/// (tuple-like) struct, including generic structs.
13/// It collects names of the fields from the struct definition and represents
14/// them as a list of string literals accessible through [`Fields::fields()`](trait.Fields.html#tymethod.fields).
15///
16/// ```rust
17/// # use extruct_core as extruct;
18/// # use extruct::Fields;
19/// # use extruct_macros::Fields;
20/// #[derive(Fields)]
21/// struct NamedStruct {
22/// one: String,
23/// two: u32,
24/// three: char,
25/// }
26/// assert_eq!(NamedStruct::fields(), ["one", "two", "three"]);
27/// ```
28#[cfg(any(feature = "fields", doc))]
29#[proc_macro_derive(Fields)]
30pub fn get_struct_fields(item: TokenStream) -> TokenStream {
31 match fields::parse(item.into()) {
32 Ok(ast) => {
33 let model = fields::analyze(ast);
34 let code = fields::codegen(model);
35
36 code.into()
37 }
38 Err(err) => err.to_compile_error().into(),
39 }
40}
41
42/// An attribute macro implements the [`std::convert::From`](https://doc.rust-lang.org/std/convert/trait.From.html)
43/// trait for an annotated non-generic named struct using a "superstruct" specified as
44/// the attribute parameter as a source type and the [`ExtructedFrom`](trait.ExtructedFrom.html)
45/// marker trait that indicates that struct fields populated during conversion from
46/// superstruct all have same names in both structs.
47///
48/// [`extruct_from`](macro@extruct_from) accepts a single parameter which is a non-generic type name referring
49/// to a named struct.
50///
51/// ```rust
52/// # use extruct_core as extruct;
53/// # use extruct::ExtructedFrom;
54/// # use extruct_macros::extruct_from;
55/// struct SuperStruct {
56/// one_field: String,
57/// another_field: u32,
58/// and_one_more: char,
59/// }
60///
61/// #[extruct_from(SuperStruct)]
62/// struct SubStruct {
63/// and_one_more: String,
64/// }
65///
66/// fn convert_preserving_names<T, S>(sup: S) -> T
67/// where
68/// T: ExtructedFrom<S>
69/// {
70/// sup.into()
71/// }
72///
73/// let sup = SuperStruct {
74/// one_field: "str".to_owned(),
75/// another_field: 1135,
76/// and_one_more: 'x',
77/// };
78///
79/// let sub: SubStruct = convert_preserving_names(sup);
80/// ```
81#[cfg(any(feature = "extruct_from", doc))]
82#[proc_macro_attribute]
83pub fn extruct_from(attr: TokenStream, item: TokenStream) -> TokenStream {
84 match extruct_from::parse(attr.into(), item.into()) {
85 Ok(ast) => {
86 let model = extruct_from::analyze(ast);
87 let code = extruct_from::codegen(model);
88
89 code.into()
90 }
91 Err(err) => err.to_compile_error().into(),
92 }
93}