(index<- )        ./libstd/ascii.rs

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


libstd/ascii.rs:213:51-213:51 -trait- definition:
/// Trait for copyless casting to an ascii vector.
pub trait OwnedAsciiCast {
    /// Check if convertible to ascii
references:- 3
240: impl OwnedAsciiCast for ~[u8] {
241:     #[inline]
--
252: impl OwnedAsciiCast for ~str {
253:     #[inline]
--
265: impl OwnedAsciiCast for Vec<u8> {
266:     #[inline]


libstd/ascii.rs:420:10-420:10 -fn- definition:
unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> ~str {
    let mut s = string.to_owned();
    for b in str::raw::as_owned_vec(&mut s).mut_iter() {
references:- 2
377:     fn to_ascii_upper(&self) -> ~str {
378:         unsafe { str_copy_map_bytes(*self, ASCII_UPPER_MAP) }
379:     }
--
382:     fn to_ascii_lower(&self) -> ~str {
383:         unsafe { str_copy_map_bytes(*self, ASCII_LOWER_MAP) }
384:     }


libstd/ascii.rs:27:53-27:53 -struct- definition:
pub struct Ascii { chr: u8 }
impl Ascii {
    /// Converts an ascii character into a `u8`.
references:- 65


libstd/ascii.rs:409:10-409:10 -fn- definition:
unsafe fn str_map_bytes(string: ~str, map: &'static [u8]) -> ~str {
    let mut bytes = string.into_bytes();
    for b in bytes.mut_iter() {
references:- 2
399:     fn into_ascii_upper(self) -> ~str {
400:         unsafe { str_map_bytes(self, ASCII_UPPER_MAP) }
401:     }
--
404:     fn into_ascii_lower(self) -> ~str {
405:         unsafe { str_map_bytes(self, ASCII_LOWER_MAP) }
406:     }


libstd/ascii.rs:136:45-136:45 -trait- definition:
/// Trait for converting into an ascii type.
pub trait AsciiCast<T> {
    /// Convert to an ascii type, fail on non-ASCII input.
references:- 4
189: impl AsciiCast<Ascii> for u8 {
190:     #[inline]
--
201: impl AsciiCast<Ascii> for char {
202:     #[inline]