1use darling::FromDeriveInput;
2use syn::parse_macro_input;
3
4use crate::attrs::{ContainerAttrs, extract_container_attr_spans};
5use crate::config::MacroConfig;
6use crate::context::MacroContext;
7
8mod attrs;
9mod build_schema;
10pub(crate) mod codegen_ir_adapter;
11pub(crate) mod config;
12pub(crate) mod context;
13mod emit_ir_common;
14mod from_eure;
15mod into_eure;
16mod ir;
17mod ir_spans;
18mod must_be_text;
19mod object_key;
20
21#[proc_macro_derive(IntoEure, attributes(eure))]
22pub fn into_eure_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
23 let input = parse_macro_input!(input as syn::DeriveInput);
24 match create_context(input) {
25 Ok(context) => into_eure::derive(context).into(),
26 Err(err) => err.to_compile_error().into(),
27 }
28}
29
30#[proc_macro_derive(FromEure, attributes(eure))]
31pub fn from_eure_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
32 let input = parse_macro_input!(input as syn::DeriveInput);
33 match create_context(input) {
34 Ok(context) => from_eure::derive(context).into(),
35 Err(err) => err.to_compile_error().into(),
36 }
37}
38
39#[proc_macro_derive(ObjectKey, attributes(eure))]
40pub fn object_key_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
41 let input = parse_macro_input!(input as syn::DeriveInput);
42 match create_context(input) {
43 Ok(context) => object_key::derive(context).into(),
44 Err(err) => err.to_compile_error().into(),
45 }
46}
47
48#[proc_macro_derive(BuildSchema, attributes(eure))]
49pub fn build_schema_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
50 let input = parse_macro_input!(input as syn::DeriveInput);
51 match create_context(input) {
52 Ok(context) => build_schema::derive(context).into(),
53 Err(err) => err.to_compile_error().into(),
54 }
55}
56
57fn create_context(input: syn::DeriveInput) -> syn::Result<MacroContext> {
58 let attrs = ContainerAttrs::from_derive_input(&input).expect("Failed to parse eure attributes");
59 let attr_spans = extract_container_attr_spans(&input);
60 let mut config = MacroConfig::from_attrs(attrs, attr_spans)?;
61 if has_non_exhaustive_attr(&input.attrs) {
62 config.non_exhaustive = true;
63 }
64 Ok(MacroContext::new(config, input))
65}
66
67fn has_non_exhaustive_attr(attrs: &[syn::Attribute]) -> bool {
68 attrs
69 .iter()
70 .any(|attr| attr.path().is_ident("non_exhaustive"))
71}
72
73#[proc_macro]
92#[allow(non_snake_case)]
93pub fn MustBeText(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
94 let input = parse_macro_input!(input as must_be_text::MustBeTextInput);
95 must_be_text::expand(input).into()
96}