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, AsSlice};
23 use str::{Str, StrSlice};
24 use string::{mod, String};
25 use to_string::IntoStr;
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 }
33 /// Converts an ascii character into a `u8`.
35 pub fn to_byte(self) -> u8 {
39 /// Converts an ascii character into a `char`.
41 pub fn to_char(self) -> char {
45 /// Convert to lowercase.
47 pub fn to_lowercase(self) -> Ascii {
48 Ascii{chr: ASCII_LOWER_MAP[self.chr as uint]}
51 /// Convert to uppercase.
53 pub fn to_uppercase(self) -> Ascii {
54 Ascii{chr: ASCII_UPPER_MAP[self.chr as uint]}
57 /// Compares two ascii characters of equality, ignoring case.
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]
63 // the following methods are like ctype, and the implementation is inspired by musl
65 /// Check if the character is a letter (a-z, A-Z)
67 pub fn is_alphabetic(&self) -> bool {
68 (self.chr >= 0x41 && self.chr <= 0x5A) || (self.chr >= 0x61 && self.chr <= 0x7A)
71 /// Check if the character is a number (0-9)
73 pub fn is_digit(&self) -> bool {
74 self.chr >= 0x30 && self.chr <= 0x39
77 /// Check if the character is a letter or number
79 pub fn is_alphanumeric(&self) -> bool {
80 self.is_alphabetic() || self.is_digit()
83 /// Check if the character is a space or horizontal tab
85 pub fn is_blank(&self) -> bool {
86 self.chr == b' ' || self.chr == b'\t'
89 /// Check if the character is a control character
91 pub fn is_control(&self) -> bool {
92 self.chr < 0x20 || self.chr == 0x7F
95 /// Checks if the character is printable (except space)
97 pub fn is_graph(&self) -> bool {
98 (self.chr - 0x21) < 0x5E
101 /// Checks if the character is printable (including space)
103 pub fn is_print(&self) -> bool {
104 (self.chr - 0x20) < 0x5F
107 /// Checks if the character is lowercase
109 pub fn is_lowercase(&self) -> bool {
110 (self.chr - b'a') < 26
113 /// Checks if the character is uppercase
115 pub fn is_uppercase(&self) -> bool {
116 (self.chr - b'A') < 26
119 /// Checks if the character is punctuation
121 pub fn is_punctuation(&self) -> bool {
122 self.is_graph() && !self.is_alphanumeric()
125 /// Checks if the character is a valid hex digit
127 pub fn is_hex(&self) -> bool {
128 self.is_digit() || ((self.chr | 32u8) - b'a') < 6
132 impl<'a> fmt::Show for Ascii {
133 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134 (self.chr as char).fmt(f)
138 /// Trait for converting into an ascii type.
139 pub trait AsciiCast<T> {
140 /// Convert to an ascii type, fail on non-ASCII input.
142 fn to_ascii(&self) -> T {
143 assert!(self.is_ascii());
144 unsafe {self.to_ascii_nocheck()}
147 /// Convert to an ascii type, return None on non-ASCII input.
149 fn to_ascii_opt(&self) -> Option<T> {
151 Some(unsafe { self.to_ascii_nocheck() })
157 /// Convert to an ascii type, not doing any range asserts
158 unsafe fn to_ascii_nocheck(&self) -> T;
160 /// Check if convertible to ascii
161 fn is_ascii(&self) -> bool;
164 impl<'a> AsciiCast<&'a[Ascii]> for &'a [u8] {
166 unsafe fn to_ascii_nocheck(&self) -> &'a[Ascii] {
167 mem::transmute(*self)
171 fn is_ascii(&self) -> bool {
172 for b in self.iter() {
173 if !b.is_ascii() { return false; }
179 impl<'a> AsciiCast<&'a [Ascii]> for &'a str {
181 unsafe fn to_ascii_nocheck(&self) -> &'a [Ascii] {
182 mem::transmute(*self)
186 fn is_ascii(&self) -> bool {
187 self.bytes().all(|b| b.is_ascii())
191 impl AsciiCast<Ascii> for u8 {
193 unsafe fn to_ascii_nocheck(&self) -> Ascii {
198 fn is_ascii(&self) -> bool {
203 impl AsciiCast<Ascii> for char {
205 unsafe fn to_ascii_nocheck(&self) -> Ascii {
206 Ascii{ chr: *self as u8 }
210 fn is_ascii(&self) -> bool {
211 *self as u32 - ('\x7F' as u32 & *self as u32) == 0
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;
220 /// Take ownership and cast to an ascii vector. Fail on non-ASCII input.
222 fn into_ascii(self) -> Vec<Ascii> {
223 assert!(self.is_ascii());
224 unsafe {self.into_ascii_nocheck()}
227 /// Take ownership and cast to an ascii vector. Return None on non-ASCII input.
229 fn into_ascii_opt(self) -> Option<Vec<Ascii>> {
231 Some(unsafe { self.into_ascii_nocheck() })
237 /// Take ownership and cast to an ascii vector.
238 /// Does not perform validation checks.
239 unsafe fn into_ascii_nocheck(self) -> Vec<Ascii>;
242 impl OwnedAsciiCast for String {
244 fn is_ascii(&self) -> bool {
245 self.as_slice().is_ascii()
249 unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
250 let v: Vec<u8> = mem::transmute(self);
251 v.into_ascii_nocheck()
255 impl OwnedAsciiCast for Vec<u8> {
257 fn is_ascii(&self) -> bool {
258 self.as_slice().is_ascii()
262 unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
267 /// Trait for converting an ascii type to a string. Needed to convert
268 /// `&[Ascii]` to `&str`.
270 /// Convert to a string.
271 fn as_str_ascii<'a>(&'a self) -> &'a str;
273 /// Deprecated: use `to_lowercase`
274 #[deprecated="renamed `to_lowercase`"]
275 fn to_lower(&self) -> Vec<Ascii>;
277 /// Convert to vector representing a lower cased ascii string.
278 fn to_lowercase(&self) -> Vec<Ascii>;
280 /// Deprecated: use `to_uppercase`
281 #[deprecated="renamed `to_uppercase`"]
282 fn to_upper(&self) -> Vec<Ascii>;
284 /// Convert to vector representing a upper cased ascii string.
285 fn to_uppercase(&self) -> Vec<Ascii>;
287 /// Compares two Ascii strings ignoring case.
288 fn eq_ignore_case(self, other: &[Ascii]) -> bool;
291 impl<'a> AsciiStr for &'a [Ascii] {
293 fn as_str_ascii<'a>(&'a self) -> &'a str {
294 unsafe { mem::transmute(*self) }
298 fn to_lower(&self) -> Vec<Ascii> {
303 fn to_lowercase(&self) -> Vec<Ascii> {
304 self.iter().map(|a| a.to_lowercase()).collect()
308 fn to_upper(&self) -> Vec<Ascii> {
313 fn to_uppercase(&self) -> Vec<Ascii> {
314 self.iter().map(|a| a.to_uppercase()).collect()
318 fn eq_ignore_case(self, other: &[Ascii]) -> bool {
319 self.iter().zip(other.iter()).all(|(&a, &b)| a.eq_ignore_case(b))
323 impl IntoStr for Vec<Ascii> {
325 fn into_string(self) -> String {
327 let s: &str = mem::transmute(self.as_slice());
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>;
339 impl IntoBytes for Vec<Ascii> {
340 fn into_bytes(self) -> Vec<u8> {
341 unsafe { mem::transmute(self) }
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;
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;
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;
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;
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;
377 impl<'a> AsciiExt<String> for &'a str {
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()) }
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()) }
391 fn eq_ignore_ascii_case(&self, other: &str) -> bool {
392 self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
396 impl OwnedAsciiExt for String {
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()) }
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()) }
410 impl<'a> AsciiExt<Vec<u8>> for &'a [u8] {
412 fn to_ascii_upper(&self) -> Vec<u8> {
413 self.iter().map(|&byte| ASCII_UPPER_MAP[byte as uint]).collect()
417 fn to_ascii_lower(&self) -> Vec<u8> {
418 self.iter().map(|&byte| ASCII_LOWER_MAP[byte as uint]).collect()
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]
432 impl OwnedAsciiExt for Vec<u8> {
434 fn into_ascii_upper(mut self) -> Vec<u8> {
435 for byte in self.iter_mut() {
436 *byte = ASCII_UPPER_MAP[*byte as uint];
442 fn into_ascii_lower(mut self) -> Vec<u8> {
443 for byte in self.iter_mut() {
444 *byte = ASCII_LOWER_MAP[*byte as uint];
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'?',
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',
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,
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'_',
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',
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,
537 macro_rules! v2ascii (
538 ( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
539 (&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
542 macro_rules! vec2ascii (
543 ($($e:expr),*) => ([$(Ascii{chr:$e}),*].to_vec());
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);
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');
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(), '{');
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());
568 assert!((0x1fu8).to_ascii().is_control());
569 assert!(!' '.to_ascii().is_control());
570 assert!((0x7fu8).to_ascii().is_control());
572 assert!("banana".chars().all(|c| c.is_ascii()));
573 assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii()));
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);
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());
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());
594 assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii()));
596 assert!("".is_ascii());
597 assert!("a".is_ascii());
598 assert!(!"\u2009".is_ascii());
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());
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]);
619 fn test_ascii_as_str() {
620 let v = v2ascii!([40, 32, 59]);
621 assert_eq!(v.as_str_ascii(), "( ;");
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());
631 fn test_ascii_to_bytes() {
632 assert_eq!(vec2ascii![40, 32, 59].into_bytes(), vec![40u8, 32u8, 59u8]);
635 #[test] #[should_fail]
636 fn test_ascii_vec_fail_u8_slice() { (&[127u8, 128u8, 255u8]).to_ascii(); }
638 #[test] #[should_fail]
639 fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); }
641 #[test] #[should_fail]
642 fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); }
644 #[test] #[should_fail]
645 fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
649 assert_eq!(65u8.to_ascii_opt(), Some(Ascii { chr: 65u8 }));
650 assert_eq!(255u8.to_ascii_opt(), None);
652 assert_eq!('A'.to_ascii_opt(), Some(Ascii { chr: 65u8 }));
653 assert_eq!('λ'.to_ascii_opt(), None);
655 assert_eq!("zoä华".to_ascii_opt(), None);
657 let test1 = &[127u8, 128u8, 255u8];
658 assert_eq!((test1).to_ascii_opt(), None);
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);
667 assert_eq!(v.to_ascii_opt(), Some(v2));
668 assert_eq!("zoä华".to_ascii_opt(), None);
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);
673 assert_eq!(("( ;".to_string()).into_ascii_opt(), Some(vec2ascii![40, 32, 59]));
674 assert_eq!(("zoä华".to_string()).into_ascii_opt(), None);
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());
684 let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
686 assert_eq!((from_u32(i).unwrap()).to_string().as_slice().to_ascii_upper(),
687 (from_u32(upper).unwrap()).to_string())
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());
700 let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
702 assert_eq!((from_u32(i).unwrap()).to_string().as_slice().to_ascii_lower(),
703 (from_u32(lower).unwrap()).to_string())
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());
716 let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
718 assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_upper(),
719 (from_u32(upper).unwrap()).to_string())
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());
733 let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
735 assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_lower(),
736 (from_u32(lower).unwrap()).to_string())
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"));
754 let lower = if 'A' as u32 <= c && c <= 'Z' as u32 { c + 'a' as u32 - 'A' as u32 }
756 assert!((from_u32(i).unwrap()).to_string().as_slice().eq_ignore_ascii_case(
757 (from_u32(lower).unwrap()).to_string().as_slice()));
763 fn test_to_string() {
764 let s = Ascii{ chr: b't' }.to_string();
765 assert_eq!(s, "t".to_string());
770 let c = Ascii { chr: b't' };
771 assert_eq!(format!("{}", c), "t".to_string());