1use std::error::Error;
2
3use quote::quote;
4use syn::{parse_quote, Stmt};
5
6use crate::{ConstructableStructure, EnumStructure, Structure, TypeOfSelf};
7
8pub struct Item<'a> {
10 pub structure: &'a mut Structure,
11 pub self_type: TypeOfSelf,
12}
13
14impl Item<'_> {
15 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}