cli_table_derive/context/
container.rs

1use quote::quote;
2use syn::{DeriveInput, Error, Ident, Lit, Path, Result};
3
4use crate::utils::get_attributes;
5
6pub struct Container<'a> {
7    pub crate_name: Path,
8    pub name: &'a Ident,
9}
10
11impl<'a> Container<'a> {
12    pub fn new(input: &'a DeriveInput) -> Result<Self> {
13        let container_attributes = get_attributes(&input.attrs)?;
14
15        let mut crate_name = None;
16
17        for (key, value) in container_attributes {
18            if key.is_ident("crate") {
19                crate_name = Some(match value {
20                    Lit::Str(lit_str) => lit_str.parse::<Path>(),
21                    bad => Err(Error::new_spanned(
22                        bad,
23                        "Invalid value for #[table(crate = \"crate_path\")]",
24                    )),
25                }?);
26            }
27        }
28
29        let mut container_builder = Container::builder(&input.ident);
30
31        if let Some(crate_name) = crate_name {
32            container_builder.crate_name(crate_name);
33        }
34
35        Ok(container_builder.build())
36    }
37
38    fn builder(name: &'a Ident) -> ContainerBuilder<'a> {
39        ContainerBuilder::new(name)
40    }
41}
42
43struct ContainerBuilder<'a> {
44    crate_name: Option<Path>,
45    name: &'a Ident,
46}
47
48impl<'a> ContainerBuilder<'a> {
49    pub fn new(name: &'a Ident) -> Self {
50        Self {
51            crate_name: None,
52            name,
53        }
54    }
55
56    pub fn crate_name(&mut self, crate_name: Path) -> &mut Self {
57        self.crate_name = Some(crate_name);
58        self
59    }
60
61    pub fn build(self) -> Container<'a> {
62        Container {
63            crate_name: self
64                .crate_name
65                .unwrap_or_else(|| syn::parse2(quote!(::cli_table)).unwrap()),
66            name: self.name,
67        }
68    }
69}