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

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

libstd/str/ascii.rs:155:51-155:51 -trait- definition:
/// Trait for copyless casting to an ascii vector.
pub trait OwnedAsciiCast {
references:-
165: impl OwnedAsciiCast for ~[u8] {
178: impl OwnedAsciiCast for ~str {


libstd/str/ascii.rs:191:91-191:91 -trait- definition:
/// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str`
pub trait AsciiStr {
references:-
206: impl<'self> AsciiStr for &'self [Ascii] {


libstd/str/ascii.rs:68:45-68:45 -trait- definition:
/// Trait for converting into an ascii type.
pub trait AsciiCast<T> {
references:-
101: impl<'self> AsciiCast<&'self [Ascii]> for &'self str {
119: impl AsciiCast<Ascii> for u8 {
137: impl AsciiCast<Ascii> for char {
80: impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] {


libstd/str/ascii.rs:243:61-243:61 -trait- definition:
/// Trait to convert to a owned byte array by consuming self
pub trait ToBytesConsume {
references:-
249: impl ToBytesConsume for ~[Ascii] {


libstd/str/ascii.rs:327:10-327:10 -fn- definition:
#[inline]
unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> ~str {
references:-
289:         unsafe { str_copy_map_bytes(*self, ASCII_UPPER_MAP) }
294:         unsafe { str_copy_map_bytes(*self, ASCII_LOWER_MAP) }


libstd/str/ascii.rs:25:47-25:47 -struct- definition:
#[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
pub struct Ascii { priv chr: u8 }
references:-
103:     fn to_ascii(&self) -> &'self [Ascii] {
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
121:     fn to_ascii(&self) -> Ascii {
60: impl ToStr for Ascii {
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
119: impl AsciiCast<Ascii> for u8 {
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
249: impl ToBytesConsume for ~[Ascii] {
203:     fn eq_ignore_case(self, other: &[Ascii]) -> bool;
186:     unsafe fn into_ascii_nocheck(self) -> ~[Ascii] {
43:     pub fn to_lower(self) -> Ascii {
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
82:     fn to_ascii(&self) -> &'self[Ascii] {
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
101: impl<'self> AsciiCast<&'self [Ascii]> for &'self str {
200:     fn to_upper(&self) -> ~[Ascii];
127:     unsafe fn to_ascii_nocheck(&self) -> Ascii {
167:     fn into_ascii(self) -> ~[Ascii] {
180:     fn into_ascii(self) -> ~[Ascii] {
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
55:     pub fn eq_ignore_case(self, other: Ascii) -> bool {
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
224:     fn eq_ignore_case(self, other: &[Ascii]) -> bool {
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
25: #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
(146)(49)(173)(28)(25)(25)(214)(88)(44)(25)(80)(25)(197)(25)(145)(229)(25)(25)(25)(162)(139)(25)(25)(137)(128)(25)(236)(25)(50)(25)(158)(25)(109)(25)(206)(25)(25)(25)(219)

libstd/str/ascii.rs:255:72-255:72 -trait- definition:
/// Extension methods for ASCII-subset only operations on owned strings
pub trait OwnedStrAsciiExt {
references:-
304: impl OwnedStrAsciiExt for ~str {


libstd/str/ascii.rs:316:10-316:10 -fn- definition:
#[inline]
unsafe fn str_map_bytes(string: ~str, map: &'static [u8]) -> ~str {
references:-
307:         unsafe { str_map_bytes(self, ASCII_UPPER_MAP) }
312:         unsafe { str_map_bytes(self, ASCII_LOWER_MAP) }


libstd/str/ascii.rs:268:72-268:72 -trait- definition:
/// Extension methods for ASCII-subset only operations on string slices
pub trait StrAsciiExt {
references:-
286: impl<'self> StrAsciiExt for &'self str {