This is an automated email from the ASF dual-hosted git repository.

mgrigorov pushed a commit to branch branch-1.11
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/branch-1.11 by this push:
     new ffa145c9a AVRO-3780: [Rust] Bug: decimal logical type usage through 
Fixed (#2283)
ffa145c9a is described below

commit ffa145c9ab4d8b4600406f82dd52427a61eb5aed
Author: theo <[email protected]>
AuthorDate: Wed Jun 14 13:16:49 2023 +0300

    AVRO-3780: [Rust] Bug: decimal logical type usage through Fixed (#2283)
    
    * feat: add failing test case
    
    * AVRO-3780: Fix parsing of `decimal` logical schema with `fixed`
    
    Signed-off-by: Martin Tzvetanov Grigorov <[email protected]>
    
    ---------
    
    Signed-off-by: Martin Tzvetanov Grigorov <[email protected]>
    Co-authored-by: Fedor Telnov <[email protected]>
    Co-authored-by: Martin Tzvetanov Grigorov <[email protected]>
    (cherry picked from commit 12d0655adaf232b82b4ca529ee985508950049d1)
---
 lang/rust/avro/src/error.rs  |  5 ++++-
 lang/rust/avro/src/schema.rs | 44 ++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/lang/rust/avro/src/error.rs b/lang/rust/avro/src/error.rs
index 4f7098d2f..17e2c4e8e 100644
--- a/lang/rust/avro/src/error.rs
+++ b/lang/rust/avro/src/error.rs
@@ -313,7 +313,10 @@ pub enum Error {
     #[error("No `values` in map")]
     GetMapValuesField,
 
-    #[error("No `size` in fixed")]
+    #[error("Fixed schema `size` value must be a positive integer: {0}")]
+    GetFixedSizeFieldPositive(serde_json::Value),
+
+    #[error("Fixed schema has no `size`")]
     GetFixedSizeField,
 
     #[error("Failed to compress with flate")]
diff --git a/lang/rust/avro/src/schema.rs b/lang/rust/avro/src/schema.rs
index 5b6e56505..aa5013ffb 100644
--- a/lang/rust/avro/src/schema.rs
+++ b/lang/rust/avro/src/schema.rs
@@ -1139,7 +1139,12 @@ impl Parser {
         ) -> AvroResult<Schema> {
             match complex.get("type") {
                 Some(value) => {
-                    let ty = parser.parse(value, enclosing_namespace)?;
+                    let ty = match value {
+                        Value::String(s) if s == "fixed" => {
+                            parser.parse_fixed(complex, enclosing_namespace)?
+                        }
+                        _ => parser.parse(value, enclosing_namespace)?,
+                    };
 
                     if kinds
                         .iter()
@@ -1576,9 +1581,12 @@ impl Parser {
             _ => None,
         });
 
-        let size = size_opt
-            .and_then(|v| v.as_i64())
-            .ok_or(Error::GetFixedSizeField)?;
+        let size = match size_opt {
+            Some(size) => size
+                .as_u64()
+                .ok_or_else(|| Error::GetFixedSizeFieldPositive(size.clone())),
+            None => Err(Error::GetFixedSizeField),
+        }?;
 
         let name = Name::parse(complex)?;
         let fully_qualified_name = 
name.fully_qualified_name(enclosing_namespace);
@@ -4679,4 +4687,32 @@ mod tests {
 
         Ok(())
     }
+
+    #[test]
+    fn test_avro_3780_decimal_schema_type_with_fixed() -> TestResult {
+        let schema = json!(
+        {
+          "type": "record",
+          "name": "recordWithDecimal",
+          "fields": [
+            {
+                "name": "decimal",
+                "type": "fixed",
+                "name": "nestedFixed",
+                "size": 8,
+                "logicalType": "decimal",
+                "precision": 4
+            }
+          ]
+        });
+
+        let parse_result = Schema::parse(&schema);
+        assert!(
+            parse_result.is_ok(),
+            "parse result must be ok, got: {:?}",
+            parse_result
+        );
+
+        Ok(())
+    }
 }

Reply via email to