syn_helpers/
model.rs

1use std::error::Error;
2
3use quote::quote;
4use syn::{parse_quote, Stmt};
5
6use crate::{ConstructableStructure, EnumStructure, Structure, TypeOfSelf};
7
8/// A intermediate type that wraps a [Structure]
9pub struct Item<'a> {
10    pub structure: &'a mut Structure,
11    pub self_type: TypeOfSelf,
12}
13
14impl Item<'_> {
15    /// Evaluates every constructable form of item and asks to produce a vector of statements to operate on item
16    pub fn map_constructable(
17        &mut self,
18        cb: impl for<'a> Fn(ConstructableStructure<'a>) -> Result<Vec<Stmt>, Box<dyn Error>>,
19    ) -> Result<Vec<Stmt>, Box<dyn Error>> {
20        let type_of_self = self.self_type;
21        match self.structure {
22            Structure::Enum(EnumStructure {
23                attrs: ref enum_attrs,
24                variants,
25                ..
26            }) => {
27                let branches = variants
28                    .iter_mut()
29                    .map(|variant| {
30                        let result = cb(ConstructableStructure::EnumVariant(variant, enum_attrs));
31                        match result {
32                            Ok(lines) => {
33                                let pattern = variant
34                                    .fields
35                                    .to_pattern(variant.full_path.clone(), type_of_self);
36                                Ok(quote!( #pattern => {
37                                    #(#lines)*
38                                }))
39                            }
40                            Err(err) => Err(err),
41                        }
42                    })
43                    .collect::<Result<Vec<_>, _>>()?;
44
45                Ok(vec![parse_quote!(match self {
46                    #(#branches)*
47                })])
48            }
49            Structure::Struct(r#struct) => {
50                let result = cb(ConstructableStructure::Struct(r#struct));
51                match result {
52                    Ok(mut lines) => {
53                        let pattern = r#struct
54                            .fields
55                            .to_pattern(r#struct.name.clone().into(), self.self_type);
56                        let destructuring_stmt = parse_quote! {
57                            let #pattern = self;
58                        };
59                        lines.insert(0, destructuring_stmt);
60                        Ok(lines)
61                    }
62                    Err(err) => Err(err),
63                }
64            }
65        }
66    }
67}