slavische opened a new pull request, #580:
URL: https://github.com/apache/avro-rs/pull/580

   ## Summary
   
   Schema parse fails when a nullable `decimal` field is expressed as
   `[{bytes, logicalType: decimal}, null]` with a JSON string default
   (e.g. `default: "\u0000"`) — `resolve_default_value` reports
   `GetDefaultUnion(Decimal, String)` because `resolve_decimal` has no
   `Value::String` arm. Java, Python and Ruby Avro accept these
   schemas; the Rust implementation should too.
   
   ## Related bugs already declared & fixed in other bindings
   
   This is the Rust counterpart of two tickets that have already been
   triaged in the Apache Avro tracker:
   
   - **AVRO-3773** — "[Ruby] Decimal logical type fail to validate
     default" (apache/avro#2275, resolved in 1.11.2 / 1.12.0). Same
     exact schema shape (`[{bytes, logicalType: decimal}, null]` with a
     JSON string default), same root cause: the validator was evaluating
     the default against the union's logical type instead of its
     underlying `bytes` type. Fixed in Ruby; the Rust binding never
     received the equivalent.
   - **AVRO-3847** — "[Rust] Support default value of pre-defined name
     for Union type field" (apache/avro#2468, closed 2023-08-31). Same
     error message (`"One union type X must match the default's value
     type Y"`), for a different union variant (`Ref` to a pre-defined
     named record). The fix added the missing resolver path for that
     variant. This PR extends the same pattern to the `Decimal` logical
     type.
   
   ## Spec citations
   
   From **Avro 1.12.0 Specification, §"Complex Types / Records"**:
   
   > "Default values for bytes and fixed fields are JSON strings, where
   > Unicode code points 0-255 are mapped to unsigned 8-bit byte values
   > 0-255."
   
   > "Default values for union fields correspond to the first schema
   > that matches in the union."
   
   The "field default values" table in the same section lists `bytes`
   with json type `string` and example `"\u00FF"`, and `fixed` similarly
   with `"\u00ff"`.
   
   `decimal` is a logical type defined on top of `bytes` (or `fixed`) in
   §"Logical Types / Decimal", so the rule transitively applies to
   decimal defaults: when a decimal field sits inside a union whose
   first branch is `{bytes, logicalType: decimal}`, its JSON default is
   a string and needs to validate against the decimal schema at parse
   time.
   
   ## Change
   
   Added a `Value::String(s)` arm to `resolve_decimal` that walks the
   string's codepoints, rejects any value > 0xFF, and collects the rest
   as bytes wrapped in `Value::Decimal`. The precision check is
   deliberately not applied here because the spec does not require a
   default's byte length to cover the declared precision — only that
   the value be a valid member of the underlying `bytes` type.
   
   Wire-level decoded records always arrive as `Value::Bytes`, so this
   arm is exclusively a default-validation path and does not affect
   record decoding.
   
   ## Test plan
   
   - [x] `types::tests::resolve_decimal_from_string_default` — `"\u0000"`
         default, full 0..=255 round-trip, and codepoint > 0xFF rejection
   - [x] `types::tests::parse_schema_with_nullable_decimal_string_default`
         — end-to-end `Schema::parse_str` of a record with a nullable
         decimal field using a JSON string default
   - [x] Full `cargo test -p apache-avro --lib` — 559 lib tests pass
   - [x] Integration test files `schema.rs`, `union_schema.rs`,
         `big_decimal.rs`, `avro-rs-285-bytes_deserialization.rs` et al.
         all still pass


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