martin-g commented on code in PR #591:
URL: https://github.com/apache/avro-rs/pull/591#discussion_r3601038676


##########
avro/src/serde/ser_schema/mod.rs:
##########
@@ -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",

Review Comment:
   If I change this to `"null"` then the assertion below fails. It still works 
fine with any other primitive type (double, long, string) and "array". 
   Looking at the code above I'd expect it to fail with an empty record too.



##########
avro/src/serde/ser_schema/mod.rs:
##########
@@ -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

Review Comment:
   Let's add a test case for this too.



##########
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)

Review Comment:
   This may fail if there are two differently named enum schemas having symbol 
with the same name.



##########
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

Review Comment:
   ```suggestion
                   let resolved_schema = match schema {
                       Schema::Ref { name } => 
self.config.get_schema(name).unwrap_or(schema),
                       _ => schema,
                   };
                   if let Schema::Enum(enum_schema) = resolved_schema
   ```
   Add support for schema references.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to