]> git.lizzy.rs Git - rust.git/blob - src/libstd/ascii.rs
Doc says to avoid mixing allocator instead of forbiding it
[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 // ignore-lexer-test FIXME #15679
12
13 //! Operations on ASCII strings and characters
14
15 #![experimental]
16
17 use collections::Collection;
18 use fmt;
19 use iter::Iterator;
20 use mem;
21 use option::{Option, Some, None};
22 use slice::{ImmutableSlice, MutableSlice, Slice};
23 use str::{Str, StrSlice};
24 use str;
25 use string::String;
26 use to_string::IntoStr;
27 use vec::Vec;
28
29 #[deprecated="this trait has been renamed to `AsciiExt`"]
30 pub use self::AsciiExt as StrAsciiExt;
31
32 #[deprecated="this trait has been renamed to `OwnedAsciiExt`"]
33 pub use self::OwnedAsciiExt as OwnedStrAsciiExt;
34
35
36 /// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
37 #[deriving(Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
38 pub struct Ascii { chr: u8 }
39
40 impl Ascii {
41     /// Converts an ascii character into a `u8`.
42     #[inline]
43     pub fn to_byte(self) -> u8 {
44         self.chr
45     }
46
47     /// Converts an ascii character into a `char`.
48     #[inline]
49     pub fn to_char(self) -> char {
50         self.chr as char
51     }
52
53     #[inline]
54     #[allow(missing_doc)]
55     #[deprecated="renamed to `to_lowercase`"]
56     pub fn to_lower(self) -> Ascii {
57         self.to_lowercase()
58     }
59
60     /// Convert to lowercase.
61     #[inline]
62     pub fn to_lowercase(self) -> Ascii {
63         Ascii{chr: ASCII_LOWER_MAP[self.chr as uint]}
64     }
65
66     #[inline]
67     #[allow(missing_doc)]
68     #[deprecated="renamed to `to_uppercase`"]
69     pub fn to_upper(self) -> Ascii {
70         self.to_uppercase()
71     }
72
73     /// Convert to uppercase.
74     #[inline]
75     pub fn to_uppercase(self) -> Ascii {
76         Ascii{chr: ASCII_UPPER_MAP[self.chr as uint]}
77     }
78
79     /// Compares two ascii characters of equality, ignoring case.
80     #[inline]
81     pub fn eq_ignore_case(self, other: Ascii) -> bool {
82         ASCII_LOWER_MAP[self.chr as uint] == ASCII_LOWER_MAP[other.chr as uint]
83     }
84
85     // the following methods are like ctype, and the implementation is inspired by musl
86
87     #[inline]
88     #[allow(missing_doc)]
89     #[deprecated="renamed to `is_alphabetic`"]
90     pub fn is_alpha(&self) -> bool {
91         self.is_alphabetic()
92     }
93
94     /// Check if the character is a letter (a-z, A-Z)
95     #[inline]
96     pub fn is_alphabetic(&self) -> bool {
97         (self.chr >= 0x41 && self.chr <= 0x5A) || (self.chr >= 0x61 && self.chr <= 0x7A)
98     }
99
100     /// Check if the character is a number (0-9)
101     #[inline]
102     pub fn is_digit(&self) -> bool {
103         self.chr >= 0x30 && self.chr <= 0x39
104     }
105
106     #[inline]
107     #[allow(missing_doc)]
108     #[deprecated="renamed to `is_alphanumeric`"]
109     pub fn is_alnum(&self) -> bool {
110         self.is_alphanumeric()
111     }
112
113     /// Check if the character is a letter or number
114     #[inline]
115     pub fn is_alphanumeric(&self) -> bool {
116         self.is_alpha() || self.is_digit()
117     }
118
119     /// Check if the character is a space or horizontal tab
120     #[inline]
121     pub fn is_blank(&self) -> bool {
122         self.chr == b' ' || self.chr == b'\t'
123     }
124
125     /// Check if the character is a control character
126     #[inline]
127     pub fn is_control(&self) -> bool {
128         self.chr < 0x20 || self.chr == 0x7F
129     }
130
131     /// Checks if the character is printable (except space)
132     #[inline]
133     pub fn is_graph(&self) -> bool {
134         (self.chr - 0x21) < 0x5E
135     }
136
137     /// Checks if the character is printable (including space)
138     #[inline]
139     pub fn is_print(&self) -> bool {
140         (self.chr - 0x20) < 0x5F
141     }
142
143     #[inline]
144     #[allow(missing_doc)]
145     #[deprecated="renamed to `is_lowercase`"]
146     pub fn is_lower(&self) -> bool {
147         self.is_lowercase()
148     }
149
150     /// Checks if the character is lowercase
151     #[inline]
152     pub fn is_lowercase(&self) -> bool {
153         (self.chr - b'a') < 26
154     }
155
156     #[inline]
157     #[allow(missing_doc)]
158     #[deprecated="renamed to `is_uppercase`"]
159     pub fn is_upper(&self) -> bool {
160         self.is_uppercase()
161     }
162
163     /// Checks if the character is uppercase
164     #[inline]
165     pub fn is_uppercase(&self) -> bool {
166         (self.chr - b'A') < 26
167     }
168
169     /// Checks if the character is punctuation
170     #[inline]
171     pub fn is_punctuation(&self) -> bool {
172         self.is_graph() && !self.is_alnum()
173     }
174
175     /// Checks if the character is a valid hex digit
176     #[inline]
177     pub fn is_hex(&self) -> bool {
178         self.is_digit() || ((self.chr | 32u8) - b'a') < 6
179     }
180 }
181
182 impl<'a> fmt::Show for Ascii {
183     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
184         (self.chr as char).fmt(f)
185     }
186 }
187
188 /// Trait for converting into an ascii type.
189 pub trait AsciiCast<T> {
190     /// Convert to an ascii type, fail on non-ASCII input.
191     #[inline]
192     fn to_ascii(&self) -> T {
193         assert!(self.is_ascii());
194         unsafe {self.to_ascii_nocheck()}
195     }
196
197     /// Convert to an ascii type, return None on non-ASCII input.
198     #[inline]
199     fn to_ascii_opt(&self) -> Option<T> {
200         if self.is_ascii() {
201             Some(unsafe { self.to_ascii_nocheck() })
202         } else {
203             None
204         }
205     }
206
207     /// Convert to an ascii type, not doing any range asserts
208     unsafe fn to_ascii_nocheck(&self) -> T;
209
210     /// Check if convertible to ascii
211     fn is_ascii(&self) -> bool;
212 }
213
214 impl<'a> AsciiCast<&'a[Ascii]> for &'a [u8] {
215     #[inline]
216     unsafe fn to_ascii_nocheck(&self) -> &'a[Ascii] {
217         mem::transmute(*self)
218     }
219
220     #[inline]
221     fn is_ascii(&self) -> bool {
222         for b in self.iter() {
223             if !b.is_ascii() { return false; }
224         }
225         true
226     }
227 }
228
229 impl<'a> AsciiCast<&'a [Ascii]> for &'a str {
230     #[inline]
231     unsafe fn to_ascii_nocheck(&self) -> &'a [Ascii] {
232         mem::transmute(*self)
233     }
234
235     #[inline]
236     fn is_ascii(&self) -> bool {
237         self.bytes().all(|b| b.is_ascii())
238     }
239 }
240
241 impl AsciiCast<Ascii> for u8 {
242     #[inline]
243     unsafe fn to_ascii_nocheck(&self) -> Ascii {
244         Ascii{ chr: *self }
245     }
246
247     #[inline]
248     fn is_ascii(&self) -> bool {
249         *self & 128 == 0u8
250     }
251 }
252
253 impl AsciiCast<Ascii> for char {
254     #[inline]
255     unsafe fn to_ascii_nocheck(&self) -> Ascii {
256         Ascii{ chr: *self as u8 }
257     }
258
259     #[inline]
260     fn is_ascii(&self) -> bool {
261         *self as u32 - ('\x7F' as u32 & *self as u32) == 0
262     }
263 }
264
265 /// Trait for copyless casting to an ascii vector.
266 pub trait OwnedAsciiCast {
267     /// Check if convertible to ascii
268     fn is_ascii(&self) -> bool;
269
270     /// Take ownership and cast to an ascii vector. Fail on non-ASCII input.
271     #[inline]
272     fn into_ascii(self) -> Vec<Ascii> {
273         assert!(self.is_ascii());
274         unsafe {self.into_ascii_nocheck()}
275     }
276
277     /// Take ownership and cast to an ascii vector. Return None on non-ASCII input.
278     #[inline]
279     fn into_ascii_opt(self) -> Option<Vec<Ascii>> {
280         if self.is_ascii() {
281             Some(unsafe { self.into_ascii_nocheck() })
282         } else {
283             None
284         }
285     }
286
287     /// Take ownership and cast to an ascii vector.
288     /// Does not perform validation checks.
289     unsafe fn into_ascii_nocheck(self) -> Vec<Ascii>;
290 }
291
292 impl OwnedAsciiCast for String {
293     #[inline]
294     fn is_ascii(&self) -> bool {
295         self.as_slice().is_ascii()
296     }
297
298     #[inline]
299     unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
300         let v: Vec<u8> = mem::transmute(self);
301         v.into_ascii_nocheck()
302     }
303 }
304
305 impl OwnedAsciiCast for Vec<u8> {
306     #[inline]
307     fn is_ascii(&self) -> bool {
308         self.as_slice().is_ascii()
309     }
310
311     #[inline]
312     unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
313         mem::transmute(self)
314     }
315 }
316
317 /// Trait for converting an ascii type to a string. Needed to convert
318 /// `&[Ascii]` to `&str`.
319 pub trait AsciiStr {
320     /// Convert to a string.
321     fn as_str_ascii<'a>(&'a self) -> &'a str;
322
323     /// Convert to vector representing a lower cased ascii string.
324     fn to_lower(&self) -> Vec<Ascii>;
325
326     /// Convert to vector representing a upper cased ascii string.
327     fn to_upper(&self) -> Vec<Ascii>;
328
329     /// Compares two Ascii strings ignoring case.
330     fn eq_ignore_case(self, other: &[Ascii]) -> bool;
331 }
332
333 impl<'a> AsciiStr for &'a [Ascii] {
334     #[inline]
335     fn as_str_ascii<'a>(&'a self) -> &'a str {
336         unsafe { mem::transmute(*self) }
337     }
338
339     #[inline]
340     fn to_lower(&self) -> Vec<Ascii> {
341         self.iter().map(|a| a.to_lower()).collect()
342     }
343
344     #[inline]
345     fn to_upper(&self) -> Vec<Ascii> {
346         self.iter().map(|a| a.to_upper()).collect()
347     }
348
349     #[inline]
350     fn eq_ignore_case(self, other: &[Ascii]) -> bool {
351         self.iter().zip(other.iter()).all(|(&a, &b)| a.eq_ignore_case(b))
352     }
353 }
354
355 impl IntoStr for Vec<Ascii> {
356     #[inline]
357     fn into_string(self) -> String {
358         unsafe {
359             let s: &str = mem::transmute(self.as_slice());
360             String::from_str(s)
361         }
362     }
363 }
364
365 /// Trait to convert to an owned byte vector by consuming self
366 pub trait IntoBytes {
367     /// Converts to an owned byte vector by consuming self
368     fn into_bytes(self) -> Vec<u8>;
369 }
370
371 impl IntoBytes for Vec<Ascii> {
372     fn into_bytes(self) -> Vec<u8> {
373         unsafe { mem::transmute(self) }
374     }
375 }
376
377
378 /// Extension methods for ASCII-subset only operations on owned strings
379 pub trait OwnedAsciiExt {
380     /// Convert the string to ASCII upper case:
381     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
382     /// but non-ASCII letters are unchanged.
383     fn into_ascii_upper(self) -> Self;
384
385     /// Convert the string to ASCII lower case:
386     /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
387     /// but non-ASCII letters are unchanged.
388     fn into_ascii_lower(self) -> Self;
389 }
390
391 /// Extension methods for ASCII-subset only operations on string slices
392 pub trait AsciiExt<T> {
393     /// Makes a copy of the string in ASCII upper case:
394     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
395     /// but non-ASCII letters are unchanged.
396     fn to_ascii_upper(&self) -> T;
397
398     /// Makes a copy of the string in ASCII lower case:
399     /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
400     /// but non-ASCII letters are unchanged.
401     fn to_ascii_lower(&self) -> T;
402
403     /// Check that two strings are an ASCII case-insensitive match.
404     /// Same as `to_ascii_lower(a) == to_ascii_lower(b)`,
405     /// but without allocating and copying temporary strings.
406     fn eq_ignore_ascii_case(&self, other: Self) -> bool;
407 }
408
409 impl<'a> AsciiExt<String> for &'a str {
410     #[inline]
411     fn to_ascii_upper(&self) -> String {
412         // Vec<u8>::to_ascii_upper() preserves the UTF-8 invariant.
413         unsafe { str::raw::from_utf8_owned(self.as_bytes().to_ascii_upper()) }
414     }
415
416     #[inline]
417     fn to_ascii_lower(&self) -> String {
418         // Vec<u8>::to_ascii_lower() preserves the UTF-8 invariant.
419         unsafe { str::raw::from_utf8_owned(self.as_bytes().to_ascii_lower()) }
420     }
421
422     #[inline]
423     fn eq_ignore_ascii_case(&self, other: &str) -> bool {
424         self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
425     }
426 }
427
428 impl OwnedAsciiExt for String {
429     #[inline]
430     fn into_ascii_upper(self) -> String {
431         // Vec<u8>::into_ascii_upper() preserves the UTF-8 invariant.
432         unsafe { str::raw::from_utf8_owned(self.into_bytes().into_ascii_upper()) }
433     }
434
435     #[inline]
436     fn into_ascii_lower(self) -> String {
437         // Vec<u8>::into_ascii_lower() preserves the UTF-8 invariant.
438         unsafe { str::raw::from_utf8_owned(self.into_bytes().into_ascii_lower()) }
439     }
440 }
441
442 impl<'a> AsciiExt<Vec<u8>> for &'a [u8] {
443     #[inline]
444     fn to_ascii_upper(&self) -> Vec<u8> {
445         self.iter().map(|&byte| ASCII_UPPER_MAP[byte as uint]).collect()
446     }
447
448     #[inline]
449     fn to_ascii_lower(&self) -> Vec<u8> {
450         self.iter().map(|&byte| ASCII_LOWER_MAP[byte as uint]).collect()
451     }
452
453     #[inline]
454     fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
455         self.len() == other.len() &&
456             self.iter().zip(other.iter()).all(
457             |(byte_self, byte_other)| {
458                 ASCII_LOWER_MAP[*byte_self as uint] ==
459                     ASCII_LOWER_MAP[*byte_other as uint]
460             })
461     }
462 }
463
464 impl OwnedAsciiExt for Vec<u8> {
465     #[inline]
466     fn into_ascii_upper(mut self) -> Vec<u8> {
467         for byte in self.mut_iter() {
468             *byte = ASCII_UPPER_MAP[*byte as uint];
469         }
470         self
471     }
472
473     #[inline]
474     fn into_ascii_lower(mut self) -> Vec<u8> {
475         for byte in self.mut_iter() {
476             *byte = ASCII_LOWER_MAP[*byte as uint];
477         }
478         self
479     }
480 }
481
482
483 pub static ASCII_LOWER_MAP: [u8, ..256] = [
484     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
485     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
486     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
487     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
488     b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
489     b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
490     b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
491     b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
492     b'@',
493
494           b'a', b'b', b'c', b'd', b'e', b'f', b'g',
495     b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
496     b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
497     b'x', b'y', b'z',
498
499                       b'[', b'\\', b']', b'^', b'_',
500     b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g',
501     b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
502     b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
503     b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f,
504     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
505     0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
506     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
507     0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
508     0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
509     0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
510     0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
511     0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
512     0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
513     0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
514     0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
515     0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
516     0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
517     0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
518     0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
519     0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
520 ];
521
522 pub static ASCII_UPPER_MAP: [u8, ..256] = [
523     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
524     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
525     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
526     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
527     b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
528     b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
529     b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
530     b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
531     b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G',
532     b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
533     b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
534     b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_',
535     b'`',
536
537           b'A', b'B', b'C', b'D', b'E', b'F', b'G',
538     b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
539     b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
540     b'X', b'Y', b'Z',
541
542                       b'{', b'|', b'}', b'~', 0x7f,
543     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
544     0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
545     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
546     0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
547     0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
548     0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
549     0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
550     0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
551     0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
552     0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
553     0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
554     0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
555     0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
556     0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
557     0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
558     0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
559 ];
560
561
562 #[cfg(test)]
563 mod tests {
564     use prelude::*;
565     use super::*;
566     use char::from_u32;
567     use vec::Vec;
568     use str::StrSlice;
569
570     macro_rules! v2ascii (
571         ( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
572         (&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
573     )
574
575     macro_rules! vec2ascii (
576         ($($e:expr),*) => (Vec::from_slice([$(Ascii{chr:$e}),*]));
577     )
578
579     #[test]
580     fn test_ascii() {
581         assert_eq!(65u8.to_ascii().to_byte(), 65u8);
582         assert_eq!(65u8.to_ascii().to_char(), 'A');
583         assert_eq!('A'.to_ascii().to_char(), 'A');
584         assert_eq!('A'.to_ascii().to_byte(), 65u8);
585
586         assert_eq!('A'.to_ascii().to_lower().to_char(), 'a');
587         assert_eq!('Z'.to_ascii().to_lower().to_char(), 'z');
588         assert_eq!('a'.to_ascii().to_upper().to_char(), 'A');
589         assert_eq!('z'.to_ascii().to_upper().to_char(), 'Z');
590
591         assert_eq!('@'.to_ascii().to_lower().to_char(), '@');
592         assert_eq!('['.to_ascii().to_lower().to_char(), '[');
593         assert_eq!('`'.to_ascii().to_upper().to_char(), '`');
594         assert_eq!('{'.to_ascii().to_upper().to_char(), '{');
595
596         assert!('0'.to_ascii().is_digit());
597         assert!('9'.to_ascii().is_digit());
598         assert!(!'/'.to_ascii().is_digit());
599         assert!(!':'.to_ascii().is_digit());
600
601         assert!((0x1fu8).to_ascii().is_control());
602         assert!(!' '.to_ascii().is_control());
603         assert!((0x7fu8).to_ascii().is_control());
604
605         assert!("banana".chars().all(|c| c.is_ascii()));
606         assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii()));
607     }
608
609     #[test]
610     fn test_ascii_vec() {
611         let test = &[40u8, 32u8, 59u8];
612         let b: &[_] = v2ascii!([40, 32, 59]);
613         assert_eq!(test.to_ascii(), b);
614         assert_eq!("( ;".to_ascii(), b);
615         let v = vec![40u8, 32u8, 59u8];
616         assert_eq!(v.as_slice().to_ascii(), b);
617         assert_eq!("( ;".to_string().as_slice().to_ascii(), b);
618
619         assert_eq!("abCDef&?#".to_ascii().to_lower().into_string(), "abcdef&?#".to_string());
620         assert_eq!("abCDef&?#".to_ascii().to_upper().into_string(), "ABCDEF&?#".to_string());
621
622         assert_eq!("".to_ascii().to_lower().into_string(), "".to_string());
623         assert_eq!("YMCA".to_ascii().to_lower().into_string(), "ymca".to_string());
624         assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_string(), "ABCDEFXYZ:.;".to_string());
625
626         assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii()));
627
628         assert!("".is_ascii());
629         assert!("a".is_ascii());
630         assert!(!"\u2009".is_ascii());
631
632     }
633
634     #[test]
635     fn test_ascii_vec_ng() {
636         assert_eq!("abCDef&?#".to_ascii().to_lower().into_string(), "abcdef&?#".to_string());
637         assert_eq!("abCDef&?#".to_ascii().to_upper().into_string(), "ABCDEF&?#".to_string());
638         assert_eq!("".to_ascii().to_lower().into_string(), "".to_string());
639         assert_eq!("YMCA".to_ascii().to_lower().into_string(), "ymca".to_string());
640         assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_string(), "ABCDEFXYZ:.;".to_string());
641     }
642
643     #[test]
644     fn test_owned_ascii_vec() {
645         assert_eq!(("( ;".to_string()).into_ascii(), vec2ascii![40, 32, 59]);
646         assert_eq!((vec![40u8, 32u8, 59u8]).into_ascii(), vec2ascii![40, 32, 59]);
647     }
648
649     #[test]
650     fn test_ascii_as_str() {
651         let v = v2ascii!([40, 32, 59]);
652         assert_eq!(v.as_str_ascii(), "( ;");
653     }
654
655     #[test]
656     fn test_ascii_into_string() {
657         assert_eq!(vec2ascii![40, 32, 59].into_string(), "( ;".to_string());
658         assert_eq!(vec2ascii!(40, 32, 59).into_string(), "( ;".to_string());
659     }
660
661     #[test]
662     fn test_ascii_to_bytes() {
663         assert_eq!(vec2ascii![40, 32, 59].into_bytes(), vec![40u8, 32u8, 59u8]);
664     }
665
666     #[test] #[should_fail]
667     fn test_ascii_vec_fail_u8_slice()  { (&[127u8, 128u8, 255u8]).to_ascii(); }
668
669     #[test] #[should_fail]
670     fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); }
671
672     #[test] #[should_fail]
673     fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); }
674
675     #[test] #[should_fail]
676     fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
677
678     #[test]
679     fn test_opt() {
680         assert_eq!(65u8.to_ascii_opt(), Some(Ascii { chr: 65u8 }));
681         assert_eq!(255u8.to_ascii_opt(), None);
682
683         assert_eq!('A'.to_ascii_opt(), Some(Ascii { chr: 65u8 }));
684         assert_eq!('λ'.to_ascii_opt(), None);
685
686         assert_eq!("zoä华".to_ascii_opt(), None);
687
688         let test1 = &[127u8, 128u8, 255u8];
689         assert_eq!((test1).to_ascii_opt(), None);
690
691         let v = [40u8, 32u8, 59u8];
692         let v2: &[_] = v2ascii!(&[40, 32, 59]);
693         assert_eq!(v.to_ascii_opt(), Some(v2));
694         let v = [127u8, 128u8, 255u8];
695         assert_eq!(v.to_ascii_opt(), None);
696
697         let v = "( ;";
698         assert_eq!(v.to_ascii_opt(), Some(v2));
699         assert_eq!("zoä华".to_ascii_opt(), None);
700
701         assert_eq!((vec![40u8, 32u8, 59u8]).into_ascii_opt(), Some(vec2ascii![40, 32, 59]));
702         assert_eq!((vec![127u8, 128u8, 255u8]).into_ascii_opt(), None);
703
704         assert_eq!(("( ;".to_string()).into_ascii_opt(), Some(vec2ascii![40, 32, 59]));
705         assert_eq!(("zoä华".to_string()).into_ascii_opt(), None);
706     }
707
708     #[test]
709     fn test_to_ascii_upper() {
710         assert_eq!("url()URL()uRl()ürl".to_ascii_upper(), "URL()URL()URL()üRL".to_string());
711         assert_eq!("hıKß".to_ascii_upper(), "HıKß".to_string());
712
713         let mut i = 0;
714         while i <= 500 {
715             let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
716                         else { i };
717             assert_eq!((from_u32(i).unwrap()).to_string().as_slice().to_ascii_upper(),
718                        (from_u32(upper).unwrap()).to_string())
719             i += 1;
720         }
721     }
722
723     #[test]
724     fn test_to_ascii_lower() {
725         assert_eq!("url()URL()uRl()Ürl".to_ascii_lower(), "url()url()url()Ürl".to_string());
726         // Dotted capital I, Kelvin sign, Sharp S.
727         assert_eq!("HİKß".to_ascii_lower(), "hİKß".to_string());
728
729         let mut i = 0;
730         while i <= 500 {
731             let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
732                         else { i };
733             assert_eq!((from_u32(i).unwrap()).to_string().as_slice().to_ascii_lower(),
734                        (from_u32(lower).unwrap()).to_string())
735             i += 1;
736         }
737     }
738
739     #[test]
740     fn test_into_ascii_upper() {
741         assert_eq!(("url()URL()uRl()ürl".to_string()).into_ascii_upper(),
742                    "URL()URL()URL()üRL".to_string());
743         assert_eq!(("hıKß".to_string()).into_ascii_upper(), "HıKß".to_string());
744
745         let mut i = 0;
746         while i <= 500 {
747             let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
748                         else { i };
749             assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_upper(),
750                        (from_u32(upper).unwrap()).to_string())
751             i += 1;
752         }
753     }
754
755     #[test]
756     fn test_into_ascii_lower() {
757         assert_eq!(("url()URL()uRl()Ürl".to_string()).into_ascii_lower(),
758                    "url()url()url()Ürl".to_string());
759         // Dotted capital I, Kelvin sign, Sharp S.
760         assert_eq!(("HİKß".to_string()).into_ascii_lower(), "hİKß".to_string());
761
762         let mut i = 0;
763         while i <= 500 {
764             let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
765                         else { i };
766             assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_lower(),
767                        (from_u32(lower).unwrap()).to_string())
768             i += 1;
769         }
770     }
771
772     #[test]
773     fn test_eq_ignore_ascii_case() {
774         assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl"));
775         assert!(!"Ürl".eq_ignore_ascii_case("ürl"));
776         // Dotted capital I, Kelvin sign, Sharp S.
777         assert!("HİKß".eq_ignore_ascii_case("hİKß"));
778         assert!(!"İ".eq_ignore_ascii_case("i"));
779         assert!(!"K".eq_ignore_ascii_case("k"));
780         assert!(!"ß".eq_ignore_ascii_case("s"));
781
782         let mut i = 0;
783         while i <= 500 {
784             let c = i;
785             let lower = if 'A' as u32 <= c && c <= 'Z' as u32 { c + 'a' as u32 - 'A' as u32 }
786                         else { c };
787             assert!((from_u32(i).unwrap()).to_string().as_slice().eq_ignore_ascii_case(
788                     (from_u32(lower).unwrap()).to_string().as_slice()));
789             i += 1;
790         }
791     }
792
793     #[test]
794     fn test_to_string() {
795         let s = Ascii{ chr: b't' }.to_string();
796         assert_eq!(s, "t".to_string());
797     }
798
799     #[test]
800     fn test_show() {
801         let c = Ascii { chr: b't' };
802         assert_eq!(format!("{}", c), "t".to_string());
803     }
804 }