]> git.lizzy.rs Git - rust.git/blob - src/libstd/ascii.rs
std: Split the `std_misc` feature
[rust.git] / src / libstd / ascii.rs
1 // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Operations on ASCII strings and characters
12
13 #![stable(feature = "rust1", since = "1.0.0")]
14
15 use prelude::v1::*;
16
17 use ops::Range;
18 use mem;
19
20 /// Extension methods for ASCII-subset only operations on owned strings
21 #[unstable(feature = "owned_ascii_ext",
22            reason = "would prefer to do this in a more general way")]
23 pub trait OwnedAsciiExt {
24     /// Converts the string to ASCII upper case:
25     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
26     /// but non-ASCII letters are unchanged.
27     fn into_ascii_uppercase(self) -> Self;
28
29     /// Converts the string to ASCII lower case:
30     /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
31     /// but non-ASCII letters are unchanged.
32     fn into_ascii_lowercase(self) -> Self;
33 }
34
35 /// Extension methods for ASCII-subset only operations on string slices.
36 #[stable(feature = "rust1", since = "1.0.0")]
37 pub trait AsciiExt {
38     /// Container type for copied ASCII characters.
39     #[stable(feature = "rust1", since = "1.0.0")]
40     type Owned;
41
42     /// Checks if within the ASCII range.
43     ///
44     /// # Examples
45     ///
46     /// ```
47     /// use std::ascii::AsciiExt;
48     ///
49     /// let ascii = 'a';
50     /// let utf8 = '❤';
51     ///
52     /// assert_eq!(true, ascii.is_ascii());
53     /// assert_eq!(false, utf8.is_ascii())
54     /// ```
55     #[stable(feature = "rust1", since = "1.0.0")]
56     fn is_ascii(&self) -> bool;
57
58     /// Makes a copy of the string in ASCII upper case.
59     ///
60     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
61     /// but non-ASCII letters are unchanged.
62     ///
63     /// # Examples
64     ///
65     /// ```
66     /// use std::ascii::AsciiExt;
67     ///
68     /// let ascii = 'a';
69     /// let utf8 = '❤';
70     ///
71     /// assert_eq!('A', ascii.to_ascii_uppercase());
72     /// assert_eq!('❤', utf8.to_ascii_uppercase());
73     /// ```
74     #[stable(feature = "rust1", since = "1.0.0")]
75     fn to_ascii_uppercase(&self) -> Self::Owned;
76
77     /// Makes a copy of the string in ASCII lower case.
78     ///
79     /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
80     /// but non-ASCII letters are unchanged.
81     ///
82     /// # Examples
83     ///
84     /// ```
85     /// use std::ascii::AsciiExt;
86     ///
87     /// let ascii = 'A';
88     /// let utf8 = '❤';
89     ///
90     /// assert_eq!('a', ascii.to_ascii_lowercase());
91     /// assert_eq!('❤', utf8.to_ascii_lowercase());
92     /// ```
93     #[stable(feature = "rust1", since = "1.0.0")]
94     fn to_ascii_lowercase(&self) -> Self::Owned;
95
96     /// Checks that two strings are an ASCII case-insensitive match.
97     ///
98     /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
99     /// but without allocating and copying temporary strings.
100     ///
101     /// # Examples
102     ///
103     /// ```
104     /// use std::ascii::AsciiExt;
105     ///
106     /// let ascii1 = 'A';
107     /// let ascii2 = 'a';
108     /// let ascii3 = 'A';
109     /// let ascii4 = 'z';
110     ///
111     /// assert_eq!(true, ascii1.eq_ignore_ascii_case(&ascii2));
112     /// assert_eq!(true, ascii1.eq_ignore_ascii_case(&ascii3));
113     /// assert_eq!(false, ascii1.eq_ignore_ascii_case(&ascii4));
114     /// ```
115     #[stable(feature = "rust1", since = "1.0.0")]
116     fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
117
118     /// Converts this type to its ASCII upper case equivalent in-place.
119     ///
120     /// See `to_ascii_uppercase` for more information.
121     ///
122     /// # Examples
123     ///
124     /// ```
125     /// # #![feature(ascii)]
126     /// use std::ascii::AsciiExt;
127     ///
128     /// let mut ascii = 'a';
129     ///
130     /// ascii.make_ascii_uppercase();
131     ///
132     /// assert_eq!('A', ascii);
133     /// ```
134     #[unstable(feature = "ascii")]
135     fn make_ascii_uppercase(&mut self);
136
137     /// Converts this type to its ASCII lower case equivalent in-place.
138     ///
139     /// See `to_ascii_lowercase` for more information.
140     ///
141     /// # Examples
142     ///
143     /// ```
144     /// # #![feature(ascii)]
145     /// use std::ascii::AsciiExt;
146     ///
147     /// let mut ascii = 'A';
148     ///
149     /// ascii.make_ascii_lowercase();
150     ///
151     /// assert_eq!('a', ascii);
152     /// ```
153     #[unstable(feature = "ascii")]
154     fn make_ascii_lowercase(&mut self);
155 }
156
157 #[stable(feature = "rust1", since = "1.0.0")]
158 impl AsciiExt for str {
159     type Owned = String;
160
161     #[inline]
162     fn is_ascii(&self) -> bool {
163         self.bytes().all(|b| b.is_ascii())
164     }
165
166     #[inline]
167     fn to_ascii_uppercase(&self) -> String {
168         self.to_string().into_ascii_uppercase()
169     }
170
171     #[inline]
172     fn to_ascii_lowercase(&self) -> String {
173         self.to_string().into_ascii_lowercase()
174     }
175
176     #[inline]
177     fn eq_ignore_ascii_case(&self, other: &str) -> bool {
178         self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
179     }
180
181     fn make_ascii_uppercase(&mut self) {
182         let me: &mut [u8] = unsafe { mem::transmute(self) };
183         me.make_ascii_uppercase()
184     }
185
186     fn make_ascii_lowercase(&mut self) {
187         let me: &mut [u8] = unsafe { mem::transmute(self) };
188         me.make_ascii_lowercase()
189     }
190 }
191
192 impl OwnedAsciiExt for String {
193     #[inline]
194     fn into_ascii_uppercase(self) -> String {
195         // Vec<u8>::into_ascii_uppercase() preserves the UTF-8 invariant.
196         unsafe { String::from_utf8_unchecked(self.into_bytes().into_ascii_uppercase()) }
197     }
198
199     #[inline]
200     fn into_ascii_lowercase(self) -> String {
201         // Vec<u8>::into_ascii_lowercase() preserves the UTF-8 invariant.
202         unsafe { String::from_utf8_unchecked(self.into_bytes().into_ascii_lowercase()) }
203     }
204 }
205
206 #[stable(feature = "rust1", since = "1.0.0")]
207 impl AsciiExt for [u8] {
208     type Owned = Vec<u8>;
209     #[inline]
210     fn is_ascii(&self) -> bool {
211         self.iter().all(|b| b.is_ascii())
212     }
213
214     #[inline]
215     fn to_ascii_uppercase(&self) -> Vec<u8> {
216         self.to_vec().into_ascii_uppercase()
217     }
218
219     #[inline]
220     fn to_ascii_lowercase(&self) -> Vec<u8> {
221         self.to_vec().into_ascii_lowercase()
222     }
223
224     #[inline]
225     fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
226         self.len() == other.len() &&
227         self.iter().zip(other).all(|(a, b)| {
228             a.eq_ignore_ascii_case(b)
229         })
230     }
231
232     fn make_ascii_uppercase(&mut self) {
233         for byte in self {
234             byte.make_ascii_uppercase();
235         }
236     }
237
238     fn make_ascii_lowercase(&mut self) {
239         for byte in self {
240             byte.make_ascii_lowercase();
241         }
242     }
243 }
244
245 impl OwnedAsciiExt for Vec<u8> {
246     #[inline]
247     fn into_ascii_uppercase(mut self) -> Vec<u8> {
248         self.make_ascii_uppercase();
249         self
250     }
251
252     #[inline]
253     fn into_ascii_lowercase(mut self) -> Vec<u8> {
254         self.make_ascii_lowercase();
255         self
256     }
257 }
258
259 #[stable(feature = "rust1", since = "1.0.0")]
260 impl AsciiExt for u8 {
261     type Owned = u8;
262     #[inline]
263     fn is_ascii(&self) -> bool { *self & 128 == 0 }
264     #[inline]
265     fn to_ascii_uppercase(&self) -> u8 { ASCII_UPPERCASE_MAP[*self as usize] }
266     #[inline]
267     fn to_ascii_lowercase(&self) -> u8 { ASCII_LOWERCASE_MAP[*self as usize] }
268     #[inline]
269     fn eq_ignore_ascii_case(&self, other: &u8) -> bool {
270         self.to_ascii_lowercase() == other.to_ascii_lowercase()
271     }
272     #[inline]
273     fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
274     #[inline]
275     fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
276 }
277
278 #[stable(feature = "rust1", since = "1.0.0")]
279 impl AsciiExt for char {
280     type Owned = char;
281     #[inline]
282     fn is_ascii(&self) -> bool {
283         *self as u32 <= 0x7F
284     }
285
286     #[inline]
287     fn to_ascii_uppercase(&self) -> char {
288         if self.is_ascii() {
289             (*self as u8).to_ascii_uppercase() as char
290         } else {
291             *self
292         }
293     }
294
295     #[inline]
296     fn to_ascii_lowercase(&self) -> char {
297         if self.is_ascii() {
298             (*self as u8).to_ascii_lowercase() as char
299         } else {
300             *self
301         }
302     }
303
304     #[inline]
305     fn eq_ignore_ascii_case(&self, other: &char) -> bool {
306         self.to_ascii_lowercase() == other.to_ascii_lowercase()
307     }
308
309     #[inline]
310     fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
311     #[inline]
312     fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
313 }
314
315 /// An iterator over the escaped version of a byte, constructed via
316 /// `std::ascii::escape_default`.
317 #[stable(feature = "rust1", since = "1.0.0")]
318 pub struct EscapeDefault {
319     range: Range<usize>,
320     data: [u8; 4],
321 }
322
323 /// Returns an iterator that produces an escaped version of a `u8`.
324 ///
325 /// The default is chosen with a bias toward producing literals that are
326 /// legal in a variety of languages, including C++11 and similar C-family
327 /// languages. The exact rules are:
328 ///
329 /// - Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
330 /// - Single-quote, double-quote and backslash chars are backslash-escaped.
331 /// - Any other chars in the range [0x20,0x7e] are not escaped.
332 /// - Any other chars are given hex escapes of the form '\xNN'.
333 /// - Unicode escapes are never generated by this function.
334 ///
335 /// # Examples
336 ///
337 /// ```
338 /// use std::ascii;
339 ///
340 /// let escaped = ascii::escape_default(b'0').next().unwrap();
341 /// assert_eq!(b'0', escaped);
342 ///
343 /// let mut escaped = ascii::escape_default(b'\t');
344 ///
345 /// assert_eq!(b'\\', escaped.next().unwrap());
346 /// assert_eq!(b't', escaped.next().unwrap());
347 /// ```
348 #[stable(feature = "rust1", since = "1.0.0")]
349 pub fn escape_default(c: u8) -> EscapeDefault {
350     let (data, len) = match c {
351         b'\t' => ([b'\\', b't', 0, 0], 2),
352         b'\r' => ([b'\\', b'r', 0, 0], 2),
353         b'\n' => ([b'\\', b'n', 0, 0], 2),
354         b'\\' => ([b'\\', b'\\', 0, 0], 2),
355         b'\'' => ([b'\\', b'\'', 0, 0], 2),
356         b'"' => ([b'\\', b'"', 0, 0], 2),
357         b'\x20' ... b'\x7e' => ([c, 0, 0, 0], 1),
358         _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
359     };
360
361     return EscapeDefault { range: (0.. len), data: data };
362
363     fn hexify(b: u8) -> u8 {
364         match b {
365             0 ... 9 => b'0' + b,
366             _ => b'a' + b - 10,
367         }
368     }
369 }
370
371 #[stable(feature = "rust1", since = "1.0.0")]
372 impl Iterator for EscapeDefault {
373     type Item = u8;
374     fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
375     fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
376 }
377 #[stable(feature = "rust1", since = "1.0.0")]
378 impl DoubleEndedIterator for EscapeDefault {
379     fn next_back(&mut self) -> Option<u8> {
380         self.range.next_back().map(|i| self.data[i])
381     }
382 }
383 #[stable(feature = "rust1", since = "1.0.0")]
384 impl ExactSizeIterator for EscapeDefault {}
385
386 static ASCII_LOWERCASE_MAP: [u8; 256] = [
387     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
388     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
389     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
390     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
391     b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
392     b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
393     b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
394     b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
395     b'@',
396
397           b'a', b'b', b'c', b'd', b'e', b'f', b'g',
398     b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
399     b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
400     b'x', b'y', b'z',
401
402                       b'[', b'\\', b']', b'^', b'_',
403     b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g',
404     b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
405     b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
406     b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f,
407     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
408     0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
409     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
410     0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
411     0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
412     0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
413     0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
414     0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
415     0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
416     0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
417     0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
418     0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
419     0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
420     0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
421     0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
422     0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
423 ];
424
425 static ASCII_UPPERCASE_MAP: [u8; 256] = [
426     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
427     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
428     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
429     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
430     b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
431     b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
432     b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
433     b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
434     b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G',
435     b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
436     b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
437     b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_',
438     b'`',
439
440           b'A', b'B', b'C', b'D', b'E', b'F', b'G',
441     b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
442     b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
443     b'X', b'Y', b'Z',
444
445                       b'{', b'|', b'}', b'~', 0x7f,
446     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
447     0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
448     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
449     0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
450     0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
451     0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
452     0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
453     0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
454     0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
455     0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
456     0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
457     0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
458     0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
459     0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
460     0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
461     0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
462 ];
463
464
465 #[cfg(test)]
466 mod tests {
467     use prelude::v1::*;
468     use super::*;
469     use char::from_u32;
470
471     #[test]
472     fn test_ascii() {
473         assert!("banana".chars().all(|c| c.is_ascii()));
474         assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii()));
475     }
476
477     #[test]
478     fn test_ascii_vec() {
479         assert!("".is_ascii());
480         assert!("a".is_ascii());
481         assert!(!"\u{2009}".is_ascii());
482     }
483
484     #[test]
485     fn test_to_ascii_uppercase() {
486         assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL");
487         assert_eq!("hıKß".to_ascii_uppercase(), "HıKß");
488
489         for i in 0..501 {
490             let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
491                         else { i };
492             assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_uppercase(),
493                        (from_u32(upper).unwrap()).to_string());
494         }
495     }
496
497     #[test]
498     fn test_to_ascii_lowercase() {
499         assert_eq!("url()URL()uRl()Ürl".to_ascii_lowercase(), "url()url()url()Ürl");
500         // Dotted capital I, Kelvin sign, Sharp S.
501         assert_eq!("HİKß".to_ascii_lowercase(), "hİKß");
502
503         for i in 0..501 {
504             let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
505                         else { i };
506             assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lowercase(),
507                        (from_u32(lower).unwrap()).to_string());
508         }
509     }
510
511     #[test]
512     fn test_into_ascii_uppercase() {
513         assert_eq!(("url()URL()uRl()ürl".to_string()).into_ascii_uppercase(),
514                    "URL()URL()URL()üRL".to_string());
515         assert_eq!(("hıKß".to_string()).into_ascii_uppercase(), "HıKß");
516
517         for i in 0..501 {
518             let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
519                         else { i };
520             assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_uppercase(),
521                        (from_u32(upper).unwrap()).to_string());
522         }
523     }
524
525     #[test]
526     fn test_into_ascii_lowercase() {
527         assert_eq!(("url()URL()uRl()Ürl".to_string()).into_ascii_lowercase(),
528                    "url()url()url()Ürl");
529         // Dotted capital I, Kelvin sign, Sharp S.
530         assert_eq!(("HİKß".to_string()).into_ascii_lowercase(), "hİKß");
531
532         for i in 0..501 {
533             let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
534                         else { i };
535             assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_lowercase(),
536                        (from_u32(lower).unwrap()).to_string());
537         }
538     }
539
540     #[test]
541     fn test_eq_ignore_ascii_case() {
542         assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl"));
543         assert!(!"Ürl".eq_ignore_ascii_case("ürl"));
544         // Dotted capital I, Kelvin sign, Sharp S.
545         assert!("HİKß".eq_ignore_ascii_case("hİKß"));
546         assert!(!"İ".eq_ignore_ascii_case("i"));
547         assert!(!"K".eq_ignore_ascii_case("k"));
548         assert!(!"ß".eq_ignore_ascii_case("s"));
549
550         for i in 0..501 {
551             let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
552                         else { i };
553             assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case(
554                     &from_u32(lower).unwrap().to_string()));
555         }
556     }
557 }