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