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


##########
crates/iceberg/src/spec/datatypes.rs:
##########
@@ -350,16 +350,35 @@ 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())?;

Review Comment:
   Fixed in 93a06c0aab3d0fd2bb04491c08381c6d7b08566b. The parser now checks 
that each trimmed numeric token contains ASCII digits before parsing. Added 
rejection cases for `decimal(+5, 2)`, `decimal(5, +2)`, `decimal(+5, +2)`, and 
`fixed[+16]` through both `Type` and `PrimitiveType`.
   
   The new test failed on the previous head and passes with the fix. All 1,761 
library tests, the pinned formatting check, and strict all-target/all-feature 
Clippy passed.



##########
crates/iceberg/src/spec/datatypes.rs:
##########
@@ -350,16 +350,35 @@ 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 {
+        return Err(D::Error::custom(
+            "Decimal precision must be greater than zero",
+        ));
+    }
+    if precision > MAX_DECIMAL_PRECISION {
+        return Err(D::Error::custom(format!(
+            "Decimals with precision larger than {MAX_DECIMAL_PRECISION} are 
not supported: {precision}"
+        )));
+    }
+    if scale > precision {
+        return Err(D::Error::custom(format!(
+            "Decimal scale {scale} must not be larger than precision 
{precision}"
+        )));
+    }

Review Comment:
   You're right: the `scale <= precision` statement in the description was too 
broad. `arrow/schema.rs` applies Arrow's stricter validation, but 
`Type::decimal` and the metadata parser did not share that restriction.
   
   In 93a06c0aab3d0fd2bb04491c08381c6d7b08566b, the constructor and 
deserializer share a private precision validator. I removed this PR's added 
scale restriction to preserve existing constructor behavior, including `(5, 
8)`, and corrected the description. Constructor-built roundtrip tests cover 
`(1, 0)`, `(5, 5)`, `(5, 8)`, and `(38, 38)`, plus rejection of precision 0 and 
39. The `(5, 8)` roundtrip failed on the previous head and now passes.
   
   All 1,761 library tests, the pinned formatting check, and strict 
all-target/all-feature Clippy passed. Tightening the public constructor's scale 
policy can be considered separately.



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