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
//! The [`ScriptSubtag`] primitive: the validated newtype, the error its door refuses with, and the
//! shared rows the family macro attaches to it.
use ;
/// An ISO 15924 script subtag, in the registry's own Titlecase: `Latn`, `Hans`, `Hant`, `Zxxx`.
///
/// The same family shape as [`Language`](super::Language) with a narrower grammar and ONE fewer
/// fold. Four ASCII letters exactly, Titlecased, and that is the whole canonicalisation — the
/// registry publishes no `Preferred-Value` on a single script record, so there is no deprecation to
/// follow and nothing here to chain.
///
/// | sent | held |
/// |---|---|
/// | `Latn`, `latn`, `LATN`, `lAtN` | `Latn` |
/// | `Hans` | `Hans` |
/// | `Hant` | `Hant` — and NOT `Hans` |
///
/// # SIMPLIFIED AND TRADITIONAL ARE TWO SCRIPTS HERE, and that is a ruling rather than an oversight
///
/// `Hans` and `Hant` are different values, they compare unequal, they store as different bytes and
/// nothing here relates them. A caller looking for a fold that makes `zh-Hant` answer a `zh-Hans`
/// question will not find one, and should not: **this is the metadata layer, and its job is to
/// carry what the file DECLARED.**
///
/// The two are genuinely different writing systems for one language, so which one a track is in is
/// a fact about the track — and a type that folded them would make the two indistinguishable in
/// every direction, including the one somebody wants. What a SEARCH over them should do is a
/// question for the retrieval layer, which has a query, a corpus and a user's intent to weigh; a
/// primitive has none of the three and would be guessing on all of them.
///
/// The composition rule is what keeps the pair reachable at all: `zh` publishes no
/// `Suppress-Script`, so `zh-Hans` composes as itself rather than collapsing to `zh` the way
/// `en-Latn` collapses to `en`. See [`LanguageId`](super::LanguageId).
///
/// # `Zxxx` and `Zzzz` are VALUES, for `und`'s reason
///
/// The registry registers both. `Zxxx` is *Code for unwritten documents* — a track with speech and
/// no writing — and `Zzzz` is *Code for uncoded script*, which is a script somebody looked at and
/// could not place. Neither is the absence of a script: that is an `Option::None`, and it says
/// nobody declared one.
///
/// [`ZXXX`](Self::ZXXX) and [`ZZZZ`](Self::ZZZZ) name them, as associated constants — the shape
/// [`Language::UND`](super::Language::UND) takes, and for the same reason.
///
/// # An unregistered subtag is ADMITTED, and the private-use range is named
///
/// [`Language`](super::Language)'s posture exactly: four letters is a script subtag's shape, so
/// `Abcd` is held and [`is_registered`](Self::is_registered) is `false`. `Qaaa` through `Qabx` are
/// the registry's reserved block, and [`is_private_use`](Self::is_private_use) is what tells a
/// deliberate private script apart from a typo — both being unregistered, and only one intentional.
///
/// # No deprecation reading, because the registry publishes none
///
/// [`Language`](super::Language) and [`Region`](super::Region) each carry `is_deprecated`, and this
/// type does not. That asymmetry is the registry's rather than this house's: not one of the 224
/// script records carries a `Deprecated` date. A predicate here would be a method that has answered
/// `false` since ISO 15924 began and would go on doing so until it silently stopped being complete.
;
/// Every script subtag is exactly this wide. ISO 15924's own shape, and BCP 47's `script = 4ALPHA`.
const WIDTH: usize = 4;
/// A string does not name a script subtag.
///
/// Three variants where [`ParseLanguageError`](super::ParseLanguageError) has four, and the missing
/// one is the grammar's doing: a script has ONE width, so there is no *too short* to tell apart
/// from *too long*.
subtag_common!;