@@ -6,7 +6,7 @@ use crate::parser::errors::ParserError;
6
6
use core:: fmt;
7
7
use core:: ops:: RangeInclusive ;
8
8
use core:: str:: FromStr ;
9
- use tinystr:: { tinystr , TinyAsciiStr } ;
9
+ use tinystr:: TinyAsciiStr ;
10
10
11
11
/// A language subtag (examples: `"en"`, `"csb"`, `"zh"`, `"und"`, etc.)
12
12
///
@@ -38,11 +38,13 @@ use tinystr::{tinystr, TinyAsciiStr};
38
38
/// but that form has not been used and ICU4X does not support it right now.
39
39
///
40
40
/// [`unicode_language_id`]: https://unicode.org/reports/tr35/#unicode_language_id
41
- #[ derive( Default , Debug , PartialEq , Eq , Clone , Hash , PartialOrd , Ord , Copy ) ]
42
- pub struct Language ( Option < TinyAsciiStr < { * LANGUAGE_LENGTH . end ( ) } > > ) ;
41
+ #[ derive( Debug , PartialEq , Eq , Clone , Hash , PartialOrd , Ord , Copy ) ]
42
+ pub struct Language ( TinyAsciiStr < { * LANGUAGE_LENGTH . end ( ) } > ) ;
43
43
44
44
const LANGUAGE_LENGTH : RangeInclusive < usize > = 2 ..=3 ;
45
- const UND_VALUE : TinyAsciiStr < 3 > = tinystr ! ( 3 , "und" ) ;
45
+ // TODO(#348): Change this to invoke a const function.
46
+ // Safe because "und" is a valid language subtag
47
+ const UND : Language = Language ( unsafe { TinyAsciiStr :: from_bytes_unchecked ( * b"und" ) } ) ;
46
48
47
49
impl Language {
48
50
/// A constructor which takes a utf8 slice, parses it and
@@ -75,16 +77,8 @@ impl Language {
75
77
return Err ( ParserError :: InvalidLanguage ) ;
76
78
}
77
79
78
- if slen == 3
79
- && v[ start] == UND_VALUE . all_bytes ( ) [ 0 ]
80
- && v[ start + 1 ] == UND_VALUE . all_bytes ( ) [ 1 ]
81
- && v[ start + 2 ] == UND_VALUE . all_bytes ( ) [ 2 ]
82
- {
83
- return Ok ( Self ( None ) ) ;
84
- }
85
-
86
80
match TinyAsciiStr :: from_bytes_manual_slice ( v, start, end) {
87
- Ok ( s) if s. is_ascii_alphabetic ( ) => Ok ( Self ( Some ( s. to_ascii_lowercase ( ) ) ) ) ,
81
+ Ok ( s) if s. is_ascii_alphabetic ( ) => Ok ( Self ( s. to_ascii_lowercase ( ) ) ) ,
88
82
_ => Err ( ParserError :: InvalidLanguage ) ,
89
83
}
90
84
}
@@ -104,8 +98,8 @@ impl Language {
104
98
/// let lang = unsafe { Language::from_raw_unchecked(raw) };
105
99
/// assert_eq!(lang, "en");
106
100
/// ```
107
- pub fn into_raw ( self ) -> Option < [ u8 ; 3 ] > {
108
- self . 0 . as_ref ( ) . map ( TinyAsciiStr :: all_bytes) . copied ( )
101
+ pub fn into_raw ( self ) -> [ u8 ; 3 ] {
102
+ * self . 0 . all_bytes ( )
109
103
}
110
104
111
105
/// Constructor which takes a raw value returned by
@@ -128,11 +122,8 @@ impl Language {
128
122
///
129
123
/// This function accepts a [`[u8; 3]`] that is expected to be a valid [`TinyAsciiStr<3>`]
130
124
/// representing a [`Language`] subtag in canonical syntax.
131
- pub const unsafe fn from_raw_unchecked ( v : Option < [ u8 ; 3 ] > ) -> Self {
132
- Self ( match v {
133
- Some ( v) => Some ( TinyAsciiStr :: from_bytes_unchecked ( v) ) ,
134
- None => None ,
135
- } )
125
+ pub const unsafe fn from_raw_unchecked ( v : [ u8 ; 3 ] ) -> Self {
126
+ Self ( TinyAsciiStr :: from_bytes_unchecked ( v) )
136
127
}
137
128
138
129
/// Returns the default undefined language "und". Same as [`default()`](Default::default()), but is `const`.
@@ -148,7 +139,7 @@ impl Language {
148
139
/// ```
149
140
#[ inline]
150
141
pub const fn und ( ) -> Self {
151
- Self ( None )
142
+ UND
152
143
}
153
144
154
145
/// A helper function for displaying
@@ -167,11 +158,12 @@ impl Language {
167
158
///
168
159
/// `Notice`: For many use cases, such as comparison,
169
160
/// [`Language`] implements [`PartialEq`]`<&`[`str`]`>` which allows for direct comparisons.
161
+ #[ inline]
170
162
pub fn as_str ( & self ) -> & str {
171
- self . 0 . as_deref ( ) . unwrap_or ( "und" )
163
+ self . 0 . as_str ( )
172
164
}
173
165
174
- /// Resets the [`Language`] subtag to an empty one.
166
+ /// Resets the [`Language`] subtag to an empty one (equal to `"und"`) .
175
167
///
176
168
/// # Examples
177
169
///
@@ -187,11 +179,12 @@ impl Language {
187
179
///
188
180
/// assert_eq!(lang.as_str(), "und");
189
181
/// ```
182
+ #[ inline]
190
183
pub fn clear ( & mut self ) {
191
- self . 0 . take ( ) ;
184
+ * self = UND
192
185
}
193
186
194
- /// Tests if the [`Language`] subtag is empty.
187
+ /// Tests if the [`Language`] subtag is empty (equal to `"und"`) .
195
188
///
196
189
/// # Examples
197
190
///
@@ -207,8 +200,9 @@ impl Language {
207
200
///
208
201
/// assert_eq!(lang.is_empty(), true);
209
202
/// ```
203
+ #[ inline]
210
204
pub fn is_empty ( self ) -> bool {
211
- self . 0 . is_none ( )
205
+ self == UND
212
206
}
213
207
}
214
208
@@ -233,7 +227,7 @@ impl writeable::Writeable for Language {
233
227
234
228
#[ inline]
235
229
fn write_len ( & self ) -> writeable:: LengthHint {
236
- writeable:: LengthHint :: exact ( self . 0 . map_or ( 3 , |t| t . len ( ) ) )
230
+ writeable:: LengthHint :: exact ( self . 0 . len ( ) )
237
231
}
238
232
}
239
233
@@ -256,8 +250,14 @@ impl<'l> From<&'l Language> for &'l str {
256
250
}
257
251
}
258
252
259
- impl From < Language > for Option < TinyAsciiStr < 3 > > {
253
+ impl From < Language > for TinyAsciiStr < 3 > {
260
254
fn from ( input : Language ) -> Self {
261
- input. 0 . map ( Into :: into)
255
+ input. 0
256
+ }
257
+ }
258
+
259
+ impl Default for Language {
260
+ fn default ( ) -> Language {
261
+ Language :: und ( )
262
262
}
263
263
}
0 commit comments