bon_macros/util/ty/
mod.rs
1mod match_types;
2
3use crate::util::prelude::*;
4use syn::punctuated::Punctuated;
5
6pub(crate) trait TypeExt {
7 fn as_path(&self) -> Option<&syn::TypePath>;
9
10 fn as_path_no_qself(&self) -> Option<&syn::Path>;
13
14 fn option_type_param(&self) -> Option<&syn::Type>;
16
17 fn as_generic_angle_bracketed_path(
21 &self,
22 is_desired_last_segment: impl FnOnce(&syn::Ident) -> bool,
23 ) -> Option<GenericAngleBracketedPath<'_>>;
24
25 fn is_option(&self) -> bool;
27
28 fn peel(&self) -> &Self;
30
31 fn matches(&self, pattern: &syn::Type) -> Result<bool>;
38}
39
40impl TypeExt for syn::Type {
41 fn as_path(&self) -> Option<&syn::TypePath> {
42 match self.peel() {
43 Self::Path(path) => Some(path),
44 _ => None,
45 }
46 }
47
48 fn as_path_no_qself(&self) -> Option<&syn::Path> {
49 let path = self.as_path()?;
50 if path.qself.is_some() {
51 return None;
52 }
53 Some(&path.path)
54 }
55
56 fn option_type_param(&self) -> Option<&syn::Type> {
57 let ty = self.as_generic_angle_bracketed_path(|last_segment| last_segment == "Option")?;
58
59 if ty.args.len() != 1 {
60 return None;
61 }
62
63 let arg = ty.args.first()?;
64
65 let arg = match arg {
66 syn::GenericArgument::Type(arg) => arg,
67 _ => return None,
68 };
69
70 Some(arg)
71 }
72
73 fn as_generic_angle_bracketed_path(
74 &self,
75 is_desired_last_segment: impl FnOnce(&syn::Ident) -> bool,
76 ) -> Option<GenericAngleBracketedPath<'_>> {
77 let path = self.as_path_no_qself()?;
78
79 let last_segment = path.segments.last()?;
80
81 if !is_desired_last_segment(&last_segment.ident) {
82 return None;
83 }
84
85 let args = match &last_segment.arguments {
86 syn::PathArguments::AngleBracketed(args) => &args.args,
87 _ => return None,
88 };
89
90 Some(GenericAngleBracketedPath { path, args })
91 }
92
93 fn is_option(&self) -> bool {
94 self.option_type_param().is_some()
95 }
96
97 fn peel(&self) -> &Self {
98 match self {
99 Self::Group(group) => group.elem.peel(),
100 Self::Paren(paren) => paren.elem.peel(),
101 _ => self,
102 }
103 }
104
105 fn matches(&self, pattern: &syn::Type) -> Result<bool> {
106 match_types::match_types(self, pattern)
107 }
108}
109
110pub(crate) struct GenericAngleBracketedPath<'a> {
111 pub(crate) path: &'a syn::Path,
112 pub(crate) args: &'a Punctuated<syn::GenericArgument, syn::Token![,]>,
113}