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


##########
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:
   The precision validation rejects `precision == 0`, but the returned message 
says "precision larger than …" which is misleading for the zero-precision case. 
Splitting the check improves error clarity without changing behavior.



##########
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:
   `check_type_serde_roundtrip_value` currently only deserializes and compares, 
so it doesn't actually verify a serde round-trip (and the name becomes 
misleading). Consider asserting that serializing `expected_type` can be 
deserialized back to the same value.



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