]> git.lizzy.rs Git - rust.git/blob - src/libcore/char/methods.rs
Rollup merge of #71488 - spastorino:normalize-ty-to-fix-broken-mir, r=eddyb
[rust.git] / src / libcore / char / methods.rs
1 //! impl char {}
2
3 use crate::slice;
4 use crate::str::from_utf8_unchecked_mut;
5 use crate::unicode::printable::is_printable;
6 use crate::unicode::{self, conversions};
7
8 use super::*;
9
10 #[lang = "char"]
11 impl char {
12     /// Checks if a `char` is a digit in the given radix.
13     ///
14     /// A 'radix' here is sometimes also called a 'base'. A radix of two
15     /// indicates a binary number, a radix of ten, decimal, and a radix of
16     /// sixteen, hexadecimal, to give some common values. Arbitrary
17     /// radices are supported.
18     ///
19     /// Compared to `is_numeric()`, this function only recognizes the characters
20     /// `0-9`, `a-z` and `A-Z`.
21     ///
22     /// 'Digit' is defined to be only the following characters:
23     ///
24     /// * `0-9`
25     /// * `a-z`
26     /// * `A-Z`
27     ///
28     /// For a more comprehensive understanding of 'digit', see [`is_numeric`][is_numeric].
29     ///
30     /// [is_numeric]: #method.is_numeric
31     ///
32     /// # Panics
33     ///
34     /// Panics if given a radix larger than 36.
35     ///
36     /// # Examples
37     ///
38     /// Basic usage:
39     ///
40     /// ```
41     /// assert!('1'.is_digit(10));
42     /// assert!('f'.is_digit(16));
43     /// assert!(!'f'.is_digit(10));
44     /// ```
45     ///
46     /// Passing a large radix, causing a panic:
47     ///
48     /// ```
49     /// use std::thread;
50     ///
51     /// let result = thread::spawn(|| {
52     ///     // this panics
53     ///     '1'.is_digit(37);
54     /// }).join();
55     ///
56     /// assert!(result.is_err());
57     /// ```
58     #[stable(feature = "rust1", since = "1.0.0")]
59     #[inline]
60     pub fn is_digit(self, radix: u32) -> bool {
61         self.to_digit(radix).is_some()
62     }
63
64     /// Converts a `char` to a digit in the given radix.
65     ///
66     /// A 'radix' here is sometimes also called a 'base'. A radix of two
67     /// indicates a binary number, a radix of ten, decimal, and a radix of
68     /// sixteen, hexadecimal, to give some common values. Arbitrary
69     /// radices are supported.
70     ///
71     /// 'Digit' is defined to be only the following characters:
72     ///
73     /// * `0-9`
74     /// * `a-z`
75     /// * `A-Z`
76     ///
77     /// # Errors
78     ///
79     /// Returns `None` if the `char` does not refer to a digit in the given radix.
80     ///
81     /// # Panics
82     ///
83     /// Panics if given a radix larger than 36.
84     ///
85     /// # Examples
86     ///
87     /// Basic usage:
88     ///
89     /// ```
90     /// assert_eq!('1'.to_digit(10), Some(1));
91     /// assert_eq!('f'.to_digit(16), Some(15));
92     /// ```
93     ///
94     /// Passing a non-digit results in failure:
95     ///
96     /// ```
97     /// assert_eq!('f'.to_digit(10), None);
98     /// assert_eq!('z'.to_digit(16), None);
99     /// ```
100     ///
101     /// Passing a large radix, causing a panic:
102     ///
103     /// ```
104     /// use std::thread;
105     ///
106     /// let result = thread::spawn(|| {
107     ///     '1'.to_digit(37);
108     /// }).join();
109     ///
110     /// assert!(result.is_err());
111     /// ```
112     #[stable(feature = "rust1", since = "1.0.0")]
113     #[inline]
114     pub fn to_digit(self, radix: u32) -> Option<u32> {
115         assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
116
117         // the code is split up here to improve execution speed for cases where
118         // the `radix` is constant and 10 or smaller
119         let val = if radix <= 10 {
120             match self {
121                 '0'..='9' => self as u32 - '0' as u32,
122                 _ => return None,
123             }
124         } else {
125             match self {
126                 '0'..='9' => self as u32 - '0' as u32,
127                 'a'..='z' => self as u32 - 'a' as u32 + 10,
128                 'A'..='Z' => self as u32 - 'A' as u32 + 10,
129                 _ => return None,
130             }
131         };
132
133         if val < radix { Some(val) } else { None }
134     }
135
136     /// Returns an iterator that yields the hexadecimal Unicode escape of a
137     /// character as `char`s.
138     ///
139     /// This will escape characters with the Rust syntax of the form
140     /// `\u{NNNNNN}` where `NNNNNN` is a hexadecimal representation.
141     ///
142     /// # Examples
143     ///
144     /// As an iterator:
145     ///
146     /// ```
147     /// for c in '❤'.escape_unicode() {
148     ///     print!("{}", c);
149     /// }
150     /// println!();
151     /// ```
152     ///
153     /// Using `println!` directly:
154     ///
155     /// ```
156     /// println!("{}", '❤'.escape_unicode());
157     /// ```
158     ///
159     /// Both are equivalent to:
160     ///
161     /// ```
162     /// println!("\\u{{2764}}");
163     /// ```
164     ///
165     /// Using `to_string`:
166     ///
167     /// ```
168     /// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}");
169     /// ```
170     #[stable(feature = "rust1", since = "1.0.0")]
171     #[inline]
172     pub fn escape_unicode(self) -> EscapeUnicode {
173         let c = self as u32;
174
175         // or-ing 1 ensures that for c==0 the code computes that one
176         // digit should be printed and (which is the same) avoids the
177         // (31 - 32) underflow
178         let msb = 31 - (c | 1).leading_zeros();
179
180         // the index of the most significant hex digit
181         let ms_hex_digit = msb / 4;
182         EscapeUnicode {
183             c: self,
184             state: EscapeUnicodeState::Backslash,
185             hex_digit_idx: ms_hex_digit as usize,
186         }
187     }
188
189     /// An extended version of `escape_debug` that optionally permits escaping
190     /// Extended Grapheme codepoints. This allows us to format characters like
191     /// nonspacing marks better when they're at the start of a string.
192     #[inline]
193     pub(crate) fn escape_debug_ext(self, escape_grapheme_extended: bool) -> EscapeDebug {
194         let init_state = match self {
195             '\t' => EscapeDefaultState::Backslash('t'),
196             '\r' => EscapeDefaultState::Backslash('r'),
197             '\n' => EscapeDefaultState::Backslash('n'),
198             '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
199             _ if escape_grapheme_extended && self.is_grapheme_extended() => {
200                 EscapeDefaultState::Unicode(self.escape_unicode())
201             }
202             _ if is_printable(self) => EscapeDefaultState::Char(self),
203             _ => EscapeDefaultState::Unicode(self.escape_unicode()),
204         };
205         EscapeDebug(EscapeDefault { state: init_state })
206     }
207
208     /// Returns an iterator that yields the literal escape code of a character
209     /// as `char`s.
210     ///
211     /// This will escape the characters similar to the `Debug` implementations
212     /// of `str` or `char`.
213     ///
214     /// # Examples
215     ///
216     /// As an iterator:
217     ///
218     /// ```
219     /// for c in '\n'.escape_debug() {
220     ///     print!("{}", c);
221     /// }
222     /// println!();
223     /// ```
224     ///
225     /// Using `println!` directly:
226     ///
227     /// ```
228     /// println!("{}", '\n'.escape_debug());
229     /// ```
230     ///
231     /// Both are equivalent to:
232     ///
233     /// ```
234     /// println!("\\n");
235     /// ```
236     ///
237     /// Using `to_string`:
238     ///
239     /// ```
240     /// assert_eq!('\n'.escape_debug().to_string(), "\\n");
241     /// ```
242     #[stable(feature = "char_escape_debug", since = "1.20.0")]
243     #[inline]
244     pub fn escape_debug(self) -> EscapeDebug {
245         self.escape_debug_ext(true)
246     }
247
248     /// Returns an iterator that yields the literal escape code of a character
249     /// as `char`s.
250     ///
251     /// The default is chosen with a bias toward producing literals that are
252     /// legal in a variety of languages, including C++11 and similar C-family
253     /// languages. The exact rules are:
254     ///
255     /// * Tab is escaped as `\t`.
256     /// * Carriage return is escaped as `\r`.
257     /// * Line feed is escaped as `\n`.
258     /// * Single quote is escaped as `\'`.
259     /// * Double quote is escaped as `\"`.
260     /// * Backslash is escaped as `\\`.
261     /// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
262     ///   inclusive is not escaped.
263     /// * All other characters are given hexadecimal Unicode escapes; see
264     ///   [`escape_unicode`][escape_unicode].
265     ///
266     /// [escape_unicode]: #method.escape_unicode
267     ///
268     /// # Examples
269     ///
270     /// As an iterator:
271     ///
272     /// ```
273     /// for c in '"'.escape_default() {
274     ///     print!("{}", c);
275     /// }
276     /// println!();
277     /// ```
278     ///
279     /// Using `println!` directly:
280     ///
281     /// ```
282     /// println!("{}", '"'.escape_default());
283     /// ```
284     ///
285     ///
286     /// Both are equivalent to:
287     ///
288     /// ```
289     /// println!("\\\"");
290     /// ```
291     ///
292     /// Using `to_string`:
293     ///
294     /// ```
295     /// assert_eq!('"'.escape_default().to_string(), "\\\"");
296     /// ```
297     #[stable(feature = "rust1", since = "1.0.0")]
298     #[inline]
299     pub fn escape_default(self) -> EscapeDefault {
300         let init_state = match self {
301             '\t' => EscapeDefaultState::Backslash('t'),
302             '\r' => EscapeDefaultState::Backslash('r'),
303             '\n' => EscapeDefaultState::Backslash('n'),
304             '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
305             '\x20'..='\x7e' => EscapeDefaultState::Char(self),
306             _ => EscapeDefaultState::Unicode(self.escape_unicode()),
307         };
308         EscapeDefault { state: init_state }
309     }
310
311     /// Returns the number of bytes this `char` would need if encoded in UTF-8.
312     ///
313     /// That number of bytes is always between 1 and 4, inclusive.
314     ///
315     /// # Examples
316     ///
317     /// Basic usage:
318     ///
319     /// ```
320     /// let len = 'A'.len_utf8();
321     /// assert_eq!(len, 1);
322     ///
323     /// let len = 'ß'.len_utf8();
324     /// assert_eq!(len, 2);
325     ///
326     /// let len = 'ℝ'.len_utf8();
327     /// assert_eq!(len, 3);
328     ///
329     /// let len = '💣'.len_utf8();
330     /// assert_eq!(len, 4);
331     /// ```
332     ///
333     /// The `&str` type guarantees that its contents are UTF-8, and so we can compare the length it
334     /// would take if each code point was represented as a `char` vs in the `&str` itself:
335     ///
336     /// ```
337     /// // as chars
338     /// let eastern = '東';
339     /// let capital = '京';
340     ///
341     /// // both can be represented as three bytes
342     /// assert_eq!(3, eastern.len_utf8());
343     /// assert_eq!(3, capital.len_utf8());
344     ///
345     /// // as a &str, these two are encoded in UTF-8
346     /// let tokyo = "東京";
347     ///
348     /// let len = eastern.len_utf8() + capital.len_utf8();
349     ///
350     /// // we can see that they take six bytes total...
351     /// assert_eq!(6, tokyo.len());
352     ///
353     /// // ... just like the &str
354     /// assert_eq!(len, tokyo.len());
355     /// ```
356     #[stable(feature = "rust1", since = "1.0.0")]
357     #[inline]
358     pub fn len_utf8(self) -> usize {
359         let code = self as u32;
360         if code < MAX_ONE_B {
361             1
362         } else if code < MAX_TWO_B {
363             2
364         } else if code < MAX_THREE_B {
365             3
366         } else {
367             4
368         }
369     }
370
371     /// Returns the number of 16-bit code units this `char` would need if
372     /// encoded in UTF-16.
373     ///
374     /// See the documentation for [`len_utf8`] for more explanation of this
375     /// concept. This function is a mirror, but for UTF-16 instead of UTF-8.
376     ///
377     /// [`len_utf8`]: #method.len_utf8
378     ///
379     /// # Examples
380     ///
381     /// Basic usage:
382     ///
383     /// ```
384     /// let n = 'ß'.len_utf16();
385     /// assert_eq!(n, 1);
386     ///
387     /// let len = '💣'.len_utf16();
388     /// assert_eq!(len, 2);
389     /// ```
390     #[stable(feature = "rust1", since = "1.0.0")]
391     #[inline]
392     pub fn len_utf16(self) -> usize {
393         let ch = self as u32;
394         if (ch & 0xFFFF) == ch { 1 } else { 2 }
395     }
396
397     /// Encodes this character as UTF-8 into the provided byte buffer,
398     /// and then returns the subslice of the buffer that contains the encoded character.
399     ///
400     /// # Panics
401     ///
402     /// Panics if the buffer is not large enough.
403     /// A buffer of length four is large enough to encode any `char`.
404     ///
405     /// # Examples
406     ///
407     /// In both of these examples, 'ß' takes two bytes to encode.
408     ///
409     /// ```
410     /// let mut b = [0; 2];
411     ///
412     /// let result = 'ß'.encode_utf8(&mut b);
413     ///
414     /// assert_eq!(result, "ß");
415     ///
416     /// assert_eq!(result.len(), 2);
417     /// ```
418     ///
419     /// A buffer that's too small:
420     ///
421     /// ```
422     /// use std::thread;
423     ///
424     /// let result = thread::spawn(|| {
425     ///     let mut b = [0; 1];
426     ///
427     ///     // this panics
428     ///    'ß'.encode_utf8(&mut b);
429     /// }).join();
430     ///
431     /// assert!(result.is_err());
432     /// ```
433     #[stable(feature = "unicode_encode_char", since = "1.15.0")]
434     #[inline]
435     pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
436         let code = self as u32;
437         let len = self.len_utf8();
438         match (len, &mut dst[..]) {
439             (1, [a, ..]) => {
440                 *a = code as u8;
441             }
442             (2, [a, b, ..]) => {
443                 *a = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
444                 *b = (code & 0x3F) as u8 | TAG_CONT;
445             }
446             (3, [a, b, c, ..]) => {
447                 *a = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
448                 *b = (code >> 6 & 0x3F) as u8 | TAG_CONT;
449                 *c = (code & 0x3F) as u8 | TAG_CONT;
450             }
451             (4, [a, b, c, d, ..]) => {
452                 *a = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
453                 *b = (code >> 12 & 0x3F) as u8 | TAG_CONT;
454                 *c = (code >> 6 & 0x3F) as u8 | TAG_CONT;
455                 *d = (code & 0x3F) as u8 | TAG_CONT;
456             }
457             _ => panic!(
458                 "encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
459                 len,
460                 code,
461                 dst.len(),
462             ),
463         };
464         // SAFETY: We just wrote UTF-8 content in, so converting to str is fine.
465         unsafe { from_utf8_unchecked_mut(&mut dst[..len]) }
466     }
467
468     /// Encodes this character as UTF-16 into the provided `u16` buffer,
469     /// and then returns the subslice of the buffer that contains the encoded character.
470     ///
471     /// # Panics
472     ///
473     /// Panics if the buffer is not large enough.
474     /// A buffer of length 2 is large enough to encode any `char`.
475     ///
476     /// # Examples
477     ///
478     /// In both of these examples, '𝕊' takes two `u16`s to encode.
479     ///
480     /// ```
481     /// let mut b = [0; 2];
482     ///
483     /// let result = '𝕊'.encode_utf16(&mut b);
484     ///
485     /// assert_eq!(result.len(), 2);
486     /// ```
487     ///
488     /// A buffer that's too small:
489     ///
490     /// ```
491     /// use std::thread;
492     ///
493     /// let result = thread::spawn(|| {
494     ///     let mut b = [0; 1];
495     ///
496     ///     // this panics
497     ///     '𝕊'.encode_utf16(&mut b);
498     /// }).join();
499     ///
500     /// assert!(result.is_err());
501     /// ```
502     #[stable(feature = "unicode_encode_char", since = "1.15.0")]
503     #[inline]
504     pub fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] {
505         let mut code = self as u32;
506         // SAFETY: each arm checks whether there are enough bits to write into
507         unsafe {
508             if (code & 0xFFFF) == code && !dst.is_empty() {
509                 // The BMP falls through (assuming non-surrogate, as it should)
510                 *dst.get_unchecked_mut(0) = code as u16;
511                 slice::from_raw_parts_mut(dst.as_mut_ptr(), 1)
512             } else if dst.len() >= 2 {
513                 // Supplementary planes break into surrogates.
514                 code -= 0x1_0000;
515                 *dst.get_unchecked_mut(0) = 0xD800 | ((code >> 10) as u16);
516                 *dst.get_unchecked_mut(1) = 0xDC00 | ((code as u16) & 0x3FF);
517                 slice::from_raw_parts_mut(dst.as_mut_ptr(), 2)
518             } else {
519                 panic!(
520                     "encode_utf16: need {} units to encode U+{:X}, but the buffer has {}",
521                     from_u32_unchecked(code).len_utf16(),
522                     code,
523                     dst.len(),
524                 )
525             }
526         }
527     }
528
529     /// Returns `true` if this `char` has the `Alphabetic` property.
530     ///
531     /// `Alphabetic` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
532     /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
533     ///
534     /// [Unicode Standard]: https://www.unicode.org/versions/latest/
535     /// [ucd]: https://www.unicode.org/reports/tr44/
536     /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
537     ///
538     /// # Examples
539     ///
540     /// Basic usage:
541     ///
542     /// ```
543     /// assert!('a'.is_alphabetic());
544     /// assert!('京'.is_alphabetic());
545     ///
546     /// let c = '💝';
547     /// // love is many things, but it is not alphabetic
548     /// assert!(!c.is_alphabetic());
549     /// ```
550     #[stable(feature = "rust1", since = "1.0.0")]
551     #[inline]
552     pub fn is_alphabetic(self) -> bool {
553         match self {
554             'a'..='z' | 'A'..='Z' => true,
555             c => c > '\x7f' && unicode::Alphabetic(c),
556         }
557     }
558
559     /// Returns `true` if this `char` has the `Lowercase` property.
560     ///
561     /// `Lowercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
562     /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
563     ///
564     /// [Unicode Standard]: https://www.unicode.org/versions/latest/
565     /// [ucd]: https://www.unicode.org/reports/tr44/
566     /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
567     ///
568     /// # Examples
569     ///
570     /// Basic usage:
571     ///
572     /// ```
573     /// assert!('a'.is_lowercase());
574     /// assert!('δ'.is_lowercase());
575     /// assert!(!'A'.is_lowercase());
576     /// assert!(!'Δ'.is_lowercase());
577     ///
578     /// // The various Chinese scripts do not have case, and so:
579     /// assert!(!'中'.is_lowercase());
580     /// ```
581     #[stable(feature = "rust1", since = "1.0.0")]
582     #[inline]
583     pub fn is_lowercase(self) -> bool {
584         match self {
585             'a'..='z' => true,
586             c => c > '\x7f' && unicode::Lowercase(c),
587         }
588     }
589
590     /// Returns `true` if this `char` has the `Uppercase` property.
591     ///
592     /// `Uppercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
593     /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
594     ///
595     /// [Unicode Standard]: https://www.unicode.org/versions/latest/
596     /// [ucd]: https://www.unicode.org/reports/tr44/
597     /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
598     ///
599     /// # Examples
600     ///
601     /// Basic usage:
602     ///
603     /// ```
604     /// assert!(!'a'.is_uppercase());
605     /// assert!(!'δ'.is_uppercase());
606     /// assert!('A'.is_uppercase());
607     /// assert!('Δ'.is_uppercase());
608     ///
609     /// // The various Chinese scripts do not have case, and so:
610     /// assert!(!'中'.is_uppercase());
611     /// ```
612     #[stable(feature = "rust1", since = "1.0.0")]
613     #[inline]
614     pub fn is_uppercase(self) -> bool {
615         match self {
616             'A'..='Z' => true,
617             c => c > '\x7f' && unicode::Uppercase(c),
618         }
619     }
620
621     /// Returns `true` if this `char` has the `White_Space` property.
622     ///
623     /// `White_Space` is specified in the [Unicode Character Database][ucd] [`PropList.txt`].
624     ///
625     /// [ucd]: https://www.unicode.org/reports/tr44/
626     /// [`PropList.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt
627     ///
628     /// # Examples
629     ///
630     /// Basic usage:
631     ///
632     /// ```
633     /// assert!(' '.is_whitespace());
634     ///
635     /// // a non-breaking space
636     /// assert!('\u{A0}'.is_whitespace());
637     ///
638     /// assert!(!'越'.is_whitespace());
639     /// ```
640     #[stable(feature = "rust1", since = "1.0.0")]
641     #[inline]
642     pub fn is_whitespace(self) -> bool {
643         match self {
644             ' ' | '\x09'..='\x0d' => true,
645             c => c > '\x7f' && unicode::White_Space(c),
646         }
647     }
648
649     /// Returns `true` if this `char` satisfies either [`is_alphabetic()`] or [`is_numeric()`].
650     ///
651     /// [`is_alphabetic()`]: #method.is_alphabetic
652     /// [`is_numeric()`]: #method.is_numeric
653     ///
654     /// # Examples
655     ///
656     /// Basic usage:
657     ///
658     /// ```
659     /// assert!('٣'.is_alphanumeric());
660     /// assert!('7'.is_alphanumeric());
661     /// assert!('৬'.is_alphanumeric());
662     /// assert!('¾'.is_alphanumeric());
663     /// assert!('①'.is_alphanumeric());
664     /// assert!('K'.is_alphanumeric());
665     /// assert!('و'.is_alphanumeric());
666     /// assert!('藏'.is_alphanumeric());
667     /// ```
668     #[stable(feature = "rust1", since = "1.0.0")]
669     #[inline]
670     pub fn is_alphanumeric(self) -> bool {
671         self.is_alphabetic() || self.is_numeric()
672     }
673
674     /// Returns `true` if this `char` has the general category for control codes.
675     ///
676     /// Control codes (code points with the general category of `Cc`) are described in Chapter 4
677     /// (Character Properties) of the [Unicode Standard] and specified in the [Unicode Character
678     /// Database][ucd] [`UnicodeData.txt`].
679     ///
680     /// [Unicode Standard]: https://www.unicode.org/versions/latest/
681     /// [ucd]: https://www.unicode.org/reports/tr44/
682     /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
683     ///
684     /// # Examples
685     ///
686     /// Basic usage:
687     ///
688     /// ```
689     /// // U+009C, STRING TERMINATOR
690     /// assert!('\9c'.is_control());
691     /// assert!(!'q'.is_control());
692     /// ```
693     #[stable(feature = "rust1", since = "1.0.0")]
694     #[inline]
695     pub fn is_control(self) -> bool {
696         unicode::Cc(self)
697     }
698
699     /// Returns `true` if this `char` has the `Grapheme_Extend` property.
700     ///
701     /// `Grapheme_Extend` is described in [Unicode Standard Annex #29 (Unicode Text
702     /// Segmentation)][uax29] and specified in the [Unicode Character Database][ucd]
703     /// [`DerivedCoreProperties.txt`].
704     ///
705     /// [uax29]: https://www.unicode.org/reports/tr29/
706     /// [ucd]: https://www.unicode.org/reports/tr44/
707     /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
708     #[inline]
709     pub(crate) fn is_grapheme_extended(self) -> bool {
710         unicode::Grapheme_Extend(self)
711     }
712
713     /// Returns `true` if this `char` has one of the general categories for numbers.
714     ///
715     /// The general categories for numbers (`Nd` for decimal digits, `Nl` for letter-like numeric
716     /// characters, and `No` for other numeric characters) are specified in the [Unicode Character
717     /// Database][ucd] [`UnicodeData.txt`].
718     ///
719     /// [Unicode Standard]: https://www.unicode.org/versions/latest/
720     /// [ucd]: https://www.unicode.org/reports/tr44/
721     /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
722     ///
723     /// # Examples
724     ///
725     /// Basic usage:
726     ///
727     /// ```
728     /// assert!('٣'.is_numeric());
729     /// assert!('7'.is_numeric());
730     /// assert!('৬'.is_numeric());
731     /// assert!('¾'.is_numeric());
732     /// assert!('①'.is_numeric());
733     /// assert!(!'K'.is_numeric());
734     /// assert!(!'و'.is_numeric());
735     /// assert!(!'藏'.is_numeric());
736     /// ```
737     #[stable(feature = "rust1", since = "1.0.0")]
738     #[inline]
739     pub fn is_numeric(self) -> bool {
740         match self {
741             '0'..='9' => true,
742             c => c > '\x7f' && unicode::N(c),
743         }
744     }
745
746     /// Returns an iterator that yields the lowercase mapping of this `char` as one or more
747     /// `char`s.
748     ///
749     /// If this `char` does not have a lowercase mapping, the iterator yields the same `char`.
750     ///
751     /// If this `char` has a one-to-one lowercase mapping given by the [Unicode Character
752     /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
753     ///
754     /// [ucd]: https://www.unicode.org/reports/tr44/
755     /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
756     ///
757     /// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields
758     /// the `char`(s) given by [`SpecialCasing.txt`].
759     ///
760     /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
761     ///
762     /// This operation performs an unconditional mapping without tailoring. That is, the conversion
763     /// is independent of context and language.
764     ///
765     /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
766     /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
767     ///
768     /// [Unicode Standard]: https://www.unicode.org/versions/latest/
769     ///
770     /// # Examples
771     ///
772     /// As an iterator:
773     ///
774     /// ```
775     /// for c in 'İ'.to_lowercase() {
776     ///     print!("{}", c);
777     /// }
778     /// println!();
779     /// ```
780     ///
781     /// Using `println!` directly:
782     ///
783     /// ```
784     /// println!("{}", 'İ'.to_lowercase());
785     /// ```
786     ///
787     /// Both are equivalent to:
788     ///
789     /// ```
790     /// println!("i\u{307}");
791     /// ```
792     ///
793     /// Using `to_string`:
794     ///
795     /// ```
796     /// assert_eq!('C'.to_lowercase().to_string(), "c");
797     ///
798     /// // Sometimes the result is more than one character:
799     /// assert_eq!('İ'.to_lowercase().to_string(), "i\u{307}");
800     ///
801     /// // Characters that do not have both uppercase and lowercase
802     /// // convert into themselves.
803     /// assert_eq!('山'.to_lowercase().to_string(), "山");
804     /// ```
805     #[stable(feature = "rust1", since = "1.0.0")]
806     #[inline]
807     pub fn to_lowercase(self) -> ToLowercase {
808         ToLowercase(CaseMappingIter::new(conversions::to_lower(self)))
809     }
810
811     /// Returns an iterator that yields the uppercase mapping of this `char` as one or more
812     /// `char`s.
813     ///
814     /// If this `char` does not have a uppercase mapping, the iterator yields the same `char`.
815     ///
816     /// If this `char` has a one-to-one uppercase mapping given by the [Unicode Character
817     /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
818     ///
819     /// [ucd]: https://www.unicode.org/reports/tr44/
820     /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
821     ///
822     /// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields
823     /// the `char`(s) given by [`SpecialCasing.txt`].
824     ///
825     /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
826     ///
827     /// This operation performs an unconditional mapping without tailoring. That is, the conversion
828     /// is independent of context and language.
829     ///
830     /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
831     /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
832     ///
833     /// [Unicode Standard]: https://www.unicode.org/versions/latest/
834     ///
835     /// # Examples
836     ///
837     /// As an iterator:
838     ///
839     /// ```
840     /// for c in 'ß'.to_uppercase() {
841     ///     print!("{}", c);
842     /// }
843     /// println!();
844     /// ```
845     ///
846     /// Using `println!` directly:
847     ///
848     /// ```
849     /// println!("{}", 'ß'.to_uppercase());
850     /// ```
851     ///
852     /// Both are equivalent to:
853     ///
854     /// ```
855     /// println!("SS");
856     /// ```
857     ///
858     /// Using `to_string`:
859     ///
860     /// ```
861     /// assert_eq!('c'.to_uppercase().to_string(), "C");
862     ///
863     /// // Sometimes the result is more than one character:
864     /// assert_eq!('ß'.to_uppercase().to_string(), "SS");
865     ///
866     /// // Characters that do not have both uppercase and lowercase
867     /// // convert into themselves.
868     /// assert_eq!('山'.to_uppercase().to_string(), "山");
869     /// ```
870     ///
871     /// # Note on locale
872     ///
873     /// In Turkish, the equivalent of 'i' in Latin has five forms instead of two:
874     ///
875     /// * 'Dotless': I / ı, sometimes written ï
876     /// * 'Dotted': İ / i
877     ///
878     /// Note that the lowercase dotted 'i' is the same as the Latin. Therefore:
879     ///
880     /// ```
881     /// let upper_i = 'i'.to_uppercase().to_string();
882     /// ```
883     ///
884     /// The value of `upper_i` here relies on the language of the text: if we're
885     /// in `en-US`, it should be `"I"`, but if we're in `tr_TR`, it should
886     /// be `"İ"`. `to_uppercase()` does not take this into account, and so:
887     ///
888     /// ```
889     /// let upper_i = 'i'.to_uppercase().to_string();
890     ///
891     /// assert_eq!(upper_i, "I");
892     /// ```
893     ///
894     /// holds across languages.
895     #[stable(feature = "rust1", since = "1.0.0")]
896     #[inline]
897     pub fn to_uppercase(self) -> ToUppercase {
898         ToUppercase(CaseMappingIter::new(conversions::to_upper(self)))
899     }
900
901     /// Checks if the value is within the ASCII range.
902     ///
903     /// # Examples
904     ///
905     /// ```
906     /// let ascii = 'a';
907     /// let non_ascii = '❤';
908     ///
909     /// assert!(ascii.is_ascii());
910     /// assert!(!non_ascii.is_ascii());
911     /// ```
912     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
913     #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.32.0")]
914     #[inline]
915     pub const fn is_ascii(&self) -> bool {
916         *self as u32 <= 0x7F
917     }
918
919     /// Makes a copy of the value in its ASCII upper case equivalent.
920     ///
921     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
922     /// but non-ASCII letters are unchanged.
923     ///
924     /// To uppercase the value in-place, use [`make_ascii_uppercase`].
925     ///
926     /// To uppercase ASCII characters in addition to non-ASCII characters, use
927     /// [`to_uppercase`].
928     ///
929     /// # Examples
930     ///
931     /// ```
932     /// let ascii = 'a';
933     /// let non_ascii = '❤';
934     ///
935     /// assert_eq!('A', ascii.to_ascii_uppercase());
936     /// assert_eq!('❤', non_ascii.to_ascii_uppercase());
937     /// ```
938     ///
939     /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
940     /// [`to_uppercase`]: #method.to_uppercase
941     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
942     #[inline]
943     pub fn to_ascii_uppercase(&self) -> char {
944         if self.is_ascii() { (*self as u8).to_ascii_uppercase() as char } else { *self }
945     }
946
947     /// Makes a copy of the value in its ASCII lower case equivalent.
948     ///
949     /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
950     /// but non-ASCII letters are unchanged.
951     ///
952     /// To lowercase the value in-place, use [`make_ascii_lowercase`].
953     ///
954     /// To lowercase ASCII characters in addition to non-ASCII characters, use
955     /// [`to_lowercase`].
956     ///
957     /// # Examples
958     ///
959     /// ```
960     /// let ascii = 'A';
961     /// let non_ascii = '❤';
962     ///
963     /// assert_eq!('a', ascii.to_ascii_lowercase());
964     /// assert_eq!('❤', non_ascii.to_ascii_lowercase());
965     /// ```
966     ///
967     /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
968     /// [`to_lowercase`]: #method.to_lowercase
969     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
970     #[inline]
971     pub fn to_ascii_lowercase(&self) -> char {
972         if self.is_ascii() { (*self as u8).to_ascii_lowercase() as char } else { *self }
973     }
974
975     /// Checks that two values are an ASCII case-insensitive match.
976     ///
977     /// Equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`.
978     ///
979     /// # Examples
980     ///
981     /// ```
982     /// let upper_a = 'A';
983     /// let lower_a = 'a';
984     /// let lower_z = 'z';
985     ///
986     /// assert!(upper_a.eq_ignore_ascii_case(&lower_a));
987     /// assert!(upper_a.eq_ignore_ascii_case(&upper_a));
988     /// assert!(!upper_a.eq_ignore_ascii_case(&lower_z));
989     /// ```
990     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
991     #[inline]
992     pub fn eq_ignore_ascii_case(&self, other: &char) -> bool {
993         self.to_ascii_lowercase() == other.to_ascii_lowercase()
994     }
995
996     /// Converts this type to its ASCII upper case equivalent in-place.
997     ///
998     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
999     /// but non-ASCII letters are unchanged.
1000     ///
1001     /// To return a new uppercased value without modifying the existing one, use
1002     /// [`to_ascii_uppercase`].
1003     ///
1004     /// # Examples
1005     ///
1006     /// ```
1007     /// let mut ascii = 'a';
1008     ///
1009     /// ascii.make_ascii_uppercase();
1010     ///
1011     /// assert_eq!('A', ascii);
1012     /// ```
1013     ///
1014     /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
1015     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
1016     #[inline]
1017     pub fn make_ascii_uppercase(&mut self) {
1018         *self = self.to_ascii_uppercase();
1019     }
1020
1021     /// Converts this type to its ASCII lower case equivalent in-place.
1022     ///
1023     /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
1024     /// but non-ASCII letters are unchanged.
1025     ///
1026     /// To return a new lowercased value without modifying the existing one, use
1027     /// [`to_ascii_lowercase`].
1028     ///
1029     /// # Examples
1030     ///
1031     /// ```
1032     /// let mut ascii = 'A';
1033     ///
1034     /// ascii.make_ascii_lowercase();
1035     ///
1036     /// assert_eq!('a', ascii);
1037     /// ```
1038     ///
1039     /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
1040     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
1041     #[inline]
1042     pub fn make_ascii_lowercase(&mut self) {
1043         *self = self.to_ascii_lowercase();
1044     }
1045
1046     /// Checks if the value is an ASCII alphabetic character:
1047     ///
1048     /// - U+0041 'A' ..= U+005A 'Z', or
1049     /// - U+0061 'a' ..= U+007A 'z'.
1050     ///
1051     /// # Examples
1052     ///
1053     /// ```
1054     /// let uppercase_a = 'A';
1055     /// let uppercase_g = 'G';
1056     /// let a = 'a';
1057     /// let g = 'g';
1058     /// let zero = '0';
1059     /// let percent = '%';
1060     /// let space = ' ';
1061     /// let lf = '\n';
1062     /// let esc: char = 0x1b_u8.into();
1063     ///
1064     /// assert!(uppercase_a.is_ascii_alphabetic());
1065     /// assert!(uppercase_g.is_ascii_alphabetic());
1066     /// assert!(a.is_ascii_alphabetic());
1067     /// assert!(g.is_ascii_alphabetic());
1068     /// assert!(!zero.is_ascii_alphabetic());
1069     /// assert!(!percent.is_ascii_alphabetic());
1070     /// assert!(!space.is_ascii_alphabetic());
1071     /// assert!(!lf.is_ascii_alphabetic());
1072     /// assert!(!esc.is_ascii_alphabetic());
1073     /// ```
1074     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1075     #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")]
1076     #[inline]
1077     pub const fn is_ascii_alphabetic(&self) -> bool {
1078         match *self {
1079             'A'..='Z' | 'a'..='z' => true,
1080             _ => false,
1081         }
1082     }
1083
1084     /// Checks if the value is an ASCII uppercase character:
1085     /// U+0041 'A' ..= U+005A 'Z'.
1086     ///
1087     /// # Examples
1088     ///
1089     /// ```
1090     /// let uppercase_a = 'A';
1091     /// let uppercase_g = 'G';
1092     /// let a = 'a';
1093     /// let g = 'g';
1094     /// let zero = '0';
1095     /// let percent = '%';
1096     /// let space = ' ';
1097     /// let lf = '\n';
1098     /// let esc: char = 0x1b_u8.into();
1099     ///
1100     /// assert!(uppercase_a.is_ascii_uppercase());
1101     /// assert!(uppercase_g.is_ascii_uppercase());
1102     /// assert!(!a.is_ascii_uppercase());
1103     /// assert!(!g.is_ascii_uppercase());
1104     /// assert!(!zero.is_ascii_uppercase());
1105     /// assert!(!percent.is_ascii_uppercase());
1106     /// assert!(!space.is_ascii_uppercase());
1107     /// assert!(!lf.is_ascii_uppercase());
1108     /// assert!(!esc.is_ascii_uppercase());
1109     /// ```
1110     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1111     #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")]
1112     #[inline]
1113     pub const fn is_ascii_uppercase(&self) -> bool {
1114         match *self {
1115             'A'..='Z' => true,
1116             _ => false,
1117         }
1118     }
1119
1120     /// Checks if the value is an ASCII lowercase character:
1121     /// U+0061 'a' ..= U+007A 'z'.
1122     ///
1123     /// # Examples
1124     ///
1125     /// ```
1126     /// let uppercase_a = 'A';
1127     /// let uppercase_g = 'G';
1128     /// let a = 'a';
1129     /// let g = 'g';
1130     /// let zero = '0';
1131     /// let percent = '%';
1132     /// let space = ' ';
1133     /// let lf = '\n';
1134     /// let esc: char = 0x1b_u8.into();
1135     ///
1136     /// assert!(!uppercase_a.is_ascii_lowercase());
1137     /// assert!(!uppercase_g.is_ascii_lowercase());
1138     /// assert!(a.is_ascii_lowercase());
1139     /// assert!(g.is_ascii_lowercase());
1140     /// assert!(!zero.is_ascii_lowercase());
1141     /// assert!(!percent.is_ascii_lowercase());
1142     /// assert!(!space.is_ascii_lowercase());
1143     /// assert!(!lf.is_ascii_lowercase());
1144     /// assert!(!esc.is_ascii_lowercase());
1145     /// ```
1146     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1147     #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")]
1148     #[inline]
1149     pub const fn is_ascii_lowercase(&self) -> bool {
1150         match *self {
1151             'a'..='z' => true,
1152             _ => false,
1153         }
1154     }
1155
1156     /// Checks if the value is an ASCII alphanumeric character:
1157     ///
1158     /// - U+0041 'A' ..= U+005A 'Z', or
1159     /// - U+0061 'a' ..= U+007A 'z', or
1160     /// - U+0030 '0' ..= U+0039 '9'.
1161     ///
1162     /// # Examples
1163     ///
1164     /// ```
1165     /// let uppercase_a = 'A';
1166     /// let uppercase_g = 'G';
1167     /// let a = 'a';
1168     /// let g = 'g';
1169     /// let zero = '0';
1170     /// let percent = '%';
1171     /// let space = ' ';
1172     /// let lf = '\n';
1173     /// let esc: char = 0x1b_u8.into();
1174     ///
1175     /// assert!(uppercase_a.is_ascii_alphanumeric());
1176     /// assert!(uppercase_g.is_ascii_alphanumeric());
1177     /// assert!(a.is_ascii_alphanumeric());
1178     /// assert!(g.is_ascii_alphanumeric());
1179     /// assert!(zero.is_ascii_alphanumeric());
1180     /// assert!(!percent.is_ascii_alphanumeric());
1181     /// assert!(!space.is_ascii_alphanumeric());
1182     /// assert!(!lf.is_ascii_alphanumeric());
1183     /// assert!(!esc.is_ascii_alphanumeric());
1184     /// ```
1185     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1186     #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")]
1187     #[inline]
1188     pub const fn is_ascii_alphanumeric(&self) -> bool {
1189         match *self {
1190             '0'..='9' | 'A'..='Z' | 'a'..='z' => true,
1191             _ => false,
1192         }
1193     }
1194
1195     /// Checks if the value is an ASCII decimal digit:
1196     /// U+0030 '0' ..= U+0039 '9'.
1197     ///
1198     /// # Examples
1199     ///
1200     /// ```
1201     /// let uppercase_a = 'A';
1202     /// let uppercase_g = 'G';
1203     /// let a = 'a';
1204     /// let g = 'g';
1205     /// let zero = '0';
1206     /// let percent = '%';
1207     /// let space = ' ';
1208     /// let lf = '\n';
1209     /// let esc: char = 0x1b_u8.into();
1210     ///
1211     /// assert!(!uppercase_a.is_ascii_digit());
1212     /// assert!(!uppercase_g.is_ascii_digit());
1213     /// assert!(!a.is_ascii_digit());
1214     /// assert!(!g.is_ascii_digit());
1215     /// assert!(zero.is_ascii_digit());
1216     /// assert!(!percent.is_ascii_digit());
1217     /// assert!(!space.is_ascii_digit());
1218     /// assert!(!lf.is_ascii_digit());
1219     /// assert!(!esc.is_ascii_digit());
1220     /// ```
1221     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1222     #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")]
1223     #[inline]
1224     pub const fn is_ascii_digit(&self) -> bool {
1225         match *self {
1226             '0'..='9' => true,
1227             _ => false,
1228         }
1229     }
1230
1231     /// Checks if the value is an ASCII hexadecimal digit:
1232     ///
1233     /// - U+0030 '0' ..= U+0039 '9', or
1234     /// - U+0041 'A' ..= U+0046 'F', or
1235     /// - U+0061 'a' ..= U+0066 'f'.
1236     ///
1237     /// # Examples
1238     ///
1239     /// ```
1240     /// let uppercase_a = 'A';
1241     /// let uppercase_g = 'G';
1242     /// let a = 'a';
1243     /// let g = 'g';
1244     /// let zero = '0';
1245     /// let percent = '%';
1246     /// let space = ' ';
1247     /// let lf = '\n';
1248     /// let esc: char = 0x1b_u8.into();
1249     ///
1250     /// assert!(uppercase_a.is_ascii_hexdigit());
1251     /// assert!(!uppercase_g.is_ascii_hexdigit());
1252     /// assert!(a.is_ascii_hexdigit());
1253     /// assert!(!g.is_ascii_hexdigit());
1254     /// assert!(zero.is_ascii_hexdigit());
1255     /// assert!(!percent.is_ascii_hexdigit());
1256     /// assert!(!space.is_ascii_hexdigit());
1257     /// assert!(!lf.is_ascii_hexdigit());
1258     /// assert!(!esc.is_ascii_hexdigit());
1259     /// ```
1260     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1261     #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")]
1262     #[inline]
1263     pub const fn is_ascii_hexdigit(&self) -> bool {
1264         match *self {
1265             '0'..='9' | 'A'..='F' | 'a'..='f' => true,
1266             _ => false,
1267         }
1268     }
1269
1270     /// Checks if the value is an ASCII punctuation character:
1271     ///
1272     /// - U+0021 ..= U+002F `! " # $ % & ' ( ) * + , - . /`, or
1273     /// - U+003A ..= U+0040 `: ; < = > ? @`, or
1274     /// - U+005B ..= U+0060 ``[ \ ] ^ _ ` ``, or
1275     /// - U+007B ..= U+007E `{ | } ~`
1276     ///
1277     /// # Examples
1278     ///
1279     /// ```
1280     /// let uppercase_a = 'A';
1281     /// let uppercase_g = 'G';
1282     /// let a = 'a';
1283     /// let g = 'g';
1284     /// let zero = '0';
1285     /// let percent = '%';
1286     /// let space = ' ';
1287     /// let lf = '\n';
1288     /// let esc: char = 0x1b_u8.into();
1289     ///
1290     /// assert!(!uppercase_a.is_ascii_punctuation());
1291     /// assert!(!uppercase_g.is_ascii_punctuation());
1292     /// assert!(!a.is_ascii_punctuation());
1293     /// assert!(!g.is_ascii_punctuation());
1294     /// assert!(!zero.is_ascii_punctuation());
1295     /// assert!(percent.is_ascii_punctuation());
1296     /// assert!(!space.is_ascii_punctuation());
1297     /// assert!(!lf.is_ascii_punctuation());
1298     /// assert!(!esc.is_ascii_punctuation());
1299     /// ```
1300     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1301     #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")]
1302     #[inline]
1303     pub const fn is_ascii_punctuation(&self) -> bool {
1304         match *self {
1305             '!'..='/' | ':'..='@' | '['..='`' | '{'..='~' => true,
1306             _ => false,
1307         }
1308     }
1309
1310     /// Checks if the value is an ASCII graphic character:
1311     /// U+0021 '!' ..= U+007E '~'.
1312     ///
1313     /// # Examples
1314     ///
1315     /// ```
1316     /// let uppercase_a = 'A';
1317     /// let uppercase_g = 'G';
1318     /// let a = 'a';
1319     /// let g = 'g';
1320     /// let zero = '0';
1321     /// let percent = '%';
1322     /// let space = ' ';
1323     /// let lf = '\n';
1324     /// let esc: char = 0x1b_u8.into();
1325     ///
1326     /// assert!(uppercase_a.is_ascii_graphic());
1327     /// assert!(uppercase_g.is_ascii_graphic());
1328     /// assert!(a.is_ascii_graphic());
1329     /// assert!(g.is_ascii_graphic());
1330     /// assert!(zero.is_ascii_graphic());
1331     /// assert!(percent.is_ascii_graphic());
1332     /// assert!(!space.is_ascii_graphic());
1333     /// assert!(!lf.is_ascii_graphic());
1334     /// assert!(!esc.is_ascii_graphic());
1335     /// ```
1336     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1337     #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")]
1338     #[inline]
1339     pub const fn is_ascii_graphic(&self) -> bool {
1340         match *self {
1341             '!'..='~' => true,
1342             _ => false,
1343         }
1344     }
1345
1346     /// Checks if the value is an ASCII whitespace character:
1347     /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
1348     /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
1349     ///
1350     /// Rust uses the WhatWG Infra Standard's [definition of ASCII
1351     /// whitespace][infra-aw]. There are several other definitions in
1352     /// wide use. For instance, [the POSIX locale][pct] includes
1353     /// U+000B VERTICAL TAB as well as all the above characters,
1354     /// but—from the very same specification—[the default rule for
1355     /// "field splitting" in the Bourne shell][bfs] considers *only*
1356     /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
1357     ///
1358     /// If you are writing a program that will process an existing
1359     /// file format, check what that format's definition of whitespace is
1360     /// before using this function.
1361     ///
1362     /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
1363     /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
1364     /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
1365     ///
1366     /// # Examples
1367     ///
1368     /// ```
1369     /// let uppercase_a = 'A';
1370     /// let uppercase_g = 'G';
1371     /// let a = 'a';
1372     /// let g = 'g';
1373     /// let zero = '0';
1374     /// let percent = '%';
1375     /// let space = ' ';
1376     /// let lf = '\n';
1377     /// let esc: char = 0x1b_u8.into();
1378     ///
1379     /// assert!(!uppercase_a.is_ascii_whitespace());
1380     /// assert!(!uppercase_g.is_ascii_whitespace());
1381     /// assert!(!a.is_ascii_whitespace());
1382     /// assert!(!g.is_ascii_whitespace());
1383     /// assert!(!zero.is_ascii_whitespace());
1384     /// assert!(!percent.is_ascii_whitespace());
1385     /// assert!(space.is_ascii_whitespace());
1386     /// assert!(lf.is_ascii_whitespace());
1387     /// assert!(!esc.is_ascii_whitespace());
1388     /// ```
1389     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1390     #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")]
1391     #[inline]
1392     pub const fn is_ascii_whitespace(&self) -> bool {
1393         match *self {
1394             '\t' | '\n' | '\x0C' | '\r' | ' ' => true,
1395             _ => false,
1396         }
1397     }
1398
1399     /// Checks if the value is an ASCII control character:
1400     /// U+0000 NUL ..= U+001F UNIT SEPARATOR, or U+007F DELETE.
1401     /// Note that most ASCII whitespace characters are control
1402     /// characters, but SPACE is not.
1403     ///
1404     /// # Examples
1405     ///
1406     /// ```
1407     /// let uppercase_a = 'A';
1408     /// let uppercase_g = 'G';
1409     /// let a = 'a';
1410     /// let g = 'g';
1411     /// let zero = '0';
1412     /// let percent = '%';
1413     /// let space = ' ';
1414     /// let lf = '\n';
1415     /// let esc: char = 0x1b_u8.into();
1416     ///
1417     /// assert!(!uppercase_a.is_ascii_control());
1418     /// assert!(!uppercase_g.is_ascii_control());
1419     /// assert!(!a.is_ascii_control());
1420     /// assert!(!g.is_ascii_control());
1421     /// assert!(!zero.is_ascii_control());
1422     /// assert!(!percent.is_ascii_control());
1423     /// assert!(!space.is_ascii_control());
1424     /// assert!(lf.is_ascii_control());
1425     /// assert!(esc.is_ascii_control());
1426     /// ```
1427     #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1428     #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")]
1429     #[inline]
1430     pub const fn is_ascii_control(&self) -> bool {
1431         match *self {
1432             '\0'..='\x1F' | '\x7F' => true,
1433             _ => false,
1434         }
1435     }
1436 }