]> git.proxmox.com Git - rustc.git/blame - src/libstd/ascii.rs
New upstream version 1.13.0+dfsg1
[rustc.git] / src / libstd / ascii.rs
CommitLineData
1a4d82fc
JJ
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.
1a4d82fc 10
54a0048b 11//! Operations on ASCII strings and characters.
1a4d82fc 12
85aaf69f 13#![stable(feature = "rust1", since = "1.0.0")]
1a4d82fc 14
85aaf69f 15use mem;
e9174d1e 16use ops::Range;
9e0c209e 17use iter::FusedIterator;
1a4d82fc 18
c34b1796 19/// Extension methods for ASCII-subset only operations on string slices.
7453a54e
SL
20///
21/// Be aware that operations on seemingly non-ASCII characters can sometimes
22/// have unexpected results. Consider this example:
23///
24/// ```
25/// use std::ascii::AsciiExt;
26///
27/// assert_eq!("café".to_ascii_uppercase(), "CAFÉ");
28/// assert_eq!("café".to_ascii_uppercase(), "CAFé");
29/// ```
30///
31/// In the first example, the lowercased string is represented `"cafe\u{301}"`
32/// (the last character is an acute accent [combining character]). Unlike the
33/// other characters in the string, the combining character will not get mapped
34/// to an uppercase variant, resulting in `"CAFE\u{301}"`. In the second
35/// example, the lowercased string is represented `"caf\u{e9}"` (the last
36/// character is a single Unicode character representing an 'e' with an acute
37/// accent). Since the last character is defined outside the scope of ASCII,
38/// it will not get mapped to an uppercase variant, resulting in `"CAF\u{e9}"`.
39///
40/// [combining character]: https://en.wikipedia.org/wiki/Combining_character
85aaf69f
SL
41#[stable(feature = "rust1", since = "1.0.0")]
42pub trait AsciiExt {
c34b1796 43 /// Container type for copied ASCII characters.
85aaf69f
SL
44 #[stable(feature = "rust1", since = "1.0.0")]
45 type Owned;
46
7453a54e 47 /// Checks if the value is within the ASCII range.
c34b1796
AL
48 ///
49 /// # Examples
50 ///
51 /// ```
52 /// use std::ascii::AsciiExt;
53 ///
54 /// let ascii = 'a';
55 /// let utf8 = '❤';
56 ///
7453a54e
SL
57 /// assert!(ascii.is_ascii());
58 /// assert!(!utf8.is_ascii());
c34b1796 59 /// ```
85aaf69f 60 #[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc
JJ
61 fn is_ascii(&self) -> bool;
62
c34b1796
AL
63 /// Makes a copy of the string in ASCII upper case.
64 ///
1a4d82fc
JJ
65 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
66 /// but non-ASCII letters are unchanged.
c34b1796
AL
67 ///
68 /// # Examples
69 ///
70 /// ```
71 /// use std::ascii::AsciiExt;
72 ///
73 /// let ascii = 'a';
74 /// let utf8 = '❤';
75 ///
76 /// assert_eq!('A', ascii.to_ascii_uppercase());
77 /// assert_eq!('❤', utf8.to_ascii_uppercase());
78 /// ```
85aaf69f
SL
79 #[stable(feature = "rust1", since = "1.0.0")]
80 fn to_ascii_uppercase(&self) -> Self::Owned;
1a4d82fc 81
c34b1796
AL
82 /// Makes a copy of the string in ASCII lower case.
83 ///
1a4d82fc
JJ
84 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
85 /// but non-ASCII letters are unchanged.
c34b1796
AL
86 ///
87 /// # Examples
88 ///
89 /// ```
90 /// use std::ascii::AsciiExt;
91 ///
92 /// let ascii = 'A';
93 /// let utf8 = '❤';
94 ///
95 /// assert_eq!('a', ascii.to_ascii_lowercase());
96 /// assert_eq!('❤', utf8.to_ascii_lowercase());
97 /// ```
85aaf69f
SL
98 #[stable(feature = "rust1", since = "1.0.0")]
99 fn to_ascii_lowercase(&self) -> Self::Owned;
1a4d82fc 100
9346a6ac 101 /// Checks that two strings are an ASCII case-insensitive match.
c34b1796 102 ///
1a4d82fc
JJ
103 /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
104 /// but without allocating and copying temporary strings.
c34b1796
AL
105 ///
106 /// # Examples
107 ///
108 /// ```
109 /// use std::ascii::AsciiExt;
110 ///
111 /// let ascii1 = 'A';
112 /// let ascii2 = 'a';
113 /// let ascii3 = 'A';
114 /// let ascii4 = 'z';
115 ///
7453a54e
SL
116 /// assert!(ascii1.eq_ignore_ascii_case(&ascii2));
117 /// assert!(ascii1.eq_ignore_ascii_case(&ascii3));
118 /// assert!(!ascii1.eq_ignore_ascii_case(&ascii4));
c34b1796 119 /// ```
85aaf69f 120 #[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc 121 fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
85aaf69f 122
9346a6ac 123 /// Converts this type to its ASCII upper case equivalent in-place.
85aaf69f
SL
124 ///
125 /// See `to_ascii_uppercase` for more information.
c34b1796
AL
126 ///
127 /// # Examples
128 ///
129 /// ```
c34b1796
AL
130 /// use std::ascii::AsciiExt;
131 ///
132 /// let mut ascii = 'a';
133 ///
134 /// ascii.make_ascii_uppercase();
135 ///
136 /// assert_eq!('A', ascii);
137 /// ```
54a0048b 138 #[stable(feature = "ascii", since = "1.9.0")]
85aaf69f
SL
139 fn make_ascii_uppercase(&mut self);
140
9346a6ac 141 /// Converts this type to its ASCII lower case equivalent in-place.
85aaf69f
SL
142 ///
143 /// See `to_ascii_lowercase` for more information.
c34b1796
AL
144 ///
145 /// # Examples
146 ///
147 /// ```
c34b1796
AL
148 /// use std::ascii::AsciiExt;
149 ///
150 /// let mut ascii = 'A';
151 ///
152 /// ascii.make_ascii_lowercase();
153 ///
154 /// assert_eq!('a', ascii);
155 /// ```
54a0048b 156 #[stable(feature = "ascii", since = "1.9.0")]
85aaf69f 157 fn make_ascii_lowercase(&mut self);
1a4d82fc
JJ
158}
159
85aaf69f
SL
160#[stable(feature = "rust1", since = "1.0.0")]
161impl AsciiExt for str {
162 type Owned = String;
163
1a4d82fc
JJ
164 #[inline]
165 fn is_ascii(&self) -> bool {
166 self.bytes().all(|b| b.is_ascii())
167 }
168
169 #[inline]
170 fn to_ascii_uppercase(&self) -> String {
e9174d1e
SL
171 let mut bytes = self.as_bytes().to_vec();
172 bytes.make_ascii_uppercase();
173 // make_ascii_uppercase() preserves the UTF-8 invariant.
174 unsafe { String::from_utf8_unchecked(bytes) }
1a4d82fc
JJ
175 }
176
177 #[inline]
178 fn to_ascii_lowercase(&self) -> String {
e9174d1e
SL
179 let mut bytes = self.as_bytes().to_vec();
180 bytes.make_ascii_lowercase();
181 // make_ascii_uppercase() preserves the UTF-8 invariant.
182 unsafe { String::from_utf8_unchecked(bytes) }
1a4d82fc
JJ
183 }
184
185 #[inline]
186 fn eq_ignore_ascii_case(&self, other: &str) -> bool {
187 self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
188 }
85aaf69f
SL
189
190 fn make_ascii_uppercase(&mut self) {
191 let me: &mut [u8] = unsafe { mem::transmute(self) };
192 me.make_ascii_uppercase()
193 }
194
195 fn make_ascii_lowercase(&mut self) {
196 let me: &mut [u8] = unsafe { mem::transmute(self) };
197 me.make_ascii_lowercase()
198 }
1a4d82fc
JJ
199}
200
85aaf69f
SL
201#[stable(feature = "rust1", since = "1.0.0")]
202impl AsciiExt for [u8] {
203 type Owned = Vec<u8>;
1a4d82fc
JJ
204 #[inline]
205 fn is_ascii(&self) -> bool {
206 self.iter().all(|b| b.is_ascii())
207 }
208
209 #[inline]
210 fn to_ascii_uppercase(&self) -> Vec<u8> {
e9174d1e
SL
211 let mut me = self.to_vec();
212 me.make_ascii_uppercase();
213 return me
1a4d82fc
JJ
214 }
215
216 #[inline]
217 fn to_ascii_lowercase(&self) -> Vec<u8> {
e9174d1e
SL
218 let mut me = self.to_vec();
219 me.make_ascii_lowercase();
220 return me
1a4d82fc
JJ
221 }
222
223 #[inline]
224 fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
225 self.len() == other.len() &&
62682a34 226 self.iter().zip(other).all(|(a, b)| {
1a4d82fc
JJ
227 a.eq_ignore_ascii_case(b)
228 })
229 }
85aaf69f
SL
230
231 fn make_ascii_uppercase(&mut self) {
232 for byte in self {
233 byte.make_ascii_uppercase();
234 }
235 }
236
237 fn make_ascii_lowercase(&mut self) {
238 for byte in self {
239 byte.make_ascii_lowercase();
240 }
241 }
1a4d82fc
JJ
242}
243
85aaf69f 244#[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc 245impl AsciiExt for u8 {
85aaf69f 246 type Owned = u8;
1a4d82fc 247 #[inline]
c34b1796 248 fn is_ascii(&self) -> bool { *self & 128 == 0 }
1a4d82fc 249 #[inline]
85aaf69f 250 fn to_ascii_uppercase(&self) -> u8 { ASCII_UPPERCASE_MAP[*self as usize] }
1a4d82fc 251 #[inline]
85aaf69f 252 fn to_ascii_lowercase(&self) -> u8 { ASCII_LOWERCASE_MAP[*self as usize] }
1a4d82fc
JJ
253 #[inline]
254 fn eq_ignore_ascii_case(&self, other: &u8) -> bool {
255 self.to_ascii_lowercase() == other.to_ascii_lowercase()
256 }
85aaf69f
SL
257 #[inline]
258 fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
259 #[inline]
260 fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
1a4d82fc
JJ
261}
262
85aaf69f 263#[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc 264impl AsciiExt for char {
85aaf69f 265 type Owned = char;
1a4d82fc
JJ
266 #[inline]
267 fn is_ascii(&self) -> bool {
268 *self as u32 <= 0x7F
269 }
270
271 #[inline]
272 fn to_ascii_uppercase(&self) -> char {
273 if self.is_ascii() {
274 (*self as u8).to_ascii_uppercase() as char
275 } else {
276 *self
277 }
278 }
279
280 #[inline]
281 fn to_ascii_lowercase(&self) -> char {
282 if self.is_ascii() {
283 (*self as u8).to_ascii_lowercase() as char
284 } else {
285 *self
286 }
287 }
288
289 #[inline]
290 fn eq_ignore_ascii_case(&self, other: &char) -> bool {
291 self.to_ascii_lowercase() == other.to_ascii_lowercase()
292 }
85aaf69f
SL
293
294 #[inline]
295 fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
296 #[inline]
297 fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
298}
299
300/// An iterator over the escaped version of a byte, constructed via
301/// `std::ascii::escape_default`.
302#[stable(feature = "rust1", since = "1.0.0")]
303pub struct EscapeDefault {
304 range: Range<usize>,
305 data: [u8; 4],
1a4d82fc
JJ
306}
307
c34b1796 308/// Returns an iterator that produces an escaped version of a `u8`.
1a4d82fc
JJ
309///
310/// The default is chosen with a bias toward producing literals that are
311/// legal in a variety of languages, including C++11 and similar C-family
312/// languages. The exact rules are:
313///
314/// - Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
315/// - Single-quote, double-quote and backslash chars are backslash-escaped.
316/// - Any other chars in the range [0x20,0x7e] are not escaped.
85aaf69f 317/// - Any other chars are given hex escapes of the form '\xNN'.
1a4d82fc 318/// - Unicode escapes are never generated by this function.
c34b1796
AL
319///
320/// # Examples
321///
322/// ```
323/// use std::ascii;
324///
325/// let escaped = ascii::escape_default(b'0').next().unwrap();
326/// assert_eq!(b'0', escaped);
327///
328/// let mut escaped = ascii::escape_default(b'\t');
329///
330/// assert_eq!(b'\\', escaped.next().unwrap());
331/// assert_eq!(b't', escaped.next().unwrap());
332/// ```
85aaf69f
SL
333#[stable(feature = "rust1", since = "1.0.0")]
334pub fn escape_default(c: u8) -> EscapeDefault {
335 let (data, len) = match c {
336 b'\t' => ([b'\\', b't', 0, 0], 2),
337 b'\r' => ([b'\\', b'r', 0, 0], 2),
338 b'\n' => ([b'\\', b'n', 0, 0], 2),
339 b'\\' => ([b'\\', b'\\', 0, 0], 2),
340 b'\'' => ([b'\\', b'\'', 0, 0], 2),
341 b'"' => ([b'\\', b'"', 0, 0], 2),
342 b'\x20' ... b'\x7e' => ([c, 0, 0, 0], 1),
343 _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
344 };
345
c34b1796 346 return EscapeDefault { range: (0.. len), data: data };
85aaf69f
SL
347
348 fn hexify(b: u8) -> u8 {
349 match b {
350 0 ... 9 => b'0' + b,
351 _ => b'a' + b - 10,
1a4d82fc
JJ
352 }
353 }
354}
355
85aaf69f
SL
356#[stable(feature = "rust1", since = "1.0.0")]
357impl Iterator for EscapeDefault {
358 type Item = u8;
359 fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
360 fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
361}
362#[stable(feature = "rust1", since = "1.0.0")]
363impl DoubleEndedIterator for EscapeDefault {
364 fn next_back(&mut self) -> Option<u8> {
365 self.range.next_back().map(|i| self.data[i])
366 }
367}
368#[stable(feature = "rust1", since = "1.0.0")]
369impl ExactSizeIterator for EscapeDefault {}
9e0c209e
SL
370#[unstable(feature = "fused", issue = "35602")]
371impl FusedIterator for EscapeDefault {}
372
85aaf69f 373
1a4d82fc
JJ
374static ASCII_LOWERCASE_MAP: [u8; 256] = [
375 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
376 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
377 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
378 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
379 b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
380 b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
381 b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
382 b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
383 b'@',
384
385 b'a', b'b', b'c', b'd', b'e', b'f', b'g',
386 b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
387 b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
388 b'x', b'y', b'z',
389
390 b'[', b'\\', b']', b'^', b'_',
391 b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g',
392 b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
393 b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
394 b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f,
395 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
396 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
397 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
398 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
399 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
400 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
401 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
402 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
403 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
404 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
405 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
406 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
407 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
408 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
409 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
410 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
411];
412
413static ASCII_UPPERCASE_MAP: [u8; 256] = [
414 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
415 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
416 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
417 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
418 b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
419 b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
420 b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
421 b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
422 b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G',
423 b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
424 b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
425 b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_',
426 b'`',
427
428 b'A', b'B', b'C', b'D', b'E', b'F', b'G',
429 b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
430 b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
431 b'X', b'Y', b'Z',
432
433 b'{', b'|', b'}', b'~', 0x7f,
434 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
435 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
436 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
437 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
438 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
439 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
440 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
441 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
442 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
443 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
444 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
445 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
446 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
447 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
448 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
449 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
450];
451
452
453#[cfg(test)]
454mod tests {
1a4d82fc
JJ
455 use super::*;
456 use char::from_u32;
457
458 #[test]
c1a9b12d
SL
459 fn test_is_ascii() {
460 assert!(b"".is_ascii());
461 assert!(b"banana\0\x7F".is_ascii());
462 assert!(b"banana\0\x7F".iter().all(|b| b.is_ascii()));
463 assert!(!b"Vi\xe1\xbb\x87t Nam".is_ascii());
464 assert!(!b"Vi\xe1\xbb\x87t Nam".iter().all(|b| b.is_ascii()));
465 assert!(!b"\xe1\xbb\x87".iter().any(|b| b.is_ascii()));
1a4d82fc 466
1a4d82fc 467 assert!("".is_ascii());
c1a9b12d
SL
468 assert!("banana\0\u{7F}".is_ascii());
469 assert!("banana\0\u{7F}".chars().all(|c| c.is_ascii()));
470 assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii()));
471 assert!(!"ประเทศไทย中华ệ ".chars().any(|c| c.is_ascii()));
1a4d82fc
JJ
472 }
473
474 #[test]
475 fn test_to_ascii_uppercase() {
476 assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL");
477 assert_eq!("hıKß".to_ascii_uppercase(), "HıKß");
478
c34b1796 479 for i in 0..501 {
1a4d82fc
JJ
480 let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
481 else { i };
482 assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_uppercase(),
483 (from_u32(upper).unwrap()).to_string());
1a4d82fc
JJ
484 }
485 }
486
487 #[test]
488 fn test_to_ascii_lowercase() {
489 assert_eq!("url()URL()uRl()Ürl".to_ascii_lowercase(), "url()url()url()Ürl");
490 // Dotted capital I, Kelvin sign, Sharp S.
491 assert_eq!("HİKß".to_ascii_lowercase(), "hİKß");
492
c34b1796 493 for i in 0..501 {
1a4d82fc
JJ
494 let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
495 else { i };
496 assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lowercase(),
497 (from_u32(lower).unwrap()).to_string());
1a4d82fc
JJ
498 }
499 }
500
c1a9b12d
SL
501 #[test]
502 fn test_make_ascii_lower_case() {
503 macro_rules! test {
504 ($from: expr, $to: expr) => {
505 {
506 let mut x = $from;
507 x.make_ascii_lowercase();
508 assert_eq!(x, $to);
509 }
510 }
511 }
512 test!(b'A', b'a');
513 test!(b'a', b'a');
514 test!(b'!', b'!');
515 test!('A', 'a');
516 test!('À', 'À');
517 test!('a', 'a');
518 test!('!', '!');
519 test!(b"H\xc3\x89".to_vec(), b"h\xc3\x89");
520 test!("HİKß".to_string(), "hİKß");
521 }
522
523
524 #[test]
525 fn test_make_ascii_upper_case() {
526 macro_rules! test {
527 ($from: expr, $to: expr) => {
528 {
529 let mut x = $from;
530 x.make_ascii_uppercase();
531 assert_eq!(x, $to);
532 }
533 }
534 }
535 test!(b'a', b'A');
536 test!(b'A', b'A');
537 test!(b'!', b'!');
538 test!('a', 'A');
539 test!('à', 'à');
540 test!('A', 'A');
541 test!('!', '!');
542 test!(b"h\xc3\xa9".to_vec(), b"H\xc3\xa9");
543 test!("hıKß".to_string(), "HıKß");
544
545 let mut x = "Hello".to_string();
546 x[..3].make_ascii_uppercase(); // Test IndexMut on String.
547 assert_eq!(x, "HELlo")
548 }
549
1a4d82fc
JJ
550 #[test]
551 fn test_eq_ignore_ascii_case() {
552 assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl"));
553 assert!(!"Ürl".eq_ignore_ascii_case("ürl"));
554 // Dotted capital I, Kelvin sign, Sharp S.
555 assert!("HİKß".eq_ignore_ascii_case("hİKß"));
556 assert!(!"İ".eq_ignore_ascii_case("i"));
557 assert!(!"K".eq_ignore_ascii_case("k"));
558 assert!(!"ß".eq_ignore_ascii_case("s"));
559
c34b1796 560 for i in 0..501 {
85aaf69f
SL
561 let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
562 else { i };
1a4d82fc 563 assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case(
85aaf69f 564 &from_u32(lower).unwrap().to_string()));
1a4d82fc
JJ
565 }
566 }
54a0048b
SL
567
568 #[test]
569 fn inference_works() {
570 let x = "a".to_string();
571 x.eq_ignore_ascii_case("A");
572 }
1a4d82fc 573}