1use std::fmt::Display;
2use quote::ToTokens;
3use syn::{
4 parse::{Parse, ParseStream}, parse_quote, punctuated::Punctuated, Lit, Meta, Token
5};
6
7
8macro_rules! fallible_macro {
9 (
10 $(
11 #[ $( $attribute_decl:tt )* ]
12 )*
13 pub fn $macro_name:ident ( $( $params:tt )* ) -> syn::Result<$inner_return:path> {
14 $( $fn_body:tt )*
15 }
16 ) => {
17 $(
18 #[ $( $attribute_decl )* ]
19 )*
20 pub fn $macro_name ( $( $params )* ) -> $inner_return {
21 let result = move || -> ::syn::Result<_> {
22 $( $fn_body )*
23 };
24
25 match result() {
26 Ok(val) => val,
27 Err(err) => err.into_compile_error().into(),
28 }
29 }
30 }
31}
32
33
34#[derive(Debug, Clone)]
35pub struct Options {
36 pub crate_path: syn::Path,
37}
38
39impl Default for Options {
40 fn default() -> Self {
41 Self {
42 crate_path: parse_quote!(::saa_schema),
43 }
44 }
45}
46
47impl Display for Options {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 write!(f, "crate_path: {}", self.crate_path.to_token_stream())
50 }
51}
52
53
54impl Parse for Options {
55 fn parse(input: ParseStream) -> syn::Result<Self> {
56 let mut acc = Self::default();
57 let params = Punctuated::<Meta, Token![,]>::parse_terminated(input)?;
58 for param in params {
59 match param {
60 Meta::NameValue(nv) => {
61 if nv.path.is_ident("crate") {
62 if let Lit::Str(s) = nv.lit {
63 acc.crate_path = s.parse()?;
64 } else {
65 return Err(syn::Error::new_spanned(nv.lit, "expected string literal"));
66 }
67 } else {
68 return Err(syn::Error::new_spanned(nv.path, "unknown option"));
69 }
70 }
71 _ => {
72 return Err(syn::Error::new_spanned(param, "expected `key = \"value\"` format"));
73 }
74 }
75 }
76 Ok(acc)
77 }
78}
79
80pub(crate) use fallible_macro;