1#![doc = include_str!("../README.md")]
2
3mod derive;
4mod fields;
5mod generic_helpers;
6mod lists_and_arguments;
7mod model;
8
9use std::error::Error;
10
11use either_n::Either2;
12use proc_macro2::{Ident, Span, TokenStream};
13use syn::{Attribute, ConstParam, Expr, FnArg, GenericParam, Path, Stmt, Type, TypeParam};
14
15pub use proc_macro2;
16pub use quote::{format_ident, quote, ToTokens};
17pub use syn;
18
19pub use derive::*;
20pub use fields::*;
21pub use lists_and_arguments::*;
22pub use model::Item;
23
24pub(crate) fn generic_parameters_have_same_name(
26 generic_parameter1: &GenericParam,
27 generic_parameter2: &GenericParam,
28) -> bool {
29 match (generic_parameter1, generic_parameter2) {
30 (GenericParam::Type(gtp1), GenericParam::Type(gtp2)) => gtp1.ident == gtp2.ident,
31 (GenericParam::Lifetime(glp1), GenericParam::Lifetime(glp2)) => {
32 glp1.lifetime.ident == glp2.lifetime.ident
33 }
34 (GenericParam::Const(gcp1), GenericParam::Const(gcp2)) => gcp1.ident == gcp2.ident,
35 _ => false,
36 }
37}
38
39pub(crate) fn generic_param_to_generic_argument_token_stream(
41 trait_generic_parameter: &GenericParam,
42) -> TokenStream {
43 match trait_generic_parameter {
44 GenericParam::Const(ConstParam { ident, .. })
45 | GenericParam::Type(TypeParam { ident, .. }) => ident.to_token_stream(),
46 GenericParam::Lifetime(lifetime) => lifetime.to_token_stream(),
47 }
48}
49
50pub fn dyn_error_to_compile_error_tokens(err: Box<dyn Error>) -> TokenStream {
51 let error_as_string = syn::LitStr::new(&err.to_string(), Span::call_site());
52 quote!(compile_error!(#error_as_string);)
53}
54
55pub struct Trait {
57 pub name: Path,
58 pub generic_parameters: Option<Vec<GenericParam>>,
59 pub items: Vec<TraitItem>,
60}
61
62type HandlerResult = Result<Vec<Stmt>, Box<dyn Error>>;
64
65pub enum TraitItem {
67 Method {
68 name: Ident,
69 generic_parameters: Option<Vec<GenericParam>>,
70 self_type: TypeOfSelf,
71 other_parameters: Vec<FnArg>,
72 return_type: Option<Type>,
73 handler: Box<dyn for<'a> Fn(Item<'a>) -> HandlerResult>,
74 },
75 AssociatedFunction {
76 name: Ident,
77 generic_parameters: Option<Vec<GenericParam>>,
78 parameters: Vec<FnArg>,
79 return_type: Option<Type>,
80 handler: Box<dyn for<'a> Fn(&'a mut Structure) -> HandlerResult>,
81 },
82}
83
84#[derive(Clone, Copy)]
86pub enum TypeOfSelf {
87 Reference,
89 MutableReference,
91 Owned,
93}
94
95impl TypeOfSelf {
96 fn as_parameter_tokens(&self) -> TokenStream {
97 match self {
98 TypeOfSelf::Reference => quote!(&self),
99 TypeOfSelf::MutableReference => quote!(&mut self),
100 TypeOfSelf::Owned => quote!(self),
101 }
102 }
103
104 fn as_matcher_tokens(&self) -> TokenStream {
105 match self {
106 TypeOfSelf::Reference => quote!(ref),
107 TypeOfSelf::MutableReference => quote!(ref mut),
108 TypeOfSelf::Owned => TokenStream::default(),
109 }
110 }
111}
112
113impl TraitItem {
114 pub fn new_method(
116 name: Ident,
117 generic_parameters: Option<Vec<GenericParam>>,
118 self_type: TypeOfSelf,
119 other_parameters: Vec<FnArg>,
120 return_type: Option<Type>,
121 handler: impl for<'a> Fn(Item<'a>) -> HandlerResult + 'static,
122 ) -> Self {
123 Self::Method {
124 name,
125 generic_parameters,
126 self_type,
127 other_parameters,
128 return_type,
129 handler: Box::new(handler),
130 }
131 }
132
133 pub fn new_associated_function(
135 name: Ident,
136 generic_parameters: Option<Vec<GenericParam>>,
137 parameters: Vec<FnArg>,
138 return_type: Option<Type>,
139 handler: impl for<'a> Fn(&'a mut Structure) -> HandlerResult + 'static,
140 ) -> Self {
141 Self::AssociatedFunction {
142 name,
143 generic_parameters,
144 parameters,
145 return_type,
146 handler: Box::new(handler),
147 }
148 }
149}
150
151pub struct EnumStructure {
153 name: Ident,
154 attrs: Vec<Attribute>,
155 variants: Vec<EnumVariant>,
156}
157
158impl EnumStructure {
159 pub fn get_variants(&self) -> &[EnumVariant] {
160 &self.variants
161 }
162
163 pub fn get_variants_mut(&mut self) -> &mut [EnumVariant] {
164 self.variants.as_mut_slice()
165 }
166}
167
168impl HasAttributes for EnumStructure {
169 fn get_attributes(&self) -> &[Attribute] {
170 &self.attrs
171 }
172}
173
174pub struct EnumVariant {
176 full_path: Path,
177 pub idx: usize,
178 fields: Fields,
179}
180
181pub struct StructStructure {
183 name: Ident,
184 fields: Fields,
185}
186
187pub trait Constructable {
189 fn get_constructor_path(&self) -> Path;
191
192 fn build_constructor(
194 &self,
195 generator: impl Fn(NamedOrUnnamedField) -> Result<Expr, Box<dyn Error>>,
196 ) -> Result<Expr, Box<dyn std::error::Error>>;
197
198 fn get_fields(&self) -> &Fields;
199 fn get_fields_mut(&mut self) -> &mut Fields;
200}
201
202impl Constructable for StructStructure {
203 fn build_constructor(
204 &self,
205 generator: impl Fn(NamedOrUnnamedField) -> Result<Expr, Box<dyn Error>>,
206 ) -> Result<Expr, Box<dyn std::error::Error>> {
207 self.fields
208 .to_constructor(generator, self.name.clone().into())
209 }
210
211 fn get_fields(&self) -> &Fields {
212 &self.fields
213 }
214
215 fn get_fields_mut(&mut self) -> &mut Fields {
216 &mut self.fields
217 }
218
219 fn get_constructor_path(&self) -> Path {
220 self.name.clone().into()
221 }
222}
223
224impl Constructable for EnumVariant {
225 fn build_constructor(
226 &self,
227 generator: impl Fn(NamedOrUnnamedField) -> Result<Expr, Box<dyn Error>>,
228 ) -> Result<Expr, Box<dyn std::error::Error>> {
229 self.fields
230 .to_constructor(generator, self.full_path.clone())
231 }
232
233 fn get_fields(&self) -> &Fields {
234 &self.fields
235 }
236
237 fn get_fields_mut(&mut self) -> &mut Fields {
238 &mut self.fields
239 }
240
241 fn get_constructor_path(&self) -> Path {
242 self.full_path.clone()
243 }
244}
245
246pub trait HasAttributes {
247 fn get_attributes(&self) -> &[Attribute];
248}
249
250pub enum Structure {
252 Struct(StructStructure),
253 Enum(EnumStructure),
254}
255
256pub enum ConstructableStructure<'a> {
258 Struct(&'a mut StructStructure),
259 EnumVariant(&'a mut EnumVariant, &'a [Attribute]),
260}
261
262impl Structure {
263 fn all_fields(&self) -> impl Iterator<Item = NamedOrUnnamedField<'_>> {
265 match self {
266 Structure::Struct(r#struct) => Either2::One(r#struct.get_fields().fields_iterator()),
267 Structure::Enum(r#enum) => Either2::Two(
268 r#enum
269 .variants
270 .iter()
271 .flat_map(|variant| variant.get_fields().fields_iterator()),
272 ),
273 }
274 }
275
276 pub fn get_attributes(&self) -> &[Attribute] {
278 match self {
279 Structure::Struct(r#struct) => r#struct.fields.get_field_attributes(),
281 Structure::Enum(r#enum) => r#enum.attrs.as_slice(),
282 }
283 }
284
285 pub fn get_name(&self) -> &Ident {
287 match self {
288 Structure::Struct(r#struct) => &r#struct.name,
289 Structure::Enum(r#enum) => &r#enum.name,
290 }
291 }
292}
293
294impl Constructable for ConstructableStructure<'_> {
295 fn build_constructor(
296 &self,
297 generator: impl Fn(NamedOrUnnamedField) -> Result<Expr, Box<dyn Error>>,
298 ) -> Result<Expr, Box<dyn std::error::Error>> {
299 match self {
300 ConstructableStructure::Struct(r#struct) => r#struct.build_constructor(generator),
301 ConstructableStructure::EnumVariant(enum_variant, _) => {
302 enum_variant.build_constructor(generator)
303 }
304 }
305 }
306
307 fn get_fields(&self) -> &Fields {
308 match self {
309 ConstructableStructure::Struct(r#struct) => r#struct.get_fields(),
310 ConstructableStructure::EnumVariant(enum_variant, _) => enum_variant.get_fields(),
311 }
312 }
313
314 fn get_fields_mut(&mut self) -> &mut Fields {
315 match self {
316 ConstructableStructure::Struct(r#struct) => r#struct.get_fields_mut(),
317 ConstructableStructure::EnumVariant(enum_variant, _) => enum_variant.get_fields_mut(),
318 }
319 }
320
321 fn get_constructor_path(&self) -> Path {
322 match self {
323 ConstructableStructure::Struct(r#struct) => r#struct.get_constructor_path(),
324 ConstructableStructure::EnumVariant(enum_variant, _) => {
325 enum_variant.get_constructor_path()
326 }
327 }
328 }
329}
330
331impl<'a> ConstructableStructure<'a> {
332 pub fn as_enum_variant(&'a self) -> Option<&'a EnumVariant> {
333 if let Self::EnumVariant(variant, _) = self {
334 Some(&**variant)
335 } else {
336 None
337 }
338 }
339
340 pub fn all_attributes<'b: 'a>(&'b self) -> impl Iterator<Item = &'b Attribute> + '_ {
341 match self {
342 ConstructableStructure::Struct(r#struct) => {
343 Either2::One(r#struct.get_fields().get_field_attributes().iter())
344 }
345 ConstructableStructure::EnumVariant(r#enum, parent_attrs) => Either2::Two(
346 parent_attrs
347 .iter()
348 .chain(r#enum.get_fields().get_field_attributes().iter()),
349 ),
350 }
351 }
352}
353
354pub fn path_to_string(path: Path) -> String {
356 let mut buf = String::new();
357 if path.leading_colon.is_some() {
358 buf.push_str("::");
359 }
360 for (idx, segment) in path.segments.iter().enumerate() {
361 buf.push_str(&segment.ident.to_string());
362 if !segment.arguments.is_empty() {
363 todo!()
364 }
365 if idx != path.segments.len() - 1 {
366 buf.push_str("::");
367 }
368 }
369 buf
370}