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