tslink/nature/
mod.rs

1mod defs;
2mod fabric;
3mod generic;
4mod origin;
5mod types;
6
7pub use defs::Composite;
8pub use defs::Primitive;
9pub use defs::Referred;
10pub use fabric::{TypeAsString, TypeTokenStream, VariableTokenStream};
11pub use generic::ExtractGenerics;
12pub use origin::OriginType;
13pub use types::Extract;
14
15use crate::{context::Context, error::E};
16use std::{collections::HashMap, ops::Deref};
17
18pub struct NatureDef {
19    pub nature: Nature,
20    pub module: Option<String>,
21}
22
23impl NatureDef {
24    pub fn new(nature: Nature, module: Option<String>) -> Self {
25        Self { nature, module }
26    }
27    pub fn get_mut(&mut self) -> &mut Nature {
28        &mut self.nature
29    }
30    pub fn get(&self) -> &Nature {
31        &self.nature
32    }
33    pub fn extract(&self) -> Nature {
34        self.nature.clone()
35    }
36}
37pub struct Natures(HashMap<String, NatureDef>);
38
39impl Natures {
40    pub fn new() -> Self {
41        Natures(HashMap::new())
42    }
43    pub fn is_any_bound(natures: &[Nature]) -> bool {
44        for nature in natures.iter() {
45            if let Nature::Referred(Referred::Field(_, _, _, binding)) = nature {
46                if binding.is_some() {
47                    return true;
48                }
49            }
50        }
51        false
52    }
53    pub fn get_fn_args_names(args: &[Nature]) -> Vec<String> {
54        args.iter()
55            .filter_map(|arg| {
56                if let Nature::Referred(Referred::FuncArg(name, _, _, _)) = arg {
57                    Some(name.to_owned())
58                } else {
59                    None
60                }
61            })
62            .collect::<Vec<String>>()
63    }
64    pub fn contains(&self, name: &str) -> bool {
65        self.0.contains_key(name)
66    }
67    pub fn insert(&mut self, name: &str, nature: Nature, module: Option<String>) -> Result<(), E> {
68        if self.contains(name) {
69            Err(E::EntityExist(name.to_owned()))
70        } else {
71            let _ = self
72                .0
73                .insert(name.to_owned(), NatureDef::new(nature, module));
74            Ok(())
75        }
76    }
77    pub fn get_module_of(&self, name: &str) -> Option<String> {
78        self.0.get(name).and_then(|n| n.module.clone())
79    }
80    pub fn exists_in_module(&self, name: &str, module: &str) -> bool {
81        self.0
82            .get(name)
83            .map(|n| n.module.as_ref().map(|m| m == module).unwrap_or_default())
84            .unwrap_or_default()
85    }
86    pub fn get_mut(
87        &mut self,
88        name: &str,
89        default_nature: Option<Nature>,
90        default_module: Option<String>,
91    ) -> Option<&mut Nature> {
92        if let (exists, Some(default_nature)) = (self.0.contains_key(name), default_nature) {
93            if !exists {
94                let _ = self.0.insert(
95                    name.to_owned(),
96                    NatureDef::new(default_nature, default_module),
97                );
98            }
99        }
100        self.0.get_mut(name).map(|n| n.get_mut())
101    }
102
103    pub fn filter(&self, filter: fn(&Nature) -> bool) -> Vec<Nature> {
104        let mut natures: Vec<Nature> = vec![];
105        for (_, n) in self.0.iter() {
106            if filter(n.get()) {
107                natures.push(n.extract());
108            }
109        }
110        natures
111    }
112
113    pub fn iter(&self) -> impl Iterator<Item = (&String, &Nature)> {
114        self.0.iter().map(|(k, n)| (k, n.get()))
115    }
116}
117
118#[derive(Clone, Debug)]
119pub enum Nature {
120    Primitive(Primitive),
121    Referred(Referred),
122    Composite(Composite),
123}
124
125impl Nature {
126    pub fn get_fn_args_names(&self) -> Result<Vec<String>, E> {
127        if let Nature::Composite(Composite::Func(_, args, _, _, _)) = self {
128            Ok(Natures::get_fn_args_names(args))
129        } else {
130            Err(E::Parsing("Fail to find arguments of function".to_string()))
131        }
132    }
133
134    pub fn is_fn_async(&self) -> Result<bool, E> {
135        if let Nature::Composite(Composite::Func(_, _, _, asyncness, _)) = self {
136            Ok(*asyncness)
137        } else {
138            Err(E::Parsing("Fail to find function".to_string()))
139        }
140    }
141
142    pub fn bind(&mut self, nature: Nature) -> Result<(), E> {
143        match self {
144            Self::Primitive(_) => Err(E::Parsing(String::from("Primitive type cannot be bound"))),
145            Self::Referred(re) => match re {
146                Referred::Struct(_, _, natures) => {
147                    natures.push(nature);
148                    Ok(())
149                }
150                Referred::TupleStruct(_, _, field) => {
151                    let _ = field.insert(Box::new(nature));
152                    Ok(())
153                }
154                Referred::Enum(_, _, natures, ..) => {
155                    natures.push(nature);
156                    Ok(())
157                }
158                Referred::EnumVariant(_, _, natures, ..) => {
159                    natures.push(nature);
160                    Ok(())
161                }
162                _ => Err(E::NotSupported("Referred".to_owned())),
163            },
164            Self::Composite(othr) => match othr {
165                Composite::HashMap(_, k, v) => {
166                    if k.is_none() {
167                        if let Self::Primitive(p) = nature {
168                            let _ = k.insert(p);
169                            Ok(())
170                        } else {
171                            Err(E::Parsing(String::from(
172                                "HashMap can use as key only Primitive type",
173                            )))
174                        }
175                    } else if v.is_none() {
176                        let _ = v.insert(Box::new(nature));
177                        Ok(())
178                    } else {
179                        Err(E::Parsing(String::from(
180                            "HashMap entity already has been bound",
181                        )))
182                    }
183                }
184                Composite::Option(_, o) => {
185                    if o.is_some() {
186                        Err(E::Parsing(String::from(
187                            "Option entity already has been bound",
188                        )))
189                    } else {
190                        let _ = o.insert(Box::new(nature));
191                        Ok(())
192                    }
193                }
194                Composite::Result(_, r, e, _, _) => {
195                    if r.is_some() && e.is_some() {
196                        Err(E::Parsing(String::from(
197                            "Result entity already has been bound",
198                        )))
199                    } else if r.is_none() {
200                        let _ = r.insert(Box::new(nature));
201
202                        Ok(())
203                    } else {
204                        let _ = e.insert(Box::new(nature));
205                        Ok(())
206                    }
207                }
208                Composite::Tuple(_, tys) => {
209                    tys.push(nature);
210                    Ok(())
211                }
212                Composite::Vec(_, v) => {
213                    if v.is_some() {
214                        Err(E::Parsing(String::from(
215                            "Vec entity already has been bound",
216                        )))
217                    } else {
218                        let _ = v.insert(Box::new(nature));
219                        Ok(())
220                    }
221                }
222                _ => Err(E::NotSupported(String::from("Composite"))),
223            },
224        }
225    }
226
227    pub fn is_method_constructor(&self) -> bool {
228        if let Nature::Referred(Referred::Field(_, _, nature, _)) = self {
229            if let Nature::Composite(Composite::Func(_, _, _, _, constructor)) = nature.deref() {
230                return *constructor;
231            }
232        }
233        false
234    }
235
236    pub fn is_field_ignored(&self) -> bool {
237        if let Nature::Referred(Referred::Field(name, context, _, _)) = self {
238            context.is_ignored(name)
239        } else {
240            false
241        }
242    }
243
244    pub fn check_ignored_fields(&self) -> Result<(), E> {
245        if let Nature::Referred(Referred::Struct(name, context, fields)) = self {
246            let ignored = context.ignored_list();
247            if ignored.is_empty() {
248                return Ok(());
249            }
250            let existed = fields
251                .iter()
252                .filter_map(|f| {
253                    if let Nature::Referred(Referred::Field(name, _, _, _)) = f {
254                        Some(name.to_owned())
255                    } else {
256                        None
257                    }
258                })
259                .collect::<Vec<String>>();
260            for n in ignored {
261                if !existed.iter().any(|name| name == &n) {
262                    return Err(E::Parsing(format!(
263                        "Field in ignored list \"{n}\" isn't found in struct \"{name}\""
264                    )));
265                }
266            }
267            Ok(())
268        } else {
269            Ok(())
270        }
271    }
272
273    pub fn get_context(&self) -> Result<&Context, E> {
274        Ok(match self {
275            Self::Primitive(_) => Err(E::Parsing(String::from("Primitives do not have context")))?,
276            Self::Composite(_composite) => {
277                Err(E::Parsing(String::from("Composite do not have context")))?
278            }
279            Self::Referred(refered) => match refered {
280                Referred::Enum(_, context, ..) => context,
281                Referred::EnumVariant(_, context, ..) => context,
282                Referred::Field(_, context, ..) => context,
283                Referred::Func(_, context, ..) => context,
284                Referred::FuncArg(_, context, ..) => context,
285                Referred::TupleStruct(_, context, ..) => context,
286                Referred::Struct(_, context, ..) => context,
287                Referred::Constant(_, context, ..) => context,
288                Referred::Ref(..) => {
289                    Err(E::Parsing(String::from("Reference do not have context")))?
290                }
291                Referred::Generic(..) => {
292                    Err(E::Parsing(String::from("Generic do not have context")))?
293                }
294            },
295        })
296    }
297}