-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AVRO-3892: [Rust] Support to resolve fixed from bytes and deserialize bytes in deserialize_any #2567
AVRO-3892: [Rust] Support to resolve fixed from bytes and deserialize bytes in deserialize_any #2567
Changes from all commits
8b331fd
80283f4
c8ad266
61eeaa9
4d93020
40bc2d7
1fb832e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -266,6 +266,8 @@ impl<'a, 'de> de::Deserializer<'de> for &'a Deserializer<'de> { | |
Value::String(ref s) => visitor.visit_borrowed_str(s), | ||
Value::Uuid(uuid) => visitor.visit_str(&uuid.to_string()), | ||
Value::Map(ref items) => visitor.visit_map(MapDeserializer::new(items)), | ||
Value::Bytes(ref bytes) | Value::Fixed(_, ref bytes) => visitor.visit_bytes(bytes), | ||
Value::Decimal(ref d) => visitor.visit_bytes(&d.to_vec()?), | ||
_ => Err(de::Error::custom(format!( | ||
"unsupported union: {:?}", | ||
self.input | ||
|
@@ -276,6 +278,8 @@ impl<'a, 'de> de::Deserializer<'de> for &'a Deserializer<'de> { | |
Value::String(ref s) => visitor.visit_borrowed_str(s), | ||
Value::Uuid(uuid) => visitor.visit_str(&uuid.to_string()), | ||
Value::Map(ref items) => visitor.visit_map(MapDeserializer::new(items)), | ||
Value::Bytes(ref bytes) | Value::Fixed(_, ref bytes) => visitor.visit_bytes(bytes), | ||
Value::Decimal(ref d) => visitor.visit_bytes(&d.to_vec()?), | ||
value => Err(de::Error::custom(format!( | ||
"incorrect value of type: {:?}", | ||
crate::schema::SchemaKind::from(value) | ||
|
@@ -350,8 +354,9 @@ impl<'a, 'de> de::Deserializer<'de> for &'a Deserializer<'de> { | |
Value::String(ref s) => visitor.visit_bytes(s.as_bytes()), | ||
Value::Bytes(ref bytes) | Value::Fixed(_, ref bytes) => visitor.visit_bytes(bytes), | ||
Value::Uuid(ref u) => visitor.visit_bytes(u.as_bytes()), | ||
Value::Decimal(ref d) => visitor.visit_bytes(&d.to_vec()?), | ||
_ => Err(de::Error::custom(format!( | ||
"Expected a String|Bytes|Fixed|Uuid, but got {:?}", | ||
"Expected a String|Bytes|Fixed|Uuid|Decimal, but got {:?}", | ||
self.input | ||
))), | ||
} | ||
|
@@ -654,6 +659,7 @@ pub fn from_value<'de, D: Deserialize<'de>>(value: &'de Value) -> Result<D, Erro | |
|
||
#[cfg(test)] | ||
mod tests { | ||
use num_bigint::BigInt; | ||
use pretty_assertions::assert_eq; | ||
use serde::Serialize; | ||
use serial_test::serial; | ||
|
@@ -662,6 +668,8 @@ mod tests { | |
|
||
use apache_avro_test_helper::TestResult; | ||
|
||
use crate::Decimal; | ||
|
||
use super::*; | ||
|
||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] | ||
|
@@ -1099,7 +1107,7 @@ mod tests { | |
fn test_from_value_uuid_str() -> TestResult { | ||
let raw_value = "9ec535ff-3e2a-45bd-91d3-0a01321b5a49"; | ||
let value = Value::Uuid(Uuid::parse_str(raw_value)?); | ||
let result = crate::from_value::<Uuid>(&value)?; | ||
let result = from_value::<Uuid>(&value)?; | ||
assert_eq!(result.to_string(), raw_value); | ||
Ok(()) | ||
} | ||
|
@@ -1315,4 +1323,102 @@ mod tests { | |
|
||
Ok(()) | ||
} | ||
|
||
#[test] | ||
fn test_avro_3892_deserialize_string_from_bytes() -> TestResult { | ||
let raw_value = vec![1, 2, 3, 4]; | ||
let value = Value::Bytes(raw_value.clone()); | ||
let result = from_value::<String>(&value)?; | ||
assert_eq!(result, String::from_utf8(raw_value)?); | ||
Ok(()) | ||
} | ||
|
||
#[test] | ||
fn test_avro_3892_deserialize_str_from_bytes() -> TestResult { | ||
let raw_value = &[1, 2, 3, 4]; | ||
let value = Value::Bytes(raw_value.to_vec()); | ||
let result = from_value::<&str>(&value)?; | ||
assert_eq!(result, std::str::from_utf8(raw_value)?); | ||
Ok(()) | ||
} | ||
|
||
#[derive(Debug)] | ||
struct Bytes(Vec<u8>); | ||
|
||
impl<'de> Deserialize<'de> for Bytes { | ||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
where | ||
D: serde::Deserializer<'de>, | ||
{ | ||
struct BytesVisitor; | ||
impl<'de> serde::de::Visitor<'de> for BytesVisitor { | ||
type Value = Bytes; | ||
|
||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
formatter.write_str("a byte array") | ||
} | ||
|
||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> | ||
where | ||
E: serde::de::Error, | ||
{ | ||
Ok(Bytes(v.to_vec())) | ||
} | ||
} | ||
deserializer.deserialize_bytes(BytesVisitor) | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_avro_3892_deserialize_bytes_from_decimal() -> TestResult { | ||
let expected_bytes = BigInt::from(123456789).to_signed_bytes_be(); | ||
let value = Value::Decimal(Decimal::from(&expected_bytes)); | ||
let raw_bytes = from_value::<Bytes>(&value)?; | ||
assert_eq!(raw_bytes.0, expected_bytes); | ||
|
||
let value = Value::Union(0, Box::new(Value::Decimal(Decimal::from(&expected_bytes)))); | ||
let raw_bytes = from_value::<Option<Bytes>>(&value)?; | ||
assert_eq!(raw_bytes.unwrap().0, expected_bytes); | ||
Ok(()) | ||
martin-g marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
#[test] | ||
fn test_avro_3892_deserialize_bytes_from_uuid() -> TestResult { | ||
let uuid_str = "10101010-2020-2020-2020-101010101010"; | ||
let expected_bytes = Uuid::parse_str(uuid_str)?.as_bytes().to_vec(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One thing may need to notice: I find that the behaviour of deserialize_str and deserialize_bytes for Value::Uuid is different. We can see that in deserialize_bytes for Value::Uuid, the bytes representation is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dunno! |
||
let value = Value::Uuid(Uuid::parse_str(uuid_str)?); | ||
let raw_bytes = from_value::<Bytes>(&value)?; | ||
assert_eq!(raw_bytes.0, expected_bytes); | ||
|
||
let value = Value::Union(0, Box::new(Value::Uuid(Uuid::parse_str(uuid_str)?))); | ||
let raw_bytes = from_value::<Option<Bytes>>(&value)?; | ||
assert_eq!(raw_bytes.unwrap().0, expected_bytes); | ||
Ok(()) | ||
} | ||
|
||
#[test] | ||
fn test_avro_3892_deserialize_bytes_from_fixed() -> TestResult { | ||
let expected_bytes = vec![1, 2, 3, 4]; | ||
let value = Value::Fixed(4, expected_bytes.clone()); | ||
let raw_bytes = from_value::<Bytes>(&value)?; | ||
assert_eq!(raw_bytes.0, expected_bytes); | ||
|
||
let value = Value::Union(0, Box::new(Value::Fixed(4, expected_bytes.clone()))); | ||
let raw_bytes = from_value::<Option<Bytes>>(&value)?; | ||
assert_eq!(raw_bytes.unwrap().0, expected_bytes); | ||
Ok(()) | ||
} | ||
|
||
#[test] | ||
fn test_avro_3892_deserialize_bytes_from_bytes() -> TestResult { | ||
let expected_bytes = vec![1, 2, 3, 4]; | ||
let value = Value::Bytes(expected_bytes.clone()); | ||
let raw_bytes = from_value::<Bytes>(&value)?; | ||
assert_eq!(raw_bytes.0, expected_bytes); | ||
|
||
let value = Value::Union(0, Box::new(Value::Bytes(expected_bytes.clone()))); | ||
let raw_bytes = from_value::<Option<Bytes>>(&value)?; | ||
assert_eq!(raw_bytes.unwrap().0, expected_bytes); | ||
Ok(()) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be nice to add new unit tests for the changes above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for review! I have added the test for it.