Lucas Javaudin created AVRO-3645:
------------------------------------

             Summary: Fix deserialization of enum with unit () type
                 Key: AVRO-3645
                 URL: https://issues.apache.org/jira/browse/AVRO-3645
             Project: Apache Avro
          Issue Type: Bug
          Components: rust
            Reporter: Lucas Javaudin


Consider the following test:
{code:java}
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
struct TestNullExternalEnum {
    a: NullExternalEnum,
}    

#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
enum NullExternalEnum {
    Val1(()),
    Val2(u64),
}

#[test]
fn test_from_value_null_enum() {
    let expected = TestNullExternalEnum {
        a: NullExternalEnum::Val1(()),
    };

    let test = Value::Record(vec![(
        "a".to_owned(),
        Value::Record(vec![
            ("type".to_owned(), Value::String("Val1".to_owned())),
            ("value".to_owned(), Value::Union(0, Box::new(Value::Null))),
        ]),
    )]);
    let final_value: TestNullExternalEnum = from_value(&test).unwrap();
    assert_eq!(
        final_value, expected,
        "Error deserializing null external enum"
    );
}{code}
On version `0.15.0`, it fails with the following error message:
{code:java}
called `Result::unwrap()` on an `Err` value: DeserializeValue("not a null") 
{code}
 

If my understanding is correct, it fails because rust is expecting a 
`Value::Null` but it got a `Value::Union(0, Box::new(Value::Null))`.

A fix that I found is to replace the `deserialize_unit`function in `de.rs` from
{code:java}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
    V: Visitor<'de>,
{
    match *self.input {
        Value::Null => visitor.visit_unit(),
        _ => Err(de::Error::custom("not a null")),
    }
} {code}
to
{code:java}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
    V: Visitor<'de>,
{
    match *self.input {
        Value::Null => visitor.visit_unit(),
        Value::Union(_i, ref x) => match **x {
            Value::Null => visitor.visit_unit(),
            _ => Err(de::Error::custom("not a null")),
        },
        _ => Err(de::Error::custom("not a null")),
    }
} {code}
i.e., we allow it to accept `Value::Union`, in the same way that the 
`deserialize_string` function accepts such values.

 

If you ask yourself what is the point of having an enum with unit type, it is 
because apache-avro is not able to handle the following enum (as far as I know):
{code:java}
enum NullExternalEnum {
    Val1,
    Val2(u64),
} {code}
I am sorry if there is any problem with this issue, it's the first time I open 
an issue here.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to