Skip to content

Commit

Permalink
AVRO-3955: [Rust] allow deserializer to decode enum string (#2785)
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorentinDUBOIS authored Mar 4, 2024
1 parent b37d5a6 commit 3c11f89
Showing 1 changed file with 86 additions and 3 deletions.
89 changes: 86 additions & 3 deletions lang/rust/avro/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ impl<'a, 'de> de::Deserializer<'de> for &'a Deserializer<'de> {
V: Visitor<'de>,
{
match *self.input {
Value::String(ref s) => visitor.visit_borrowed_str(s),
Value::Enum(_, ref s) | Value::String(ref s) => visitor.visit_borrowed_str(s),
Value::Bytes(ref bytes) | Value::Fixed(_, ref bytes) => {
String::from_utf8(bytes.to_owned())
.map_err(|e| de::Error::custom(e.to_string()))
Expand All @@ -344,7 +344,7 @@ impl<'a, 'de> de::Deserializer<'de> for &'a Deserializer<'de> {
))),
},
_ => Err(de::Error::custom(format!(
"Expected a String|Bytes|Fixed|Uuid|Union, but got {:?}",
"Expected a String|Bytes|Fixed|Uuid|Union|Enum, but got {:?}",
self.input
))),
}
Expand Down Expand Up @@ -665,7 +665,7 @@ pub fn from_value<'de, D: Deserialize<'de>>(value: &'de Value) -> Result<D, Erro
mod tests {
use num_bigint::BigInt;
use pretty_assertions::assert_eq;
use serde::Serialize;
use serde::{Deserialize, Serialize};
use serial_test::serial;
use std::sync::atomic::Ordering;
use uuid::Uuid;
Expand All @@ -676,6 +676,89 @@ mod tests {

use super::*;

#[derive(PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct StringEnum {
pub source: String,
}

#[test]
fn avro_3955_decode_enum() -> TestResult {
let schema_content = r#"
{
"name": "AccessLog",
"namespace": "com.clevercloud.accesslogs.common.avro",
"type": "record",
"fields": [
{
"name": "source",
"type": {
"type": "enum",
"name": "SourceType",
"items": "string",
"symbols": ["SOZU", "HAPROXY", "HAPROXY_TCP"]
}
}
]
}
"#;

let schema = crate::Schema::parse_str(schema_content)?;
let data = StringEnum {
source: "SOZU".to_string(),
};

// encode into avro
let value = crate::to_value(&data)?;

let mut buf = std::io::Cursor::new(crate::to_avro_datum(&schema, value)?);

// decode from avro
let value = crate::from_avro_datum(&schema, &mut buf, None)?;

let decoded_data: StringEnum = crate::from_value(&value)?;

assert_eq!(decoded_data, data);

Ok(())
}

#[test]
fn avro_3955_encode_enum_data_with_wrong_content() -> TestResult {
let schema_content = r#"
{
"name": "AccessLog",
"namespace": "com.clevercloud.accesslogs.common.avro",
"type": "record",
"fields": [
{
"name": "source",
"type": {
"type": "enum",
"name": "SourceType",
"items": "string",
"symbols": ["SOZU", "HAPROXY", "HAPROXY_TCP"]
}
}
]
}
"#;

let schema = crate::Schema::parse_str(schema_content)?;
let data = StringEnum {
source: "WRONG_ITEM".to_string(),
};

// encode into avro
let value = crate::to_value(data)?;

// The following sentence have to fail has the data is wrong.
let encoded_data = crate::to_avro_datum(&schema, value);

assert!(encoded_data.is_err());

Ok(())
}

#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
struct Test {
a: i64,
Expand Down

0 comments on commit 3c11f89

Please sign in to comment.