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}