shoemoney commented on code in PR #3256:
URL: https://github.com/apache/iceberg-rust/pull/3256#discussion_r4059163475


##########
crates/iceberg/src/spec/datatypes.rs:
##########
@@ -350,16 +350,30 @@ impl Serialize for PrimitiveType {
 fn deserialize_decimal<'de, D>(deserializer: D) -> 
std::result::Result<PrimitiveType, D::Error>
 where D: Deserializer<'de> {
     let s = String::deserialize(deserializer)?;
+    let malformed = || D::Error::custom(format!("Invalid decimal type: {s}"));
+
     let (precision, scale) = s
-        .trim_start_matches(r"decimal(")
-        .trim_end_matches(')')
+        .strip_prefix("decimal(")
+        .and_then(|inner| inner.strip_suffix(')'))
+        .ok_or_else(malformed)?
         .split_once(',')
-        .ok_or_else(|| D::Error::custom("Decimal requires precision and scale: 
{s}"))?;
+        .ok_or_else(|| D::Error::custom(format!("Decimal requires precision 
and scale: {s}")))?;
+
+    let precision: u32 = precision.trim().parse().map_err(|_| malformed())?;
+    let scale: u32 = scale.trim().parse().map_err(|_| malformed())?;
+
+    if precision == 0 || precision > MAX_DECIMAL_PRECISION {
+        return Err(D::Error::custom(format!(
+            "Decimals with precision larger than {MAX_DECIMAL_PRECISION} are 
not supported: {precision}"
+        )));
+    }

Review Comment:
   Fixed in 7d88ecb. Zero precision now has its own error message; the 
regression test failed with the old message and passes with the fix.



##########
crates/iceberg/src/spec/datatypes.rs:
##########
@@ -1326,6 +1338,65 @@ mod tests {
         assert_eq!(16, Type::decimal_required_bytes(38).unwrap());
     }
 
+    #[test]
+    fn test_reject_malformed_decimal_and_fixed_type_strings() {
+        for invalid in [
+            r#""decimal(50, 2)""#,
+            r#""decimal(0, 0)""#,
+            r#""decimal(5, 8)""#,
+            r#""decimal(decimal(5, 2)))""#,
+            r#""decimal(5, 2""#,
+            r#""decimal(5, 2)))))""#,
+            r#""decimal(5, 2, 3)""#,
+            r#""decimal(-5, 2)""#,
+            r#""decimal()""#,
+            r#""fixed[fixed[16]]]""#,
+            r#""fixed[16""#,
+            r#""fixed[16]]]""#,
+            r#""fixed[]""#,
+        ] {
+            assert!(
+                serde_json::from_str::<Type>(invalid).is_err(),
+                "expected {invalid} to be rejected"
+            );
+        }
+    }
+
+    #[test]
+    fn test_accept_valid_decimal_and_fixed_type_strings() {
+        for (json, expected) in [
+            (
+                r#""decimal(9, 2)""#,
+                Type::Primitive(PrimitiveType::Decimal {
+                    precision: 9,
+                    scale: 2,
+                }),
+            ),
+            (
+                r#""decimal(38, 10)""#,
+                Type::Primitive(PrimitiveType::Decimal {
+                    precision: 38,
+                    scale: 10,
+                }),
+            ),
+            (
+                r#""decimal(5,2)""#,
+                Type::Primitive(PrimitiveType::Decimal {
+                    precision: 5,
+                    scale: 2,
+                }),
+            ),
+            (r#""fixed[16]""#, Type::Primitive(PrimitiveType::Fixed(16))),
+        ] {
+            check_type_serde_roundtrip_value(json, expected);
+        }
+    }
+
+    fn check_type_serde_roundtrip_value(json: &str, expected_type: Type) {
+        let parsed: Type = serde_json::from_str(json).unwrap();
+        assert_eq!(parsed, expected_type);
+    }

Review Comment:
   Fixed in 7d88ecb. The helper now serializes the expected type and 
deserializes it again before comparing. All 1,759 iceberg library tests, 
nightly formatting, and crate Clippy passed.



-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to