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
//! Errors of the build-side locale data.
use thiserror::Error;
/// A syntax error in one `pluralRule-count-*` string.
#[derive(Debug, Error, PartialEq, Eq)]
#[non_exhaustive]
pub enum ParseError {
/// A character the rule grammar does not allow here.
#[error("unexpected character {ch:?} at byte {at}")]
UnexpectedChar {
/// Its byte offset.
at: usize,
/// The character.
ch: char,
},
/// Something else was expected.
#[error("expected {expected} at byte {at}")]
Expected {
/// The byte offset.
at: usize,
/// What the grammar expected.
expected: &'static str,
},
/// A number does not fit.
#[error("number too large at byte {at}")]
Overflow {
/// Its byte offset.
at: usize,
},
/// A range whose low end is above its high end.
#[error("range {lo}..{hi} is empty")]
EmptyRange {
/// The low end.
lo: u64,
/// The high end.
hi: u64,
},
/// `n % 0`.
#[error("modulus 0")]
ZeroModulus,
/// The `other` category has a condition.
#[error("the `other` rule must have no condition")]
OtherWithCondition,
/// A category other than `other` has none.
#[error("a non-`other` rule has no condition")]
MissingCondition,
/// Not one of CLDR's plural categories.
#[error("unknown category {0:?}")]
UnknownCategory(String),
/// More OR groups than the encoding holds.
#[error("more than 31 OR groups in one rule")]
TooManyGroups,
/// A value beyond the operand contract.
#[error("a modulus or value ≥ 10^18 (plans/02-catalog-format.md §4.1 operand contract)")]
TooLarge,
/// A malformed `@integer` / `@decimal` sample.
#[error("bad sample {0:?}")]
Sample(String),
/// A sample range whose ends cannot be compared.
#[error("sample range {0:?}: endpoints differ in fraction digits or use an exponent")]
SampleRange(String),
}
/// A problem with the shipped rule table or the CLDR input.
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum Error {
/// A plural rule does not parse.
#[error("{0}")]
Parse(#[from] ParseError),
/// A plural rule of the shipped table does not parse.
#[error("{kind} {locale} {category}: {source}")]
Rule {
/// `cardinal` or `ordinal`.
kind: &'static str,
/// The locale.
locale: String,
/// The plural category.
category: String,
/// Why.
#[source]
source: ParseError,
},
/// A line of a shipped table is malformed.
#[error("table line {line}: {message}")]
Table {
/// One-based line.
line: usize,
/// What is wrong.
message: String,
},
/// A CLDR number pattern the encoder does not accept.
#[error("CLDR number pattern {pattern:?}: {message}")]
Pattern {
/// The pattern.
pattern: String,
/// What is wrong.
message: &'static str,
},
/// A locale's number data lacks a field.
#[error("number data of {locale} ({system}): no {field}")]
Missing {
/// The locale.
locale: String,
/// The numbering system.
system: String,
/// The missing field.
field: &'static str,
},
/// The catalog writer refused a LOCALE entry.
#[error("LOCALE entry: {0}")]
Entry(#[from] mf2_catalog::WriteError),
/// The CLDR JSON does not parse (`extract`).
#[cfg(feature = "extract")]
#[error("CLDR JSON: {0}")]
Json(#[from] serde_json::Error),
/// The CLDR JSON is not shaped as expected (`extract`).
#[cfg(feature = "extract")]
#[error("unexpected CLDR JSON shape: {0}")]
Shape(String),
/// The CLDR input breaks an assumption the table format rests on (the
/// extractor checks each one, so a CLDR update that changes them is
/// noticed, not silently mis-encoded).
#[cfg(feature = "extract")]
#[error("CLDR data: {0}")]
Assumption(String),
/// A file could not be read or written (`extract`).
#[cfg(feature = "extract")]
#[error("{path}: {source}")]
Io {
/// The file.
path: std::path::PathBuf,
/// What the operating system said.
#[source]
source: std::io::Error,
},
/// ICU4X data for `icu.blob` (`icu-blob`).
#[cfg(feature = "icu-blob")]
#[error("icu.blob: {0}")]
IcuData(#[from] icu_provider::DataError),
/// Some formatter of the `datetime-icu` backend does not build from
/// ICU4X's data for the locale (`icu-blob`).
#[cfg(feature = "icu-blob")]
#[error("icu.blob for {locale}: {count} formatter(s) do not build, e.g. {first}")]
IcuBlobBuild {
/// The locale.
locale: String,
/// How many formatters fail.
count: usize,
/// The first that does.
first: String,
},
}