argus_ser_macros/
lib.rs

1pub(crate) mod utils;
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{Item, parse_macro_input};
6use utils::*;
7
8#[proc_macro_attribute]
9pub fn argus(_attr: TokenStream, item: TokenStream) -> TokenStream {
10  item
11}
12
13#[proc_macro]
14pub fn serialize_custom_seq(input: TokenStream) -> TokenStream {
15  let SerializeCustomSeqArgs {
16    wrap,
17    serializer,
18    value,
19  } = parse_macro_input!(input as SerializeCustomSeqArgs);
20
21  TokenStream::from(quote! {{
22     use serde::ser::SerializeSeq;
23     let mut seq = #serializer.serialize_seq(Some(#value.len()))?;
24     for e in #value.into_iter() {
25         seq.serialize_element(&(#wrap)(e))?;
26     }
27     seq.end()
28  }})
29}
30
31#[proc_macro_derive(Many)]
32pub fn create_slice_wrapper(item: TokenStream) -> TokenStream {
33  let ast = parse_macro_input!(item as Item);
34  let argus: ArgusIdentifiers = argus_identifiers(&ast);
35
36  let mut generics_outlive_a = argus.generics.clone();
37  let life_a = introduce_outlives(&mut generics_outlive_a);
38
39  let ArgusIdentifiers {
40    name,
41    remote,
42    slice: slice_name,
43    generics,
44    ..
45  } = argus;
46  let name_str = name.to_string();
47  let raw = remote.path();
48
49  TokenStream::from(quote! {
50      pub struct #slice_name;
51      impl #slice_name {
52        pub fn serialize<S: serde::Serializer>(
53          value: &[#raw],
54          s: S
55        ) -> Result<S::Ok, S::Error> {
56          #[derive(serde::Serialize)]
57          struct Wrapper #generics_outlive_a (
58            #[serde(with = #name_str)]
59            & #life_a #raw #generics
60          );
61          crate::serialize_custom_seq!(Wrapper, s, value)
62        }
63      }
64  })
65}
66
67#[proc_macro_derive(Poly)]
68pub fn create_poly_wrapper(item: TokenStream) -> TokenStream {
69  let ast = parse_macro_input!(item as Item);
70
71  let ArgusIdentifiers {
72    name, remote, poly, ..
73  } = argus_identifiers(&ast);
74
75  let raw = remote.path();
76  let remote_path_str = remote.lit();
77  let ts_ty_str = remote.path().segments.last().unwrap().ident.to_string();
78  let name_str = name.to_string();
79  let ts_str = format!("Poly{}", remove_def_annotation(&name_str));
80
81  TokenStream::from(quote! {
82      #[derive(Clone, Debug, serde::Serialize)]
83      #[serde(rename_all = "camelCase")]
84      #[argus(remote = #remote_path_str)]
85      #[cfg_attr(feature = "testing", derive(ts_rs::TS))]
86      #[cfg_attr(feature = "testing", ts(export, rename = #ts_str))]
87      pub struct #poly<'tcx> {
88          #[serde(with = #name_str)]
89          #[cfg_attr(feature = "testing", ts(type = #ts_ty_str))]
90          value: #raw<'tcx>,
91
92          #[serde(with = "crate::ty::BoundVariableKindDefs")]
93          #[cfg_attr(feature = "testing", ts(type = "BoundVariableKind[]"))]
94          bound_vars: &'tcx rustc_middle::ty::List<rustc_middle::ty::BoundVariableKind>,
95      }
96
97      impl<'tcx> #poly<'tcx> {
98          pub fn new(value: &rustc_middle::ty::Binder<'tcx, #raw<'tcx>>) -> Self {
99              let value = value.clone();
100              Self {
101                  bound_vars: value.bound_vars(),
102                  value: value.skip_binder(),
103              }
104          }
105
106          pub fn serialize<S: serde::Serializer>(
107              value: &rustc_middle::ty::Binder<'tcx, #raw<'tcx>>,
108              s: S,
109          ) -> Result<S::Ok, S::Error> {
110              Self::new(value).serialize(s)
111          }
112      }
113  })
114}
115
116#[proc_macro_derive(Maybe)]
117pub fn create_maybe_wrapper(item: TokenStream) -> TokenStream {
118  let ast = parse_macro_input!(item as Item);
119
120  let ArgusIdentifiers {
121    name,
122    remote,
123    maybe,
124    ..
125  } = argus_identifiers(&ast);
126
127  let raw = remote.path();
128
129  TokenStream::from(quote! {
130      pub struct #maybe;
131    impl #maybe {
132        pub fn serialize<S>(value: &Option<#raw>, s: S) -> Result<S::Ok, S::Error>
133        where
134            S: serde::Serializer,
135        {
136            match value {
137            None => s.serialize_none(),
138            Some(ty) => #name::serialize(ty, s),
139            }
140        }
141        }
142  })
143}