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
//! The [`Language`] primitive: the validated newtype, the error its door refuses with, and the
//! shared rows the family macro attaches to it.
use ;
/// A primary language subtag, in the shortest spelling BCP 47 has for it: `de`, `zh`, `yue`, `und`.
///
/// WIDE IN, STRICT OUT. What a container writes is dirty in four separate ways and each has a fold,
/// none of which is a rule invented here — every one is a column of a vendored registry:
///
/// | sent | held | the column that did it |
/// |---|---|---|
/// | `DE`, `De` | `de` | none — ASCII case is a spelling, not a value |
/// | `ger` (mkv, ISO 639-2/B) | `de` | [`registry::alpha3`] |
/// | `deu` (mp4, ISO 639-2/T) | `de` | the same, in ONE hop rather than through `ger` |
/// | `iw` | `he` | [`registry::language_preferred`] |
///
/// The two folds are applied in that order and each at most once, so `GER` reaches `de` and stops.
/// See [`new`](Self::new).
///
/// # `und` is a VALUE, and it is not the absence of one
///
/// The registry registers `und` — *Undetermined* — like any other subtag, and this type holds it
/// like any other value. A track whose language nobody recorded has NO language, which is an
/// `Option::None`; a track a muxer explicitly tagged `und` has one, and it says the
/// muxer looked and could not tell. Collapsing the two would lose the difference between *nobody
/// asked* and *somebody asked and did not know*, and the second is the one that says a detector has
/// work to do.
///
/// [`UND`](Self::UND) is how the value is named — an associated constant, which the seat being an
/// inline byte buffer makes trivially possible. It allocates nothing and it never could: this type
/// has no pointer in it.
///
/// # A subtag the registry does not carry is ADMITTED
///
/// Structure and registration are two questions and this type only refuses on the first. `xyz` is
/// three ASCII letters, which is a language subtag's shape, so it is held — and
/// [`is_registered`](Self::is_registered) is what says the registry has never heard of it.
///
/// Refusing it would be the worse bargain by some distance. The registry gains subtags, a vendored
/// copy is a snapshot, and a container in the wild carries whatever its muxer believed: refusing
/// would make a file unindexable because of a table this crate last fetched in August, where
/// admitting it stores the tag, answers `false` to the one question that is actually about the
/// registry, and lets everything else proceed.
///
/// The PRIVATE-USE range is the same posture with a name: `qaa` through `qtz` are reserved by the
/// registry as a block and individually registered by nobody, so
/// [`is_private_use`](Self::is_private_use) is what tells a deliberate private tag apart from a
/// typo. Both answer `is_registered() == false`, and only the first is intentional.
///
/// # Equality is the CANONICAL subtag, so the folds are what make it useful
///
/// `Language::new("ger")? == Language::new("de")?`, because both hold `de`. That is the whole
/// point of folding at the door rather than at comparison time: an mkv's German and an mp4's German
/// are one value, one map key and one hash bucket — and nothing downstream has to know that
/// ISO 639-2 has two alphabets.
///
/// It also means a value that has been stored is canonical, which is what lets a row written from
/// an mkv and a query built from `de` meet without either side knowing the other's spelling.
///
/// # Ordering is ALPHABETICAL, and that is all it is
///
/// [`Ord`] is derived through the text, so `de < en < fr`. It orders the SPELLINGS and says nothing
/// about the languages — `zh` sorts last of those four and is spoken by the most people — which is
/// the same bargain any single-word vocabulary states for its sort order, and it earns its place
/// for the same reason: total and stable, and therefore a usable key wherever values have to be
/// walked in a fixed order.
;
/// A string does not name a language subtag.
///
/// One variant per way the GRAMMAR can fail, and no variant for the registry — an unregistered
/// subtag is admitted, which the type docs argue. The text arrives from a container or from a
/// caller, and which rule broke is the only part of the answer either can act on.
subtag_common!;