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}