Skip to content

Commit bf3778f

Browse files
authored
Add currency fractions provider (#7278)
1 parent ed4f577 commit bf3778f

File tree

14 files changed

+885
-1
lines changed

14 files changed

+885
-1
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// This file is part of ICU4X. For terms of use, please see the file
2+
// called LICENSE at the top level of the ICU4X source tree
3+
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4+
5+
// Provider structs must be stable
6+
#![allow(clippy::exhaustive_structs, clippy::exhaustive_enums)]
7+
8+
//! Data provider struct definitions for currency fraction data.
9+
//!
10+
//! Read more about data providers: [`icu_provider`]
11+
12+
use icu_provider::prelude::*;
13+
use tinystr::UnvalidatedTinyAsciiStr;
14+
use zerovec::ZeroMap;
15+
16+
#[cfg(feature = "compiled_data")]
17+
/// Baked data
18+
///
19+
/// <div class="stab unstable">
20+
/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
21+
/// including in SemVer minor releases. In particular, the `DataProvider` implementations are only
22+
/// guaranteed to match with this version's `*_unstable` providers. Use with caution.
23+
/// </div>
24+
pub use crate::provider::Baked;
25+
26+
icu_provider::data_marker!(
27+
/// `CurrencyFractionsV1` provides currency fraction data for rounding and decimal digit rules.
28+
CurrencyFractionsV1,
29+
CurrencyFractions<'static>,
30+
is_singleton = true
31+
);
32+
33+
/// Currency fraction information for all currencies.
34+
///
35+
/// <div class="stab unstable">
36+
/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
37+
/// including in SemVer minor releases. While the serde representation of data structs is guaranteed
38+
/// to be stable, their Rust representation might not be. Use with caution.
39+
/// </div>
40+
#[derive(Clone, PartialEq, Debug, yoke::Yokeable, zerofrom::ZeroFrom)]
41+
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
42+
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
43+
#[cfg_attr(feature = "datagen", databake(path = icu_experimental::dimension::provider::currency::fractions))]
44+
#[yoke(prove_covariance_manually)]
45+
pub struct CurrencyFractions<'data> {
46+
/// Map from 3-letter ISO code to fraction info (only currencies that differ from default)
47+
#[cfg_attr(feature = "serde", serde(borrow))]
48+
pub fractions: ZeroMap<'data, UnvalidatedTinyAsciiStr<3>, FractionInfo>,
49+
50+
/// Default fraction info (used when currency not in map)
51+
pub default: FractionInfo,
52+
}
53+
54+
icu_provider::data_struct!(CurrencyFractions<'_>, #[cfg(feature = "datagen")]);
55+
56+
/// Fraction and rounding information for a currency.
57+
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
58+
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
59+
#[cfg_attr(feature = "datagen", databake(path = icu_experimental::dimension::provider::currency::fractions))]
60+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
61+
pub struct FractionInfo {
62+
/// Number of decimal digits for standard formatting
63+
pub digits: u8,
64+
/// Rounding increment (0 = no special rounding)
65+
pub rounding: u8,
66+
/// Number of decimal digits for cash transactions (if different)
67+
pub cash_digits: Option<u8>,
68+
/// Rounding increment for cash transactions (if different)
69+
pub cash_rounding: Option<u8>,
70+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// This file is part of ICU4X. For terms of use, please see the file
2+
// called LICENSE at the top level of the ICU4X source tree
3+
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4+
5+
use super::fractions::FractionInfo;
6+
use zerovec::{
7+
maps::ZeroMapKV,
8+
ule::{AsULE, RawBytesULE},
9+
};
10+
11+
/// Marker value indicating None for cash_digits and cash_rounding fields.
12+
const NONE_MARKER: u8 = 15;
13+
14+
/// ULE type for FractionInfo - packed into 4 bytes.
15+
///
16+
/// Data layout:
17+
/// - Byte 0, bits 0-3: digits (lower nibble)
18+
/// - Byte 0, bits 4-7: rounding (upper nibble)
19+
/// - Byte 1, bits 0-3: cash_digits (lower nibble, 15 = None)
20+
/// - Byte 1, bits 4-7: cash_rounding (upper nibble, 15 = None)
21+
type FractionInfoULE = RawBytesULE<2>;
22+
23+
impl AsULE for FractionInfo {
24+
type ULE = FractionInfoULE;
25+
26+
#[inline]
27+
fn to_unaligned(self) -> Self::ULE {
28+
debug_assert!(self.digits < 16);
29+
debug_assert!(self.rounding < 16);
30+
31+
let cash_digits = self.cash_digits.unwrap_or(NONE_MARKER);
32+
debug_assert!(cash_digits < 16);
33+
34+
let cash_rounding = match self.cash_rounding {
35+
None => 15,
36+
Some(50) => 14,
37+
Some(n) => {
38+
debug_assert!(n < 14);
39+
n
40+
}
41+
};
42+
43+
RawBytesULE([
44+
(self.digits & 0x0f) | (self.rounding << 4),
45+
(cash_digits & 0x0f) | (cash_rounding << 4),
46+
])
47+
}
48+
49+
#[inline]
50+
fn from_unaligned(unaligned: Self::ULE) -> Self {
51+
let [b0, b1] = unaligned.0;
52+
53+
let digits = b0 & 0x0f;
54+
let rounding = b0 >> 4;
55+
let cash_digits = b1 & 0x0f;
56+
let cash_rounding = b1 >> 4;
57+
58+
FractionInfo {
59+
digits,
60+
rounding,
61+
cash_digits: if cash_digits == NONE_MARKER {
62+
None
63+
} else {
64+
Some(cash_digits)
65+
},
66+
cash_rounding: match cash_rounding {
67+
14 => Some(50),
68+
15 => None,
69+
n => Some(n),
70+
},
71+
}
72+
}
73+
}
74+
75+
impl<'a> ZeroMapKV<'a> for FractionInfo {
76+
type Container = zerovec::ZeroVec<'a, FractionInfo>;
77+
type Slice = zerovec::ZeroSlice<FractionInfo>;
78+
type GetType = <FractionInfo as AsULE>::ULE;
79+
type OwnedType = FractionInfo;
80+
}

components/experimental/src/dimension/provider/currency/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@ pub mod compact_count_ule;
77
pub mod displayname;
88
pub mod essentials;
99
pub mod extended;
10+
pub mod fractions;
11+
mod fractions_ule;
1012
pub mod patterns;
1113
pub mod ule;

components/experimental/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub mod provider {
5252
impl_currency_displayname_v1!(Baked);
5353
impl_currency_patterns_data_v1!(Baked);
5454
impl_currency_extended_data_v1!(Baked);
55+
impl_currency_fractions_v1!(Baked);
5556
impl_units_display_names_v1!(Baked);
5657
impl_units_names_area_core_v1!(Baked);
5758
impl_units_names_area_extended_v1!(Baked);
@@ -121,6 +122,7 @@ pub mod provider {
121122
super::dimension::provider::currency::essentials::CurrencyEssentialsV1::INFO,
122123
super::dimension::provider::currency::patterns::CurrencyPatternsDataV1::INFO,
123124
super::dimension::provider::currency::extended::CurrencyExtendedDataV1::INFO,
125+
super::dimension::provider::currency::fractions::CurrencyFractionsV1::INFO,
124126
super::dimension::provider::percent::PercentEssentialsV1::INFO,
125127
super::dimension::provider::units::essentials::UnitsEssentialsV1::INFO,
126128
super::dimension::provider::units::display_names::UnitsDisplayNamesV1::INFO,

provider/data/experimental/data/currency_fractions_v1.rs.data

Lines changed: 86 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

provider/data/experimental/data/mod.rs

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

provider/data/experimental/fingerprints.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63259,6 +63259,7 @@ currency/extended/data/v1, zu/ZAR, 45B, 22B, b41d10033141372c
6325963259
currency/extended/data/v1, zu/ZMK, 55B, 32B, 556373753497cd9f
6326063260
currency/extended/data/v1, zu/ZMW, 41B, 18B, 5df40b65221c99b7
6326163261
currency/extended/data/v1, zu/ZWG, -> en/ZWG
63262+
currency/fractions/v1, <singleton>, 406B, 358B, e796b7e579009f83
6326263263
currency/patterns/data/v1, <lookup>, 95B, 14 identifiers
6326363264
currency/patterns/data/v1, <total>, 248B, 64B, 8 unique payloads
6326463265
currency/patterns/data/v1, blo, 28B, 5B, 62a8398982cad180

provider/data/experimental/stubdata/currency_fractions_v1.rs.data

Lines changed: 86 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

provider/data/experimental/stubdata/mod.rs

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)