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}