]> git.lizzy.rs Git - rust.git/blob - src/libstd/ascii.rs
Merge branch 'refactor-select' of https://github.com/aravind-pg/rust into update...
[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 //! Most string operations in Rust act on UTF-8 strings. However, at times it
14 //! makes more sense to only consider the ASCII character set for a specific
15 //! operation.
16 //!
17 //! The [`AsciiExt`] trait provides methods that allow for character
18 //! operations that only act on the ASCII subset and leave non-ASCII characters
19 //! alone.
20 //!
21 //! The [`escape_default`] function provides an iterator over the bytes of an
22 //! escaped version of the character given.
23 //!
24 //! [`AsciiExt`]: trait.AsciiExt.html
25 //! [`escape_default`]: fn.escape_default.html
26
27 #![stable(feature = "rust1", since = "1.0.0")]
28
29 use fmt;
30 use ops::Range;
31 use iter::FusedIterator;
32
33 /// Extension methods for ASCII-subset only operations.
34 ///
35 /// Be aware that operations on seemingly non-ASCII characters can sometimes
36 /// have unexpected results. Consider this example:
37 ///
38 /// ```
39 /// use std::ascii::AsciiExt;
40 ///
41 /// assert_eq!(AsciiExt::to_ascii_uppercase("café"), "CAFÉ");
42 /// assert_eq!(AsciiExt::to_ascii_uppercase("café"), "CAFé");
43 /// ```
44 ///
45 /// In the first example, the lowercased string is represented `"cafe\u{301}"`
46 /// (the last character is an acute accent [combining character]). Unlike the
47 /// other characters in the string, the combining character will not get mapped
48 /// to an uppercase variant, resulting in `"CAFE\u{301}"`. In the second
49 /// example, the lowercased string is represented `"caf\u{e9}"` (the last
50 /// character is a single Unicode character representing an 'e' with an acute
51 /// accent). Since the last character is defined outside the scope of ASCII,
52 /// it will not get mapped to an uppercase variant, resulting in `"CAF\u{e9}"`.
53 ///
54 /// [combining character]: https://en.wikipedia.org/wiki/Combining_character
55 #[stable(feature = "rust1", since = "1.0.0")]
56 pub trait AsciiExt {
57     /// Container type for copied ASCII characters.
58     #[stable(feature = "rust1", since = "1.0.0")]
59     type Owned;
60
61     /// Checks if the value is within the ASCII range.
62     ///
63     /// # Note
64     ///
65     /// This method will be deprecated in favor of the identically-named
66     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
67     #[stable(feature = "rust1", since = "1.0.0")]
68     fn is_ascii(&self) -> bool;
69
70     /// Makes a copy of the value in its ASCII upper case equivalent.
71     ///
72     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
73     /// but non-ASCII letters are unchanged.
74     ///
75     /// To uppercase the value in-place, use [`make_ascii_uppercase`].
76     ///
77     /// To uppercase ASCII characters in addition to non-ASCII characters, use
78     /// [`str::to_uppercase`].
79     ///
80     /// # Note
81     ///
82     /// This method will be deprecated in favor of the identically-named
83     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
84     ///
85     /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase
86     /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase
87     #[stable(feature = "rust1", since = "1.0.0")]
88     fn to_ascii_uppercase(&self) -> Self::Owned;
89
90     /// Makes a copy of the value in its ASCII lower case equivalent.
91     ///
92     /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
93     /// but non-ASCII letters are unchanged.
94     ///
95     /// To lowercase the value in-place, use [`make_ascii_lowercase`].
96     ///
97     /// To lowercase ASCII characters in addition to non-ASCII characters, use
98     /// [`str::to_lowercase`].
99     ///
100     /// # Note
101     ///
102     /// This method will be deprecated in favor of the identically-named
103     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
104     ///
105     /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase
106     /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase
107     #[stable(feature = "rust1", since = "1.0.0")]
108     fn to_ascii_lowercase(&self) -> Self::Owned;
109
110     /// Checks that two values are an ASCII case-insensitive match.
111     ///
112     /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
113     /// but without allocating and copying temporaries.
114     ///
115     /// # Note
116     ///
117     /// This method will be deprecated in favor of the identically-named
118     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
119     #[stable(feature = "rust1", since = "1.0.0")]
120     fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
121
122     /// Converts this type to its ASCII upper case equivalent in-place.
123     ///
124     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
125     /// but non-ASCII letters are unchanged.
126     ///
127     /// To return a new uppercased value without modifying the existing one, use
128     /// [`to_ascii_uppercase`].
129     ///
130     /// # Note
131     ///
132     /// This method will be deprecated in favor of the identically-named
133     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
134     ///
135     /// [`to_ascii_uppercase`]: #tymethod.to_ascii_uppercase
136     #[stable(feature = "ascii", since = "1.9.0")]
137     fn make_ascii_uppercase(&mut self);
138
139     /// Converts this type to its ASCII lower case equivalent in-place.
140     ///
141     /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
142     /// but non-ASCII letters are unchanged.
143     ///
144     /// To return a new lowercased value without modifying the existing one, use
145     /// [`to_ascii_lowercase`].
146     ///
147     /// # Note
148     ///
149     /// This method will be deprecated in favor of the identically-named
150     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
151     ///
152     /// [`to_ascii_lowercase`]: #tymethod.to_ascii_lowercase
153     #[stable(feature = "ascii", since = "1.9.0")]
154     fn make_ascii_lowercase(&mut self);
155
156     /// Checks if the value is an ASCII alphabetic character:
157     /// U+0041 'A' ... U+005A 'Z' or U+0061 'a' ... U+007A 'z'.
158     /// For strings, true if all characters in the string are
159     /// ASCII alphabetic.
160     ///
161     /// # Note
162     ///
163     /// This method will be deprecated in favor of the identically-named
164     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
165     #[unstable(feature = "ascii_ctype", issue = "39658")]
166     fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); }
167
168     /// Checks if the value is an ASCII uppercase character:
169     /// U+0041 'A' ... U+005A 'Z'.
170     /// For strings, true if all characters in the string are
171     /// ASCII uppercase.
172     ///
173     /// # Note
174     ///
175     /// This method will be deprecated in favor of the identically-named
176     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
177     #[unstable(feature = "ascii_ctype", issue = "39658")]
178     fn is_ascii_uppercase(&self) -> bool { unimplemented!(); }
179
180     /// Checks if the value is an ASCII lowercase character:
181     /// U+0061 'a' ... U+007A 'z'.
182     /// For strings, true if all characters in the string are
183     /// ASCII lowercase.
184     ///
185     /// # Note
186     ///
187     /// This method will be deprecated in favor of the identically-named
188     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
189     #[unstable(feature = "ascii_ctype", issue = "39658")]
190     fn is_ascii_lowercase(&self) -> bool { unimplemented!(); }
191
192     /// Checks if the value is an ASCII alphanumeric character:
193     /// U+0041 'A' ... U+005A 'Z', U+0061 'a' ... U+007A 'z', or
194     /// U+0030 '0' ... U+0039 '9'.
195     /// For strings, true if all characters in the string are
196     /// ASCII alphanumeric.
197     ///
198     /// # Note
199     ///
200     /// This method will be deprecated in favor of the identically-named
201     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
202     #[unstable(feature = "ascii_ctype", issue = "39658")]
203     fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); }
204
205     /// Checks if the value is an ASCII decimal digit:
206     /// U+0030 '0' ... U+0039 '9'.
207     /// For strings, true if all characters in the string are
208     /// ASCII digits.
209     ///
210     /// # Note
211     ///
212     /// This method will be deprecated in favor of the identically-named
213     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
214     #[unstable(feature = "ascii_ctype", issue = "39658")]
215     fn is_ascii_digit(&self) -> bool { unimplemented!(); }
216
217     /// Checks if the value is an ASCII hexadecimal digit:
218     /// U+0030 '0' ... U+0039 '9', U+0041 'A' ... U+0046 'F', or
219     /// U+0061 'a' ... U+0066 'f'.
220     /// For strings, true if all characters in the string are
221     /// ASCII hex digits.
222     ///
223     /// # Note
224     ///
225     /// This method will be deprecated in favor of the identically-named
226     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
227     #[unstable(feature = "ascii_ctype", issue = "39658")]
228     fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); }
229
230     /// Checks if the value is an ASCII punctuation character:
231     ///
232     /// U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`
233     /// U+003A ... U+0040 `: ; < = > ? @`
234     /// U+005B ... U+0060 ``[ \\ ] ^ _ ` ``
235     /// U+007B ... U+007E `{ | } ~`
236     ///
237     /// For strings, true if all characters in the string are
238     /// ASCII punctuation.
239     ///
240     /// # Note
241     ///
242     /// This method will be deprecated in favor of the identically-named
243     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
244     #[unstable(feature = "ascii_ctype", issue = "39658")]
245     fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
246
247     /// Checks if the value is an ASCII graphic character:
248     /// U+0021 '!' ... U+007E '~'.
249     /// For strings, true if all characters in the string are
250     /// ASCII graphic characters.
251     ///
252     /// # Note
253     ///
254     /// This method will be deprecated in favor of the identically-named
255     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
256     #[unstable(feature = "ascii_ctype", issue = "39658")]
257     fn is_ascii_graphic(&self) -> bool { unimplemented!(); }
258
259     /// Checks if the value is an ASCII whitespace character:
260     /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
261     /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
262     /// For strings, true if all characters in the string are
263     /// ASCII whitespace.
264     ///
265     /// Rust uses the WhatWG Infra Standard's [definition of ASCII
266     /// whitespace][infra-aw].  There are several other definitions in
267     /// wide use.  For instance, [the POSIX locale][pct] includes
268     /// U+000B VERTICAL TAB as well as all the above characters,
269     /// but—from the very same specification—[the default rule for
270     /// "field splitting" in the Bourne shell][bfs] considers *only*
271     /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
272     ///
273     /// If you are writing a program that will process an existing
274     /// file format, check what that format's definition of whitespace is
275     /// before using this function.
276     ///
277     /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
278     /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
279     /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
280     ///
281     /// # Note
282     ///
283     /// This method will be deprecated in favor of the identically-named
284     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
285     #[unstable(feature = "ascii_ctype", issue = "39658")]
286     fn is_ascii_whitespace(&self) -> bool { unimplemented!(); }
287
288     /// Checks if the value is an ASCII control character:
289     /// U+0000 NUL ... U+001F UNIT SEPARATOR, or U+007F DELETE.
290     /// Note that most ASCII whitespace characters are control
291     /// characters, but SPACE is not.
292     ///
293     /// # Note
294     ///
295     /// This method will be deprecated in favor of the identically-named
296     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
297     #[unstable(feature = "ascii_ctype", issue = "39658")]
298     fn is_ascii_control(&self) -> bool { unimplemented!(); }
299 }
300
301 macro_rules! delegating_ascii_methods {
302     () => {
303         #[inline]
304         fn is_ascii(&self) -> bool { self.is_ascii() }
305
306         #[inline]
307         fn to_ascii_uppercase(&self) -> Self::Owned { self.to_ascii_uppercase() }
308
309         #[inline]
310         fn to_ascii_lowercase(&self) -> Self::Owned { self.to_ascii_lowercase() }
311
312         #[inline]
313         fn eq_ignore_ascii_case(&self, o: &Self) -> bool { self.eq_ignore_ascii_case(o) }
314
315         #[inline]
316         fn make_ascii_uppercase(&mut self) { self.make_ascii_uppercase(); }
317
318         #[inline]
319         fn make_ascii_lowercase(&mut self) { self.make_ascii_lowercase(); }
320     }
321 }
322
323 macro_rules! delegating_ascii_ctype_methods {
324     () => {
325         #[inline]
326         fn is_ascii_alphabetic(&self) -> bool { self.is_ascii_alphabetic() }
327
328         #[inline]
329         fn is_ascii_uppercase(&self) -> bool { self.is_ascii_uppercase() }
330
331         #[inline]
332         fn is_ascii_lowercase(&self) -> bool { self.is_ascii_lowercase() }
333
334         #[inline]
335         fn is_ascii_alphanumeric(&self) -> bool { self.is_ascii_alphanumeric() }
336
337         #[inline]
338         fn is_ascii_digit(&self) -> bool { self.is_ascii_digit() }
339
340         #[inline]
341         fn is_ascii_hexdigit(&self) -> bool { self.is_ascii_hexdigit() }
342
343         #[inline]
344         fn is_ascii_punctuation(&self) -> bool { self.is_ascii_punctuation() }
345
346         #[inline]
347         fn is_ascii_graphic(&self) -> bool { self.is_ascii_graphic() }
348
349         #[inline]
350         fn is_ascii_whitespace(&self) -> bool { self.is_ascii_whitespace() }
351
352         #[inline]
353         fn is_ascii_control(&self) -> bool { self.is_ascii_control() }
354     }
355 }
356
357 #[stable(feature = "rust1", since = "1.0.0")]
358 impl AsciiExt for u8 {
359     type Owned = u8;
360
361     delegating_ascii_methods!();
362     delegating_ascii_ctype_methods!();
363 }
364
365 #[stable(feature = "rust1", since = "1.0.0")]
366 impl AsciiExt for char {
367     type Owned = char;
368
369     delegating_ascii_methods!();
370     delegating_ascii_ctype_methods!();
371 }
372
373 #[stable(feature = "rust1", since = "1.0.0")]
374 impl AsciiExt for [u8] {
375     type Owned = Vec<u8>;
376
377     delegating_ascii_methods!();
378
379     #[inline]
380     fn is_ascii_alphabetic(&self) -> bool {
381         self.iter().all(|b| b.is_ascii_alphabetic())
382     }
383
384     #[inline]
385     fn is_ascii_uppercase(&self) -> bool {
386         self.iter().all(|b| b.is_ascii_uppercase())
387     }
388
389     #[inline]
390     fn is_ascii_lowercase(&self) -> bool {
391         self.iter().all(|b| b.is_ascii_lowercase())
392     }
393
394     #[inline]
395     fn is_ascii_alphanumeric(&self) -> bool {
396         self.iter().all(|b| b.is_ascii_alphanumeric())
397     }
398
399     #[inline]
400     fn is_ascii_digit(&self) -> bool {
401         self.iter().all(|b| b.is_ascii_digit())
402     }
403
404     #[inline]
405     fn is_ascii_hexdigit(&self) -> bool {
406         self.iter().all(|b| b.is_ascii_hexdigit())
407     }
408
409     #[inline]
410     fn is_ascii_punctuation(&self) -> bool {
411         self.iter().all(|b| b.is_ascii_punctuation())
412     }
413
414     #[inline]
415     fn is_ascii_graphic(&self) -> bool {
416         self.iter().all(|b| b.is_ascii_graphic())
417     }
418
419     #[inline]
420     fn is_ascii_whitespace(&self) -> bool {
421         self.iter().all(|b| b.is_ascii_whitespace())
422     }
423
424     #[inline]
425     fn is_ascii_control(&self) -> bool {
426         self.iter().all(|b| b.is_ascii_control())
427     }
428 }
429
430 #[stable(feature = "rust1", since = "1.0.0")]
431 impl AsciiExt for str {
432     type Owned = String;
433
434     delegating_ascii_methods!();
435
436     #[inline]
437     fn is_ascii_alphabetic(&self) -> bool {
438         self.bytes().all(|b| b.is_ascii_alphabetic())
439     }
440
441     #[inline]
442     fn is_ascii_uppercase(&self) -> bool {
443         self.bytes().all(|b| b.is_ascii_uppercase())
444     }
445
446     #[inline]
447     fn is_ascii_lowercase(&self) -> bool {
448         self.bytes().all(|b| b.is_ascii_lowercase())
449     }
450
451     #[inline]
452     fn is_ascii_alphanumeric(&self) -> bool {
453         self.bytes().all(|b| b.is_ascii_alphanumeric())
454     }
455
456     #[inline]
457     fn is_ascii_digit(&self) -> bool {
458         self.bytes().all(|b| b.is_ascii_digit())
459     }
460
461     #[inline]
462     fn is_ascii_hexdigit(&self) -> bool {
463         self.bytes().all(|b| b.is_ascii_hexdigit())
464     }
465
466     #[inline]
467     fn is_ascii_punctuation(&self) -> bool {
468         self.bytes().all(|b| b.is_ascii_punctuation())
469     }
470
471     #[inline]
472     fn is_ascii_graphic(&self) -> bool {
473         self.bytes().all(|b| b.is_ascii_graphic())
474     }
475
476     #[inline]
477     fn is_ascii_whitespace(&self) -> bool {
478         self.bytes().all(|b| b.is_ascii_whitespace())
479     }
480
481     #[inline]
482     fn is_ascii_control(&self) -> bool {
483         self.bytes().all(|b| b.is_ascii_control())
484     }
485 }
486
487 /// An iterator over the escaped version of a byte.
488 ///
489 /// This `struct` is created by the [`escape_default`] function. See its
490 /// documentation for more.
491 ///
492 /// [`escape_default`]: fn.escape_default.html
493 #[stable(feature = "rust1", since = "1.0.0")]
494 pub struct EscapeDefault {
495     range: Range<usize>,
496     data: [u8; 4],
497 }
498
499 /// Returns an iterator that produces an escaped version of a `u8`.
500 ///
501 /// The default is chosen with a bias toward producing literals that are
502 /// legal in a variety of languages, including C++11 and similar C-family
503 /// languages. The exact rules are:
504 ///
505 /// - Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
506 /// - Single-quote, double-quote and backslash chars are backslash-escaped.
507 /// - Any other chars in the range [0x20,0x7e] are not escaped.
508 /// - Any other chars are given hex escapes of the form '\xNN'.
509 /// - Unicode escapes are never generated by this function.
510 ///
511 /// # Examples
512 ///
513 /// ```
514 /// use std::ascii;
515 ///
516 /// let escaped = ascii::escape_default(b'0').next().unwrap();
517 /// assert_eq!(b'0', escaped);
518 ///
519 /// let mut escaped = ascii::escape_default(b'\t');
520 ///
521 /// assert_eq!(b'\\', escaped.next().unwrap());
522 /// assert_eq!(b't', escaped.next().unwrap());
523 ///
524 /// let mut escaped = ascii::escape_default(b'\r');
525 ///
526 /// assert_eq!(b'\\', escaped.next().unwrap());
527 /// assert_eq!(b'r', escaped.next().unwrap());
528 ///
529 /// let mut escaped = ascii::escape_default(b'\n');
530 ///
531 /// assert_eq!(b'\\', escaped.next().unwrap());
532 /// assert_eq!(b'n', escaped.next().unwrap());
533 ///
534 /// let mut escaped = ascii::escape_default(b'\'');
535 ///
536 /// assert_eq!(b'\\', escaped.next().unwrap());
537 /// assert_eq!(b'\'', escaped.next().unwrap());
538 ///
539 /// let mut escaped = ascii::escape_default(b'"');
540 ///
541 /// assert_eq!(b'\\', escaped.next().unwrap());
542 /// assert_eq!(b'"', escaped.next().unwrap());
543 ///
544 /// let mut escaped = ascii::escape_default(b'\\');
545 ///
546 /// assert_eq!(b'\\', escaped.next().unwrap());
547 /// assert_eq!(b'\\', escaped.next().unwrap());
548 ///
549 /// let mut escaped = ascii::escape_default(b'\x9d');
550 ///
551 /// assert_eq!(b'\\', escaped.next().unwrap());
552 /// assert_eq!(b'x', escaped.next().unwrap());
553 /// assert_eq!(b'9', escaped.next().unwrap());
554 /// assert_eq!(b'd', escaped.next().unwrap());
555 /// ```
556 #[stable(feature = "rust1", since = "1.0.0")]
557 pub fn escape_default(c: u8) -> EscapeDefault {
558     let (data, len) = match c {
559         b'\t' => ([b'\\', b't', 0, 0], 2),
560         b'\r' => ([b'\\', b'r', 0, 0], 2),
561         b'\n' => ([b'\\', b'n', 0, 0], 2),
562         b'\\' => ([b'\\', b'\\', 0, 0], 2),
563         b'\'' => ([b'\\', b'\'', 0, 0], 2),
564         b'"' => ([b'\\', b'"', 0, 0], 2),
565         b'\x20' ... b'\x7e' => ([c, 0, 0, 0], 1),
566         _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
567     };
568
569     return EscapeDefault { range: (0.. len), data: data };
570
571     fn hexify(b: u8) -> u8 {
572         match b {
573             0 ... 9 => b'0' + b,
574             _ => b'a' + b - 10,
575         }
576     }
577 }
578
579 #[stable(feature = "rust1", since = "1.0.0")]
580 impl Iterator for EscapeDefault {
581     type Item = u8;
582     fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
583     fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
584 }
585 #[stable(feature = "rust1", since = "1.0.0")]
586 impl DoubleEndedIterator for EscapeDefault {
587     fn next_back(&mut self) -> Option<u8> {
588         self.range.next_back().map(|i| self.data[i])
589     }
590 }
591 #[stable(feature = "rust1", since = "1.0.0")]
592 impl ExactSizeIterator for EscapeDefault {}
593 #[stable(feature = "fused", since = "1.26.0")]
594 impl FusedIterator for EscapeDefault {}
595
596 #[stable(feature = "std_debug", since = "1.16.0")]
597 impl fmt::Debug for EscapeDefault {
598     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
599         f.pad("EscapeDefault { .. }")
600     }
601 }
602
603
604 #[cfg(test)]
605 mod tests {
606     //! Note that most of these tests are not testing `AsciiExt` methods, but
607     //! test inherent ascii methods of char, u8, str and [u8]. `AsciiExt` is
608     //! just using those methods, though.
609     use super::AsciiExt;
610     use char::from_u32;
611
612     #[test]
613     fn test_is_ascii() {
614         assert!(b"".is_ascii());
615         assert!(b"banana\0\x7F".is_ascii());
616         assert!(b"banana\0\x7F".iter().all(|b| b.is_ascii()));
617         assert!(!b"Vi\xe1\xbb\x87t Nam".is_ascii());
618         assert!(!b"Vi\xe1\xbb\x87t Nam".iter().all(|b| b.is_ascii()));
619         assert!(!b"\xe1\xbb\x87".iter().any(|b| b.is_ascii()));
620
621         assert!("".is_ascii());
622         assert!("banana\0\u{7F}".is_ascii());
623         assert!("banana\0\u{7F}".chars().all(|c| c.is_ascii()));
624         assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii()));
625         assert!(!"ประเทศไทย中华ệ ".chars().any(|c| c.is_ascii()));
626     }
627
628     #[test]
629     fn test_to_ascii_uppercase() {
630         assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL");
631         assert_eq!("hıKß".to_ascii_uppercase(), "HıKß");
632
633         for i in 0..501 {
634             let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
635                         else { i };
636             assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_uppercase(),
637                        (from_u32(upper).unwrap()).to_string());
638         }
639     }
640
641     #[test]
642     fn test_to_ascii_lowercase() {
643         assert_eq!("url()URL()uRl()Ürl".to_ascii_lowercase(), "url()url()url()Ürl");
644         // Dotted capital I, Kelvin sign, Sharp S.
645         assert_eq!("HİKß".to_ascii_lowercase(), "hİKß");
646
647         for i in 0..501 {
648             let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
649                         else { i };
650             assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lowercase(),
651                        (from_u32(lower).unwrap()).to_string());
652         }
653     }
654
655     #[test]
656     fn test_make_ascii_lower_case() {
657         macro_rules! test {
658             ($from: expr, $to: expr) => {
659                 {
660                     let mut x = $from;
661                     x.make_ascii_lowercase();
662                     assert_eq!(x, $to);
663                 }
664             }
665         }
666         test!(b'A', b'a');
667         test!(b'a', b'a');
668         test!(b'!', b'!');
669         test!('A', 'a');
670         test!('À', 'À');
671         test!('a', 'a');
672         test!('!', '!');
673         test!(b"H\xc3\x89".to_vec(), b"h\xc3\x89");
674         test!("HİKß".to_string(), "hİKß");
675     }
676
677
678     #[test]
679     fn test_make_ascii_upper_case() {
680         macro_rules! test {
681             ($from: expr, $to: expr) => {
682                 {
683                     let mut x = $from;
684                     x.make_ascii_uppercase();
685                     assert_eq!(x, $to);
686                 }
687             }
688         }
689         test!(b'a', b'A');
690         test!(b'A', b'A');
691         test!(b'!', b'!');
692         test!('a', 'A');
693         test!('à', 'à');
694         test!('A', 'A');
695         test!('!', '!');
696         test!(b"h\xc3\xa9".to_vec(), b"H\xc3\xa9");
697         test!("hıKß".to_string(), "HıKß");
698
699         let mut x = "Hello".to_string();
700         x[..3].make_ascii_uppercase();  // Test IndexMut on String.
701         assert_eq!(x, "HELlo")
702     }
703
704     #[test]
705     fn test_eq_ignore_ascii_case() {
706         assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl"));
707         assert!(!"Ürl".eq_ignore_ascii_case("ürl"));
708         // Dotted capital I, Kelvin sign, Sharp S.
709         assert!("HİKß".eq_ignore_ascii_case("hİKß"));
710         assert!(!"İ".eq_ignore_ascii_case("i"));
711         assert!(!"K".eq_ignore_ascii_case("k"));
712         assert!(!"ß".eq_ignore_ascii_case("s"));
713
714         for i in 0..501 {
715             let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
716                         else { i };
717             assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case(
718                     &from_u32(lower).unwrap().to_string()));
719         }
720     }
721
722     #[test]
723     fn inference_works() {
724         let x = "a".to_string();
725         x.eq_ignore_ascii_case("A");
726     }
727
728     // Shorthands used by the is_ascii_* tests.
729     macro_rules! assert_all {
730         ($what:ident, $($str:tt),+) => {{
731             $(
732                 for b in $str.chars() {
733                     if !b.$what() {
734                         panic!("expected {}({}) but it isn't",
735                                stringify!($what), b);
736                     }
737                 }
738                 for b in $str.as_bytes().iter() {
739                     if !b.$what() {
740                         panic!("expected {}(0x{:02x})) but it isn't",
741                                stringify!($what), b);
742                     }
743                 }
744                 assert!($str.$what());
745                 assert!($str.as_bytes().$what());
746             )+
747         }};
748         ($what:ident, $($str:tt),+,) => (assert_all!($what,$($str),+))
749     }
750     macro_rules! assert_none {
751         ($what:ident, $($str:tt),+) => {{
752             $(
753                 for b in $str.chars() {
754                     if b.$what() {
755                         panic!("expected not-{}({}) but it is",
756                                stringify!($what), b);
757                     }
758                 }
759                 for b in $str.as_bytes().iter() {
760                     if b.$what() {
761                         panic!("expected not-{}(0x{:02x})) but it is",
762                                stringify!($what), b);
763                     }
764                 }
765             )*
766         }};
767         ($what:ident, $($str:tt),+,) => (assert_none!($what,$($str),+))
768     }
769
770     #[test]
771     fn test_is_ascii_alphabetic() {
772         assert_all!(is_ascii_alphabetic,
773             "",
774             "abcdefghijklmnopqrstuvwxyz",
775             "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
776         );
777         assert_none!(is_ascii_alphabetic,
778             "0123456789",
779             "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
780             " \t\n\x0c\r",
781             "\x00\x01\x02\x03\x04\x05\x06\x07",
782             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
783             "\x10\x11\x12\x13\x14\x15\x16\x17",
784             "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
785             "\x7f",
786         );
787     }
788
789     #[test]
790     fn test_is_ascii_uppercase() {
791         assert_all!(is_ascii_uppercase,
792             "",
793             "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
794         );
795         assert_none!(is_ascii_uppercase,
796             "abcdefghijklmnopqrstuvwxyz",
797             "0123456789",
798             "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
799             " \t\n\x0c\r",
800             "\x00\x01\x02\x03\x04\x05\x06\x07",
801             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
802             "\x10\x11\x12\x13\x14\x15\x16\x17",
803             "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
804             "\x7f",
805         );
806     }
807
808     #[test]
809     fn test_is_ascii_lowercase() {
810         assert_all!(is_ascii_lowercase,
811             "abcdefghijklmnopqrstuvwxyz",
812         );
813         assert_none!(is_ascii_lowercase,
814             "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
815             "0123456789",
816             "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
817             " \t\n\x0c\r",
818             "\x00\x01\x02\x03\x04\x05\x06\x07",
819             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
820             "\x10\x11\x12\x13\x14\x15\x16\x17",
821             "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
822             "\x7f",
823         );
824     }
825
826     #[test]
827     fn test_is_ascii_alphanumeric() {
828         assert_all!(is_ascii_alphanumeric,
829             "",
830             "abcdefghijklmnopqrstuvwxyz",
831             "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
832             "0123456789",
833         );
834         assert_none!(is_ascii_alphanumeric,
835             "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
836             " \t\n\x0c\r",
837             "\x00\x01\x02\x03\x04\x05\x06\x07",
838             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
839             "\x10\x11\x12\x13\x14\x15\x16\x17",
840             "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
841             "\x7f",
842         );
843     }
844
845     #[test]
846     fn test_is_ascii_digit() {
847         assert_all!(is_ascii_digit,
848             "",
849             "0123456789",
850         );
851         assert_none!(is_ascii_digit,
852             "abcdefghijklmnopqrstuvwxyz",
853             "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
854             "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
855             " \t\n\x0c\r",
856             "\x00\x01\x02\x03\x04\x05\x06\x07",
857             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
858             "\x10\x11\x12\x13\x14\x15\x16\x17",
859             "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
860             "\x7f",
861         );
862     }
863
864     #[test]
865     fn test_is_ascii_hexdigit() {
866         assert_all!(is_ascii_hexdigit,
867             "",
868             "0123456789",
869             "abcdefABCDEF",
870         );
871         assert_none!(is_ascii_hexdigit,
872             "ghijklmnopqrstuvwxyz",
873             "GHIJKLMNOQPRSTUVWXYZ",
874             "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
875             " \t\n\x0c\r",
876             "\x00\x01\x02\x03\x04\x05\x06\x07",
877             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
878             "\x10\x11\x12\x13\x14\x15\x16\x17",
879             "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
880             "\x7f",
881         );
882     }
883
884     #[test]
885     fn test_is_ascii_punctuation() {
886         assert_all!(is_ascii_punctuation,
887             "",
888             "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
889         );
890         assert_none!(is_ascii_punctuation,
891             "abcdefghijklmnopqrstuvwxyz",
892             "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
893             "0123456789",
894             " \t\n\x0c\r",
895             "\x00\x01\x02\x03\x04\x05\x06\x07",
896             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
897             "\x10\x11\x12\x13\x14\x15\x16\x17",
898             "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
899             "\x7f",
900         );
901     }
902
903     #[test]
904     fn test_is_ascii_graphic() {
905         assert_all!(is_ascii_graphic,
906             "",
907             "abcdefghijklmnopqrstuvwxyz",
908             "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
909             "0123456789",
910             "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
911         );
912         assert_none!(is_ascii_graphic,
913             " \t\n\x0c\r",
914             "\x00\x01\x02\x03\x04\x05\x06\x07",
915             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
916             "\x10\x11\x12\x13\x14\x15\x16\x17",
917             "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
918             "\x7f",
919         );
920     }
921
922     #[test]
923     fn test_is_ascii_whitespace() {
924         assert_all!(is_ascii_whitespace,
925             "",
926             " \t\n\x0c\r",
927         );
928         assert_none!(is_ascii_whitespace,
929             "abcdefghijklmnopqrstuvwxyz",
930             "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
931             "0123456789",
932             "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
933             "\x00\x01\x02\x03\x04\x05\x06\x07",
934             "\x08\x0b\x0e\x0f",
935             "\x10\x11\x12\x13\x14\x15\x16\x17",
936             "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
937             "\x7f",
938         );
939     }
940
941     #[test]
942     fn test_is_ascii_control() {
943         assert_all!(is_ascii_control,
944             "",
945             "\x00\x01\x02\x03\x04\x05\x06\x07",
946             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
947             "\x10\x11\x12\x13\x14\x15\x16\x17",
948             "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
949             "\x7f",
950         );
951         assert_none!(is_ascii_control,
952             "abcdefghijklmnopqrstuvwxyz",
953             "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
954             "0123456789",
955             "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
956             " ",
957         );
958     }
959 }