Skip to main content

typhoon_syn/helpers/
path.rs

1use syn::{Expr, ExprLit, Ident, Lit, Path, ReturnType, Type, TypePath};
2
3pub trait PathHelper {
4    fn get_element_with_inner(&self) -> Option<(Ident, Option<Type>, Option<usize>)>;
5}
6
7impl PathHelper for ReturnType {
8    fn get_element_with_inner(&self) -> Option<(Ident, Option<Type>, Option<usize>)> {
9        match self {
10            ReturnType::Default => None,
11            ReturnType::Type(_, boxed_type) => match boxed_type.as_ref() {
12                Type::Path(ty_path) => ty_path.get_element_with_inner(),
13                _ => None,
14            },
15        }
16    }
17}
18
19impl PathHelper for TypePath {
20    fn get_element_with_inner(&self) -> Option<(Ident, Option<Type>, Option<usize>)> {
21        self.path.get_element_with_inner()
22    }
23}
24
25impl PathHelper for Path {
26    fn get_element_with_inner(&self) -> Option<(Ident, Option<Type>, Option<usize>)> {
27        let seg = self.segments.last()?;
28        let (inner_type, inner_const_size) = extract_generic_arguments(&seg.arguments);
29
30        Some((seg.ident.clone(), inner_type, inner_const_size))
31    }
32}
33
34fn extract_generic_arguments(args: &syn::PathArguments) -> (Option<Type>, Option<usize>) {
35    let mut inner_type = None;
36    let mut inner_const_size = None;
37
38    if let syn::PathArguments::AngleBracketed(angle_args) = args {
39        for arg in &angle_args.args {
40            match arg {
41                syn::GenericArgument::Type(ty) if inner_type.is_none() => {
42                    inner_type = Some(ty.clone());
43                }
44                syn::GenericArgument::Const(Expr::Lit(ExprLit {
45                    lit: Lit::Int(lit), ..
46                })) if inner_const_size.is_none() => {
47                    if let Ok(val) = lit.base10_parse() {
48                        inner_const_size = Some(val);
49                    }
50                }
51                _ => continue,
52            }
53        }
54    }
55
56    (inner_type, inner_const_size)
57}