(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, other: Ascii) -> 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, _lsb0: bool, 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ıâªÃ".to_ascii_upper(), ~"HıâªÃ");
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Ä°âªÃ".to_ascii_lower(), ~"hÄ°âªÃ");
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ıâªÃ").into_ascii_upper(), ~"HıâªÃ");
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Ä°âªÃ").into_ascii_lower(), ~"hÄ°âªÃ");
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Ä°âªÃ".eq_ignore_ascii_case("hÄ°âªÃ"));
560 assert!(!"Ä°".eq_ignore_ascii_case("i"));
561 assert!(!"âª".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 {