use proc_macro2::TokenStream;
use syn::{Attribute, Error, Lit};
use crate::encoding::PayloadEncoding;
pub struct EventMeta {
pub encoding: PayloadEncoding,
pub version: Option<String>,
}
impl Default for EventMeta {
fn default() -> Self {
Self {
encoding: PayloadEncoding::Json,
version: None,
}
}
}
impl TryFrom<Option<&Attribute>> for EventMeta {
type Error = TokenStream;
fn try_from(attr: Option<&Attribute>) -> Result<Self, Self::Error> {
let mut event_attrs = EventMeta::default();
if let Some(attr) = attr {
let meta = attr.parse_meta().unwrap();
match meta {
syn::Meta::List(list) => {
for nested in list.nested {
match nested {
syn::NestedMeta::Meta(meta) => match meta {
syn::Meta::NameValue(nv) => {
if nv.path.is_ident("encoding") {
if let Lit::Str(lit) = nv.lit {
event_attrs.encoding =
PayloadEncoding::try_from(lit.value().as_ref())
.unwrap();
}
} else if nv.path.is_ident("version") {
if let Lit::Str(lit) = nv.lit {
event_attrs.version = Some(lit.value());
}
}
}
meta_type => {
return Err(Error::new_spanned(
meta_type,
"Unexpected meta type",
)
.to_compile_error());
}
},
meta_type => {
return Err(Error::new_spanned(
meta_type,
"Unexpected nested meta type",
)
.to_compile_error());
}
}
}
}
meta_type => {
return Err(
Error::new_spanned(meta_type, "Unexpected meta type").to_compile_error()
)
}
}
}
Ok(event_attrs)
}
}
impl quote::ToTokens for EventMeta {
fn to_tokens(&self, tokens: &mut TokenStream) {
let version_token = match self.version.clone() {
Some(version) => quote!(std::option::Option::Some(#version)),
None => quote!(std::option::Option::None),
};
let payload_kind_token = match self.encoding {
PayloadEncoding::Json => quote!(timesource::PayloadEncoding::Json),
PayloadEncoding::Cbor => quote!(timesource::PayloadEncoding::Cbor),
PayloadEncoding::ProtoBuf => quote!(timesource::PayloadEncoding::ProtoBuf),
};
let mut encoding_token = TokenStream::new();
self.encoding.to_tokens(&mut encoding_token);
tokens.extend(quote! {
fn version() -> Option<&'static str> {
#version_token
}
fn encoding() -> timesource::PayloadEncoding {
#payload_kind_token
}
#encoding_token
});
}
}