view_types/
lib.rs

1use parse::Views;
2use syn::ItemStruct;
3
4mod expand;
5mod parse;
6mod resolve;
7
8/// The main views procedural macro
9/// 
10/// # Example
11/// ```rust
12/// #[views(
13///     fragment all {
14///         offset,
15///         limit,
16///     }
17///     fragment keyword {
18///         Some(query),
19///         words_limit
20///     }
21///     fragment semantic {
22///         vector
23///     }
24///     view KeywordSearch {
25///         ..all,
26///         ..keyword,
27///     }
28///     view SemanticSearch<'a> {
29///         ..all,
30///         ..semantic,
31///     }
32///     view HybridSearch<'a> {
33///         ..all,
34///         ..keyword,
35///         ..semantic,
36///         Some(ratio) if validate_ratio(ratio)
37///     }
38/// )]
39/// pub struct Search<'a> {
40///     query: Option<String>,
41///     offset: usize,
42///     limit: usize,
43///     words_limit: Option<usize>,
44///     vector: Option<&'a Vec<u8>>,
45///     ratio: Option<f32>,
46/// }
47/// ```
48#[proc_macro_attribute]
49pub fn views(args: proc_macro::TokenStream, input: proc_macro::TokenStream) -> proc_macro::TokenStream {
50    match views_impl(args, input) {
51        Ok(tokens) => tokens,
52        Err(err) => err.to_compile_error().into(),
53    }
54}
55
56fn views_impl(args: proc_macro::TokenStream, input: proc_macro::TokenStream) -> syn::Result<proc_macro::TokenStream> {
57    let view_spec = syn::parse::<Views>(args.into())?;
58    
59    let mut original_struct = syn::parse::<ItemStruct>(input.into())?;
60    let enum_attributes = crate::parse::extract_nested_attributes("Variant", &mut original_struct.attrs)?;
61    let resolution = resolve::resolve(&original_struct, &view_spec, enum_attributes)?;
62    
63    let generated_code = expand::expand(&original_struct, resolution)?;
64    
65    Ok(quote::quote! {
66        #original_struct
67        #generated_code
68    }.into())
69}