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
//! THE SEAT ALL THREE SUBTAG TYPES ARE: a fixed ASCII buffer, its length, and the folds that fill
//! it — plus the two structural questions every door asks before it reaches a registry.
//!
//! None of this is language knowledge, which is why it is written here rather than generated: a
//! subtag's shape is BCP 47's grammar — so many letters, or so many digits — and its case is a
//! spelling convention. What each type admits, and which case it folds onto, is the type's own
//! subject and is stated there.
//!
//! # A SUBTAG IS BOUNDED, so it is stored INLINE and it is [`Copy`]
//!
//! BCP 47 bounds every one of the three: a language is `2*3ALPHA / 4ALPHA / 5*8ALPHA`, a script is
//! `4ALPHA` exactly, and a region is `2ALPHA / 3DIGIT`. Eight bytes is the widest thing any of them
//! can be, and none of them can be empty. So there is no heap here and no pointer: a value IS its
//! bytes, which makes all three `Copy`, makes a clone a register move, and makes equality a
//! fixed-width comparison rather than a dereference.
//!
//! That is the whole difference from a text seat like `smol_bytes::Utf8Bytes`, which exists for
//! text whose length is *not* bounded — and the one seat in this household that still needs one is
//! [`LanguageId`](super::LanguageId)'s tail, which holds every variant, extension and private-use
//! subtag a tag carries and has no width the grammar bounds.
//!
//! # The PADDING is what keeps the derived order the text's order
//!
//! [`Ascii`] derives [`Ord`], so it compares the whole buffer and then the length. Unused bytes are
//! zero and every byte a subtag can hold is an ASCII letter or digit (`0x30` at the lowest), so a
//! shorter subtag's first unused byte sorts BELOW any byte a longer one could have there — which is
//! exactly what `str`'s own comparison does when one operand runs out. `en` sorts before `eng` on
//! both readings, and two subtags that differ before either ends are decided by the same first
//! differing byte.
//!
//! The length can therefore never be the tiebreak, since two equal padded buffers hold the same
//! bytes and no subtag contains a `NUL`. It is compared anyway, because deriving is what keeps the
//! rule one line rather than a hand-written comparison to get wrong.
/// The widest subtag BCP 47's grammar admits, and therefore the width [`Language`] is stored at.
///
/// Eight, from `language = 2*3ALPHA / 4ALPHA / 5*8ALPHA`. Nothing longer can be a subtag, so a text
/// longer than this is refused on its LENGTH before any fold is attempted — which is what makes the
/// buffer a fixed one.
///
/// [`Language`]: super::Language
pub const MAX: usize = 8;
/// One canonical subtag: `N` bytes of ASCII with a length, and nothing else.
///
/// The storage of all three subtag types, and — since a value is its bytes — the whole of what
/// makes them [`Copy`]. See the module docs for why the derived [`Ord`] is the text's order.
///
/// `pub(crate)` rather than `pub(super)`: the generated registry's compacted key columns
/// (`table::LANGUAGES` and its siblings) are themselves `pub(crate)`, and a public item cannot name
/// a less-visible type in its own signature. The inherent methods below stay `pub(super)` — naming
/// the TYPE is not calling its constructors, and nothing outside `lang` does either.
pub
/// The first character of `text` that is not an ASCII letter, or [`None`] where every one is.
///
/// It answers with the CHARACTER rather than a `bool` so a refusal can name what it found: `zh_CN`
/// is refused for its underscore and `dé` for its `é`, and a client told only that its input was
/// malformed has to guess which.
pub
/// The first character of `text` that is neither an ASCII letter nor an ASCII digit, or [`None`]
/// where every one is.
///
/// A region has TWO grammars, so its door cannot ask a single-class question: what it needs to tell
/// a client is whether the input left the alphanumeric alphabet altogether — `zh_CN`'s underscore —
/// or stayed inside it and belonged to neither arm, which is `D1`.
pub