Skip to content

Add Decimal2 type for precise 2-decimal-place values#1283

Merged
oguzkocer merged 4 commits intotrunkfrom
decimal2-type
Apr 17, 2026
Merged

Add Decimal2 type for precise 2-decimal-place values#1283
oguzkocer merged 4 commits intotrunkfrom
decimal2-type

Conversation

@oguzkocer
Copy link
Copy Markdown
Contributor

Replaces f64 for monetary fields (raw_price, renew_raw_price, sale_cost) in domain suggestions to avoid floating-point precision issues.

Replaces f64 for monetary fields (raw_price, renew_raw_price, sale_cost)
in domain suggestions to avoid floating-point precision issues.
@oguzkocer oguzkocer added this to the 0.2 milestone Apr 15, 2026
@oguzkocer oguzkocer added the Rust label Apr 15, 2026
@wpmobilebot
Copy link
Copy Markdown
Collaborator

wpmobilebot commented Apr 15, 2026

XCFramework Build

This PR's XCFramework is available for testing. Add to your Package.swift:

.package(url: "https://github.com/automattic/wordpress-rs", branch: "pr-build/1283")

Built from 7ea2b13

@oguzkocer oguzkocer marked this pull request as ready for review April 15, 2026 06:16
@oguzkocer oguzkocer enabled auto-merge (squash) April 15, 2026 06:16
@oguzkocer oguzkocer requested a review from jkmassel April 15, 2026 06:16
Comment thread wp_api/src/decimal2.rs
/// A decimal number with at most 2 fractional digits, stored as an integer
/// count of hundredths to avoid floating-point precision issues.
///
/// Deserialization rejects values with more than 2 decimal places rather
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably the right answer, though I wonder if we'll eventually hit a case where an API fails to round for us. I guess in that case we just fix the API.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add a Decimal3 or Decimal4 if that helps? I think Decimal2 is still useful, so I'd suggest keeping it for cases when we know it's only 2 decimals.

I guess one option was to turn it into a String and not let clients do math on it, but then you might have people parsing it, so... I think a solution like this is safer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking was that if it's Decimal2 we know how how many significant digits the developer would like it rounded to, so we could coerce it and only implement Decimal4 if we decide we have a type that needs to be that specific.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We started this work for money related calculations and the potential of it being wrong when we used floats. Using any kind of rounding in this type feels quite wrong to me. Am I missing something?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok to leave it for now. We can revisit if in the future some API response expresses a dollar amount as 1.635 or something.

Copy link
Copy Markdown
Contributor

@jkmassel jkmassel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This generally looks good in its current form, but I had a few questions.

Comment thread wp_api/src/decimal2.rs Outdated

fn visit_i64<E: de::Error>(self, v: i64) -> Result<Self::Value, E> {
Ok(Decimal2 {
hundredths: v * 100,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to use checked_mul for this and error out if the value is unreasonably large? Seems like overkill, but it'd never be incorrect?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 3f3b054.

Comment thread wp_api/src/decimal2.rs

struct Decimal2Visitor;

impl de::Visitor<'_> for Decimal2Visitor {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we bother implementing visit_str for values like "19.99"?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in d5210e7.

Comment thread wp_api/src/decimal2.rs Outdated
Comment on lines +171 to +174
#[case(1100, "1100")]
#[case(863, "8.63")]
#[case(0, "0")]
#[case(1800, "1800")]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#[case(1100, "1100")]
#[case(863, "8.63")]
#[case(0, "0")]
#[case(1800, "1800")]
#[case(1100, "11.00")]
#[case(863, "8.63")]
#[case(0, "0")]
#[case(1800, "18.00")]

nit – there's a bit of inconsistency here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 7ea2b13.

Comment thread wp_api/src/decimal2.rs
/// A decimal number with at most 2 fractional digits, stored as an integer
/// count of hundredths to avoid floating-point precision issues.
///
/// Deserialization rejects values with more than 2 decimal places rather
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking was that if it's Decimal2 we know how how many significant digits the developer would like it rounded to, so we could coerce it and only implement Decimal4 if we decide we have a type that needs to be that specific.

@oguzkocer oguzkocer requested a review from jkmassel April 16, 2026 23:42
@oguzkocer oguzkocer merged commit e4ee499 into trunk Apr 17, 2026
33 checks passed
@oguzkocer oguzkocer deleted the decimal2-type branch April 17, 2026 20:16
@jkmassel jkmassel mentioned this pull request Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants