icu_provider_source/cldr_serde/units/
data.rs

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//! Serde structs representing CLDR JSON units.json file.
6//!
7//! Sample file:
8//! <https://github.com/unicode-org/cldr-json/blob/master/cldr-json/cldr-units-full/main/en/units.json>
9
10use icu_pattern::{PatternString, SinglePlaceholder};
11use serde::Deserialize;
12use std::collections::BTreeMap;
13
14/// Represents various patterns for a unit according to plural rules.
15/// The plural rule categories are: zero, one, two, few, many and other.
16/// For more details, refer to the technical report:
17///     https://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules
18#[derive(PartialEq, Debug, Deserialize, Clone)]
19pub(crate) struct Patterns {
20    #[serde(rename = "displayName-count-0")]
21    pub(crate) explicit_zero: Option<PatternString<SinglePlaceholder>>,
22
23    #[serde(rename = "displayName-count-1")]
24    pub(crate) explicit_one: Option<PatternString<SinglePlaceholder>>,
25
26    #[serde(rename = "unitPattern-count-zero")]
27    pub(crate) zero: Option<PatternString<SinglePlaceholder>>,
28
29    #[serde(rename = "unitPattern-count-one")]
30    pub(crate) one: Option<PatternString<SinglePlaceholder>>,
31
32    #[serde(rename = "unitPattern-count-two")]
33    pub(crate) two: Option<PatternString<SinglePlaceholder>>,
34
35    #[serde(rename = "unitPattern-count-few")]
36    pub(crate) few: Option<PatternString<SinglePlaceholder>>,
37
38    #[serde(rename = "unitPattern-count-many")]
39    pub(crate) many: Option<PatternString<SinglePlaceholder>>,
40
41    #[serde(rename = "unitPattern-count-other")]
42    pub(crate) other: Option<PatternString<SinglePlaceholder>>,
43
44    #[serde(rename = "compoundUnitPattern")]
45    pub(crate) compound_unit_pattern: Option<String>,
46
47    #[serde(rename = "unitPrefixPattern")]
48    pub(crate) unit_prefix_pattern: Option<String>,
49
50    #[serde(rename = "compoundUnitPattern1")]
51    pub(crate) compound_unit_pattern1: Option<String>,
52
53    #[serde(rename = "compountUnitPattern1-count-0")]
54    pub(crate) explicit_zero_compound_unit_pattern1: Option<String>,
55
56    #[serde(rename = "compountUnitPattern1-count-1")]
57    pub(crate) explicit_one_compound_unit_pattern1: Option<String>,
58
59    #[serde(rename = "compoundUnitPattern1-count-zero")]
60    pub(crate) zero_compound_unit_pattern1: Option<String>,
61
62    #[serde(rename = "compoundUnitPattern1-count-one")]
63    pub(crate) one_compound_unit_pattern1: Option<String>,
64
65    #[serde(rename = "compoundUnitPattern1-count-two")]
66    pub(crate) two_compound_unit_pattern1: Option<String>,
67
68    #[serde(rename = "compoundUnitPattern1-count-few")]
69    pub(crate) few_compound_unit_pattern1: Option<String>,
70
71    #[serde(rename = "compoundUnitPattern1-count-many")]
72    pub(crate) many_compound_unit_pattern1: Option<String>,
73
74    #[serde(rename = "compoundUnitPattern1-count-other")]
75    pub(crate) other_compound_unit_pattern1: Option<String>,
76}
77
78#[derive(PartialEq, Debug, Deserialize)]
79pub struct DurationUnit {
80    #[serde(rename = "durationUnitPattern")]
81    pub(crate) pat: String,
82    #[serde(rename = "durationUnitPattern-alt-variant")]
83    pub(crate) alt_pat: Option<String>,
84}
85
86#[derive(PartialEq, Debug, Deserialize)]
87pub struct DurationUnits {
88    #[serde(rename = "durationUnit-type-hm")]
89    pub hm: DurationUnit,
90    #[serde(rename = "durationUnit-type-hms")]
91    pub hms: DurationUnit,
92    #[serde(rename = "durationUnit-type-ms")]
93    pub ms: DurationUnit,
94}
95
96// TODO: replace Value with specific structs
97#[derive(PartialEq, Debug)]
98pub(crate) struct UnitsData {
99    pub(crate) long: UnitsLengthData,
100
101    pub(crate) short: UnitsLengthData,
102
103    pub(crate) narrow: UnitsLengthData,
104
105    pub(crate) duration: DurationUnits,
106}
107
108#[derive(PartialEq, Debug)]
109pub(crate) struct UnitsLengthData {
110    pub(crate) units: BTreeMap<String, Patterns>,
111    pub(crate) per: Patterns,
112    pub(crate) times: Patterns,
113    pub(crate) powers: BTreeMap<usize, Patterns>,
114    pub(crate) binary: BTreeMap<u8, Patterns>,
115    pub(crate) decimal: BTreeMap<i8, Patterns>,
116}
117
118impl<'de> Deserialize<'de> for UnitsData {
119    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
120    where
121        D: serde::Deserializer<'de>,
122    {
123        #[derive(Deserialize)]
124        struct Raw {
125            long: BTreeMap<String, Patterns>,
126            short: BTreeMap<String, Patterns>,
127            narrow: BTreeMap<String, Patterns>,
128            #[serde(flatten)]
129            duration: DurationUnits,
130        }
131
132        let Raw {
133            long,
134            short,
135            narrow,
136            duration,
137        } = Raw::deserialize(deserializer)?;
138
139        let construct = |mut map: BTreeMap<String, Patterns>| UnitsLengthData {
140            per: map.remove("per").unwrap(),
141            times: map.remove("times").unwrap(),
142            powers: map
143                .iter()
144                .filter_map(|(k, v)| Some((k.strip_prefix("power")?.parse().ok()?, v.clone())))
145                .collect(),
146            binary: map
147                .iter()
148                .filter_map(|(k, v)| Some((k.strip_prefix("1024p")?.parse().ok()?, v.clone())))
149                .collect(),
150            decimal: map
151                .iter()
152                .filter_map(|(k, v)| Some((k.strip_prefix("10p")?.parse().ok()?, v.clone())))
153                .collect(),
154            units: map
155                .into_iter()
156                .filter_map(|(k, v)| {
157                    if k.starts_with("10p")
158                        || k.starts_with("1024p")
159                        || (k.starts_with("power") && !k.starts_with("power-"))
160                    {
161                        return None;
162                    }
163                    k.split_once('-').map(|(_, unit)| (unit.to_string(), v))
164                })
165                .collect(),
166        };
167
168        Ok(Self {
169            long: construct(long),
170            short: construct(short),
171            narrow: construct(narrow),
172            duration,
173        })
174    }
175}
176
177#[derive(PartialEq, Debug, Deserialize)]
178pub(crate) struct LangUnits {
179    pub(crate) units: UnitsData,
180}
181
182pub(crate) type Resource = super::super::LocaleResource<LangUnits>;