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 //! Operations on ASCII strings and characters
15 use collections::Collection;
19 use option::{Option, Some, None};
20 use slice::{ImmutableVector, MutableVector, Vector};
21 use str::{OwnedStr, Str, StrAllocating, StrSlice};
23 use to_str::{IntoStr};
26 /// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
27 #[deriving(Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
28 pub struct Ascii { chr: u8 }
31 /// Converts an ascii character into a `u8`.
33 pub fn to_byte(self) -> u8 {
37 /// Converts an ascii character into a `char`.
39 pub fn to_char(self) -> char {
45 #[deprecated="renamed to `to_lowercase`"]
46 pub fn to_lower(self) -> Ascii {
50 /// Convert to lowercase.
52 pub fn to_lowercase(self) -> Ascii {
53 Ascii{chr: ASCII_LOWER_MAP[self.chr as uint]}
58 #[deprecated="renamed to `to_uppercase`"]
59 pub fn to_upper(self) -> Ascii {
63 /// Convert to uppercase.
65 pub fn to_uppercase(self) -> Ascii {
66 Ascii{chr: ASCII_UPPER_MAP[self.chr as uint]}
69 /// Compares two ascii characters of equality, ignoring case.
71 pub fn eq_ignore_case(self, other: Ascii) -> bool {
72 ASCII_LOWER_MAP[self.chr as uint] == ASCII_LOWER_MAP[other.chr as uint]
75 // the following methods are like ctype, and the implementation is inspired by musl
79 #[deprecated="renamed to `is_alphabetic`"]
80 pub fn is_alpha(&self) -> bool {
84 /// Check if the character is a letter (a-z, A-Z)
86 pub fn is_alphabetic(&self) -> bool {
87 (self.chr >= 0x41 && self.chr <= 0x5A) || (self.chr >= 0x61 && self.chr <= 0x7A)
90 /// Check if the character is a number (0-9)
92 pub fn is_digit(&self) -> bool {
93 self.chr >= 0x30 && self.chr <= 0x39
98 #[deprecated="renamed to `is_alphanumeric`"]
99 pub fn is_alnum(&self) -> bool {
100 self.is_alphanumeric()
103 /// Check if the character is a letter or number
105 pub fn is_alphanumeric(&self) -> bool {
106 self.is_alpha() || self.is_digit()
109 /// Check if the character is a space or horizontal tab
111 pub fn is_blank(&self) -> bool {
112 self.chr == ' ' as u8 || self.chr == '\t' as u8
115 /// Check if the character is a control character
117 pub fn is_control(&self) -> bool {
118 self.chr < 0x20 || self.chr == 0x7F
121 /// Checks if the character is printable (except space)
123 pub fn is_graph(&self) -> bool {
124 (self.chr - 0x21) < 0x5E
127 /// Checks if the character is printable (including space)
129 pub fn is_print(&self) -> bool {
130 (self.chr - 0x20) < 0x5F
134 #[allow(missing_doc)]
135 #[deprecated="renamed to `is_lowercase`"]
136 pub fn is_lower(&self) -> bool {
140 /// Checks if the character is lowercase
142 pub fn is_lowercase(&self) -> bool {
143 (self.chr - 'a' as u8) < 26
147 #[allow(missing_doc)]
148 #[deprecated="renamed to `is_uppercase`"]
149 pub fn is_upper(&self) -> bool {
153 /// Checks if the character is uppercase
155 pub fn is_uppercase(&self) -> bool {
156 (self.chr - 'A' as u8) < 26
159 /// Checks if the character is punctuation
161 pub fn is_punctuation(&self) -> bool {
162 self.is_graph() && !self.is_alnum()
165 /// Checks if the character is a valid hex digit
167 pub fn is_hex(&self) -> bool {
168 self.is_digit() || ((self.chr | 32u8) - 'a' as u8) < 6
172 impl<'a> fmt::Show for Ascii {
173 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
174 (self.chr as char).fmt(f)
178 /// Trait for converting into an ascii type.
179 pub trait AsciiCast<T> {
180 /// Convert to an ascii type, fail on non-ASCII input.
182 fn to_ascii(&self) -> T {
183 assert!(self.is_ascii());
184 unsafe {self.to_ascii_nocheck()}
187 /// Convert to an ascii type, return None on non-ASCII input.
189 fn to_ascii_opt(&self) -> Option<T> {
191 Some(unsafe { self.to_ascii_nocheck() })
197 /// Convert to an ascii type, not doing any range asserts
198 unsafe fn to_ascii_nocheck(&self) -> T;
200 /// Check if convertible to ascii
201 fn is_ascii(&self) -> bool;
204 impl<'a> AsciiCast<&'a[Ascii]> for &'a [u8] {
206 unsafe fn to_ascii_nocheck(&self) -> &'a[Ascii] {
207 mem::transmute(*self)
211 fn is_ascii(&self) -> bool {
212 for b in self.iter() {
213 if !b.is_ascii() { return false; }
219 impl<'a> AsciiCast<&'a [Ascii]> for &'a str {
221 unsafe fn to_ascii_nocheck(&self) -> &'a [Ascii] {
222 mem::transmute(*self)
226 fn is_ascii(&self) -> bool {
227 self.bytes().all(|b| b.is_ascii())
231 impl AsciiCast<Ascii> for u8 {
233 unsafe fn to_ascii_nocheck(&self) -> Ascii {
238 fn is_ascii(&self) -> bool {
243 impl AsciiCast<Ascii> for char {
245 unsafe fn to_ascii_nocheck(&self) -> Ascii {
246 Ascii{ chr: *self as u8 }
250 fn is_ascii(&self) -> bool {
251 *self as u32 - ('\x7F' as u32 & *self as u32) == 0
255 /// Trait for copyless casting to an ascii vector.
256 pub trait OwnedAsciiCast {
257 /// Check if convertible to ascii
258 fn is_ascii(&self) -> bool;
260 /// Take ownership and cast to an ascii vector. Fail on non-ASCII input.
262 fn into_ascii(self) -> Vec<Ascii> {
263 assert!(self.is_ascii());
264 unsafe {self.into_ascii_nocheck()}
267 /// Take ownership and cast to an ascii vector. Return None on non-ASCII input.
269 fn into_ascii_opt(self) -> Option<Vec<Ascii>> {
271 Some(unsafe { self.into_ascii_nocheck() })
277 /// Take ownership and cast to an ascii vector.
278 /// Does not perform validation checks.
279 unsafe fn into_ascii_nocheck(self) -> Vec<Ascii>;
282 impl OwnedAsciiCast for String {
284 fn is_ascii(&self) -> bool {
285 self.as_slice().is_ascii()
289 unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
290 let v: Vec<u8> = mem::transmute(self);
291 v.into_ascii_nocheck()
295 impl OwnedAsciiCast for Vec<u8> {
297 fn is_ascii(&self) -> bool {
298 self.as_slice().is_ascii()
302 unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
307 /// Trait for converting an ascii type to a string. Needed to convert
308 /// `&[Ascii]` to `&str`.
310 /// Convert to a string.
311 fn as_str_ascii<'a>(&'a self) -> &'a str;
313 /// Convert to vector representing a lower cased ascii string.
314 fn to_lower(&self) -> Vec<Ascii>;
316 /// Convert to vector representing a upper cased ascii string.
317 fn to_upper(&self) -> Vec<Ascii>;
319 /// Compares two Ascii strings ignoring case.
320 fn eq_ignore_case(self, other: &[Ascii]) -> bool;
323 impl<'a> AsciiStr for &'a [Ascii] {
325 fn as_str_ascii<'a>(&'a self) -> &'a str {
326 unsafe { mem::transmute(*self) }
330 fn to_lower(&self) -> Vec<Ascii> {
331 self.iter().map(|a| a.to_lower()).collect()
335 fn to_upper(&self) -> Vec<Ascii> {
336 self.iter().map(|a| a.to_upper()).collect()
340 fn eq_ignore_case(self, other: &[Ascii]) -> bool {
341 self.iter().zip(other.iter()).all(|(&a, &b)| a.eq_ignore_case(b))
345 impl IntoStr for Vec<Ascii> {
347 fn into_string(self) -> String {
349 let s: &str = mem::transmute(self.as_slice());
355 /// Trait to convert to an owned byte vector by consuming self
356 pub trait IntoBytes {
357 /// Converts to an owned byte vector by consuming self
358 fn into_bytes(self) -> Vec<u8>;
361 impl IntoBytes for Vec<Ascii> {
362 fn into_bytes(self) -> Vec<u8> {
363 unsafe { mem::transmute(self) }
367 /// Extension methods for ASCII-subset only operations on owned strings
368 pub trait OwnedStrAsciiExt {
369 /// Convert the string to ASCII upper case:
370 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
371 /// but non-ASCII letters are unchanged.
372 fn into_ascii_upper(self) -> String;
374 /// Convert the string to ASCII lower case:
375 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
376 /// but non-ASCII letters are unchanged.
377 fn into_ascii_lower(self) -> String;
380 /// Extension methods for ASCII-subset only operations on string slices
381 pub trait StrAsciiExt {
382 /// Makes a copy of the string in ASCII upper case:
383 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
384 /// but non-ASCII letters are unchanged.
385 fn to_ascii_upper(&self) -> String;
387 /// Makes a copy of the string in ASCII lower case:
388 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
389 /// but non-ASCII letters are unchanged.
390 fn to_ascii_lower(&self) -> String;
392 /// Check that two strings are an ASCII case-insensitive match.
393 /// Same as `to_ascii_lower(a) == to_ascii_lower(b)`,
394 /// but without allocating and copying temporary strings.
395 fn eq_ignore_ascii_case(&self, other: &str) -> bool;
398 impl<'a> StrAsciiExt for &'a str {
400 fn to_ascii_upper(&self) -> String {
401 unsafe { str_copy_map_bytes(*self, ASCII_UPPER_MAP) }
405 fn to_ascii_lower(&self) -> String {
406 unsafe { str_copy_map_bytes(*self, ASCII_LOWER_MAP) }
410 fn eq_ignore_ascii_case(&self, other: &str) -> bool {
411 self.len() == other.len() &&
412 self.as_bytes().iter().zip(other.as_bytes().iter()).all(
413 |(byte_self, byte_other)| {
414 ASCII_LOWER_MAP[*byte_self as uint] ==
415 ASCII_LOWER_MAP[*byte_other as uint]
420 impl OwnedStrAsciiExt for String {
422 fn into_ascii_upper(self) -> String {
423 unsafe { str_map_bytes(self, ASCII_UPPER_MAP) }
427 fn into_ascii_lower(self) -> String {
428 unsafe { str_map_bytes(self, ASCII_LOWER_MAP) }
433 unsafe fn str_map_bytes(string: String, map: &'static [u8]) -> String {
434 let mut bytes = string.into_bytes();
436 for b in bytes.mut_iter() {
437 *b = map[*b as uint];
440 String::from_utf8(bytes).unwrap()
444 unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> String {
445 let mut s = String::from_str(string);
446 for b in s.as_mut_bytes().mut_iter() {
447 *b = map[*b as uint];
452 static ASCII_LOWER_MAP: &'static [u8] = &[
453 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
454 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
455 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
456 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
457 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
458 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
459 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
460 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
461 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
462 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
463 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
464 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
465 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
466 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
467 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
468 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
469 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
470 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
471 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
472 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
473 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
474 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
475 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
476 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
477 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
478 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
479 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
480 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
481 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
482 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
483 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
484 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
487 static ASCII_UPPER_MAP: &'static [u8] = &[
488 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
489 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
490 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
491 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
492 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
493 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
494 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
495 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
496 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
497 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
498 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
499 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
500 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
501 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
502 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
503 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 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,
531 macro_rules! v2ascii (
532 ( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
533 (&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
536 macro_rules! vec2ascii (
537 ($($e:expr),*) => (Vec::from_slice([$(Ascii{chr:$e}),*]));
542 assert_eq!(65u8.to_ascii().to_byte(), 65u8);
543 assert_eq!(65u8.to_ascii().to_char(), 'A');
544 assert_eq!('A'.to_ascii().to_char(), 'A');
545 assert_eq!('A'.to_ascii().to_byte(), 65u8);
547 assert_eq!('A'.to_ascii().to_lower().to_char(), 'a');
548 assert_eq!('Z'.to_ascii().to_lower().to_char(), 'z');
549 assert_eq!('a'.to_ascii().to_upper().to_char(), 'A');
550 assert_eq!('z'.to_ascii().to_upper().to_char(), 'Z');
552 assert_eq!('@'.to_ascii().to_lower().to_char(), '@');
553 assert_eq!('['.to_ascii().to_lower().to_char(), '[');
554 assert_eq!('`'.to_ascii().to_upper().to_char(), '`');
555 assert_eq!('{'.to_ascii().to_upper().to_char(), '{');
557 assert!('0'.to_ascii().is_digit());
558 assert!('9'.to_ascii().is_digit());
559 assert!(!'/'.to_ascii().is_digit());
560 assert!(!':'.to_ascii().is_digit());
562 assert!((0x1fu8).to_ascii().is_control());
563 assert!(!' '.to_ascii().is_control());
564 assert!((0x7fu8).to_ascii().is_control());
566 assert!("banana".chars().all(|c| c.is_ascii()));
567 assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii()));
571 fn test_ascii_vec() {
572 let test = &[40u8, 32u8, 59u8];
573 assert_eq!(test.to_ascii(), v2ascii!([40, 32, 59]));
574 assert_eq!("( ;".to_ascii(), v2ascii!([40, 32, 59]));
575 let v = vec![40u8, 32u8, 59u8];
576 assert_eq!(v.as_slice().to_ascii(), v2ascii!([40, 32, 59]));
577 assert_eq!("( ;".to_string().as_slice().to_ascii(), v2ascii!([40, 32, 59]));
579 assert_eq!("abCDef&?#".to_ascii().to_lower().into_string(), "abcdef&?#".to_string());
580 assert_eq!("abCDef&?#".to_ascii().to_upper().into_string(), "ABCDEF&?#".to_string());
582 assert_eq!("".to_ascii().to_lower().into_string(), "".to_string());
583 assert_eq!("YMCA".to_ascii().to_lower().into_string(), "ymca".to_string());
584 assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_string(), "ABCDEFXYZ:.;".to_string());
586 assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii()));
588 assert!("".is_ascii());
589 assert!("a".is_ascii());
590 assert!(!"\u2009".is_ascii());
595 fn test_ascii_vec_ng() {
596 assert_eq!("abCDef&?#".to_ascii().to_lower().into_string(), "abcdef&?#".to_string());
597 assert_eq!("abCDef&?#".to_ascii().to_upper().into_string(), "ABCDEF&?#".to_string());
598 assert_eq!("".to_ascii().to_lower().into_string(), "".to_string());
599 assert_eq!("YMCA".to_ascii().to_lower().into_string(), "ymca".to_string());
600 assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_string(), "ABCDEFXYZ:.;".to_string());
604 fn test_owned_ascii_vec() {
605 assert_eq!(("( ;".to_string()).into_ascii(), vec2ascii![40, 32, 59]);
606 assert_eq!((vec![40u8, 32u8, 59u8]).into_ascii(), vec2ascii![40, 32, 59]);
610 fn test_ascii_as_str() {
611 let v = v2ascii!([40, 32, 59]);
612 assert_eq!(v.as_str_ascii(), "( ;");
616 fn test_ascii_into_string() {
617 assert_eq!(vec2ascii![40, 32, 59].into_string(), "( ;".to_string());
618 assert_eq!(vec2ascii!(40, 32, 59).into_string(), "( ;".to_string());
622 fn test_ascii_to_bytes() {
623 assert_eq!(vec2ascii![40, 32, 59].into_bytes(), vec![40u8, 32u8, 59u8]);
626 #[test] #[should_fail]
627 fn test_ascii_vec_fail_u8_slice() { (&[127u8, 128u8, 255u8]).to_ascii(); }
629 #[test] #[should_fail]
630 fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); }
632 #[test] #[should_fail]
633 fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); }
635 #[test] #[should_fail]
636 fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
640 assert_eq!(65u8.to_ascii_opt(), Some(Ascii { chr: 65u8 }));
641 assert_eq!(255u8.to_ascii_opt(), None);
643 assert_eq!('A'.to_ascii_opt(), Some(Ascii { chr: 65u8 }));
644 assert_eq!('λ'.to_ascii_opt(), None);
646 assert_eq!("zoä华".to_ascii_opt(), None);
648 let test1 = &[127u8, 128u8, 255u8];
649 assert_eq!((test1).to_ascii_opt(), None);
651 let v = [40u8, 32u8, 59u8];
652 let v2 = v2ascii!(&[40, 32, 59]);
653 assert_eq!(v.to_ascii_opt(), Some(v2));
654 let v = [127u8, 128u8, 255u8];
655 assert_eq!(v.to_ascii_opt(), None);
658 let v2 = v2ascii!(&[40, 32, 59]);
659 assert_eq!(v.to_ascii_opt(), Some(v2));
660 assert_eq!("zoä华".to_ascii_opt(), None);
662 assert_eq!((vec![40u8, 32u8, 59u8]).into_ascii_opt(), Some(vec2ascii![40, 32, 59]));
663 assert_eq!((vec![127u8, 128u8, 255u8]).into_ascii_opt(), None);
665 assert_eq!(("( ;".to_string()).into_ascii_opt(), Some(vec2ascii![40, 32, 59]));
666 assert_eq!(("zoä华".to_string()).into_ascii_opt(), None);
670 fn test_to_ascii_upper() {
671 assert_eq!("url()URL()uRl()ürl".to_ascii_upper(), "URL()URL()URL()üRL".to_string());
672 assert_eq!("hıKß".to_ascii_upper(), "HıKß".to_string());
676 let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
678 assert_eq!((from_u32(i).unwrap()).to_string().as_slice().to_ascii_upper(),
679 (from_u32(upper).unwrap()).to_string())
685 fn test_to_ascii_lower() {
686 assert_eq!("url()URL()uRl()Ürl".to_ascii_lower(), "url()url()url()Ürl".to_string());
687 // Dotted capital I, Kelvin sign, Sharp S.
688 assert_eq!("HİKß".to_ascii_lower(), "hİKß".to_string());
692 let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
694 assert_eq!((from_u32(i).unwrap()).to_string().as_slice().to_ascii_lower(),
695 (from_u32(lower).unwrap()).to_string())
701 fn test_into_ascii_upper() {
702 assert_eq!(("url()URL()uRl()ürl".to_string()).into_ascii_upper(),
703 "URL()URL()URL()üRL".to_string());
704 assert_eq!(("hıKß".to_string()).into_ascii_upper(), "HıKß".to_string());
708 let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
710 assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_upper(),
711 (from_u32(upper).unwrap()).to_string())
717 fn test_into_ascii_lower() {
718 assert_eq!(("url()URL()uRl()Ürl".to_string()).into_ascii_lower(),
719 "url()url()url()Ürl".to_string());
720 // Dotted capital I, Kelvin sign, Sharp S.
721 assert_eq!(("HİKß".to_string()).into_ascii_lower(), "hİKß".to_string());
725 let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
727 assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_lower(),
728 (from_u32(lower).unwrap()).to_string())
734 fn test_eq_ignore_ascii_case() {
735 assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl"));
736 assert!(!"Ürl".eq_ignore_ascii_case("ürl"));
737 // Dotted capital I, Kelvin sign, Sharp S.
738 assert!("HİKß".eq_ignore_ascii_case("hİKß"));
739 assert!(!"İ".eq_ignore_ascii_case("i"));
740 assert!(!"K".eq_ignore_ascii_case("k"));
741 assert!(!"ß".eq_ignore_ascii_case("s"));
746 let lower = if 'A' as u32 <= c && c <= 'Z' as u32 { c + 'a' as u32 - 'A' as u32 }
748 assert!((from_u32(i).unwrap()).to_string().as_slice().eq_ignore_ascii_case(
749 (from_u32(lower).unwrap()).to_string().as_slice()));
755 fn test_to_string() {
756 let s = Ascii{ chr: 't' as u8 }.to_string();
757 assert_eq!(s, "t".to_string());
762 let c = Ascii { chr: 't' as u8 };
763 assert_eq!(format!("{}", c), "t".to_string());