martin-g commented on code in PR #414:
URL: https://github.com/apache/avro-rs/pull/414#discussion_r2705990610
##########
avro/src/serde/de.rs:
##########
@@ -1667,4 +1878,79 @@ mod tests {
assert_eq!(raw_bytes.unwrap().0, expected_bytes);
Ok(())
}
+
+ #[test]
+ fn avro_rs_414_deserialize_char_from_string() -> TestResult {
+ let value = Value::String('a'.to_string());
+ let result = from_value::<char>(&value)?;
+ assert_eq!(result, 'a');
+
+ Ok(())
+ }
+
+ #[test]
+ fn avro_rs_414_deserialize_char_from_bytes() -> TestResult {
+ let value = Value::Bytes('a'.to_string().into_bytes());
Review Comment:
```suggestion
let value = Value::Bytes(b'a');
```
##########
avro/src/serde/de.rs:
##########
@@ -382,26 +383,241 @@ impl<'de> de::Deserializer<'de> for &Deserializer<'de> {
}
forward_to_deserialize_any! {
- bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64
+ bool i8 i16 i32 i64 u8 u16 u32 f32 f64
}
- fn deserialize_char<V>(self, _: V) -> Result<V::Value, Self::Error>
+ fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
- Err(de::Error::custom("avro does not support char"))
+ match self.input {
+ Value::Int(i) | Value::Date(i) | Value::TimeMillis(i) => {
+ let n = u64::try_from(*i).map_err(|e|
Details::ConvertI32ToU64(e, *i))?;
+ visitor.visit_u64(n)
+ }
+ Value::Long(i)
+ | Value::TimeMicros(i)
+ | Value::TimestampMillis(i)
+ | Value::TimestampMicros(i)
+ | Value::TimestampNanos(i)
+ | Value::LocalTimestampMillis(i)
+ | Value::LocalTimestampMicros(i)
+ | Value::LocalTimestampNanos(i) => {
+ let n = u64::try_from(*i).map_err(|e|
Details::ConvertI64ToU64(e, *i))?;
+ visitor.visit_u64(n)
+ }
+ Value::Fixed(8, bytes) => {
+ let n =
u64::from_le_bytes(bytes.as_slice().try_into().expect("Size is 8"));
+ visitor.visit_u64(n)
+ }
+ Value::Union(_i, x) => match x.deref() {
+ Value::Int(i) | Value::Date(i) | Value::TimeMillis(i) => {
+ let n = u64::try_from(*i).map_err(|e|
Details::ConvertI32ToU64(e, *i))?;
+ visitor.visit_u64(n)
+ }
+ Value::Long(i)
+ | Value::TimeMicros(i)
+ | Value::TimestampMillis(i)
+ | Value::TimestampMicros(i)
+ | Value::TimestampNanos(i)
+ | Value::LocalTimestampMillis(i)
+ | Value::LocalTimestampMicros(i)
+ | Value::LocalTimestampNanos(i) => {
+ let n = u64::try_from(*i).map_err(|e|
Details::ConvertI64ToU64(e, *i))?;
+ visitor.visit_u64(n)
+ }
+ Value::Fixed(8, bytes) => {
+ let n =
u64::from_le_bytes(bytes.as_slice().try_into().expect("Size is 8"));
+ visitor.visit_u64(n)
+ }
+ _ => Err(de::Error::custom(format!(
+ "Expected a Int|Long|Fixed(8), but got {:?}",
+ self.input
+ ))),
+ },
+ _ => Err(de::Error::custom(format!(
+ "Expected a Int|Long|Fixed(8), but got {:?}",
+ self.input
+ ))),
+ }
+ }
+
+ fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+ where
+ V: Visitor<'de>,
+ {
+ match self.input {
+ Value::Int(i) | Value::Date(i) | Value::TimeMillis(i) => {
+ let n = u128::try_from(*i).map_err(|e|
Details::ConvertI32ToU64(e, *i))?;
+ visitor.visit_u128(n)
+ }
+ Value::Long(i)
+ | Value::TimeMicros(i)
+ | Value::TimestampMillis(i)
+ | Value::TimestampMicros(i)
+ | Value::TimestampNanos(i)
+ | Value::LocalTimestampMillis(i)
+ | Value::LocalTimestampMicros(i)
+ | Value::LocalTimestampNanos(i) => {
+ let n = u128::try_from(*i).map_err(|e|
Details::ConvertI64ToU64(e, *i))?;
+ visitor.visit_u128(n)
+ }
+ Value::Fixed(16, bytes) => {
+ let n =
u128::from_le_bytes(bytes.as_slice().try_into().expect("Size is 16"));
+ visitor.visit_u128(n)
+ }
+ Value::Union(_i, x) => match x.deref() {
+ Value::Int(i) | Value::Date(i) | Value::TimeMillis(i) => {
+ let n = u128::try_from(*i).map_err(|e|
Details::ConvertI32ToU64(e, *i))?;
+ visitor.visit_u128(n)
+ }
+ Value::Long(i)
+ | Value::TimeMicros(i)
+ | Value::TimestampMillis(i)
+ | Value::TimestampMicros(i)
+ | Value::TimestampNanos(i)
+ | Value::LocalTimestampMillis(i)
+ | Value::LocalTimestampMicros(i)
+ | Value::LocalTimestampNanos(i) => {
+ let n = u128::try_from(*i).map_err(|e|
Details::ConvertI64ToU64(e, *i))?;
Review Comment:
```suggestion
let n = u128::try_from(*i).map_err(|e|
Details::ConvertI64ToU128(e, *i))?;
```
##########
avro/src/serde/ser_schema.rs:
##########
@@ -941,6 +987,40 @@ impl<'s, W: Write> SchemaAwareWriteSerializer<'s, W> {
expected => Err(create_error(format!("Expected {expected}. Got:
Int/Long"))),
}
}
Review Comment:
```suggestion
}
```
##########
avro/src/serde/ser_schema.rs:
##########
Review Comment:
```suggestion
"Cannot find a matching Int-like, Long-like or
Fixed(size=8, name=\"u64\") schema in {:?}",
```
##########
avro/src/serde/de.rs:
##########
@@ -1667,4 +1878,79 @@ mod tests {
assert_eq!(raw_bytes.unwrap().0, expected_bytes);
Ok(())
}
+
+ #[test]
+ fn avro_rs_414_deserialize_char_from_string() -> TestResult {
+ let value = Value::String('a'.to_string());
+ let result = from_value::<char>(&value)?;
+ assert_eq!(result, 'a');
+
+ Ok(())
+ }
+
+ #[test]
+ fn avro_rs_414_deserialize_char_from_bytes() -> TestResult {
+ let value = Value::Bytes('a'.to_string().into_bytes());
+ let result = from_value::<char>(&value)?;
+ assert_eq!(result, 'a');
+
+ Ok(())
+ }
+
+ #[test]
+ fn avro_rs_414_deserialize_char_from_fixed() -> TestResult {
+ let value = Value::Fixed(4, [b'a', 0, 0, 0].to_vec());
+ let result = from_value::<char>(&value)?;
+ assert_eq!(result, 'a');
+
+ Ok(())
+ }
+
+ #[test]
+ fn avro_rs_414_deserialize_char_from_long_string() -> TestResult {
+ let value = Value::String("avro".to_string());
+ let result = from_value::<char>(&value).unwrap_err().to_string();
+ assert_eq!(
+ result,
+ "Failed to deserialize Avro value into value: Tried to deserialize
char from string, but the string was longer than one char: avro"
+ );
+
+ Ok(())
+ }
+
+ #[test]
+ fn avro_rs_414_deserialize_char_from_long_bytes() -> TestResult {
+ let value = Value::Bytes("avro".to_string().into_bytes());
Review Comment:
```suggestion
let value = Value::Bytes(b"avro");
```
##########
avro/src/serde/de.rs:
##########
@@ -382,26 +383,241 @@ impl<'de> de::Deserializer<'de> for &Deserializer<'de> {
}
forward_to_deserialize_any! {
- bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64
+ bool i8 i16 i32 i64 u8 u16 u32 f32 f64
}
- fn deserialize_char<V>(self, _: V) -> Result<V::Value, Self::Error>
+ fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
- Err(de::Error::custom("avro does not support char"))
+ match self.input {
+ Value::Int(i) | Value::Date(i) | Value::TimeMillis(i) => {
+ let n = u64::try_from(*i).map_err(|e|
Details::ConvertI32ToU64(e, *i))?;
+ visitor.visit_u64(n)
+ }
+ Value::Long(i)
+ | Value::TimeMicros(i)
+ | Value::TimestampMillis(i)
+ | Value::TimestampMicros(i)
+ | Value::TimestampNanos(i)
+ | Value::LocalTimestampMillis(i)
+ | Value::LocalTimestampMicros(i)
+ | Value::LocalTimestampNanos(i) => {
+ let n = u64::try_from(*i).map_err(|e|
Details::ConvertI64ToU64(e, *i))?;
+ visitor.visit_u64(n)
+ }
+ Value::Fixed(8, bytes) => {
+ let n =
u64::from_le_bytes(bytes.as_slice().try_into().expect("Size is 8"));
+ visitor.visit_u64(n)
+ }
+ Value::Union(_i, x) => match x.deref() {
+ Value::Int(i) | Value::Date(i) | Value::TimeMillis(i) => {
+ let n = u64::try_from(*i).map_err(|e|
Details::ConvertI32ToU64(e, *i))?;
+ visitor.visit_u64(n)
+ }
+ Value::Long(i)
+ | Value::TimeMicros(i)
+ | Value::TimestampMillis(i)
+ | Value::TimestampMicros(i)
+ | Value::TimestampNanos(i)
+ | Value::LocalTimestampMillis(i)
+ | Value::LocalTimestampMicros(i)
+ | Value::LocalTimestampNanos(i) => {
+ let n = u64::try_from(*i).map_err(|e|
Details::ConvertI64ToU64(e, *i))?;
+ visitor.visit_u64(n)
+ }
+ Value::Fixed(8, bytes) => {
+ let n =
u64::from_le_bytes(bytes.as_slice().try_into().expect("Size is 8"));
+ visitor.visit_u64(n)
+ }
+ _ => Err(de::Error::custom(format!(
+ "Expected a Int|Long|Fixed(8), but got {:?}",
+ self.input
+ ))),
+ },
+ _ => Err(de::Error::custom(format!(
+ "Expected a Int|Long|Fixed(8), but got {:?}",
+ self.input
+ ))),
+ }
+ }
+
+ fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+ where
+ V: Visitor<'de>,
+ {
+ match self.input {
+ Value::Int(i) | Value::Date(i) | Value::TimeMillis(i) => {
+ let n = u128::try_from(*i).map_err(|e|
Details::ConvertI32ToU64(e, *i))?;
+ visitor.visit_u128(n)
+ }
+ Value::Long(i)
+ | Value::TimeMicros(i)
+ | Value::TimestampMillis(i)
+ | Value::TimestampMicros(i)
+ | Value::TimestampNanos(i)
+ | Value::LocalTimestampMillis(i)
+ | Value::LocalTimestampMicros(i)
+ | Value::LocalTimestampNanos(i) => {
+ let n = u128::try_from(*i).map_err(|e|
Details::ConvertI64ToU64(e, *i))?;
Review Comment:
```suggestion
let n = u128::try_from(*i).map_err(|e|
Details::ConvertI64ToU128(e, *i))?;
```
##########
avro/src/serde/ser_schema.rs:
##########
Review Comment:
```suggestion
"Cannot find a matching String, Bytes or Fixed(size=4,
name="\char\") schema in {union_schema:?}"
```
##########
avro/src/serde/ser_schema.rs:
##########
@@ -783,6 +785,40 @@ impl<'s, W: Write> SchemaAwareWriteSerializer<'s, W> {
expected => Err(create_error(format!("Expected: {expected}. Got:
Int/Long"))),
}
}
Review Comment:
```suggestion
}
```
##########
avro/src/serde/de.rs:
##########
@@ -382,26 +383,241 @@ impl<'de> de::Deserializer<'de> for &Deserializer<'de> {
}
forward_to_deserialize_any! {
- bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64
+ bool i8 i16 i32 i64 u8 u16 u32 f32 f64
}
- fn deserialize_char<V>(self, _: V) -> Result<V::Value, Self::Error>
+ fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
- Err(de::Error::custom("avro does not support char"))
+ match self.input {
+ Value::Int(i) | Value::Date(i) | Value::TimeMillis(i) => {
+ let n = u64::try_from(*i).map_err(|e|
Details::ConvertI32ToU64(e, *i))?;
+ visitor.visit_u64(n)
+ }
+ Value::Long(i)
+ | Value::TimeMicros(i)
+ | Value::TimestampMillis(i)
+ | Value::TimestampMicros(i)
+ | Value::TimestampNanos(i)
+ | Value::LocalTimestampMillis(i)
+ | Value::LocalTimestampMicros(i)
+ | Value::LocalTimestampNanos(i) => {
+ let n = u64::try_from(*i).map_err(|e|
Details::ConvertI64ToU64(e, *i))?;
+ visitor.visit_u64(n)
+ }
+ Value::Fixed(8, bytes) => {
+ let n =
u64::from_le_bytes(bytes.as_slice().try_into().expect("Size is 8"));
+ visitor.visit_u64(n)
+ }
+ Value::Union(_i, x) => match x.deref() {
+ Value::Int(i) | Value::Date(i) | Value::TimeMillis(i) => {
+ let n = u64::try_from(*i).map_err(|e|
Details::ConvertI32ToU64(e, *i))?;
+ visitor.visit_u64(n)
+ }
+ Value::Long(i)
+ | Value::TimeMicros(i)
+ | Value::TimestampMillis(i)
+ | Value::TimestampMicros(i)
+ | Value::TimestampNanos(i)
+ | Value::LocalTimestampMillis(i)
+ | Value::LocalTimestampMicros(i)
+ | Value::LocalTimestampNanos(i) => {
+ let n = u64::try_from(*i).map_err(|e|
Details::ConvertI64ToU64(e, *i))?;
+ visitor.visit_u64(n)
+ }
+ Value::Fixed(8, bytes) => {
+ let n =
u64::from_le_bytes(bytes.as_slice().try_into().expect("Size is 8"));
+ visitor.visit_u64(n)
+ }
+ _ => Err(de::Error::custom(format!(
+ "Expected a Int|Long|Fixed(8), but got {:?}",
+ self.input
+ ))),
+ },
+ _ => Err(de::Error::custom(format!(
+ "Expected a Int|Long|Fixed(8), but got {:?}",
+ self.input
+ ))),
+ }
+ }
+
+ fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+ where
+ V: Visitor<'de>,
+ {
+ match self.input {
+ Value::Int(i) | Value::Date(i) | Value::TimeMillis(i) => {
+ let n = u128::try_from(*i).map_err(|e|
Details::ConvertI32ToU64(e, *i))?;
Review Comment:
```suggestion
let n = u128::try_from(*i).map_err(|e|
Details::ConvertI32ToU128(e, *i))?;
```
##########
avro/src/serde/ser_schema.rs:
##########
@@ -783,6 +785,40 @@ impl<'s, W: Write> SchemaAwareWriteSerializer<'s, W> {
expected => Err(create_error(format!("Expected: {expected}. Got:
Int/Long"))),
}
}
+ fn serialize_i128_with_schema(&mut self, value: i128, schema: &Schema) ->
Result<usize, Error> {
+ let create_error = |cause: String| {
+ Error::new(Details::SerializeValueWithSchema {
+ value_type: "i128",
+ value: format!("{value}. Cause: {cause}"),
+ schema: schema.clone(),
+ })
+ };
+
+ match schema {
+ Schema::Fixed(fixed) if fixed.size == 16 && fixed.name.name ==
"i128" => {
+ self.writer
+ .write_all(&value.to_le_bytes())
+ .map_err(Details::WriteBytes)?;
+ Ok(16)
+ }
+ Schema::Union(union_schema) => {
+ for (i, variant_schema) in
union_schema.schemas.iter().enumerate() {
+ match variant_schema {
+ Schema::Fixed(fixed) if fixed.size == 16 &&
fixed.name.name == "i128" => {
+ encode_int(i as i32, &mut *self.writer)?;
+ return self.serialize_i128_with_schema(value,
variant_schema);
+ }
+ _ => { /* skip */ }
+ }
+ }
+ Err(create_error(format!(
+ "Cannot find a matching Int-like or Long-like schema in
{:?}",
Review Comment:
```suggestion
"Cannot find a matching Fixed(size=16, name=\"i128\")
schema in {:?}",
```
##########
avro/src/serde/ser_schema.rs:
##########
@@ -941,6 +987,40 @@ impl<'s, W: Write> SchemaAwareWriteSerializer<'s, W> {
expected => Err(create_error(format!("Expected {expected}. Got:
Int/Long"))),
}
}
+ fn serialize_u128_with_schema(&mut self, value: u128, schema: &Schema) ->
Result<usize, Error> {
+ let create_error = |cause: String| {
+ Error::new(Details::SerializeValueWithSchema {
+ value_type: "u128",
+ value: format!("{value}. Cause: {cause}"),
+ schema: schema.clone(),
+ })
+ };
+
+ match schema {
+ Schema::Fixed(fixed) if fixed.size == 16 && fixed.name.name ==
"u128" => {
+ self.writer
+ .write_all(&value.to_le_bytes())
+ .map_err(Details::WriteBytes)?;
+ Ok(16)
+ }
+ Schema::Union(union_schema) => {
+ for (i, variant_schema) in
union_schema.schemas.iter().enumerate() {
+ match variant_schema {
+ Schema::Fixed(fixed) if fixed.size == 16 &&
fixed.name.name == "u128" => {
+ encode_int(i as i32, &mut *self.writer)?;
+ return self.serialize_u128_with_schema(value,
variant_schema);
+ }
+ _ => { /* skip */ }
+ }
+ }
+ Err(create_error(format!(
+ "Cannot find a matching Int-like or Long-like schema in
{:?}",
Review Comment:
```suggestion
"Cannot find a matching Fixed(size=16, name=\"u128\")
schema in {:?}",
```
--
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]