miniextendr_macros/
type_inspect.rs1pub(crate) fn nth_type_argument(seg: &syn::PathSegment, n: usize) -> Option<&syn::Type> {
5 if let syn::PathArguments::AngleBracketed(ab) = &seg.arguments {
6 let mut count = 0;
7 for arg in ab.args.iter() {
8 if let syn::GenericArgument::Type(ty) = arg {
9 if count == n {
10 return Some(ty);
11 }
12 count += 1;
13 }
14 }
15 }
16 None
17}
18
19pub(crate) fn first_type_argument(seg: &syn::PathSegment) -> Option<&syn::Type> {
21 nth_type_argument(seg, 0)
22}
23
24pub(crate) fn second_type_argument(seg: &syn::PathSegment) -> Option<&syn::Type> {
26 nth_type_argument(seg, 1)
27}
28
29#[inline]
31pub(crate) fn is_sexp_type(ty: &syn::Type) -> bool {
32 matches!(ty, syn::Type::Path(p) if p
33 .path
34 .segments
35 .last()
36 .map(|s| s.ident == "SEXP")
37 .unwrap_or(false))
38}
39
40#[derive(Debug, Clone)]
43pub(crate) enum SeveralOkContainer {
44 Vec,
46 BoxedSlice,
48 Array(usize),
50 BorrowedSlice,
52}
53
54pub(crate) fn classify_several_ok_container(
60 ty: &syn::Type,
61) -> Option<(SeveralOkContainer, &syn::Type)> {
62 match ty {
63 syn::Type::Path(tp) => {
65 let seg = tp.path.segments.last()?;
66 if seg.ident == "Vec" {
67 let inner = first_type_argument(seg)?;
68 return Some((SeveralOkContainer::Vec, inner));
69 }
70 if seg.ident == "Box"
72 && let syn::PathArguments::AngleBracketed(ab) = &seg.arguments
73 {
74 for arg in &ab.args {
75 if let syn::GenericArgument::Type(syn::Type::Slice(s)) = arg {
76 return Some((SeveralOkContainer::BoxedSlice, s.elem.as_ref()));
77 }
78 }
79 }
80 None
81 }
82 syn::Type::Array(arr) => {
84 if let syn::Expr::Lit(syn::ExprLit {
85 lit: syn::Lit::Int(n),
86 ..
87 }) = &arr.len
88 {
89 let n = n.base10_parse::<usize>().ok()?;
90 return Some((SeveralOkContainer::Array(n), arr.elem.as_ref()));
91 }
92 None
93 }
94 syn::Type::Reference(r) => {
96 if let syn::Type::Slice(s) = r.elem.as_ref() {
97 return Some((SeveralOkContainer::BorrowedSlice, s.elem.as_ref()));
98 }
99 None
100 }
101 _ => None,
102 }
103}