feat(currency): Migrate CurrencyFormatter to adopt the new design with generic ValueRepresentation (Decimal) and add short/narrow constructors#8145
Conversation
0e87de5 to
b35fab7
Compare
| #[test] | ||
| pub fn test_en_us() { | ||
| let locale = locale!("en-US").into(); | ||
| let locale: CurrencyFormatterPreferences = locale!("en-US").into(); |
There was a problem hiding this comment.
nit:
| let locale: CurrencyFormatterPreferences = locale!("en-US").into(); | |
| let prefs: CurrencyFormatterPreferences = locale!("en-US").into(); |
| pub fn format_fixed_decimal<'l>( | ||
| &'l self, | ||
| value: &'l Decimal, | ||
| value: &'l FixedDecimal, |
There was a problem hiding this comment.
issue, pre-existing: this should probably take some integer numeric type (which is capable of representing exact decimal fractions) (like https://github.com/googleapis/googleapis/blob/fdd6a6e4ef12853400539139d014d96e34253166/google/type/money.proto#L30-L40), and use some logic on the ValueRepresentation to work with that
it does not make sense to accept a FixedDecimal, which is basically an int with a user-selected magnitude, if we use currency-specific magnitude and rounding anyway
There was a problem hiding this comment.
This is a very good point. The question of what the optimal input representation for currency formatting should be—whether FixedDecimal is the right fit, or if we need an exact decimal/money representation (like units/nanos)—is a crucial architectural question.
However, since this is a pre-existing design aspect (as you noted), changing it would require a much broader discussion that is out of scope for this migration PR.
To ensure we don't lose track of this, I have created a dedicated issue to host this discussion: #8146. I have also added a TODO(#8146) in format_fixed_decimal to track this and ensure we address it before stabilizing the formatter.
| } | ||
|
|
||
| #[test] | ||
| pub fn test_en_us_aud() { |
There was a problem hiding this comment.
this doesn't test anything that the CAD test doesn't test
There was a problem hiding this comment.
Good point! It is indeed redundant with the CAD test. I have removed the AUD test case to keep the test suite clean and DRY. Thanks!
| try_new: skip, | ||
| try_new_with_buffer_provider, | ||
| try_new_unstable, | ||
| try_new_narrow: skip, |
There was a problem hiding this comment.
why not use the macro-generated version?
There was a problem hiding this comment.
Thanks for the suggestion! We have refactored the constructors to use the macro-generated versions as much as possible (for the buffer and unstable constructors).
However, we still have to skip the compiled constructors (try_new_short/try_new_narrow) in the macro and implement them manually. This is because CurrencyFormatter is a composite formatter that internally instantiates DecimalFormatter (from icu_decimal). Since icu_experimental's local compiled data provider (Baked) only contains experimental keys and does not implement the stable decimal keys, the macro-generated compiled constructors fail to compile due to unsatisfied trait bounds on Baked.
Manually implementing them allows us to initialize DecimalFormatter using its own compiled data, while loading the currency-specific data from icu_experimental's Baked provider. This is the same established pattern used in RelativeTimeFormatter (see relativetime.rs:178).
We have added a TODO comment in the code to re-evaluate and try to use the macro-generated compiled versions once CurrencyFormatter is stabilized and migrated out of experimental.
Additionally, while refactoring, we noticed that try_new_narrow was missing the numbering system fallback loading logic that try_new_short had. We have updated both the compiled and unstable versions of narrow to use the fallback loader, so they are now fully consistent and correct.
|
We have updated this PR to refactor the
This aligns the |
13d73f5 to
8a68189
Compare
|
@robertbastian : Ping |
Implement the ValueRepresentation trait and Decimal marker struct. Migrate CurrencyFormatter to CurrencyFormatter<Decimal> with try_new_short and try_new_narrow constructors, removing the old non-generic try_new constructors. Update tests accordingly. TAG=agy CONV=0f8e0e91-077a-4704-b63f-0c02f37cbc41
- Update try_new_narrow and try_new_narrow_unstable to use robust fallback loading, ensuring consistency with short constructors and supporting numbering system overrides. - Add explanatory comments and TODOs for the manual constructors explaining the cross-crate dependency constraint. TAG=agy CONV=0f8e0e91-077a-4704-b63f-0c02f37cbc41
…sentation - Add TODO(unicode-org#8146) to format_fixed_decimal to track the discussion about whether FixedDecimal is the correct input type for currency formatting. TAG=agy CONV=0f8e0e91-077a-4704-b63f-0c02f37cbc41
- Remove test_en_us_aud to keep the test suite DRY, addressing reviewer feedback. CAD and USD tests already provide full coverage for the dollar currency prefix and narrow/short resolution logic. TAG=agy CONV=0f8e0e91-077a-4704-b63f-0c02f37cbc41
- Rename locale variable to prefs of type CurrencyFormatterPreferences across all test cases in format.rs for naming consistency and to address reviewer feedback. TAG=agy CONV=0f8e0e91-077a-4704-b63f-0c02f37cbc41
- Add test cases to test_numbering_system_override to verify that try_new_narrow correctly respects numbering system overrides (like ar-EG-u-nu-latn), ensuring consistency with try_new_short. - Rename short test variables for clarity. TAG=agy CONV=0f8e0e91-077a-4704-b63f-0c02f37cbc41
8a68189 to
8e24118
Compare
8e24118 to
5ffcd74
Compare
5ffcd74 to
e9b611c
Compare
Migrate the currency formatter based on the design doc:
https://hackmd.io/@younies/number_formatter_4x
Overview
This PR refactors the
CurrencyFormatterinicu_experimentalto align with the proposed design for modular, zero-copy currency formatting (Option 1 in the design doc).Specifically, it introduces the
ValueRepresentationtypestate pattern to partition constructors by capability and representation, starting with the standardDecimalrepresentation, while ensuring consistent locale and numbering system resolution across both short and narrow widths.Changelog
ValueRepresentationtrait andDecimalmarker struct to support typestate-based currency formatting.CurrencyFormatterto be generic overValueRepresentation:pub struct CurrencyFormatter<V: ValueRepresentation>.CurrencyFormatter<Decimal>with newtry_new_shortandtry_new_narrowconstructors (and their unstable/buffer variants), removing the old non-generictry_newconstructors.try_new_narrowto use robust fallback loading, ensuring they correctly support numbering system overrides consistently withtry_new_short.TAG=agy
CONV=0f8e0e91-077a-4704-b63f-0c02f37cbc41