typhoon_syn/helpers/
path.rs1use 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}