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.
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.
11 // ignore-lexer-test FIXME #15679
13 //! Operations on ASCII strings and characters
17 use collections::Collection;
21 use option::{Option, Some, None};
22 use slice::{ImmutableSlice, MutableSlice, Slice};
23 use str::{Str, StrSlice};
26 use to_string::IntoStr;
29 #[deprecated="this trait has been renamed to `AsciiExt`"]
30 pub use self::AsciiExt as StrAsciiExt;
32 #[deprecated="this trait has been renamed to `OwnedAsciiExt`"]
33 pub use self::OwnedAsciiExt as OwnedStrAsciiExt;
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 }
41 /// Converts an ascii character into a `u8`.
43 pub fn to_byte(self) -> u8 {
47 /// Converts an ascii character into a `char`.
49 pub fn to_char(self) -> char {
55 #[deprecated="renamed to `to_lowercase`"]
56 pub fn to_lower(self) -> Ascii {
60 /// Convert to lowercase.
62 pub fn to_lowercase(self) -> Ascii {
63 Ascii{chr: ASCII_LOWER_MAP[self.chr as uint]}
68 #[deprecated="renamed to `to_uppercase`"]
69 pub fn to_upper(self) -> Ascii {
73 /// Convert to uppercase.
75 pub fn to_uppercase(self) -> Ascii {
76 Ascii{chr: ASCII_UPPER_MAP[self.chr as uint]}
79 /// Compares two ascii characters of equality, ignoring case.
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]
85 // the following methods are like ctype, and the implementation is inspired by musl
89 #[deprecated="renamed to `is_alphabetic`"]
90 pub fn is_alpha(&self) -> bool {
94 /// Check if the character is a letter (a-z, A-Z)
96 pub fn is_alphabetic(&self) -> bool {
97 (self.chr >= 0x41 && self.chr <= 0x5A) || (self.chr >= 0x61 && self.chr <= 0x7A)
100 /// Check if the character is a number (0-9)
102 pub fn is_digit(&self) -> bool {
103 self.chr >= 0x30 && self.chr <= 0x39
107 #[allow(missing_doc)]
108 #[deprecated="renamed to `is_alphanumeric`"]
109 pub fn is_alnum(&self) -> bool {
110 self.is_alphanumeric()
113 /// Check if the character is a letter or number
115 pub fn is_alphanumeric(&self) -> bool {
116 self.is_alpha() || self.is_digit()
119 /// Check if the character is a space or horizontal tab
121 pub fn is_blank(&self) -> bool {
122 self.chr == b' ' || self.chr == b'\t'
125 /// Check if the character is a control character
127 pub fn is_control(&self) -> bool {
128 self.chr < 0x20 || self.chr == 0x7F
131 /// Checks if the character is printable (except space)
133 pub fn is_graph(&self) -> bool {
134 (self.chr - 0x21) < 0x5E
137 /// Checks if the character is printable (including space)
139 pub fn is_print(&self) -> bool {
140 (self.chr - 0x20) < 0x5F
144 #[allow(missing_doc)]
145 #[deprecated="renamed to `is_lowercase`"]
146 pub fn is_lower(&self) -> bool {
150 /// Checks if the character is lowercase
152 pub fn is_lowercase(&self) -> bool {
153 (self.chr - b'a') < 26
157 #[allow(missing_doc)]
158 #[deprecated="renamed to `is_uppercase`"]
159 pub fn is_upper(&self) -> bool {
163 /// Checks if the character is uppercase
165 pub fn is_uppercase(&self) -> bool {
166 (self.chr - b'A') < 26
169 /// Checks if the character is punctuation
171 pub fn is_punctuation(&self) -> bool {
172 self.is_graph() && !self.is_alnum()
175 /// Checks if the character is a valid hex digit
177 pub fn is_hex(&self) -> bool {
178 self.is_digit() || ((self.chr | 32u8) - b'a') < 6
182 impl<'a> fmt::Show for Ascii {
183 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
184 (self.chr as char).fmt(f)
188 /// Trait for converting into an ascii type.
189 pub trait AsciiCast<T> {
190 /// Convert to an ascii type, fail on non-ASCII input.
192 fn to_ascii(&self) -> T {
193 assert!(self.is_ascii());
194 unsafe {self.to_ascii_nocheck()}
197 /// Convert to an ascii type, return None on non-ASCII input.
199 fn to_ascii_opt(&self) -> Option<T> {
201 Some(unsafe { self.to_ascii_nocheck() })
207 /// Convert to an ascii type, not doing any range asserts
208 unsafe fn to_ascii_nocheck(&self) -> T;
210 /// Check if convertible to ascii
211 fn is_ascii(&self) -> bool;
214 impl<'a> AsciiCast<&'a[Ascii]> for &'a [u8] {
216 unsafe fn to_ascii_nocheck(&self) -> &'a[Ascii] {
217 mem::transmute(*self)
221 fn is_ascii(&self) -> bool {
222 for b in self.iter() {
223 if !b.is_ascii() { return false; }
229 impl<'a> AsciiCast<&'a [Ascii]> for &'a str {
231 unsafe fn to_ascii_nocheck(&self) -> &'a [Ascii] {
232 mem::transmute(*self)
236 fn is_ascii(&self) -> bool {
237 self.bytes().all(|b| b.is_ascii())
241 impl AsciiCast<Ascii> for u8 {
243 unsafe fn to_ascii_nocheck(&self) -> Ascii {
248 fn is_ascii(&self) -> bool {
253 impl AsciiCast<Ascii> for char {
255 unsafe fn to_ascii_nocheck(&self) -> Ascii {
256 Ascii{ chr: *self as u8 }
260 fn is_ascii(&self) -> bool {
261 *self as u32 - ('\x7F' as u32 & *self as u32) == 0
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;
270 /// Take ownership and cast to an ascii vector. Fail on non-ASCII input.
272 fn into_ascii(self) -> Vec<Ascii> {
273 assert!(self.is_ascii());
274 unsafe {self.into_ascii_nocheck()}
277 /// Take ownership and cast to an ascii vector. Return None on non-ASCII input.
279 fn into_ascii_opt(self) -> Option<Vec<Ascii>> {
281 Some(unsafe { self.into_ascii_nocheck() })
287 /// Take ownership and cast to an ascii vector.
288 /// Does not perform validation checks.
289 unsafe fn into_ascii_nocheck(self) -> Vec<Ascii>;
292 impl OwnedAsciiCast for String {
294 fn is_ascii(&self) -> bool {
295 self.as_slice().is_ascii()
299 unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
300 let v: Vec<u8> = mem::transmute(self);
301 v.into_ascii_nocheck()
305 impl OwnedAsciiCast for Vec<u8> {
307 fn is_ascii(&self) -> bool {
308 self.as_slice().is_ascii()
312 unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
317 /// Trait for converting an ascii type to a string. Needed to convert
318 /// `&[Ascii]` to `&str`.
320 /// Convert to a string.
321 fn as_str_ascii<'a>(&'a self) -> &'a str;
323 /// Convert to vector representing a lower cased ascii string.
324 fn to_lower(&self) -> Vec<Ascii>;
326 /// Convert to vector representing a upper cased ascii string.
327 fn to_upper(&self) -> Vec<Ascii>;
329 /// Compares two Ascii strings ignoring case.
330 fn eq_ignore_case(self, other: &[Ascii]) -> bool;
333 impl<'a> AsciiStr for &'a [Ascii] {
335 fn as_str_ascii<'a>(&'a self) -> &'a str {
336 unsafe { mem::transmute(*self) }
340 fn to_lower(&self) -> Vec<Ascii> {
341 self.iter().map(|a| a.to_lower()).collect()
345 fn to_upper(&self) -> Vec<Ascii> {
346 self.iter().map(|a| a.to_upper()).collect()
350 fn eq_ignore_case(self, other: &[Ascii]) -> bool {
351 self.iter().zip(other.iter()).all(|(&a, &b)| a.eq_ignore_case(b))
355 impl IntoStr for Vec<Ascii> {
357 fn into_string(self) -> String {
359 let s: &str = mem::transmute(self.as_slice());
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>;
371 impl IntoBytes for Vec<Ascii> {
372 fn into_bytes(self) -> Vec<u8> {
373 unsafe { mem::transmute(self) }
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;
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;
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;
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;
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;
409 impl<'a> AsciiExt<String> for &'a str {
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()) }
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()) }
423 fn eq_ignore_ascii_case(&self, other: &str) -> bool {
424 self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
428 impl OwnedAsciiExt for String {
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()) }
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()) }
442 impl<'a> AsciiExt<Vec<u8>> for &'a [u8] {
444 fn to_ascii_upper(&self) -> Vec<u8> {
445 self.iter().map(|&byte| ASCII_UPPER_MAP[byte as uint]).collect()
449 fn to_ascii_lower(&self) -> Vec<u8> {
450 self.iter().map(|&byte| ASCII_LOWER_MAP[byte as uint]).collect()
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]
464 impl OwnedAsciiExt for Vec<u8> {
466 fn into_ascii_upper(mut self) -> Vec<u8> {
467 for byte in self.mut_iter() {
468 *byte = ASCII_UPPER_MAP[*byte as uint];
474 fn into_ascii_lower(mut self) -> Vec<u8> {
475 for byte in self.mut_iter() {
476 *byte = ASCII_LOWER_MAP[*byte as uint];
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'?',
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',
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,
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'_',
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',
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,
570 macro_rules! v2ascii (
571 ( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
572 (&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
575 macro_rules! vec2ascii (
576 ($($e:expr),*) => (Vec::from_slice([$(Ascii{chr:$e}),*]));
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);
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');
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(), '{');
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());
601 assert!((0x1fu8).to_ascii().is_control());
602 assert!(!' '.to_ascii().is_control());
603 assert!((0x7fu8).to_ascii().is_control());
605 assert!("banana".chars().all(|c| c.is_ascii()));
606 assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii()));
610 fn test_ascii_vec() {
611 let test = &[40u8, 32u8, 59u8];
612 assert_eq!(test.to_ascii(), v2ascii!([40, 32, 59]));
613 assert_eq!("( ;".to_ascii(), v2ascii!([40, 32, 59]));
614 let v = vec![40u8, 32u8, 59u8];
615 assert_eq!(v.as_slice().to_ascii(), v2ascii!([40, 32, 59]));
616 assert_eq!("( ;".to_string().as_slice().to_ascii(), v2ascii!([40, 32, 59]));
618 assert_eq!("abCDef&?#".to_ascii().to_lower().into_string(), "abcdef&?#".to_string());
619 assert_eq!("abCDef&?#".to_ascii().to_upper().into_string(), "ABCDEF&?#".to_string());
621 assert_eq!("".to_ascii().to_lower().into_string(), "".to_string());
622 assert_eq!("YMCA".to_ascii().to_lower().into_string(), "ymca".to_string());
623 assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_string(), "ABCDEFXYZ:.;".to_string());
625 assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii()));
627 assert!("".is_ascii());
628 assert!("a".is_ascii());
629 assert!(!"\u2009".is_ascii());
634 fn test_ascii_vec_ng() {
635 assert_eq!("abCDef&?#".to_ascii().to_lower().into_string(), "abcdef&?#".to_string());
636 assert_eq!("abCDef&?#".to_ascii().to_upper().into_string(), "ABCDEF&?#".to_string());
637 assert_eq!("".to_ascii().to_lower().into_string(), "".to_string());
638 assert_eq!("YMCA".to_ascii().to_lower().into_string(), "ymca".to_string());
639 assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_string(), "ABCDEFXYZ:.;".to_string());
643 fn test_owned_ascii_vec() {
644 assert_eq!(("( ;".to_string()).into_ascii(), vec2ascii![40, 32, 59]);
645 assert_eq!((vec![40u8, 32u8, 59u8]).into_ascii(), vec2ascii![40, 32, 59]);
649 fn test_ascii_as_str() {
650 let v = v2ascii!([40, 32, 59]);
651 assert_eq!(v.as_str_ascii(), "( ;");
655 fn test_ascii_into_string() {
656 assert_eq!(vec2ascii![40, 32, 59].into_string(), "( ;".to_string());
657 assert_eq!(vec2ascii!(40, 32, 59).into_string(), "( ;".to_string());
661 fn test_ascii_to_bytes() {
662 assert_eq!(vec2ascii![40, 32, 59].into_bytes(), vec![40u8, 32u8, 59u8]);
665 #[test] #[should_fail]
666 fn test_ascii_vec_fail_u8_slice() { (&[127u8, 128u8, 255u8]).to_ascii(); }
668 #[test] #[should_fail]
669 fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); }
671 #[test] #[should_fail]
672 fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); }
674 #[test] #[should_fail]
675 fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
679 assert_eq!(65u8.to_ascii_opt(), Some(Ascii { chr: 65u8 }));
680 assert_eq!(255u8.to_ascii_opt(), None);
682 assert_eq!('A'.to_ascii_opt(), Some(Ascii { chr: 65u8 }));
683 assert_eq!('λ'.to_ascii_opt(), None);
685 assert_eq!("zoä华".to_ascii_opt(), None);
687 let test1 = &[127u8, 128u8, 255u8];
688 assert_eq!((test1).to_ascii_opt(), None);
690 let v = [40u8, 32u8, 59u8];
691 let v2 = v2ascii!(&[40, 32, 59]);
692 assert_eq!(v.to_ascii_opt(), Some(v2));
693 let v = [127u8, 128u8, 255u8];
694 assert_eq!(v.to_ascii_opt(), None);
697 let v2 = v2ascii!(&[40, 32, 59]);
698 assert_eq!(v.to_ascii_opt(), Some(v2));
699 assert_eq!("zoä华".to_ascii_opt(), None);
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);
704 assert_eq!(("( ;".to_string()).into_ascii_opt(), Some(vec2ascii![40, 32, 59]));
705 assert_eq!(("zoä华".to_string()).into_ascii_opt(), None);
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());
715 let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
717 assert_eq!((from_u32(i).unwrap()).to_string().as_slice().to_ascii_upper(),
718 (from_u32(upper).unwrap()).to_string())
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());
731 let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
733 assert_eq!((from_u32(i).unwrap()).to_string().as_slice().to_ascii_lower(),
734 (from_u32(lower).unwrap()).to_string())
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());
747 let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
749 assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_upper(),
750 (from_u32(upper).unwrap()).to_string())
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());
764 let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
766 assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_lower(),
767 (from_u32(lower).unwrap()).to_string())
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"));
785 let lower = if 'A' as u32 <= c && c <= 'Z' as u32 { c + 'a' as u32 - 'A' as u32 }
787 assert!((from_u32(i).unwrap()).to_string().as_slice().eq_ignore_ascii_case(
788 (from_u32(lower).unwrap()).to_string().as_slice()));
794 fn test_to_string() {
795 let s = Ascii{ chr: b't' }.to_string();
796 assert_eq!(s, "t".to_string());
801 let c = Ascii { chr: b't' };
802 assert_eq!(format!("{}", c), "t".to_string());