1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
// 19.364 number:title
macro_rules! number_title {
($acc:ident) => {
/// The number:title attribute specifies the title of a data style.
pub fn set_title<S: Into<String>>(&mut self, title: S) {
self.$acc.set_attr("number:title", title.into());
}
/// The number:title attribute specifies the title of a data style.
pub fn title(&self) -> Option<&str> {
self.$acc.attr("number:title")
}
};
}
// 19.351 number:language
// 19.342 number:country
// 19.361 number:script
macro_rules! number_locale {
($acc:ident) => {
/// The number:language attribute specifies a language code. The country code is used for
/// formatting properties whose evaluation is locale-dependent.
/// If a language code is not specified, either the system settings or the setting for the system's
/// language are used, depending on the property whose value should be evaluated.
///
/// The number:country attribute specifies a country code for a data style. The country code is
/// used for formatting properties whose evaluation is locale-dependent.
/// If a country is not specified, the system settings are used.
///
/// The number:script attribute specifies a script code. The script code is used for formatting
/// properties whose evaluation is locale-dependent. The attribute should be used only if necessary
/// according to the rules of ยง2.2.3 of [RFC5646](https://datatracker.ietf.org/doc/html/rfc5646), or its successors.
pub fn set_locale(&mut self, locale: Locale) {
if locale != Locale::UNKNOWN {
self.attr
.set_attr("number:language", locale.id.language.to_string());
if let Some(region) = locale.id.region {
self.attr.set_attr("number:country", region.to_string());
} else {
self.attr.clear_attr("number:country");
}
if let Some(script) = locale.id.script {
self.attr.set_attr("number:script", script.to_string());
} else {
self.attr.clear_attr("number:script");
}
} else {
self.attr.clear_attr("number:language");
self.attr.clear_attr("number:country");
self.attr.clear_attr("number:script");
}
}
/// Returns number:language, number:country and number:script as a locale.
pub fn locale(&self) -> Option<Locale> {
if let Some(language) = self.attr.attr("number:language") {
if let Ok(language) = Language::try_from_utf8(language.as_bytes()) {
let region = if let Some(region) = self.attr.attr("number:country") {
Region::try_from_utf8(region.as_bytes()).ok()
} else {
None
};
let script = if let Some(script) = self.attr.attr("number:script") {
Script::try_from_utf8(script.as_bytes()).ok()
} else {
None
};
let id = LanguageIdentifier::from((language, script, region));
Some(Locale::from(id))
} else {
None
}
} else {
None
}
}
};
}
// 19.367 number:transliteration-language
// 19.365 number:transliteration-country
macro_rules! number_transliteration_locale {
($acc:ident) => {
/// The number:transliteration-language attribute specifies a language code in
/// conformance with [RFC5646](https://datatracker.ietf.org/doc/html/rfc5646).
/// If no language/country (locale) combination is specified, the locale of the data style is used
///
/// The number:transliteration-country attribute specifies a country code in conformance
/// with [RFC5646](https://datatracker.ietf.org/doc/html/rfc5646).
/// If no language/country (locale) combination is specified, the locale of the data style is used.
pub fn set_transliteration_locale(&mut self, locale: Locale) {
if locale != Locale::UNKNOWN {
self.attr.set_attr(
"number:transliteration-language",
locale.id.language.to_string(),
);
if let Some(region) = locale.id.region {
self.attr
.set_attr("number:transliteration-country", region.to_string());
} else {
self.attr.clear_attr("number:transliteration-country");
}
} else {
self.attr.clear_attr("number:transliteration-language");
self.attr.clear_attr("number:transliteration-country");
}
}
/// Returns number:transliteration_language and number:transliteration_country as a locale.
pub fn transliteration_locale(&self) -> Option<Locale> {
if let Some(language) = self.attr.attr("number:language") {
if let Ok(language) = Language::try_from_utf8(language.as_bytes()) {
let region = if let Some(region) = self.attr.attr("number:country") {
Region::try_from_utf8(region.as_bytes()).ok()
} else {
None
};
let id = LanguageIdentifier::from((language, None, region));
Some(Locale::from(id))
} else {
None
}
} else {
None
}
}
};
}
// 19.366 number:transliteration-format
macro_rules! number_transliteration_format {
($acc:ident) => {
/// The number:transliteration-format attribute specifies which number characters to use.
///
/// The value of the number:transliteration-format attribute shall be a decimal "DIGIT ONE"
/// character with numeric value 1 as listed in the Unicode Character Database file UnicodeData.txt
/// with value 'Nd' (Numeric decimal digit) in the General_Category/Numeric_Type property field 6
/// and value '1' in the Numeric_Value fields 7 and 8, respectively as listed in
/// DerivedNumericValues.txt
///
/// If no format is specified the default ASCII representation of Latin-Indic digits is used, other
/// transliteration attributes present in that case are ignored.
///
/// The default value for this attribute is 1
pub fn set_transliteration_format(&mut self, format: char) {
self.attr
.set_attr("number:transliteration-format", format.to_string());
}
/// Transliteration format.
pub fn transliteration_format(&self) -> Option<char> {
match self.attr.attr("number:transliteration-format") {
None => None,
Some(v) => v.chars().next(),
}
}
};
}
// 19.368 number:transliteration-style
macro_rules! number_transliteration_style {
($acc:ident) => {
/// The number:transliteration-style attribute specifies the transliteration format of a
/// number system.
///
/// The semantics of the values of the number:transliteration-style attribute are locale- and
/// implementation-dependent.
///
/// The default value for this attribute is short.
pub fn set_transliteration_style(&mut self, style: TransliterationStyle) {
self.attr
.set_attr("number:transliteration-style", style.to_string());
}
/// Transliteration style.
pub fn transliteration_style(&self) -> Result<Option<TransliterationStyle>, OdsError> {
TransliterationStyle::parse_attr(self.attr.attr("number:transliteration-style"))
}
};
}
// 19.340 number:automatic-order
macro_rules! number_automatic_order {
($acc:ident) => {
/// The number:automatic-order attribute specifies whether data is ordered to match the default
/// order for the language and country of a data style.
/// The defined values for the number:automatic-order attribute are:
/// * false: data is not ordered to match the default order for the language and country of a data
/// style.
/// * true: data is ordered to match the default order for the language and country of a data style.
/// The default value for this attribute is false.
///
/// This attribute is valid for ValueType::DateTime and ValueType::TimeDuration.
pub fn set_automatic_order(&mut self, volatile: bool) {
self.attr
.set_attr("number:automatic-order", volatile.to_string());
}
/// Automatic order.
pub fn automatic_order(&self) -> Option<bool> {
if let Some(v) = self.attr.attr("number:automatic-order") {
v.parse().ok()
} else {
None
}
}
};
}
// 19.348 number:format-source
macro_rules! number_format_source {
($acc:ident) => {
/// The number:format-source attribute specifies the source of definitions of the short and
/// long display formats.
///
/// The defined values for the number:format-source attribute are:
/// * fixed: the values short and long of the number:style attribute are defined by this
/// standard.
/// * language: the meaning of the values long and short of the number:style attribute
/// depend upon the number:language and number:country attributes of the date style. If
/// neither of those attributes are specified, consumers should use their default locale for short
/// and long date and time formats.
///
/// The default value for this attribute is fixed.
///
/// This attribute is valid for ValueType::DateTime and ValueType::TimeDuration.
pub fn set_format_source(&mut self, source: FormatSource) {
self.attr
.set_attr("number:format-source", source.to_string());
}
/// The source of definitions of the short and long display formats.
pub fn format_source(&mut self) -> Result<Option<FormatSource>, OdsError> {
FormatSource::parse_attr(self.attr.attr("number:format-source"))
}
};
}
// 19.369 number:truncate-on-overflow
macro_rules! number_truncate_on_overflow {
($acc:ident) => {
/// The number:truncate-on-overflow attribute specifies if a time or duration for which the
/// value to be displayed by the largest time component specified in the style is too large to be
/// displayed using the value range for number:hours 16.29.20 (0 to 23), or
/// number:minutes 16.29.21 or number:seconds 16.29.22 (0 to 59) is truncated or if the
/// value range of this component is extended. The largest time component is those for which a value
/// of "1" represents the longest period of time.
/// If a value gets truncated, then its value is displayed modulo 24 (for number:hours) or modulo
/// 60 (for number:minutes and number:seconds).
///
/// If the value range of a component get extended, then values larger than 23 or 59 are displayed.
/// The defined values for the number:truncate-on-overflow element are:
/// * false: the value range of the component is extended.
/// * true: the value range of the component is not extended.
///
/// The default value for this attribute is true.
///
/// This attribute is valid for ValueType::TimeDuration.
pub fn set_truncate_on_overflow(&mut self, truncate: bool) {
self.attr
.set_attr("number:truncate-on-overflow", truncate.to_string());
}
/// Truncate time-values on overflow.
pub fn truncate_on_overflow(&mut self) -> Option<bool> {
if let Some(v) = self.attr.attr("number:truncate-on-overflow") {
v.parse().ok()
} else {
None
}
}
};
}