This is an automated email from the ASF dual-hosted git repository.
kriskras99 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/avro-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 89403dc chore: Move enum derive to `enums::plain` in `avro_derive`
(#487)
89403dc is described below
commit 89403dc8b32650417cf3d8ac5c59e1ca17fbb531
Author: Kriskras99 <[email protected]>
AuthorDate: Thu Feb 26 09:50:53 2026 +0100
chore: Move enum derive to `enums::plain` in `avro_derive` (#487)
Prep for more complete enum support
---
avro_derive/src/enums/mod.rs | 67 +++++++++++++++++++++++++++++++++++
avro_derive/src/enums/plain.rs | 66 +++++++++++++++++++++++++++++++++++
avro_derive/src/lib.rs | 79 +++---------------------------------------
3 files changed, 138 insertions(+), 74 deletions(-)
diff --git a/avro_derive/src/enums/mod.rs b/avro_derive/src/enums/mod.rs
new file mode 100644
index 0000000..e44f4a1
--- /dev/null
+++ b/avro_derive/src/enums/mod.rs
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+mod plain;
+
+use crate::attributes::NamedTypeOptions;
+use proc_macro2::{Ident, Span, TokenStream};
+use syn::{Attribute, DataEnum, Fields, Meta};
+
+/// Generate a schema definition for a enum.
+pub fn get_data_enum_schema_def(
+ container_attrs: &NamedTypeOptions,
+ data_enum: DataEnum,
+ ident_span: Span,
+) -> Result<TokenStream, Vec<syn::Error>> {
+ if data_enum.variants.iter().all(|v| Fields::Unit == v.fields) {
+ plain::schema_def(container_attrs, data_enum, ident_span)
+ } else {
+ Err(vec![syn::Error::new(
+ ident_span,
+ "AvroSchema: derive does not work for enums with non unit structs",
+ )])
+ }
+}
+
+fn default_enum_variant(
+ data_enum: &DataEnum,
+ error_span: Span,
+) -> Result<Option<String>, Vec<syn::Error>> {
+ match data_enum
+ .variants
+ .iter()
+ .filter(|v| v.attrs.iter().any(is_default_attr))
+ .collect::<Vec<_>>()
+ {
+ variants if variants.is_empty() => Ok(None),
+ single if single.len() == 1 => Ok(Some(single[0].ident.to_string())),
+ multiple => Err(vec![syn::Error::new(
+ error_span,
+ format!(
+ "Multiple defaults defined: {:?}",
+ multiple
+ .iter()
+ .map(|v| v.ident.to_string())
+ .collect::<Vec<String>>()
+ ),
+ )]),
+ }
+}
+
+fn is_default_attr(attr: &Attribute) -> bool {
+ matches!(attr, Attribute { meta: Meta::Path(path), .. } if
path.get_ident().map(Ident::to_string).as_deref() == Some("default"))
+}
diff --git a/avro_derive/src/enums/plain.rs b/avro_derive/src/enums/plain.rs
new file mode 100644
index 0000000..89de59c
--- /dev/null
+++ b/avro_derive/src/enums/plain.rs
@@ -0,0 +1,66 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::attributes::{NamedTypeOptions, VariantOptions};
+use crate::case::RenameRule;
+use crate::enums::default_enum_variant;
+use crate::{aliases, preserve_optional};
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use syn::spanned::Spanned;
+use syn::{DataEnum, Fields};
+
+pub fn schema_def(
+ container_attrs: &NamedTypeOptions,
+ data_enum: DataEnum,
+ ident_span: Span,
+) -> Result<TokenStream, Vec<syn::Error>> {
+ let doc = preserve_optional(container_attrs.doc.as_ref());
+ let enum_aliases = aliases(&container_attrs.aliases);
+ if data_enum.variants.iter().all(|v| Fields::Unit == v.fields) {
+ let default_value = default_enum_variant(&data_enum, ident_span)?;
+ let default = preserve_optional(default_value);
+ let mut symbols = Vec::new();
+ for variant in &data_enum.variants {
+ let field_attrs = VariantOptions::new(&variant.attrs,
variant.span())?;
+ let name = match (field_attrs.rename, container_attrs.rename_all) {
+ (Some(rename), _) => rename,
+ (None, rename_all) if !matches!(rename_all, RenameRule::None)
=> {
+ rename_all.apply_to_variant(&variant.ident.to_string())
+ }
+ _ => variant.ident.to_string(),
+ };
+ symbols.push(name);
+ }
+ let full_schema_name = &container_attrs.name;
+ Ok(quote! {
+
::apache_avro::schema::Schema::Enum(apache_avro::schema::EnumSchema {
+ name:
::apache_avro::schema::Name::new(#full_schema_name).expect(&format!("Unable to
parse enum name for schema {}", #full_schema_name)[..]),
+ aliases: #enum_aliases,
+ doc: #doc,
+ symbols: vec![#(#symbols.to_owned()),*],
+ default: #default,
+ attributes: Default::default(),
+ })
+ })
+ } else {
+ Err(vec![syn::Error::new(
+ ident_span,
+ "AvroSchema: derive does not work for enums with non unit structs",
+ )])
+ }
+}
diff --git a/avro_derive/src/lib.rs b/avro_derive/src/lib.rs
index d6562c8..3b9b724 100644
--- a/avro_derive/src/lib.rs
+++ b/avro_derive/src/lib.rs
@@ -31,16 +31,18 @@
mod attributes;
mod case;
+mod enums;
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{
- Attribute, DataEnum, DataStruct, DeriveInput, Expr, Field, Fields,
Generics, Ident, Meta, Type,
- parse_macro_input, spanned::Spanned,
+ DataStruct, DeriveInput, Expr, Field, Fields, Generics, Ident, Type,
parse_macro_input,
+ spanned::Spanned,
};
+use crate::enums::get_data_enum_schema_def;
use crate::{
- attributes::{FieldDefault, FieldOptions, NamedTypeOptions, VariantOptions,
With},
+ attributes::{FieldDefault, FieldOptions, NamedTypeOptions, With},
case::RenameRule,
};
@@ -383,48 +385,6 @@ fn get_field_get_record_fields_expr(
}
}
-/// Generate a schema definition for a enum.
-fn get_data_enum_schema_def(
- container_attrs: &NamedTypeOptions,
- data_enum: DataEnum,
- ident_span: Span,
-) -> Result<TokenStream, Vec<syn::Error>> {
- let doc = preserve_optional(container_attrs.doc.as_ref());
- let enum_aliases = aliases(&container_attrs.aliases);
- if data_enum.variants.iter().all(|v| Fields::Unit == v.fields) {
- let default_value = default_enum_variant(&data_enum, ident_span)?;
- let default = preserve_optional(default_value);
- let mut symbols = Vec::new();
- for variant in &data_enum.variants {
- let field_attrs = VariantOptions::new(&variant.attrs,
variant.span())?;
- let name = match (field_attrs.rename, container_attrs.rename_all) {
- (Some(rename), _) => rename,
- (None, rename_all) if !matches!(rename_all, RenameRule::None)
=> {
- rename_all.apply_to_variant(&variant.ident.to_string())
- }
- _ => variant.ident.to_string(),
- };
- symbols.push(name);
- }
- let full_schema_name = &container_attrs.name;
- Ok(quote! {
-
::apache_avro::schema::Schema::Enum(apache_avro::schema::EnumSchema {
- name:
::apache_avro::schema::Name::new(#full_schema_name).expect(&format!("Unable to
parse enum name for schema {}", #full_schema_name)[..]),
- aliases: #enum_aliases,
- doc: #doc,
- symbols: vec![#(#symbols.to_owned()),*],
- default: #default,
- attributes: Default::default(),
- })
- })
- } else {
- Err(vec![syn::Error::new(
- ident_span,
- "AvroSchema: derive does not work for enums with non unit structs",
- )])
- }
-}
-
/// Takes in the Tokens of a type and returns the tokens of an expression with
return type `Schema`
fn type_to_schema_expr(ty: &Type) -> Result<TokenStream, Vec<syn::Error>> {
match ty {
@@ -492,35 +452,6 @@ fn type_to_field_default_expr(ty: &Type) ->
Result<TokenStream, Vec<syn::Error>>
}
}
-fn default_enum_variant(
- data_enum: &syn::DataEnum,
- error_span: Span,
-) -> Result<Option<String>, Vec<syn::Error>> {
- match data_enum
- .variants
- .iter()
- .filter(|v| v.attrs.iter().any(is_default_attr))
- .collect::<Vec<_>>()
- {
- variants if variants.is_empty() => Ok(None),
- single if single.len() == 1 => Ok(Some(single[0].ident.to_string())),
- multiple => Err(vec![syn::Error::new(
- error_span,
- format!(
- "Multiple defaults defined: {:?}",
- multiple
- .iter()
- .map(|v| v.ident.to_string())
- .collect::<Vec<String>>()
- ),
- )]),
- }
-}
-
-fn is_default_attr(attr: &Attribute) -> bool {
- matches!(attr, Attribute { meta: Meta::Path(path), .. } if
path.get_ident().map(Ident::to_string).as_deref() == Some("default"))
-}
-
/// Stolen from serde
fn to_compile_errors(errors: Vec<syn::Error>) -> proc_macro2::TokenStream {
let compile_errors = errors.iter().map(syn::Error::to_compile_error);