1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{Data, DeriveInput, Fields, parse_macro_input};
4
5#[proc_macro_derive(SiaEncode)]
6pub fn derive_sia_encode(input: TokenStream) -> TokenStream {
7 let input = parse_macro_input!(input as DeriveInput);
8 let name = &input.ident;
9
10 let encode_impl = match &input.data {
11 Data::Struct(data) => {
12 let fields = match &data.fields {
13 Fields::Named(fields) => {
14 let encodes = fields.named.iter().filter_map(|f| match f.vis {
15 syn::Visibility::Public(_) => {
16 let name = &f.ident;
17 Some(quote! { self.#name.encode(w)?; })
18 }
19 _ => None,
20 });
21 quote! { #(#encodes)* }
22 }
23 Fields::Unnamed(fields) => {
24 let encodes = fields.unnamed.iter().enumerate().map(|(i, _)| {
25 let index = syn::Index::from(i);
26 quote! { self.#index.encode(w)?; }
27 });
28 quote! { #(#encodes)* }
29 }
30 Fields::Unit => quote! {},
31 };
32 quote! {
33 #fields
34 Ok(())
35 }
36 }
37 Data::Enum(_) => panic!("enums not supported"),
38 Data::Union(_) => panic!("unions not supported"),
39 };
40
41 let expanded = quote! {
42 impl SiaEncodable for #name {
43 fn encode<W: std::io::Write>(&self, w: &mut W) -> sia::encoding::Result<()> {
44 #encode_impl
45 }
46 }
47 };
48
49 TokenStream::from(expanded)
50}
51
52#[proc_macro_derive(SiaDecode)]
53pub fn derive_sia_decode(input: TokenStream) -> TokenStream {
54 let input = parse_macro_input!(input as DeriveInput);
55 let name = &input.ident;
56
57 let decode_impl = match &input.data {
58 Data::Struct(data) => match &data.fields {
59 Fields::Named(fields) => {
60 let decodes = fields.named.iter().filter_map(|f| match f.vis {
61 syn::Visibility::Public(_) => {
62 let name = &f.ident;
63 let ty = &f.ty;
64 Some(quote! { #name: <#ty>::decode(r)?, })
65 }
66 _ => None,
67 });
68 quote! {
69 Ok(Self {
70 #(#decodes)*
71 })
72 }
73 }
74 Fields::Unnamed(fields) => {
75 let decodes = fields.unnamed.iter().map(|f| {
76 let ty = &f.ty;
77 quote! { <#ty>::decode(r)?, }
78 });
79 quote! {
80 Ok(Self(#(#decodes)*))
81 }
82 }
83 Fields::Unit => quote! { Ok(Self) },
84 },
85 Data::Enum(_) => panic!("enums not supported"),
86 Data::Union(_) => panic!("unions not supported"),
87 };
88
89 let expanded = quote! {
90 impl SiaDecodable for #name {
91 fn decode<R: std::io::Read>(r: &mut R) -> sia::encoding::Result<Self> {
92 #decode_impl
93 }
94 }
95 };
96 TokenStream::from(expanded)
97}
98
99#[proc_macro_derive(V1SiaEncode)]
100pub fn derive_v1_sia_encode(input: TokenStream) -> TokenStream {
101 let input = parse_macro_input!(input as DeriveInput);
102 let name = &input.ident;
103
104 let encode_impl = match &input.data {
105 Data::Struct(data) => {
106 let fields = match &data.fields {
107 Fields::Named(fields) => {
108 let encodes = fields.named.iter().map(|f| {
109 let name = &f.ident;
110 quote! { self.#name.encode_v1(enc)?; }
111 });
112 quote! { #(#encodes)* }
113 }
114 Fields::Unnamed(fields) => {
115 let encodes = fields.unnamed.iter().enumerate().map(|(i, _)| {
116 let index = syn::Index::from(i);
117 quote! { self.#index.encode_v1(enc)?; }
118 });
119 quote! { #(#encodes)* }
120 }
121 Fields::Unit => quote! {},
122 };
123 quote! {
124 #fields
125 Ok(())
126 }
127 }
128 Data::Enum(_) => panic!("enums not supported"),
129 Data::Union(_) => panic!("unions not supported"),
130 };
131
132 let expanded = quote! {
133 impl V1SiaEncodable for #name {
134 fn encode_v1<W: std::io::Write>(&self, enc: &mut W) -> crate::encoding::Result<()> {
135 #encode_impl
136 }
137 }
138 };
139 TokenStream::from(expanded)
140}
141
142#[proc_macro_derive(V1SiaDecode)]
143pub fn derive_v1_sia_decode(input: TokenStream) -> TokenStream {
144 let input = parse_macro_input!(input as DeriveInput);
145 let name = &input.ident;
146
147 let decode_impl = match &input.data {
148 Data::Struct(data) => match &data.fields {
149 Fields::Named(fields) => {
150 let decodes = fields.named.iter().map(|f| {
151 let name = &f.ident;
152 let ty = &f.ty;
153 quote! { #name: <#ty>::decode_v1(r)?, }
154 });
155 quote! {
156 Ok(Self {
157 #(#decodes)*
158 })
159 }
160 }
161 Fields::Unnamed(fields) => {
162 let decodes = fields.unnamed.iter().map(|f| {
163 let ty = &f.ty;
164 quote! { <#ty>::decode_v1(r)?, }
165 });
166 quote! {
167 Ok(Self(#(#decodes)*))
168 }
169 }
170 Fields::Unit => quote! { Ok(Self) },
171 },
172 Data::Enum(_) => panic!("enums not supported"),
173 Data::Union(_) => panic!("unions not supported"),
174 };
175
176 let expanded = quote! {
177 impl V1SiaDecodable for #name {
178 fn decode_v1<R: std::io::Read>(r: &mut R) -> crate::encoding::Result<Self> {
179 #decode_impl
180 }
181 }
182 };
183 TokenStream::from(expanded)
184}
185
186#[proc_macro_derive(AsyncSiaEncode)]
187pub fn derive_async_sia_encode(input: TokenStream) -> TokenStream {
188 let input = parse_macro_input!(input as DeriveInput);
189 let name = &input.ident;
190
191 let encode_impl = match &input.data {
192 Data::Struct(data) => {
193 let fields = match &data.fields {
194 Fields::Named(fields) => {
195 let encodes = fields.named.iter().filter_map(|f| match f.vis {
196 syn::Visibility::Public(_) => {
197 let name = &f.ident;
198 Some(quote! { self.#name.encode_async(e).await?; })
199 }
200 _ => None,
201 });
202 quote! { #(#encodes)* }
203 }
204 Fields::Unnamed(fields) => {
205 let encodes = fields.unnamed.iter().enumerate().map(|(i, _)| {
206 let index = syn::Index::from(i);
207 quote! { self.#index.encode_async(e).await?; }
208 });
209 quote! { #(#encodes)* }
210 }
211 Fields::Unit => quote! {},
212 };
213 quote! {
214 #fields
215 Ok(())
216 }
217 }
218 Data::Enum(_) => panic!("enums not supported"),
219 Data::Union(_) => panic!("unions not supported"),
220 };
221
222 let expanded = quote! {
223 impl AsyncSiaEncodable for #name {
224 async fn encode_async<E: crate::encoding_async::AsyncEncoder>(&self, e: &mut E) -> Result<(), E::Error> {
225 #encode_impl
226 }
227 }
228 };
229
230 TokenStream::from(expanded)
231}
232
233#[proc_macro_derive(AsyncSiaDecode)]
234pub fn derive_async_sia_decode(input: TokenStream) -> TokenStream {
235 let input = parse_macro_input!(input as DeriveInput);
236 let name = &input.ident;
237
238 let decode_impl = match &input.data {
239 Data::Struct(data) => match &data.fields {
240 Fields::Named(fields) => {
241 let decodes = fields.named.iter().filter_map(|f| match f.vis {
242 syn::Visibility::Public(_) => {
243 let name = &f.ident;
244 let ty = &f.ty;
245 Some(quote! { #name: <#ty>::decode_async(d).await?, })
246 }
247 _ => None,
248 });
249 quote! {
250 Ok(Self {
251 #(#decodes)*
252 })
253 }
254 }
255 Fields::Unnamed(fields) => {
256 let decodes = fields.unnamed.iter().map(|f| {
257 let ty = &f.ty;
258 quote! { <#ty>::decode_async(d).await?, }
259 });
260 quote! {
261 Ok(Self(#(#decodes)*))
262 }
263 }
264 Fields::Unit => quote! { Ok(Self) },
265 },
266 Data::Enum(_) => panic!("enums not supported"),
267 Data::Union(_) => panic!("unions not supported"),
268 };
269
270 let expanded = quote! {
271 impl AsyncSiaDecodable for #name {
272 async fn decode_async<D: crate::encoding_async::AsyncDecoder>(d: &mut D) -> Result<Self, D::Error> {
273 #decode_impl
274 }
275 }
276 };
277 TokenStream::from(expanded)
278}