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