]> git.proxmox.com Git - rustc.git/blob - src/libstd/ascii.rs
9b94b7f7003ed62f521e37eae944b7848cf61f66
[rustc.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 }