apache_avro_derive/attributes/
serde.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Attribute parsing for Serde attributes
19//!
20//! # Serde attributes
21//! This module only parses the minimal amount to be able to read Serde attributes. This means
22//! most attributes are decoded as an `Option<String>` as the actual content is not relevant.
23//! Attributes which are not needed by the derive are prefixed with a `_` as we can't ignore them
24//! (this would be a compile error).
25//!
26//! If Serde adds new attributes they need to be added here too.
27
28use darling::{FromAttributes, FromMeta};
29use syn::Expr;
30
31use crate::case::RenameRule;
32
33/// Represents `rename_all` and `rename_all_fields`.
34///
35/// These attributes can take the following forms:
36///   1. `rename_all = ".."`
37///   2. `rename_all(serialize = "..", deserialize = "..")`
38///
39/// To parse the first form, we use Darling's `from_expr`.
40/// To parse the second form, we use Darling's `FromMeta` derive.
41#[derive(Debug, Default, FromMeta, PartialEq, Eq)]
42#[darling(from_expr = RenameAll::from_expr)]
43pub struct RenameAll {
44    #[darling(default)]
45    pub serialize: RenameRule,
46    #[darling(default)]
47    pub deserialize: RenameRule,
48}
49
50impl From<RenameRule> for RenameAll {
51    fn from(value: RenameRule) -> Self {
52        Self {
53            serialize: value,
54            deserialize: value,
55        }
56    }
57}
58
59impl RenameAll {
60    fn from_expr(expr: &Expr) -> darling::Result<Self> {
61        let Expr::Lit(lit) = expr else {
62            return Err(darling::Error::custom("Expected a string literal!"));
63        };
64        let rule = RenameRule::from_value(&lit.lit)?;
65        Ok(RenameAll::from(rule))
66    }
67}
68
69/// Represents `default`.
70///
71/// This attribute can take the following forms:
72///   1. `default`
73///   2. `default = ".."`
74///
75/// To parse the first form, we use Darling's `FromMeta` derive with `word, skip`.
76/// To parse the second form, we use Darling's `from_expr`.
77#[derive(Debug, FromMeta, PartialEq)]
78#[darling(from_expr = |expr| Ok(SerdeDefault::Expr(expr.clone())))]
79pub enum SerdeDefault {
80    #[darling(word, skip)]
81    UseTrait,
82    Expr(Expr),
83}
84
85/// All Serde attributes that a container can have.
86#[derive(Debug, FromAttributes)]
87#[darling(attributes(serde))]
88pub struct ContainerAttributes {
89    /// Rename this container.
90    pub rename: Option<String>,
91    /// Rename all the fields (if this is a struct) or variants (if this is an enum) according to the given case convention.
92    #[darling(default)]
93    pub rename_all: RenameAll,
94    /// Rename all the fields of the struct variants in this enum.
95    #[darling(default, rename = "rename_all_fields")]
96    pub _rename_all_fields: RenameAll,
97    /// Error when encountering unknown fields when deserialising.
98    #[darling(default, rename = "deny_unknown_fields")]
99    pub _deny_unknown_fields: bool,
100    /// Add/expect a tag during serialisation.
101    ///
102    /// When used on a struct, this adds an extra field which is not in the schema definition.
103    /// When used on an enum, serde transforms it into a struct which does not match the schema definition.
104    pub tag: Option<String>,
105    /// Put the content in a field with this name.
106    pub content: Option<String>,
107    /// This makes the enum transparent, (de)serializing based on the variant directly.
108    ///
109    /// This does not match the schema definition.
110    #[darling(default)]
111    pub untagged: bool,
112    /// Add a bound to the Serialize/Deserialize trait.
113    #[darling(default, rename = "bound")]
114    pub _bound: Option<String>,
115    /// When deserializing, any missing fields should be filled in from the struct's implementation of `Default`.
116    #[darling(rename = "default")]
117    pub _default: Option<SerdeDefault>,
118    /// This type is the serde implementation for a "remote" type.
119    ///
120    /// This makes the (de)serialisation use/return a different type.
121    pub remote: Option<String>,
122    /// Directly use the inner type for (de)serialisation.
123    #[darling(default)]
124    pub transparent: bool,
125    /// Deserialize using the given type and then convert to this type with `From`.
126    #[darling(default, rename = "from")]
127    pub _from: Option<String>,
128    /// Deserialize using the given type and then convert to this type with `TryFrom`.
129    #[darling(default, rename = "try_from")]
130    pub _try_from: Option<String>,
131    /// Convert this type to the given type using `Into` and then serialize using the given type.
132    #[darling(default, rename = "into")]
133    pub _into: Option<String>,
134    /// Use the Serde API at this path.
135    #[darling(default, rename = "crate")]
136    pub _crate: Option<String>,
137    /// Custom error text.
138    #[darling(default, rename = "expecting")]
139    pub _expecting: Option<String>,
140    /// This does something with tags, which are incompatible.
141    #[darling(default)]
142    pub variant_identifier: bool,
143    /// This does something with tags, which are incompatible.
144    #[darling(default)]
145    pub field_identifier: bool,
146}
147
148/// All Serde attributes that a enum variant can have.
149#[derive(Debug, FromAttributes)]
150#[darling(attributes(serde))]
151pub struct VariantAttributes {
152    /// Rename the variant.
153    #[darling(default)]
154    pub rename: Option<String>,
155    /// Aliases for this variant, only used during deserialisation.
156    #[darling(multiple, rename = "alias")]
157    pub _alias: Vec<String>,
158    #[darling(default, rename = "rename_all")]
159    pub _rename_all: RenameAll,
160    /// Do not serialize or deserialize this variant.
161    #[darling(default, rename = "skip")]
162    pub _skip: bool,
163    /// Do not serialize this variant.
164    #[darling(default, rename = "skip_serializing")]
165    pub _skip_serializing: bool,
166    /// Do not deserialize this variant.
167    #[darling(default, rename = "skip_deserializing")]
168    pub _skip_deserializing: bool,
169    /// Use this function for serializing.
170    #[darling(rename = "serialize_with")]
171    pub _serialize_with: Option<String>,
172    /// Use this function for deserializing.
173    #[darling(rename = "deserialize_with")]
174    pub _deserialize_with: Option<String>,
175    /// Use this module for (de)serializing.
176    #[darling(rename = "with")]
177    pub _with: Option<String>,
178    /// Put trait bounds on the implementations.
179    #[darling(rename = "bound")]
180    pub _bound: Option<String>,
181    /// Put bounds on the lifetimes.
182    #[darling(rename = "borrow")]
183    pub _borrow: Option<SerdeBorrow>,
184    /// This does something with tags, which are incompatible.
185    #[darling(default)]
186    pub other: bool,
187    /// (De)serialize this variant as if it was not part of the enum.
188    #[darling(default)]
189    pub untagged: bool,
190}
191
192/// Represents `borrow`.
193///
194/// This attribute can take the following forms:
195///   1. `borrow`
196///   2. `borrow = ".."`
197///
198/// To parse the first form, we use Darling's `FromMeta` derive with `word, skip`.
199/// To parse the second form, we use Darling's `from_expr`.
200#[derive(Debug, FromMeta, PartialEq)]
201#[darling(from_expr = |expr| Ok(SerdeBorrow::Expr(expr.clone())))]
202pub enum SerdeBorrow {
203    #[darling(word, skip)]
204    Default,
205    Expr(Expr),
206}
207
208/// All Serde attributes that a field can have.
209#[derive(Debug, FromAttributes)]
210#[darling(attributes(serde))]
211pub struct FieldAttributes {
212    /// Rename the field.
213    #[darling(default)]
214    pub rename: Option<String>,
215    /// Aliases for this field, only used during deserialisation.
216    #[darling(multiple)]
217    pub alias: Vec<String>,
218    /// When deserializing, if this field is missing use `Default` or the given function.
219    #[darling(rename = "default")]
220    pub _default: Option<SerdeDefault>,
221    #[darling(default)]
222    pub flatten: bool,
223    /// Do not serialize or deserialize this field.
224    #[darling(default)]
225    pub skip: bool,
226    /// Do not serialize this field.
227    #[darling(default)]
228    pub skip_serializing: bool,
229    /// Do not deserialize this field.
230    #[darling(default)]
231    pub skip_deserializing: bool,
232    /// Do not serialize this field if the function returns `false`.
233    pub skip_serializing_if: Option<String>,
234    /// Use this function for serializing.
235    #[darling(rename = "serialize_with")]
236    pub _serialize_with: Option<String>,
237    /// Use this function for deserializing.
238    #[darling(rename = "deserialize_with")]
239    pub _deserialize_with: Option<String>,
240    /// Use this module for (de)serializing.
241    pub with: Option<String>,
242    /// Put bounds on the lifetimes.
243    #[darling(rename = "borrow")]
244    pub _borrow: Option<SerdeBorrow>,
245    /// Used for remote types.
246    pub getter: Option<String>,
247}
248
249#[cfg(test)]
250mod tests {
251    use crate::{
252        RenameRule,
253        attributes::serde::{ContainerAttributes, RenameAll, SerdeDefault},
254    };
255    use darling::FromAttributes;
256    use syn::DeriveInput;
257
258    #[test]
259    fn test_rename_all() {
260        let derive: DeriveInput = syn::parse_quote! {
261            #[serde(rename_all = "lowercase")]
262            struct Config {
263                field: String,
264            }
265        };
266        let input = ContainerAttributes::from_attributes(&derive.attrs).unwrap();
267        assert_eq!(input.rename_all, RenameAll::from(RenameRule::LowerCase));
268
269        let derive: DeriveInput = syn::parse_quote! {
270            #[serde(rename_all(serialize = "lowercase"))]
271            struct Config {
272                field: String,
273            }
274        };
275        let input = ContainerAttributes::from_attributes(&derive.attrs).unwrap();
276        assert_eq!(
277            input.rename_all,
278            RenameAll {
279                serialize: RenameRule::LowerCase,
280                deserialize: RenameRule::None
281            }
282        );
283
284        let derive: DeriveInput = syn::parse_quote! {
285            #[serde(rename_all(deserialize = "lowercase"))]
286            struct Config {
287                field: String,
288            }
289        };
290        let input = ContainerAttributes::from_attributes(&derive.attrs).unwrap();
291        assert_eq!(
292            input.rename_all,
293            RenameAll {
294                serialize: RenameRule::None,
295                deserialize: RenameRule::LowerCase
296            }
297        );
298
299        let derive: DeriveInput = syn::parse_quote! {
300            struct Config {
301                field: String,
302            }
303        };
304        let input = ContainerAttributes::from_attributes(&derive.attrs).unwrap();
305        assert_eq!(input.rename_all, RenameAll::from(RenameRule::None));
306    }
307
308    #[test]
309    fn test_default() {
310        let derive: DeriveInput = syn::parse_quote! {
311            #[serde(default)]
312            struct Config {
313                field: String,
314            }
315        };
316        let input = ContainerAttributes::from_attributes(&derive.attrs).unwrap();
317        assert_eq!(input._default, Some(SerdeDefault::UseTrait));
318
319        let derive: DeriveInput = syn::parse_quote! {
320            #[serde(default = "some::path")]
321            struct Config {
322                field: String,
323            }
324        };
325        let input = ContainerAttributes::from_attributes(&derive.attrs).unwrap();
326        assert!(matches!(input._default, Some(SerdeDefault::Expr(_))));
327
328        let derive: DeriveInput = syn::parse_quote! {
329            struct Config {
330                field: String,
331            }
332        };
333        let input = ContainerAttributes::from_attributes(&derive.attrs).unwrap();
334        assert_eq!(input._default, None);
335    }
336}