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