Skip to main content

apache_avro_derive/attributes/
avro.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 Avro attributes
19//!
20//! # Avro attributes
21//! Although a user will mostly use the Serde attributes, there are some Avro specific attributes
22//! a user can use. These add extra metadata to the generated schema.
23
24use crate::attributes::FieldDefault;
25use crate::case::RenameRule;
26use darling::FromMeta;
27use proc_macro2::Span;
28use syn::Expr;
29
30/// All the Avro attributes a container can have.
31#[derive(darling::FromAttributes)]
32#[darling(attributes(avro))]
33pub struct ContainerAttributes {
34    /// Deprecated. Use [`serde::ContainerAttributes::rename`] instead.
35    ///
36    /// Change the name of this record/enum in the schema.
37    ///
38    /// [`serde::ContainerAttributes::rename`]: crate::attributes::serde::ContainerAttributes::rename
39    #[darling(default)]
40    pub name: Option<String>,
41    /// Adds a `namespace` field to the schema.
42    #[darling(default)]
43    pub namespace: Option<String>,
44    /// Adds a `doc` field to the schema.
45    #[darling(default)]
46    pub doc: Option<String>,
47    /// Adds the `aliases` field to the schema.
48    #[darling(multiple)]
49    pub alias: Vec<String>,
50    /// Deprecated. Use [`serde::ContainerAttributes::rename_all`] instead.
51    ///
52    /// Change the name of all fields in the schema according to the [`RenameRule`].
53    ///
54    /// [`serde::ContainerAttributes::rename_all`]: crate::attributes::serde::ContainerAttributes::rename_all
55    #[darling(default)]
56    pub rename_all: RenameRule,
57    /// Set the default value if this schema is used as a field
58    #[darling(default)]
59    pub default: Option<String>,
60}
61
62impl ContainerAttributes {
63    pub fn deprecated(&self, span: Span) {
64        if self.name.is_some() {
65            super::warn(
66                span,
67                r#"`#[avro(name = "...")]` is deprecated."#,
68                r#"Use `#[serde(rename = "...")]` instead."#,
69            );
70        }
71        if self.rename_all != RenameRule::None {
72            super::warn(
73                span,
74                r#"`#[avro(rename_all = "..")]` is deprecated"#,
75                r#"Use `#[serde(rename_all = "..")]` instead"#,
76            );
77        }
78    }
79}
80
81/// All the Avro attributes a variant can have.
82#[derive(darling::FromAttributes)]
83#[darling(attributes(avro))]
84pub struct VariantAttributes {
85    /// Deprecated. Use [`serde::VariantAttributes::rename`] instead.
86    ///
87    /// Changes the name of the variant in the schema.
88    ///
89    /// [`serde::VariantAttributes::rename`]: crate::attributes::serde::VariantAttributes::rename
90    #[darling(default)]
91    pub rename: Option<String>,
92}
93
94impl VariantAttributes {
95    pub fn deprecated(&self, span: Span) {
96        if self.rename.is_some() {
97            super::warn(
98                span,
99                r#"`#[avro(rename = "..")]` is deprecated"#,
100                r#"Use `#[serde(rename = "..")]` instead"#,
101            );
102        }
103    }
104}
105
106/// How to get the schema for a field.
107#[derive(Debug, FromMeta, PartialEq, Default)]
108#[darling(from_expr = |expr| Ok(With::Expr(expr.clone())))]
109pub enum With {
110    /// Use `<T as AvroSchemaComponent>::get_schema_in_ctxt`.
111    #[default]
112    #[darling(skip)]
113    Trait,
114    /// Use `module::get_schema_in_ctxt` where the module is defined by Serde's `with` attribute.
115    #[darling(word, skip)]
116    Serde,
117    /// Call the function in this expression.
118    Expr(Expr),
119}
120
121/// All the Avro attributes a field can have.
122#[derive(darling::FromAttributes)]
123#[darling(attributes(avro))]
124pub struct FieldAttributes {
125    /// Adds a `doc` field to the schema.
126    #[darling(default)]
127    pub doc: Option<String>,
128    /// Adds a `default` field to the schema.
129    ///
130    /// This is also used as the default when `skip_serializing{_if}` is used.
131    #[darling(default)]
132    pub default: FieldDefault,
133    /// Deprecated. Use [`serde::FieldAttributes::alias`] instead.
134    ///
135    /// Adds the `aliases` field to the schema.
136    ///
137    /// [`serde::FieldAttributes::alias`]: crate::attributes::serde::FieldAttributes::alias
138    #[darling(multiple)]
139    pub alias: Vec<String>,
140    /// Deprecated. Use [`serde::FieldAttributes::rename`] instead.
141    ///
142    /// Changes the name of the field in the schema.
143    ///
144    /// [`serde::FieldAttributes::rename`]: crate::attributes::serde::FieldAttributes::rename
145    #[darling(default)]
146    pub rename: Option<String>,
147    /// Deprecated. Use [`serde::FieldAttributes::skip`] instead.
148    ///
149    /// Don't include this field in the schema.
150    ///
151    /// [`serde::FieldAttributes::skip`]: crate::attributes::serde::FieldAttributes::skip
152    #[darling(default)]
153    pub skip: bool,
154    /// Deprecated. Use [`serde::FieldAttributes::flatten`] instead.
155    ///
156    /// Replace this field by the fields of its schema.
157    ///
158    /// [`serde::FieldAttributes::flatten`]: crate::attributes::serde::FieldAttributes::flatten
159    #[darling(default)]
160    pub flatten: bool,
161    /// How to get the schema for a field.
162    ///
163    /// By default uses `<T as AvroSchemaComponent>::get_schema_in_ctxt`.
164    ///
165    /// When it's provided without an argument (`#[avro(with)]`), it will use the function `get_schema_in_ctxt` defined
166    /// in the same module as the `#[serde(with = "some_module")]` attribute.
167    ///
168    /// When it's provided with an argument (`#[avro(with = some_fn)]`), it will use that function.
169    #[darling(default)]
170    pub with: With,
171}
172
173impl FieldAttributes {
174    pub fn deprecated(&self, span: Span) {
175        if !self.alias.is_empty() {
176            super::warn(
177                span,
178                r#"`#[avro(alias = "..")]` is deprecated"#,
179                r#"Use `#[serde(alias = "..")]` instead"#,
180            );
181        }
182        if self.rename.is_some() {
183            super::warn(
184                span,
185                r#"`#[avro(rename = "..")]` is deprecated"#,
186                r#"Use `#[serde(rename = "..")]` instead"#,
187            );
188        }
189        if self.skip {
190            super::warn(
191                span,
192                "`#[avro(skip)]` is deprecated",
193                "Use `#[serde(skip)]` instead",
194            );
195        }
196        if self.flatten {
197            super::warn(
198                span,
199                "`#[avro(flatten)]` is deprecated",
200                "Use `#[serde(flatten)]` instead",
201            );
202        }
203    }
204}