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