osal_rs_serde_derive/
lib.rs1use proc_macro::TokenStream;
41use quote::quote;
42use proc_macro2::Literal;
43use syn::{parse_macro_input, Data, DeriveInput, Fields};
44
45#[proc_macro_derive(Serialize)]
59pub fn derive_serialize(input: TokenStream) -> TokenStream {
60 let input = parse_macro_input!(input as DeriveInput);
61 let name = &input.ident;
62
63
64 let serialize_impl = match &input.data {
65 Data::Struct(data_struct) => match &data_struct.fields {
66 Fields::Named(fields) => {
67 let field_count = fields.named.len();
68 let field_serializations = fields.named.iter().map(|f| {
69 let field_name = &f.ident;
70 let field_name_str = field_name.as_ref().unwrap().to_string();
71 quote! {
72 serializer.serialize_field(#field_name_str, &self.#field_name)?;
73 }
74 });
75
76 quote! {
77 impl osal_rs_serde::Serialize for #name {
78 fn serialize<S: osal_rs_serde::Serializer>(&self, name: &str, serializer: &mut S) -> Result<(), S::Error> {
79 serializer.serialize_struct_start(name, #field_count)?;
80 #(#field_serializations)*
81 serializer.serialize_struct_end()?;
82 Ok(())
83 }
84 }
85 }
86 }
87 Fields::Unnamed(fields) => {
88 let field_count = fields.unnamed.len();
89 let field_serializations = (0..fields.unnamed.len()).map(|i| {
90 let index = syn::Index::from(i);
91 let name_lit = Literal::string(&i.to_string());
92 quote! {
93 serializer.serialize_field(#name_lit, &self.#index)?;
94 }
95 });
96
97 quote! {
98 impl osal_rs_serde::Serialize for #name {
99 fn serialize<S: osal_rs_serde::Serializer>(&self, name: &str, serializer: &mut S) -> Result<(), S::Error> {
100 serializer.serialize_struct_start(name, #field_count)?;
101 #(#field_serializations)*
102 serializer.serialize_struct_end()?;
103 Ok(())
104 }
105 }
106 }
107 }
108 Fields::Unit => {
109 quote! {
110 impl osal_rs_serde::Serialize for #name {
111 fn serialize<S: osal_rs_serde::Serializer>(&self, _name: &str, _serializer: &mut S) -> Result<(), S::Error> {
112 Ok(())
113 }
114 }
115 }
116 }
117 },
118 Data::Enum(_) => {
119 return syn::Error::new_spanned(
120 name,
121 "Serialize derive macro does not support enums yet"
122 )
123 .to_compile_error()
124 .into();
125 }
126 Data::Union(_) => {
127 return syn::Error::new_spanned(
128 name,
129 "Serialize derive macro does not support unions"
130 )
131 .to_compile_error()
132 .into();
133 }
134 };
135
136 TokenStream::from(serialize_impl)
137}
138
139#[proc_macro_derive(Deserialize)]
153pub fn derive_deserialize(input: TokenStream) -> TokenStream {
154 let input = parse_macro_input!(input as DeriveInput);
155 let name = &input.ident;
156
157 let deserialize_impl = match &input.data {
158 Data::Struct(data_struct) => match &data_struct.fields {
159 Fields::Named(fields) => {
160 let field_deserializations = fields.named.iter().map(|f| {
161 let field_name = &f.ident;
162 let field_name_str = field_name.as_ref().unwrap().to_string();
163 let field_type = &f.ty;
164 quote! {
165 #field_name: deserializer.deserialize_field::<#field_type>(#field_name_str)?
166 }
167 });
168
169 quote! {
170 impl osal_rs_serde::Deserialize for #name {
171 fn deserialize<D: osal_rs_serde::Deserializer>(deserializer: &mut D, name: &str) -> Result<Self, D::Error> {
172 deserializer.deserialize_struct_start(name)?;
173 let result = Self {
174 #(#field_deserializations,)*
175 };
176 deserializer.deserialize_struct_end()?;
177 Ok(result)
178 }
179 }
180 }
181 }
182 Fields::Unnamed(fields) => {
183 let field_types = fields.unnamed.iter().map(|f| &f.ty);
184
185 quote! {
186 impl osal_rs_serde::Deserialize for #name {
187 fn deserialize<D: osal_rs_serde::Deserializer>(deserializer: &mut D, name: &str) -> Result<Self, D::Error> {
188 Ok(Self(
189 #(<#field_types as osal_rs_serde::Deserialize>::deserialize(deserializer, name)?,)*
190 ))
191 }
192 }
193 }
194 }
195 Fields::Unit => {
196 quote! {
197 impl osal_rs_serde::Deserialize for #name {
198 fn deserialize<D: osal_rs_serde::Deserializer>(_deserializer: &mut D, _name: &str) -> Result<Self, D::Error> {
199 Ok(Self)
200 }
201 }
202 }
203 }
204 },
205 Data::Enum(_) => {
206 return syn::Error::new_spanned(
207 name,
208 "Deserialize derive macro does not support enums yet"
209 )
210 .to_compile_error()
211 .into();
212 }
213 Data::Union(_) => {
214 return syn::Error::new_spanned(
215 name,
216 "Deserialize derive macro does not support unions"
217 )
218 .to_compile_error()
219 .into();
220 }
221 };
222
223 TokenStream::from(deserialize_impl)
224}