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::{ImmutableVector, MutableVector, Vector};
23 use str::{OwnedStr, Str, StrAllocating, StrSlice};
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 {
47 #[deprecated="renamed to `to_lowercase`"]
48 pub fn to_lower(self) -> Ascii {
52 /// Convert to lowercase.
54 pub fn to_lowercase(self) -> Ascii {
55 Ascii{chr: ASCII_LOWER_MAP[self.chr as uint]}
60 #[deprecated="renamed to `to_uppercase`"]
61 pub fn to_upper(self) -> Ascii {
65 /// Convert to uppercase.
67 pub fn to_uppercase(self) -> Ascii {
68 Ascii{chr: ASCII_UPPER_MAP[self.chr as uint]}
71 /// Compares two ascii characters of equality, ignoring case.
73 pub fn eq_ignore_case(self, other: Ascii) -> bool {
74 ASCII_LOWER_MAP[self.chr as uint] == ASCII_LOWER_MAP[other.chr as uint]
77 // the following methods are like ctype, and the implementation is inspired by musl
81 #[deprecated="renamed to `is_alphabetic`"]
82 pub fn is_alpha(&self) -> bool {
86 /// Check if the character is a letter (a-z, A-Z)
88 pub fn is_alphabetic(&self) -> bool {
89 (self.chr >= 0x41 && self.chr <= 0x5A) || (self.chr >= 0x61 && self.chr <= 0x7A)
92 /// Check if the character is a number (0-9)
94 pub fn is_digit(&self) -> bool {
95 self.chr >= 0x30 && self.chr <= 0x39
100 #[deprecated="renamed to `is_alphanumeric`"]
101 pub fn is_alnum(&self) -> bool {
102 self.is_alphanumeric()
105 /// Check if the character is a letter or number
107 pub fn is_alphanumeric(&self) -> bool {
108 self.is_alpha() || self.is_digit()
111 /// Check if the character is a space or horizontal tab
113 pub fn is_blank(&self) -> bool {
114 self.chr == ' ' as u8 || self.chr == '\t' as u8
117 /// Check if the character is a control character
119 pub fn is_control(&self) -> bool {
120 self.chr < 0x20 || self.chr == 0x7F
123 /// Checks if the character is printable (except space)
125 pub fn is_graph(&self) -> bool {
126 (self.chr - 0x21) < 0x5E
129 /// Checks if the character is printable (including space)
131 pub fn is_print(&self) -> bool {
132 (self.chr - 0x20) < 0x5F
136 #[allow(missing_doc)]
137 #[deprecated="renamed to `is_lowercase`"]
138 pub fn is_lower(&self) -> bool {
142 /// Checks if the character is lowercase
144 pub fn is_lowercase(&self) -> bool {
145 (self.chr - 'a' as u8) < 26
149 #[allow(missing_doc)]
150 #[deprecated="renamed to `is_uppercase`"]
151 pub fn is_upper(&self) -> bool {
155 /// Checks if the character is uppercase
157 pub fn is_uppercase(&self) -> bool {
158 (self.chr - 'A' as u8) < 26
161 /// Checks if the character is punctuation
163 pub fn is_punctuation(&self) -> bool {
164 self.is_graph() && !self.is_alnum()
167 /// Checks if the character is a valid hex digit
169 pub fn is_hex(&self) -> bool {
170 self.is_digit() || ((self.chr | 32u8) - 'a' as u8) < 6
174 impl<'a> fmt::Show for Ascii {
175 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
176 (self.chr as char).fmt(f)
180 /// Trait for converting into an ascii type.
181 pub trait AsciiCast<T> {
182 /// Convert to an ascii type, fail on non-ASCII input.
184 fn to_ascii(&self) -> T {
185 assert!(self.is_ascii());
186 unsafe {self.to_ascii_nocheck()}
189 /// Convert to an ascii type, return None on non-ASCII input.
191 fn to_ascii_opt(&self) -> Option<T> {
193 Some(unsafe { self.to_ascii_nocheck() })
199 /// Convert to an ascii type, not doing any range asserts
200 unsafe fn to_ascii_nocheck(&self) -> T;
202 /// Check if convertible to ascii
203 fn is_ascii(&self) -> bool;
206 impl<'a> AsciiCast<&'a[Ascii]> for &'a [u8] {
208 unsafe fn to_ascii_nocheck(&self) -> &'a[Ascii] {
209 mem::transmute(*self)
213 fn is_ascii(&self) -> bool {
214 for b in self.iter() {
215 if !b.is_ascii() { return false; }
221 impl<'a> AsciiCast<&'a [Ascii]> for &'a str {
223 unsafe fn to_ascii_nocheck(&self) -> &'a [Ascii] {
224 mem::transmute(*self)
228 fn is_ascii(&self) -> bool {
229 self.bytes().all(|b| b.is_ascii())
233 impl AsciiCast<Ascii> for u8 {
235 unsafe fn to_ascii_nocheck(&self) -> Ascii {
240 fn is_ascii(&self) -> bool {
245 impl AsciiCast<Ascii> for char {
247 unsafe fn to_ascii_nocheck(&self) -> Ascii {
248 Ascii{ chr: *self as u8 }
252 fn is_ascii(&self) -> bool {
253 *self as u32 - ('\x7F' as u32 & *self as u32) == 0
257 /// Trait for copyless casting to an ascii vector.
258 pub trait OwnedAsciiCast {
259 /// Check if convertible to ascii
260 fn is_ascii(&self) -> bool;
262 /// Take ownership and cast to an ascii vector. Fail on non-ASCII input.
264 fn into_ascii(self) -> Vec<Ascii> {
265 assert!(self.is_ascii());
266 unsafe {self.into_ascii_nocheck()}
269 /// Take ownership and cast to an ascii vector. Return None on non-ASCII input.
271 fn into_ascii_opt(self) -> Option<Vec<Ascii>> {
273 Some(unsafe { self.into_ascii_nocheck() })
279 /// Take ownership and cast to an ascii vector.
280 /// Does not perform validation checks.
281 unsafe fn into_ascii_nocheck(self) -> Vec<Ascii>;
284 impl OwnedAsciiCast for String {
286 fn is_ascii(&self) -> bool {
287 self.as_slice().is_ascii()
291 unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
292 let v: Vec<u8> = mem::transmute(self);
293 v.into_ascii_nocheck()
297 impl OwnedAsciiCast for Vec<u8> {
299 fn is_ascii(&self) -> bool {
300 self.as_slice().is_ascii()
304 unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
309 /// Trait for converting an ascii type to a string. Needed to convert
310 /// `&[Ascii]` to `&str`.
312 /// Convert to a string.
313 fn as_str_ascii<'a>(&'a self) -> &'a str;
315 /// Convert to vector representing a lower cased ascii string.
316 fn to_lower(&self) -> Vec<Ascii>;
318 /// Convert to vector representing a upper cased ascii string.
319 fn to_upper(&self) -> Vec<Ascii>;
321 /// Compares two Ascii strings ignoring case.
322 fn eq_ignore_case(self, other: &[Ascii]) -> bool;
325 impl<'a> AsciiStr for &'a [Ascii] {
327 fn as_str_ascii<'a>(&'a self) -> &'a str {
328 unsafe { mem::transmute(*self) }
332 fn to_lower(&self) -> Vec<Ascii> {
333 self.iter().map(|a| a.to_lower()).collect()
337 fn to_upper(&self) -> Vec<Ascii> {
338 self.iter().map(|a| a.to_upper()).collect()
342 fn eq_ignore_case(self, other: &[Ascii]) -> bool {
343 self.iter().zip(other.iter()).all(|(&a, &b)| a.eq_ignore_case(b))
347 impl IntoStr for Vec<Ascii> {
349 fn into_string(self) -> String {
351 let s: &str = mem::transmute(self.as_slice());
357 /// Trait to convert to an owned byte vector by consuming self
358 pub trait IntoBytes {
359 /// Converts to an owned byte vector by consuming self
360 fn into_bytes(self) -> Vec<u8>;
363 impl IntoBytes for Vec<Ascii> {
364 fn into_bytes(self) -> Vec<u8> {
365 unsafe { mem::transmute(self) }
369 /// Extension methods for ASCII-subset only operations on owned strings
370 pub trait OwnedStrAsciiExt {
371 /// Convert the string to ASCII upper case:
372 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
373 /// but non-ASCII letters are unchanged.
374 fn into_ascii_upper(self) -> String;
376 /// Convert the string to ASCII lower case:
377 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
378 /// but non-ASCII letters are unchanged.
379 fn into_ascii_lower(self) -> String;
382 /// Extension methods for ASCII-subset only operations on string slices
383 pub trait StrAsciiExt {
384 /// Makes a copy of the string in ASCII upper case:
385 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
386 /// but non-ASCII letters are unchanged.
387 fn to_ascii_upper(&self) -> String;
389 /// Makes a copy of the string in ASCII lower case:
390 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
391 /// but non-ASCII letters are unchanged.
392 fn to_ascii_lower(&self) -> String;
394 /// Check that two strings are an ASCII case-insensitive match.
395 /// Same as `to_ascii_lower(a) == to_ascii_lower(b)`,
396 /// but without allocating and copying temporary strings.
397 fn eq_ignore_ascii_case(&self, other: &str) -> bool;
400 impl<'a> StrAsciiExt for &'a str {
402 fn to_ascii_upper(&self) -> String {
403 unsafe { str_copy_map_bytes(*self, ASCII_UPPER_MAP) }
407 fn to_ascii_lower(&self) -> String {
408 unsafe { str_copy_map_bytes(*self, ASCII_LOWER_MAP) }
412 fn eq_ignore_ascii_case(&self, other: &str) -> bool {
413 self.len() == other.len() &&
414 self.as_bytes().iter().zip(other.as_bytes().iter()).all(
415 |(byte_self, byte_other)| {
416 ASCII_LOWER_MAP[*byte_self as uint] ==
417 ASCII_LOWER_MAP[*byte_other as uint]
422 impl OwnedStrAsciiExt for String {
424 fn into_ascii_upper(self) -> String {
425 unsafe { str_map_bytes(self, ASCII_UPPER_MAP) }
429 fn into_ascii_lower(self) -> String {
430 unsafe { str_map_bytes(self, ASCII_LOWER_MAP) }
435 unsafe fn str_map_bytes(string: String, map: &'static [u8]) -> String {
436 let mut bytes = string.into_bytes();
438 for b in bytes.mut_iter() {
439 *b = map[*b as uint];
442 String::from_utf8(bytes).unwrap()
446 unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> String {
447 let mut s = String::from_str(string);
448 for b in s.as_mut_bytes().mut_iter() {
449 *b = map[*b as uint];
454 static ASCII_LOWER_MAP: &'static [u8] = &[
455 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
456 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
457 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
458 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
459 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
460 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
461 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
462 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
463 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
464 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
465 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
466 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
467 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
468 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
469 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
470 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
471 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
472 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
473 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
474 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
475 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
476 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
477 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
478 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
479 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
480 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
481 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
482 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
483 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
484 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
485 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
486 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
489 static ASCII_UPPER_MAP: &'static [u8] = &[
490 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
491 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
492 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
493 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
494 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
495 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
496 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
497 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
498 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
499 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
500 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
501 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
502 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
503 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
504 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
505 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
506 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
507 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
508 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
509 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
510 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
511 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
512 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
513 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
514 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
515 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
516 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
517 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
518 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
519 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
520 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
521 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
533 macro_rules! v2ascii (
534 ( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
535 (&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
538 macro_rules! vec2ascii (
539 ($($e:expr),*) => (Vec::from_slice([$(Ascii{chr:$e}),*]));
544 assert_eq!(65u8.to_ascii().to_byte(), 65u8);
545 assert_eq!(65u8.to_ascii().to_char(), 'A');
546 assert_eq!('A'.to_ascii().to_char(), 'A');
547 assert_eq!('A'.to_ascii().to_byte(), 65u8);
549 assert_eq!('A'.to_ascii().to_lower().to_char(), 'a');
550 assert_eq!('Z'.to_ascii().to_lower().to_char(), 'z');
551 assert_eq!('a'.to_ascii().to_upper().to_char(), 'A');
552 assert_eq!('z'.to_ascii().to_upper().to_char(), 'Z');
554 assert_eq!('@'.to_ascii().to_lower().to_char(), '@');
555 assert_eq!('['.to_ascii().to_lower().to_char(), '[');
556 assert_eq!('`'.to_ascii().to_upper().to_char(), '`');
557 assert_eq!('{'.to_ascii().to_upper().to_char(), '{');
559 assert!('0'.to_ascii().is_digit());
560 assert!('9'.to_ascii().is_digit());
561 assert!(!'/'.to_ascii().is_digit());
562 assert!(!':'.to_ascii().is_digit());
564 assert!((0x1fu8).to_ascii().is_control());
565 assert!(!' '.to_ascii().is_control());
566 assert!((0x7fu8).to_ascii().is_control());
568 assert!("banana".chars().all(|c| c.is_ascii()));
569 assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii()));
573 fn test_ascii_vec() {
574 let test = &[40u8, 32u8, 59u8];
575 assert_eq!(test.to_ascii(), v2ascii!([40, 32, 59]));
576 assert_eq!("( ;".to_ascii(), v2ascii!([40, 32, 59]));
577 let v = vec![40u8, 32u8, 59u8];
578 assert_eq!(v.as_slice().to_ascii(), v2ascii!([40, 32, 59]));
579 assert_eq!("( ;".to_string().as_slice().to_ascii(), v2ascii!([40, 32, 59]));
581 assert_eq!("abCDef&?#".to_ascii().to_lower().into_string(), "abcdef&?#".to_string());
582 assert_eq!("abCDef&?#".to_ascii().to_upper().into_string(), "ABCDEF&?#".to_string());
584 assert_eq!("".to_ascii().to_lower().into_string(), "".to_string());
585 assert_eq!("YMCA".to_ascii().to_lower().into_string(), "ymca".to_string());
586 assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_string(), "ABCDEFXYZ:.;".to_string());
588 assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii()));
590 assert!("".is_ascii());
591 assert!("a".is_ascii());
592 assert!(!"\u2009".is_ascii());
597 fn test_ascii_vec_ng() {
598 assert_eq!("abCDef&?#".to_ascii().to_lower().into_string(), "abcdef&?#".to_string());
599 assert_eq!("abCDef&?#".to_ascii().to_upper().into_string(), "ABCDEF&?#".to_string());
600 assert_eq!("".to_ascii().to_lower().into_string(), "".to_string());
601 assert_eq!("YMCA".to_ascii().to_lower().into_string(), "ymca".to_string());
602 assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_string(), "ABCDEFXYZ:.;".to_string());
606 fn test_owned_ascii_vec() {
607 assert_eq!(("( ;".to_string()).into_ascii(), vec2ascii![40, 32, 59]);
608 assert_eq!((vec![40u8, 32u8, 59u8]).into_ascii(), vec2ascii![40, 32, 59]);
612 fn test_ascii_as_str() {
613 let v = v2ascii!([40, 32, 59]);
614 assert_eq!(v.as_str_ascii(), "( ;");
618 fn test_ascii_into_string() {
619 assert_eq!(vec2ascii![40, 32, 59].into_string(), "( ;".to_string());
620 assert_eq!(vec2ascii!(40, 32, 59).into_string(), "( ;".to_string());
624 fn test_ascii_to_bytes() {
625 assert_eq!(vec2ascii![40, 32, 59].into_bytes(), vec![40u8, 32u8, 59u8]);
628 #[test] #[should_fail]
629 fn test_ascii_vec_fail_u8_slice() { (&[127u8, 128u8, 255u8]).to_ascii(); }
631 #[test] #[should_fail]
632 fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); }
634 #[test] #[should_fail]
635 fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); }
637 #[test] #[should_fail]
638 fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
642 assert_eq!(65u8.to_ascii_opt(), Some(Ascii { chr: 65u8 }));
643 assert_eq!(255u8.to_ascii_opt(), None);
645 assert_eq!('A'.to_ascii_opt(), Some(Ascii { chr: 65u8 }));
646 assert_eq!('λ'.to_ascii_opt(), None);
648 assert_eq!("zoä华".to_ascii_opt(), None);
650 let test1 = &[127u8, 128u8, 255u8];
651 assert_eq!((test1).to_ascii_opt(), None);
653 let v = [40u8, 32u8, 59u8];
654 let v2 = v2ascii!(&[40, 32, 59]);
655 assert_eq!(v.to_ascii_opt(), Some(v2));
656 let v = [127u8, 128u8, 255u8];
657 assert_eq!(v.to_ascii_opt(), None);
660 let v2 = v2ascii!(&[40, 32, 59]);
661 assert_eq!(v.to_ascii_opt(), Some(v2));
662 assert_eq!("zoä华".to_ascii_opt(), None);
664 assert_eq!((vec![40u8, 32u8, 59u8]).into_ascii_opt(), Some(vec2ascii![40, 32, 59]));
665 assert_eq!((vec![127u8, 128u8, 255u8]).into_ascii_opt(), None);
667 assert_eq!(("( ;".to_string()).into_ascii_opt(), Some(vec2ascii![40, 32, 59]));
668 assert_eq!(("zoä华".to_string()).into_ascii_opt(), None);
672 fn test_to_ascii_upper() {
673 assert_eq!("url()URL()uRl()ürl".to_ascii_upper(), "URL()URL()URL()üRL".to_string());
674 assert_eq!("hıKß".to_ascii_upper(), "HıKß".to_string());
678 let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
680 assert_eq!((from_u32(i).unwrap()).to_string().as_slice().to_ascii_upper(),
681 (from_u32(upper).unwrap()).to_string())
687 fn test_to_ascii_lower() {
688 assert_eq!("url()URL()uRl()Ürl".to_ascii_lower(), "url()url()url()Ürl".to_string());
689 // Dotted capital I, Kelvin sign, Sharp S.
690 assert_eq!("HİKß".to_ascii_lower(), "hİKß".to_string());
694 let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
696 assert_eq!((from_u32(i).unwrap()).to_string().as_slice().to_ascii_lower(),
697 (from_u32(lower).unwrap()).to_string())
703 fn test_into_ascii_upper() {
704 assert_eq!(("url()URL()uRl()ürl".to_string()).into_ascii_upper(),
705 "URL()URL()URL()üRL".to_string());
706 assert_eq!(("hıKß".to_string()).into_ascii_upper(), "HıKß".to_string());
710 let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
712 assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_upper(),
713 (from_u32(upper).unwrap()).to_string())
719 fn test_into_ascii_lower() {
720 assert_eq!(("url()URL()uRl()Ürl".to_string()).into_ascii_lower(),
721 "url()url()url()Ürl".to_string());
722 // Dotted capital I, Kelvin sign, Sharp S.
723 assert_eq!(("HİKß".to_string()).into_ascii_lower(), "hİKß".to_string());
727 let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
729 assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_lower(),
730 (from_u32(lower).unwrap()).to_string())
736 fn test_eq_ignore_ascii_case() {
737 assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl"));
738 assert!(!"Ürl".eq_ignore_ascii_case("ürl"));
739 // Dotted capital I, Kelvin sign, Sharp S.
740 assert!("HİKß".eq_ignore_ascii_case("hİKß"));
741 assert!(!"İ".eq_ignore_ascii_case("i"));
742 assert!(!"K".eq_ignore_ascii_case("k"));
743 assert!(!"ß".eq_ignore_ascii_case("s"));
748 let lower = if 'A' as u32 <= c && c <= 'Z' as u32 { c + 'a' as u32 - 'A' as u32 }
750 assert!((from_u32(i).unwrap()).to_string().as_slice().eq_ignore_ascii_case(
751 (from_u32(lower).unwrap()).to_string().as_slice()));
757 fn test_to_string() {
758 let s = Ascii{ chr: 't' as u8 }.to_string();
759 assert_eq!(s, "t".to_string());
764 let c = Ascii { chr: 't' as u8 };
765 assert_eq!(format!("{}", c), "t".to_string());