1mod fn_arg;
18mod fn_epilog;
19mod fn_prolog;
20mod foreign_mod_arg;
21mod foreign_mod_epilog;
22mod foreign_mod_prolog;
23mod traits;
24mod utils;
25mod vector_ser_der;
26
27pub(crate) use fn_arg::*;
28pub(crate) use fn_epilog::*;
29pub(crate) use fn_prolog::*;
30pub(crate) use foreign_mod_prolog::*;
31pub(crate) use foreign_mod_epilog::*;
32pub(crate) use utils::*;
33pub(crate) use vector_ser_der::*;
34
35use serde::Serialize;
36use serde::Deserialize;
37use syn::parse::Error;
38use syn::spanned::Spanned;
39
40#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
42pub enum ParsedType {
43 I8(PassingStyle),
44 I16(PassingStyle),
45 I32(PassingStyle),
46 I64(PassingStyle),
47 U8(PassingStyle),
48 U16(PassingStyle),
49 U32(PassingStyle),
50 U64(PassingStyle),
51 F32(PassingStyle),
52 F64(PassingStyle),
53 Boolean(PassingStyle),
54 Utf8Str(PassingStyle),
55 Utf8String(PassingStyle),
56 Vector(Box<ParsedType>, PassingStyle),
57 Record(String, PassingStyle), }
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
61pub enum PassingStyle {
62 ByValue,
63 ByRef,
64 ByMutRef,
65}
66
67impl ParsedType {
68 pub fn from_type(input_type: &syn::Type) -> syn::Result<Self> {
69 use quote::ToTokens;
70
71 let (path, passing_style) = type_to_path_passing_style(input_type)?;
72
73 let type_segment = path
74 .segments
75 .last()
78 .ok_or_else(|| Error::new(path.span(), "Type should be specified"))?;
79
80 match type_segment.ident.to_string().as_str() {
81 "i8" => Ok(ParsedType::I8(passing_style)),
82 "i16" => Ok(ParsedType::I16(passing_style)),
83 "i32" => Ok(ParsedType::I32(passing_style)),
84 "i64" => Ok(ParsedType::I64(passing_style)),
85 "u8" => Ok(ParsedType::U8(passing_style)),
86 "u16" => Ok(ParsedType::U16(passing_style)),
87 "u32" => Ok(ParsedType::U32(passing_style)),
88 "u64" => Ok(ParsedType::U64(passing_style)),
89 "f32" => Ok(ParsedType::F32(passing_style)),
90 "f64" => Ok(ParsedType::F64(passing_style)),
91 "bool" => Ok(ParsedType::Boolean(passing_style)),
92 "str" => Ok(ParsedType::Utf8Str(passing_style)),
93 "String" => Ok(ParsedType::Utf8String(passing_style)),
94 "Vec" => {
95 let vec_type = parse_vec_bracket(&type_segment.arguments)?;
96 let parsed_type = ParsedType::from_type(vec_type)?;
97
98 Ok(ParsedType::Vector(Box::new(parsed_type), passing_style))
99 }
100 _ if !type_segment.arguments.is_empty() => Err(Error::new(
101 type_segment.span(),
102 "types with lifetimes or generics aren't allowed".to_string(),
103 )),
104 _ => Ok(ParsedType::Record(
105 (&type_segment.ident).into_token_stream().to_string(),
106 passing_style,
107 )),
108 }
109 }
110
111 pub fn from_fn_arg(fn_arg: &syn::FnArg) -> syn::Result<Self> {
112 match fn_arg {
113 syn::FnArg::Typed(arg) => ParsedType::from_type(&arg.ty),
114 _ => Err(Error::new(
115 fn_arg.span(),
116 "`self` argument types aren't supported",
117 )),
118 }
119 }
120
121 pub fn from_return_type(ret_type: &syn::ReturnType) -> syn::Result<Option<Self>> {
122 match ret_type {
123 syn::ReturnType::Type(_, t) => Ok(Some(ParsedType::from_type(t.as_ref())?)),
124 syn::ReturnType::Default => Ok(None),
125 }
126 }
127
128 pub fn is_complex_type(&self) -> bool {
129 match self {
130 ParsedType::Boolean(_)
131 | ParsedType::I8(_)
132 | ParsedType::I16(_)
133 | ParsedType::I32(_)
134 | ParsedType::I64(_)
135 | ParsedType::U8(_)
136 | ParsedType::U16(_)
137 | ParsedType::U32(_)
138 | ParsedType::U64(_)
139 | ParsedType::F32(_)
140 | ParsedType::F64(_) => false,
141 ParsedType::Utf8Str(_)
142 | ParsedType::Utf8String(_)
143 | ParsedType::Vector(..)
144 | ParsedType::Record(..) => true,
145 }
146 }
147}
148
149fn type_to_path_passing_style(input_type: &syn::Type) -> syn::Result<(&syn::Path, PassingStyle)> {
150 match input_type {
151 syn::Type::Path(path) => Ok((&path.path, PassingStyle::ByValue)),
152 syn::Type::Reference(type_reference) => match &*type_reference.elem {
153 syn::Type::Path(path) => {
154 let passing_style = match type_reference.mutability {
155 Some(_) => PassingStyle::ByMutRef,
156 None => PassingStyle::ByRef,
157 };
158
159 Ok((&path.path, passing_style))
160 }
161 _ => Err(Error::new(
162 input_type.span(),
163 "Incorrect argument type, only path is available on this position",
164 )),
165 },
166 _ => Err(Error::new(
167 input_type.span(),
168 "Incorrect argument type, only path or reference are available on this position",
169 )),
170 }
171}
172
173fn parse_vec_bracket(args: &syn::PathArguments) -> syn::Result<&syn::Type> {
175 let generic_arg = match args {
177 syn::PathArguments::AngleBracketed(args) => Ok(args),
178 _ => Err(Error::new(
179 args.span(),
180 "expected value in angle brackets (<>)",
181 )),
182 }?;
183
184 let arg = generic_arg.args.first().ok_or_else(|| {
185 Error::new(
186 generic_arg.span(),
187 "Invalid type in Vec brackets. (NOTE: lifetimes, bindings, constraints and consts are not supported)",
188 )
189 })?;
190
191 match arg {
193 syn::GenericArgument::Type(ty) => Ok(ty),
194 _ => Err(Error::new(
195 arg.span(),
196 "Invalid type in Vec brackets. (NOTE: lifetimes, bindings, constraints and consts are not supported)",
197 )),
198 }
199}