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]

Reply via email to