Skip to main content

surrealguard_macros/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, LitStr};
4
5#[proc_macro]
6pub fn kind(input: TokenStream) -> TokenStream {
7    // Parse the input literal.
8    let input_str = parse_macro_input!(input as LitStr);
9    let type_str = format!(
10        "DEFINE FIELD placeholder ON user TYPE {}",
11        input_str.value()
12    );
13
14    // Attempt to parse at macro expansion time.
15    let parsed = ::surrealdb::sql::parse(&type_str)
16        .map_err(|err| err.to_string())
17        .and_then(|mut stmts| {
18            stmts
19                .pop()
20                .ok_or_else(|| "Empty statement generated".to_string())
21        });
22
23    if let Err(err_msg) = parsed {
24        // Emit a compile_error! invocation.
25        return quote! {
26            compile_error!(#err_msg)
27        }
28        .into();
29    }
30
31    // Otherwise, generate code that parses the type string at runtime.
32    quote! {
33        {
34            let stmt = ::surrealdb::sql::parse(#type_str)
35                .expect("Failed to parse type")
36                .into_iter()
37                .next()
38                .expect("Empty statement");
39
40            match stmt {
41                ::surrealdb::sql::Statement::Define(::surrealdb::sql::statements::DefineStatement::Field(f)) => {
42                    f.kind.expect("Field definition must include a type")
43                },
44                _ => panic!("Expected field definition"),
45            }
46        }
47    }
48    .into()
49}