1 use darling::{FromDeriveInput, FromField, FromMeta, FromVariant};
2 use proc_macro::TokenStream;
3 use proc_macro2::TokenStream as TokStr;
4 use quote::{quote, ToTokens};
5 use syn::{parse_macro_input, parse_quote};
7 #[derive(Debug, FromMeta, Copy, Clone, Eq, PartialEq)]
8 #[darling(rename_all = "snake_case")]
14 #[derive(Debug, FromMeta)]
17 repr: Option<syn::Type>,
19 content: Option<String>,
26 fn wrap_attr(attr: &mut syn::Attribute) {
27 let path = attr.path.clone();
28 let tokens = attr.tokens.clone();
30 match attr.path.get_ident().map(|i| i.to_string()).as_deref() {
32 *attr = parse_quote! {
33 #[cfg_attr(any(feature = "client", feature = "server"), #path #tokens)]
37 *attr = parse_quote! {
38 #[cfg_attr(feature = "serde", #path #tokens)]
45 #[proc_macro_attribute]
46 pub fn mt_derive(attr: TokenStream, item: TokenStream) -> TokenStream {
47 let item2 = item.clone();
49 let attr_args = parse_macro_input!(attr as syn::AttributeArgs);
50 let mut input = parse_macro_input!(item2 as syn::Item);
52 let args = match MacroArgs::from_list(&attr_args) {
55 return TokenStream::from(e.write_errors());
59 let (serializer, deserializer) = match args.to {
60 To::Clt => ("server", "client"),
61 To::Srv => ("client", "server"),
64 let mut out = quote! {
66 #[cfg_attr(feature = "random", derive(GenerateRandom))]
67 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
71 ($t:expr, $f:expr) => {
72 $t.iter_mut().for_each($f)
77 syn::Item::Enum(e) => {
78 iter!(e.attrs, wrap_attr);
79 iter!(e.variants, |v| {
80 iter!(v.attrs, wrap_attr);
81 iter!(v.fields, |f| iter!(f.attrs, wrap_attr));
84 let repr = args.repr.expect("missing repr for enum");
87 let repr_str = repr.to_token_stream().to_string();
90 #[derive(EnumSetType)]
91 #[enumset(repr = #repr_str, serialize_as_map)]
97 .find_map(|v| if v.fields.is_empty() { None } else { Some(()) })
101 let tag = args.tag.expect("missing tag for enum with payload");
104 #[cfg_attr(feature = "serde", serde(tag = #tag))]
107 if let Some(content) = args.content {
109 #[cfg_attr(feature = "serde", serde(content = #content))]
120 #[derive(Clone, PartialEq)]
125 #[cfg_attr(feature = #serializer, derive(MtSerialize))]
126 #[cfg_attr(feature = #deserializer, derive(MtDeserialize))]
132 #[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
135 syn::Item::Struct(s) => {
136 iter!(s.attrs, wrap_attr);
137 iter!(s.fields, |f| iter!(f.attrs, wrap_attr));
140 #[derive(Clone, PartialEq)]
145 #[cfg_attr(feature = #serializer, derive(MtSerialize))]
146 #[cfg_attr(feature = #deserializer, derive(MtDeserialize))]
150 _ => panic!("only enum and struct supported"),
153 out.extend(input.to_token_stream());
157 #[derive(Debug, Default, FromDeriveInput, FromVariant, FromField)]
158 #[darling(attributes(mt))]
162 const16: Option<u16>,
163 const32: Option<u32>,
164 const64: Option<u64>,
180 fn get_cfg(args: &MtArgs) -> syn::Type {
181 let mut ty: syn::Type = parse_quote! { mt_ser::DefCfg };
184 ty = parse_quote! { () };
187 macro_rules! impl_len {
188 ($name:ident, $T:ty) => {
190 ty = parse_quote! { $T };
196 impl_len!(len16, u16);
197 impl_len!(len32, u32);
198 impl_len!(len64, u64);
201 ty = parse_quote! { mt_ser::Utf16<#ty> };
207 type Fields<'a> = Vec<(TokStr, &'a syn::Field)>;
209 fn get_fields(fields: &syn::Fields, ident: impl Fn(TokStr) -> TokStr) -> Fields {
211 syn::Fields::Named(fs) => fs
214 .map(|f| (ident(f.ident.as_ref().unwrap().to_token_stream()), f))
216 syn::Fields::Unnamed(fs) => fs
220 .map(|(i, f)| (ident(i.to_string().to_token_stream()), f))
222 syn::Fields::Unit => Vec::new(),
226 fn serialize_args(res: darling::Result<MtArgs>, body: impl FnOnce(&MtArgs) -> TokStr) -> TokStr {
229 let mut code = TokStr::new();
231 macro_rules! impl_const {
233 if let Some(x) = args.$name {
235 #x.mt_serialize::<mt_ser::DefCfg>(__writer)?;
242 impl_const!(const16);
243 impl_const!(const32);
244 impl_const!(const64);
246 code.extend(body(&args));
251 let mut __stream = mt_ser::flate2::write::ZlibEncoder::new(
253 mt_ser::flate2::Compression::default(),
255 let __writer = &mut __stream;
262 macro_rules! impl_size {
263 ($name:ident, $T:ty) => {
266 mt_ser::MtSerialize::mt_serialize::<$T>(&{
267 let mut __buf = Vec::new();
268 let __writer = &mut __buf;
277 impl_size!(size8, u8);
278 impl_size!(size16, u16);
279 impl_size!(size32, u32);
280 impl_size!(size64, u64);
284 Err(e) => return e.write_errors(),
288 fn deserialize_args(res: darling::Result<MtArgs>, body: impl FnOnce(&MtArgs) -> TokStr) -> TokStr {
291 let mut code = body(&args);
293 macro_rules! impl_const {
295 if let Some(want) = args.$name {
297 mt_ser::MtDeserialize::mt_deserialize::<mt_ser::DefCfg>(__reader)
302 Err(mt_ser::DeserializeError::InvalidConst(
303 #want as u64, got as u64
312 impl_const!(const64);
313 impl_const!(const32);
314 impl_const!(const16);
320 let mut __owned_reader = mt_ser::flate2::read::ZlibDecoder::new(
321 mt_ser::WrapRead(__reader));
322 let __reader = &mut __owned_reader;
329 macro_rules! impl_size {
330 ($name:ident, $T:ty) => {
333 $T::mt_deserialize::<DefCfg>(__reader).and_then(|size| {
334 let mut __owned_reader = std::io::Read::take(
335 mt_ser::WrapRead(__reader), size as u64);
336 let __reader = &mut __owned_reader;
345 impl_size!(size8, u8);
346 impl_size!(size16, u16);
347 impl_size!(size32, u32);
348 impl_size!(size64, u64);
352 Err(e) => return e.write_errors()
356 fn serialize_fields(fields: &Fields) -> TokStr {
359 .map(|(ident, field)| {
360 serialize_args(MtArgs::from_field(field), |args| {
361 let cfg = get_cfg(args);
362 quote! { mt_ser::MtSerialize::mt_serialize::<#cfg>(#ident, __writer)?; }
368 fn deserialize_fields(fields: &Fields) -> TokStr {
371 .map(|(ident, field)| {
372 let code = deserialize_args(MtArgs::from_field(field), |args| {
373 let cfg = get_cfg(args);
374 let mut code = quote! { mt_ser::MtDeserialize::mt_deserialize::<#cfg>(__reader) };
378 mt_ser::OrDefault::or_default(#code)
392 fn get_fields_struct(input: &syn::Fields) -> (Fields, TokStr) {
393 let ident_fn = match input {
394 syn::Fields::Unnamed(_) => |f| quote! {
395 mt_ser::paste::paste! { [<field_ #f>] }
397 _ => |f| quote! { #f },
400 let fields = get_fields(input, ident_fn);
401 let fields_comma: TokStr = fields.iter()
402 .rfold(TokStr::new(), |after, (ident, _)| quote! { #ident, #after });
404 let fields_struct = match input {
405 syn::Fields::Named(_) => quote! { { #fields_comma } },
406 syn::Fields::Unnamed(_) => quote! { ( #fields_comma ) },
407 syn::Fields::Unit => TokStr::new(),
410 (fields, fields_struct)
413 fn get_repr(input: &syn::DeriveInput) -> syn::Type {
417 .find(|a| a.path.is_ident("repr"))
418 .expect("missing repr")
420 .expect("invalid repr")
423 #[proc_macro_derive(MtSerialize, attributes(mt))]
424 pub fn derive_serialize(input: TokenStream) -> TokenStream {
425 let input = parse_macro_input!(input as syn::DeriveInput);
426 let typename = &input.ident;
428 let code = serialize_args(MtArgs::from_derive_input(&input), |_| match &input.data {
429 syn::Data::Enum(e) => {
430 let repr = get_repr(&input);
431 let variants: TokStr = e.variants
433 .fold((parse_quote! { 0 }, TokStr::new()), |(discr, before), v| {
434 let discr = v.discriminant.clone().map(|x| x.1).unwrap_or(discr);
435 let (fields, fields_struct) = get_fields_struct(&v.fields);
437 let code = serialize_args(MtArgs::from_variant(v), |_|
438 serialize_fields(&fields));
439 let variant = &v.ident;
442 parse_quote! { 1 + #discr },
445 #typename::#variant #fields_struct => {
446 mt_ser::MtSerialize::mt_serialize::<mt_ser::DefCfg>(&((#discr) as #repr), __writer)?;
459 syn::Data::Struct(s) => serialize_fields(&get_fields(&s.fields, |f| quote! { &self.#f })),
461 panic!("only enum and struct supported");
466 #[automatically_derived]
467 impl mt_ser::MtSerialize for #typename {
468 fn mt_serialize<C: mt_ser::MtCfg>(&self, __writer: &mut impl std::io::Write) -> Result<(), mt_ser::SerializeError> {
477 #[proc_macro_derive(MtDeserialize, attributes(mt))]
478 pub fn derive_deserialize(input: TokenStream) -> TokenStream {
479 let input = parse_macro_input!(input as syn::DeriveInput);
480 let typename = &input.ident;
482 let code = deserialize_args(MtArgs::from_derive_input(&input), |_| match &input.data {
483 syn::Data::Enum(e) => {
484 let repr = get_repr(&input);
485 let type_str = typename.to_string();
487 let mut consts = TokStr::new();
488 let mut arms = TokStr::new();
489 let mut discr = parse_quote! { 0 };
491 for v in e.variants.iter() {
492 discr = v.discriminant.clone().map(|x| x.1).unwrap_or(discr);
494 let ident = &v.ident;
495 let (fields, fields_struct) = get_fields_struct(&v.fields);
496 let code = deserialize_args(MtArgs::from_variant(v), |_| {
497 let fields_code = deserialize_fields(&fields);
501 Ok(Self::#ident #fields_struct)
505 consts.extend(quote! {
506 const #ident: #repr = #discr;
513 discr = parse_quote! { 1 + #discr };
519 match mt_ser::MtDeserialize::mt_deserialize::<DefCfg>(__reader)? {
521 x => Err(mt_ser::DeserializeError::InvalidEnumVariant(#type_str, x as u64))
525 syn::Data::Struct(s) => {
526 let (fields, fields_struct) = get_fields_struct(&s.fields);
527 let code = deserialize_fields(&fields);
531 Ok(Self #fields_struct)
535 panic!("only enum and struct supported");
540 #[automatically_derived]
541 impl mt_ser::MtDeserialize for #typename {
542 #[allow(non_upper_case_globals)]
543 fn mt_deserialize<C: mt_ser::MtCfg>(__reader: &mut impl std::io::Read) -> Result<Self, mt_ser::DeserializeError> {