You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by mg...@apache.org on 2022/04/17 19:43:48 UTC

[avro] branch avro-3492-derive-aliases created (now de8ff487e)

This is an automated email from the ASF dual-hosted git repository.

mgrigorov pushed a change to branch avro-3492-derive-aliases
in repository https://gitbox.apache.org/repos/asf/avro.git


      at de8ff487e AVRO-3492: Add support for deriving Schema::Record aliases

This branch includes the following new commits:

     new de8ff487e AVRO-3492: Add support for deriving Schema::Record aliases

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[avro] 01/01: AVRO-3492: Add support for deriving Schema::Record aliases

Posted by mg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mgrigorov pushed a commit to branch avro-3492-derive-aliases
in repository https://gitbox.apache.org/repos/asf/avro.git

commit de8ff487e454b294f2865ee8c7c29d2b72aa3fc4
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
AuthorDate: Sun Apr 17 22:42:38 2022 +0300

    AVRO-3492: Add support for deriving Schema::Record aliases
    
    Uses Darling's 'multiple' attribute feature.
    
    Signed-off-by: Martin Tzvetanov Grigorov <mg...@apache.org>
---
 lang/rust/avro_derive/src/lib.rs      | 16 +++++++++++++++-
 lang/rust/avro_derive/tests/derive.rs | 36 +++++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/lang/rust/avro_derive/src/lib.rs b/lang/rust/avro_derive/src/lib.rs
index 96575e090..11ab7a616 100644
--- a/lang/rust/avro_derive/src/lib.rs
+++ b/lang/rust/avro_derive/src/lib.rs
@@ -39,6 +39,8 @@ struct NamedTypeOptions {
     namespace: Option<String>,
     #[darling(default)]
     doc: Option<String>,
+    #[darling(multiple)]
+    alias: Vec<String>,
 }
 
 #[proc_macro_derive(AvroSchema, attributes(avro))]
@@ -64,6 +66,7 @@ fn derive_avro_schema(input: &mut DeriveInput) -> Result<TokenStream, Vec<syn::E
             named_type_options
                 .doc
                 .or_else(|| extract_outer_doc(&input.attrs)),
+            named_type_options.alias,
             s,
             input.ident.span(),
         )?,
@@ -104,6 +107,7 @@ fn derive_avro_schema(input: &mut DeriveInput) -> Result<TokenStream, Vec<syn::E
 fn get_data_struct_schema_def(
     full_schema_name: &str,
     record_doc: Option<String>,
+    aliases: Vec<String>,
     s: &syn::DataStruct,
     error_span: Span,
 ) -> Result<TokenStream, Vec<syn::Error>> {
@@ -143,6 +147,7 @@ fn get_data_struct_schema_def(
         }
     }
     let record_doc = preserve_optional(record_doc);
+    let record_aliases = preserve_vec(aliases);
     Ok(quote! {
         let schema_fields = vec![#(#record_field_exprs),*];
         let name = apache_avro::schema::Name::new(#full_schema_name).expect(&format!("Unable to parse struct name for schema {}", #full_schema_name)[..]);
@@ -152,7 +157,7 @@ fn get_data_struct_schema_def(
             .collect();
         apache_avro::schema::Schema::Record {
             name,
-            aliases: None,
+            aliases: #record_aliases,
             doc: #record_doc,
             fields: schema_fields,
             lookup,
@@ -277,6 +282,15 @@ fn preserve_optional(op: Option<impl quote::ToTokens>) -> TokenStream {
     }
 }
 
+fn preserve_vec(op: Vec<impl quote::ToTokens>) -> TokenStream {
+    let items: Vec<TokenStream> = op.iter().map(|tt| quote! {#tt.into()}).collect();
+    if items.is_empty() {
+        quote! {None}
+    } else {
+        quote! {Some(vec![#(#items),*])}
+    }
+}
+
 fn darling_to_syn(e: darling::Error) -> Vec<syn::Error> {
     let msg = format!("{}", e);
     let token_errors = e.write_errors();
diff --git a/lang/rust/avro_derive/tests/derive.rs b/lang/rust/avro_derive/tests/derive.rs
index 8ac95755f..1178cdebc 100644
--- a/lang/rust/avro_derive/tests/derive.rs
+++ b/lang/rust/avro_derive/tests/derive.rs
@@ -1063,4 +1063,40 @@ mod test_derive {
         serde_assert(TestBasicWithU32 { a: u32::MIN });
         serde_assert(TestBasicWithU32 { a: 1_u32 });
     }
+
+    #[derive(Debug, Serialize, Deserialize, AvroSchema, Clone, PartialEq)]
+    #[avro(alias = "a", alias = "b", alias = "c")]
+    struct TestBasicWithAliases {
+        a: i32,
+    }
+
+    #[test]
+    fn test_basic_with_aliases() {
+        let schema = r#"
+        {
+            "type":"record",
+            "name":"TestBasicWithAliases",
+            "aliases":["a", "b", "c"],
+            "fields":[
+                {
+                    "name":"a",
+                    "type":"int"
+                }
+            ]
+        }
+        "#;
+        let schema = Schema::parse_str(schema).unwrap();
+        if let Schema::Record { name, aliases, .. } = TestBasicWithAliases::get_schema() {
+            assert_eq!("TestBasicWithAliases", name.fullname(None));
+            assert_eq!(
+                Some(vec!["a".to_owned(), "b".to_owned(), "c".to_owned()]),
+                aliases
+            );
+        } else {
+            panic!("TestBasicWithAliases schema must be a record schema")
+        }
+        assert_eq!(schema, TestBasicWithAliases::get_schema());
+
+        serde_assert(TestBasicWithAliases { a: i32::MAX });
+    }
 }