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

Kriskras99 pushed a commit to branch fix/enum_in_union
in repository https://gitbox.apache.org/repos/asf/avro-rs.git

commit 9382632cdb43081513a6a7e4245b361eeed80265
Author: Kriskras99 <[email protected]>
AuthorDate: Wed Jul 15 12:52:45 2026 +0200

    fix: Allow serializing an enum inside a union
---
 avro/src/serde/ser_schema/mod.rs   | 37 ++++++++++++++++++++++++++++++++++---
 avro/src/serde/ser_schema/union.rs | 34 ++++++++++++++++++++++++++++++----
 2 files changed, 64 insertions(+), 7 deletions(-)

diff --git a/avro/src/serde/ser_schema/mod.rs b/avro/src/serde/ser_schema/mod.rs
index 5aba68b..a33702e 100644
--- a/avro/src/serde/ser_schema/mod.rs
+++ b/avro/src/serde/ser_schema/mod.rs
@@ -428,7 +428,7 @@ impl<'s, 'w, W: Write, S: Borrow<Schema>> Serializer for 
SchemaAwareSerializer<'
 
     fn serialize_unit_variant(
         self,
-        _name: &'static str,
+        name: &'static str,
         variant_index: u32,
         variant: &'static str,
     ) -> Result<Self::Ok, Self::Error> {
@@ -445,15 +445,17 @@ impl<'s, 'w, W: Write, S: Borrow<Schema>> Serializer for 
SchemaAwareSerializer<'
                     Err(self.error("unit variant", format!(r#"Expected symbol 
"{variant}" at index {variant_index} in enum"#)))
                 }
             }
-            Schema::Union(union) => match 
self.get_resolved_union_variant(union, variant_index)? {
+            Schema::Union(union) if (variant_index as usize) < 
union.variants().len() => match self.get_resolved_union_variant(union, 
variant_index)? {
                 // Bare union
                 Schema::Null => zig_i32(variant_index as i32, &mut 
*self.writer),
                 Schema::Record(record) if record.fields.is_empty() && 
record.name.name() == variant => {
                     // Union of records
                     zig_i32(variant_index as i32, &mut *self.writer)
                 }
-                _ => Err(self.error("unit variant", format!("Expected 
Schema::Null | Schema::Record(name: {variant}, fields: []) at index 
{variant_index} in the union"))),
+                _ => UnionSerializer::new(self.writer, union, 
self.config).serialize_unit_variant(name, variant_index, variant)
             }
+            // This branch happens if the enum has more variants than the 
union, which is valid if the target schema is a enum schema in the union
+            Schema::Union(union) => UnionSerializer::new(self.writer, union, 
self.config).serialize_unit_variant(name, variant_index, variant),
             _ => Err(self.error("unit variant", format!("Expected 
Schema::Enum(symbols[{variant_index}] == {variant}) | 
Schema::Union(variants[{variant_index}] == Schema::Null | Schema::Record(name: 
{variant}, fields: []))"))),
         }
     }
@@ -2216,4 +2218,33 @@ mod tests {
 
         Ok(())
     }
+
+    #[test]
+    fn avro_rs_529_enum_with_union_schema() -> TestResult {
+        #[derive(Debug, Serialize)]
+        enum TestEnum {
+            A,
+            B,
+            C,
+        }
+
+        let schema = Schema::parse_str(
+            r#"
+            [
+                "int",
+                {
+                    "type": "enum",
+                    "name": "TestEnum",
+                    "symbols": ["A", "B", "C"]
+                }
+            ]
+            "#,
+        )?;
+        let names = HashMap::new();
+        assert_serialize(TestEnum::A, &schema, &names, &[2, 0]);
+        assert_serialize(TestEnum::B, &schema, &names, &[2, 2]);
+        assert_serialize(TestEnum::C, &schema, &names, &[2, 4]);
+
+        Ok(())
+    }
 }
diff --git a/avro/src/serde/ser_schema/union.rs 
b/avro/src/serde/ser_schema/union.rs
index 4c02011..fde485c 100644
--- a/avro/src/serde/ser_schema/union.rs
+++ b/avro/src/serde/ser_schema/union.rs
@@ -356,11 +356,37 @@ impl<'s, 'w, W: Write, S: Borrow<Schema>> Serializer for 
UnionSerializer<'s, 'w,
 
     fn serialize_unit_variant(
         self,
-        _: &'static str,
-        _: u32,
-        _: &'static str,
+        name: &'static str,
+        variant_index: u32,
+        variant: &'static str,
     ) -> Result<Self::Ok, Self::Error> {
-        Err(self.error("unit variant", "Nested unions are not supported"))
+        if let Some((index, Schema::Enum(enum_schema))) =
+            self.union.find_named_schema(name, self.config.names)?
+            && enum_schema
+                .symbols
+                .get(variant_index as usize)
+                .map(String::as_str)
+                == Some(variant)
+        {
+            // Fast path for if the name and variant match (no #[serde(skip)] 
or other trickery)
+            let mut bytes_written = zig_i32(index as i32, &mut *self.writer)?;
+            bytes_written += zig_i32(variant_index as i32, &mut *self.writer)?;
+            Ok(bytes_written)
+        } else {
+            for (index, schema) in self.union.variants().iter().enumerate() {
+                if let Schema::Enum(enum_schema) = schema
+                    && let Some(symbol) = 
enum_schema.symbols.iter().position(|s| s == variant)
+                {
+                    let mut bytes_written = zig_i32(index as i32, &mut 
*self.writer)?;
+                    bytes_written += zig_i32(symbol as i32, &mut 
*self.writer)?;
+                    return Ok(bytes_written);
+                }
+            }
+            Err(self.error(
+                "unit variant",
+                format!("Expected Schema::Enum(symbols: [.., {variant}, ..]) 
in variants"),
+            ))
+        }
     }
 
     fn serialize_newtype_struct<T>(

Reply via email to