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