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