Skip to main content

core/char/
methods.rs

1//! impl char {}
2
3use super::*;
4use crate::panic::const_panic;
5use crate::slice;
6use crate::str::from_utf8_unchecked_mut;
7use crate::ub_checks::assert_unsafe_precondition;
8use crate::unicode::{self, conversions};
9
10impl char {
11    /// The lowest valid code point a `char` can have, `'\0'`.
12    ///
13    /// Unlike integer types, `char` actually has a gap in the middle,
14    /// meaning that the range of possible `char`s is smaller than you
15    /// might expect. Ranges of `char` will automatically hop this gap
16    /// for you:
17    ///
18    /// ```
19    /// let dist = u32::from(char::MAX) - u32::from(char::MIN);
20    /// let size = (char::MIN..=char::MAX).count() as u32;
21    /// assert!(size < dist);
22    /// ```
23    ///
24    /// Despite this gap, the `MIN` and [`MAX`] values can be used as bounds for
25    /// all `char` values.
26    ///
27    /// [`MAX`]: char::MAX
28    ///
29    /// # Examples
30    ///
31    /// ```
32    /// # fn something_which_returns_char() -> char { 'a' }
33    /// let c: char = something_which_returns_char();
34    /// assert!(char::MIN <= c);
35    ///
36    /// let value_at_min = u32::from(char::MIN);
37    /// assert_eq!(char::from_u32(value_at_min), Some('\0'));
38    /// ```
39    #[stable(feature = "char_min", since = "1.83.0")]
40    pub const MIN: char = '\0';
41
42    /// The highest valid code point a `char` can have, `'\u{10FFFF}'`.
43    ///
44    /// Unlike integer types, `char` actually has a gap in the middle,
45    /// meaning that the range of possible `char`s is smaller than you
46    /// might expect. Ranges of `char` will automatically hop this gap
47    /// for you:
48    ///
49    /// ```
50    /// let dist = u32::from(char::MAX) - u32::from(char::MIN);
51    /// let size = (char::MIN..=char::MAX).count() as u32;
52    /// assert!(size < dist);
53    /// ```
54    ///
55    /// Despite this gap, the [`MIN`] and `MAX` values can be used as bounds for
56    /// all `char` values.
57    ///
58    /// [`MIN`]: char::MIN
59    ///
60    /// # Examples
61    ///
62    /// ```
63    /// # fn something_which_returns_char() -> char { 'a' }
64    /// let c: char = something_which_returns_char();
65    /// assert!(c <= char::MAX);
66    ///
67    /// let value_at_max = u32::from(char::MAX);
68    /// assert_eq!(char::from_u32(value_at_max), Some('\u{10FFFF}'));
69    /// assert_eq!(char::from_u32(value_at_max + 1), None);
70    /// ```
71    #[stable(feature = "assoc_char_consts", since = "1.52.0")]
72    pub const MAX: char = '\u{10FFFF}';
73
74    /// The maximum number of bytes required to [encode](char::encode_utf8) a `char` to
75    /// UTF-8 encoding.
76    #[stable(feature = "char_max_len_assoc", since = "1.93.0")]
77    pub const MAX_LEN_UTF8: usize = 4;
78
79    /// The maximum number of two-byte units required to [encode](char::encode_utf16) a `char`
80    /// to UTF-16 encoding.
81    #[stable(feature = "char_max_len_assoc", since = "1.93.0")]
82    pub const MAX_LEN_UTF16: usize = 2;
83
84    /// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
85    /// decoding error.
86    ///
87    /// It can occur, for example, when giving ill-formed UTF-8 bytes to
88    /// [`String::from_utf8_lossy`](../std/string/struct.String.html#method.from_utf8_lossy).
89    #[stable(feature = "assoc_char_consts", since = "1.52.0")]
90    pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}';
91
92    /// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of
93    /// `char` and `str` methods are based on.
94    ///
95    /// New versions of Unicode are released regularly, and subsequently all methods
96    /// in the standard library depending on Unicode are updated. Therefore, the
97    /// behavior of some `char` and `str` methods, and the value of this constant,
98    /// change over time (within the boundaries of Unicode's [stability policies]).
99    /// This is *not* considered to be a breaking change.
100    ///
101    /// [stability policies]: https://www.unicode.org/policies/stability_policy.html
102    ///
103    /// The version numbering scheme is explained in
104    /// [Section 3.1 (Version Numbering)] of the Unicode Standard.
105    ///
106    /// [Section 3.1 (Version Numbering)]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G49512
107    #[stable(feature = "assoc_char_consts", since = "1.52.0")]
108    pub const UNICODE_VERSION: (u8, u8, u8) = crate::unicode::UNICODE_VERSION;
109
110    /// Creates an iterator over the native endian UTF-16 encoded code points in `iter`,
111    /// returning unpaired surrogates as `Err`s.
112    ///
113    /// # Examples
114    ///
115    /// Basic usage:
116    ///
117    /// ```
118    /// // 𝄞mus<invalid>ic<invalid>
119    /// let v = [
120    ///     0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
121    /// ];
122    ///
123    /// assert_eq!(
124    ///     char::decode_utf16(v)
125    ///         .map(|r| r.map_err(|e| e.unpaired_surrogate()))
126    ///         .collect::<Vec<_>>(),
127    ///     vec![
128    ///         Ok('𝄞'),
129    ///         Ok('m'), Ok('u'), Ok('s'),
130    ///         Err(0xDD1E),
131    ///         Ok('i'), Ok('c'),
132    ///         Err(0xD834)
133    ///     ]
134    /// );
135    /// ```
136    ///
137    /// A lossy decoder can be obtained by replacing `Err` results with the replacement character:
138    ///
139    /// ```
140    /// // 𝄞mus<invalid>ic<invalid>
141    /// let v = [
142    ///     0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
143    /// ];
144    ///
145    /// assert_eq!(
146    ///     char::decode_utf16(v)
147    ///        .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
148    ///        .collect::<String>(),
149    ///     "𝄞mus�ic�"
150    /// );
151    /// ```
152    #[stable(feature = "assoc_char_funcs", since = "1.52.0")]
153    #[inline]
154    #[ferrocene::prevalidated]
155    pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
156        super::decode::decode_utf16(iter)
157    }
158
159    /// Converts a `u32` to a `char`.
160    ///
161    /// Note that all `char`s are valid [`u32`]s, and can be cast to one with
162    /// [`as`](../std/keyword.as.html):
163    ///
164    /// ```
165    /// let c = '💯';
166    /// let i = c as u32;
167    ///
168    /// assert_eq!(128175, i);
169    /// ```
170    ///
171    /// However, the reverse is not true: not all valid [`u32`]s are valid
172    /// `char`s. `from_u32()` will return `None` if the input is not a valid value
173    /// for a `char`.
174    ///
175    /// For an unsafe version of this function which ignores these checks, see
176    /// [`from_u32_unchecked`].
177    ///
178    /// [`from_u32_unchecked`]: #method.from_u32_unchecked
179    ///
180    /// # Examples
181    ///
182    /// Basic usage:
183    ///
184    /// ```
185    /// let c = char::from_u32(0x2764);
186    ///
187    /// assert_eq!(Some('❤'), c);
188    /// ```
189    ///
190    /// Returning `None` when the input is not a valid `char`:
191    ///
192    /// ```
193    /// let c = char::from_u32(0x110000);
194    ///
195    /// assert_eq!(None, c);
196    /// ```
197    #[stable(feature = "assoc_char_funcs", since = "1.52.0")]
198    #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
199    #[must_use]
200    #[inline]
201    pub const fn from_u32(i: u32) -> Option<char> {
202        super::convert::from_u32(i)
203    }
204
205    /// Converts a `u32` to a `char`, ignoring validity.
206    ///
207    /// Note that all `char`s are valid [`u32`]s, and can be cast to one with
208    /// `as`:
209    ///
210    /// ```
211    /// let c = '💯';
212    /// let i = c as u32;
213    ///
214    /// assert_eq!(128175, i);
215    /// ```
216    ///
217    /// However, the reverse is not true: not all valid [`u32`]s are valid
218    /// `char`s. `from_u32_unchecked()` will ignore this, and blindly cast to
219    /// `char`, possibly creating an invalid one.
220    ///
221    /// # Safety
222    ///
223    /// This function is unsafe, as it may construct invalid `char` values.
224    ///
225    /// For a safe version of this function, see the [`from_u32`] function.
226    ///
227    /// [`from_u32`]: #method.from_u32
228    ///
229    /// # Examples
230    ///
231    /// Basic usage:
232    ///
233    /// ```
234    /// let c = unsafe { char::from_u32_unchecked(0x2764) };
235    ///
236    /// assert_eq!('❤', c);
237    /// ```
238    #[stable(feature = "assoc_char_funcs", since = "1.52.0")]
239    #[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")]
240    #[must_use]
241    #[inline]
242    #[ferrocene::prevalidated]
243    pub const unsafe fn from_u32_unchecked(i: u32) -> char {
244        // SAFETY: the safety contract must be upheld by the caller.
245        unsafe { super::convert::from_u32_unchecked(i) }
246    }
247
248    /// Converts a digit in the given radix to a `char`.
249    ///
250    /// A 'radix' here is sometimes also called a 'base'. A radix of two
251    /// indicates a binary number, a radix of ten, decimal, and a radix of
252    /// sixteen, hexadecimal, to give some common values. Arbitrary
253    /// radices are supported.
254    ///
255    /// `from_digit()` will return `None` if the input is not a digit in
256    /// the given radix.
257    ///
258    /// # Panics
259    ///
260    /// Panics if given a radix larger than 36.
261    ///
262    /// # Examples
263    ///
264    /// Basic usage:
265    ///
266    /// ```
267    /// let c = char::from_digit(4, 10);
268    ///
269    /// assert_eq!(Some('4'), c);
270    ///
271    /// // Decimal 11 is a single digit in base 16
272    /// let c = char::from_digit(11, 16);
273    ///
274    /// assert_eq!(Some('b'), c);
275    /// ```
276    ///
277    /// Returning `None` when the input is not a digit:
278    ///
279    /// ```
280    /// let c = char::from_digit(20, 10);
281    ///
282    /// assert_eq!(None, c);
283    /// ```
284    ///
285    /// Passing a large radix, causing a panic:
286    ///
287    /// ```should_panic
288    /// // this panics
289    /// let _c = char::from_digit(1, 37);
290    /// ```
291    #[stable(feature = "assoc_char_funcs", since = "1.52.0")]
292    #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
293    #[must_use]
294    #[inline]
295    pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
296        super::convert::from_digit(num, radix)
297    }
298
299    /// Checks if a `char` is a digit in the given radix.
300    ///
301    /// A 'radix' here is sometimes also called a 'base'. A radix of two
302    /// indicates a binary number, a radix of ten, decimal, and a radix of
303    /// sixteen, hexadecimal, to give some common values. Arbitrary
304    /// radices are supported.
305    ///
306    /// Compared to [`is_numeric()`], this function only recognizes the characters
307    /// `0-9`, `a-z` and `A-Z`.
308    ///
309    /// 'Digit' is defined to be only the following characters:
310    ///
311    /// * `0-9`
312    /// * `a-z`
313    /// * `A-Z`
314    ///
315    /// For a more comprehensive understanding of 'digit', see [`is_numeric()`].
316    ///
317    /// [`is_numeric()`]: #method.is_numeric
318    ///
319    /// # Panics
320    ///
321    /// Panics if given a radix smaller than 2 or larger than 36.
322    ///
323    /// # Examples
324    ///
325    /// Basic usage:
326    ///
327    /// ```
328    /// assert!('1'.is_digit(10));
329    /// assert!('f'.is_digit(16));
330    /// assert!(!'f'.is_digit(10));
331    /// ```
332    ///
333    /// Passing a large radix, causing a panic:
334    ///
335    /// ```should_panic
336    /// // this panics
337    /// '1'.is_digit(37);
338    /// ```
339    ///
340    /// Passing a small radix, causing a panic:
341    ///
342    /// ```should_panic
343    /// // this panics
344    /// '1'.is_digit(1);
345    /// ```
346    #[stable(feature = "rust1", since = "1.0.0")]
347    #[rustc_const_stable(feature = "const_char_classify", since = "1.87.0")]
348    #[inline]
349    pub const fn is_digit(self, radix: u32) -> bool {
350        self.to_digit(radix).is_some()
351    }
352
353    /// Converts a `char` to a digit in the given radix.
354    ///
355    /// A 'radix' here is sometimes also called a 'base'. A radix of two
356    /// indicates a binary number, a radix of ten, decimal, and a radix of
357    /// sixteen, hexadecimal, to give some common values. Arbitrary
358    /// radices are supported.
359    ///
360    /// 'Digit' is defined to be only the following characters:
361    ///
362    /// * `0-9`
363    /// * `a-z`
364    /// * `A-Z`
365    ///
366    /// # Errors
367    ///
368    /// Returns `None` if the `char` does not refer to a digit in the given radix.
369    ///
370    /// # Panics
371    ///
372    /// Panics if given a radix smaller than 2 or larger than 36.
373    ///
374    /// # Examples
375    ///
376    /// Basic usage:
377    ///
378    /// ```
379    /// assert_eq!('1'.to_digit(10), Some(1));
380    /// assert_eq!('f'.to_digit(16), Some(15));
381    /// ```
382    ///
383    /// Passing a non-digit results in failure:
384    ///
385    /// ```
386    /// assert_eq!('f'.to_digit(10), None);
387    /// assert_eq!('z'.to_digit(16), None);
388    /// ```
389    ///
390    /// Passing a large radix, causing a panic:
391    ///
392    /// ```should_panic
393    /// // this panics
394    /// let _ = '1'.to_digit(37);
395    /// ```
396    /// Passing a small radix, causing a panic:
397    ///
398    /// ```should_panic
399    /// // this panics
400    /// let _ = '1'.to_digit(1);
401    /// ```
402    #[stable(feature = "rust1", since = "1.0.0")]
403    #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
404    #[rustc_diagnostic_item = "char_to_digit"]
405    #[must_use = "this returns the result of the operation, \
406                  without modifying the original"]
407    #[inline]
408    #[ferrocene::prevalidated]
409    pub const fn to_digit(self, radix: u32) -> Option<u32> {
410        assert!(
411            radix >= 2 && radix <= 36,
412            "to_digit: invalid radix -- radix must be in the range 2 to 36 inclusive"
413        );
414        // check radix to remove letter handling code when radix is a known constant
415        let value = if self > '9' && radix > 10 {
416            // mask to convert ASCII letters to uppercase
417            const TO_UPPERCASE_MASK: u32 = !0b0010_0000;
418            // Converts an ASCII letter to its corresponding integer value:
419            // A-Z => 10-35, a-z => 10-35. Other characters produce values >= 36.
420            //
421            // Add Overflow Safety:
422            // By applying the mask after the subtraction, the first addendum is
423            // constrained such that it never exceeds u32::MAX - 0x20.
424            ((self as u32).wrapping_sub('A' as u32) & TO_UPPERCASE_MASK) + 10
425        } else {
426            // convert digit to value, non-digits wrap to values > 36
427            (self as u32).wrapping_sub('0' as u32)
428        };
429        // FIXME(const-hack): once then_some is const fn, use it here
430        if value < radix { Some(value) } else { None }
431    }
432
433    /// Returns an iterator that yields the hexadecimal Unicode escape of a
434    /// character as `char`s.
435    ///
436    /// This will escape characters with the Rust syntax of the form
437    /// `\u{NNNNNN}` where `NNNNNN` is a hexadecimal representation.
438    ///
439    /// # Examples
440    ///
441    /// As an iterator:
442    ///
443    /// ```
444    /// for c in '❤'.escape_unicode() {
445    ///     print!("{c}");
446    /// }
447    /// println!();
448    /// ```
449    ///
450    /// Using `println!` directly:
451    ///
452    /// ```
453    /// println!("{}", '❤'.escape_unicode());
454    /// ```
455    ///
456    /// Both are equivalent to:
457    ///
458    /// ```
459    /// println!("\\u{{2764}}");
460    /// ```
461    ///
462    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
463    ///
464    /// ```
465    /// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}");
466    /// ```
467    #[must_use = "this returns the escaped char as an iterator, \
468                  without modifying the original"]
469    #[stable(feature = "rust1", since = "1.0.0")]
470    #[inline]
471    #[ferrocene::prevalidated]
472    pub fn escape_unicode(self) -> EscapeUnicode {
473        EscapeUnicode::new(self)
474    }
475
476    /// An extended version of `escape_debug` that optionally permits escaping
477    /// Extended Grapheme codepoints, single quotes, and double quotes. This
478    /// allows us to format characters like nonspacing marks better when they're
479    /// at the start of a string, and allows escaping single quotes in
480    /// characters, and double quotes in strings.
481    #[inline]
482    #[ferrocene::prevalidated]
483    pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
484        match self {
485            // Special escapes
486            '\"' if args.escape_double_quote => EscapeDebug::backslash(ascii::Char::QuotationMark),
487            '\'' if args.escape_single_quote => EscapeDebug::backslash(ascii::Char::Apostrophe),
488            '\\' => EscapeDebug::backslash(ascii::Char::ReverseSolidus),
489            '\n' => EscapeDebug::backslash(ascii::Char::SmallN),
490            '\t' => EscapeDebug::backslash(ascii::Char::SmallT),
491            '\r' => EscapeDebug::backslash(ascii::Char::SmallR),
492            '\0' => EscapeDebug::backslash(ascii::Char::Digit0),
493
494            // ASCII fast path,
495            // plus U+FF9E HALFWIDTH KATAKANA VOICED SOUND MARK
496            // and U+FF9F HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
497            // which should not be escaped despite being grapheme extenders.
498            '\x20'..='\x7E' | '\u{FF9E}' | '\u{FF9F}' => EscapeDebug::printable(self),
499
500            _ if self.is_control()
501                || self.is_private_use()
502                || self.is_whitespace()
503                || args.escape_grapheme_extender && self.is_grapheme_extender()
504                || self.is_default_ignorable()
505                || self.is_format_control()
506                || !self.is_assigned() =>
507            {
508                EscapeDebug::unicode(self)
509            }
510
511            _ => EscapeDebug::printable(self),
512        }
513    }
514
515    /// Returns an iterator that yields the literal escape code of a character
516    /// as `char`s.
517    ///
518    /// This will escape the characters similar to the [`Debug`](core::fmt::Debug) implementations
519    /// of `str` or `char`.
520    ///
521    /// # Examples
522    ///
523    /// As an iterator:
524    ///
525    /// ```
526    /// for c in '\n'.escape_debug() {
527    ///     print!("{c}");
528    /// }
529    /// println!();
530    /// ```
531    ///
532    /// Using `println!` directly:
533    ///
534    /// ```
535    /// println!("{}", '\n'.escape_debug());
536    /// ```
537    ///
538    /// Both are equivalent to:
539    ///
540    /// ```
541    /// println!("\\n");
542    /// ```
543    ///
544    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
545    ///
546    /// ```
547    /// assert_eq!('\n'.escape_debug().to_string(), "\\n");
548    /// ```
549    #[must_use = "this returns the escaped char as an iterator, \
550                  without modifying the original"]
551    #[stable(feature = "char_escape_debug", since = "1.20.0")]
552    #[inline]
553    #[ferrocene::prevalidated]
554    pub fn escape_debug(self) -> EscapeDebug {
555        self.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL)
556    }
557
558    /// Returns an iterator that yields the literal escape code of a character
559    /// as `char`s.
560    ///
561    /// The default is chosen with a bias toward producing literals that are
562    /// legal in a variety of languages, including C++11 and similar C-family
563    /// languages. The exact rules are:
564    ///
565    /// * Tab is escaped as `\t`.
566    /// * Carriage return is escaped as `\r`.
567    /// * Line feed is escaped as `\n`.
568    /// * Single quote is escaped as `\'`.
569    /// * Double quote is escaped as `\"`.
570    /// * Backslash is escaped as `\\`.
571    /// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
572    ///   inclusive is not escaped.
573    /// * All other characters are given hexadecimal Unicode escapes; see
574    ///   [`escape_unicode`].
575    ///
576    /// [`escape_unicode`]: #method.escape_unicode
577    ///
578    /// # Examples
579    ///
580    /// As an iterator:
581    ///
582    /// ```
583    /// for c in '"'.escape_default() {
584    ///     print!("{c}");
585    /// }
586    /// println!();
587    /// ```
588    ///
589    /// Using `println!` directly:
590    ///
591    /// ```
592    /// println!("{}", '"'.escape_default());
593    /// ```
594    ///
595    /// Both are equivalent to:
596    ///
597    /// ```
598    /// println!("\\\"");
599    /// ```
600    ///
601    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
602    ///
603    /// ```
604    /// assert_eq!('"'.escape_default().to_string(), "\\\"");
605    /// ```
606    #[must_use = "this returns the escaped char as an iterator, \
607                  without modifying the original"]
608    #[stable(feature = "rust1", since = "1.0.0")]
609    #[inline]
610    #[ferrocene::prevalidated]
611    pub fn escape_default(self) -> EscapeDefault {
612        match self {
613            '\t' => EscapeDefault::backslash(ascii::Char::SmallT),
614            '\r' => EscapeDefault::backslash(ascii::Char::SmallR),
615            '\n' => EscapeDefault::backslash(ascii::Char::SmallN),
616            '\\' | '\'' | '\"' => EscapeDefault::backslash(self.as_ascii().unwrap()),
617            '\x20'..='\x7e' => EscapeDefault::printable(self.as_ascii().unwrap()),
618            _ => EscapeDefault::unicode(self),
619        }
620    }
621
622    /// Returns the number of bytes this `char` would need if encoded in UTF-8.
623    ///
624    /// That number of bytes is always between 1 and 4, inclusive.
625    ///
626    /// # Examples
627    ///
628    /// Basic usage:
629    ///
630    /// ```
631    /// let len = 'A'.len_utf8();
632    /// assert_eq!(len, 1);
633    ///
634    /// let len = 'ß'.len_utf8();
635    /// assert_eq!(len, 2);
636    ///
637    /// let len = 'ℝ'.len_utf8();
638    /// assert_eq!(len, 3);
639    ///
640    /// let len = '💣'.len_utf8();
641    /// assert_eq!(len, 4);
642    /// ```
643    ///
644    /// The `&str` type guarantees that its contents are UTF-8, and so we can compare the length it
645    /// would take if each code point was represented as a `char` vs in the `&str` itself:
646    ///
647    /// ```
648    /// // as chars
649    /// let eastern = '東';
650    /// let capital = '京';
651    ///
652    /// // both can be represented as three bytes
653    /// assert_eq!(3, eastern.len_utf8());
654    /// assert_eq!(3, capital.len_utf8());
655    ///
656    /// // as a &str, these two are encoded in UTF-8
657    /// let tokyo = "東京";
658    ///
659    /// let len = eastern.len_utf8() + capital.len_utf8();
660    ///
661    /// // we can see that they take six bytes total...
662    /// assert_eq!(6, tokyo.len());
663    ///
664    /// // ... just like the &str
665    /// assert_eq!(len, tokyo.len());
666    /// ```
667    #[stable(feature = "rust1", since = "1.0.0")]
668    #[rustc_const_stable(feature = "const_char_len_utf", since = "1.52.0")]
669    #[inline]
670    #[must_use]
671    #[ferrocene::prevalidated]
672    pub const fn len_utf8(self) -> usize {
673        len_utf8(self as u32)
674    }
675
676    /// Returns the number of 16-bit code units this `char` would need if
677    /// encoded in UTF-16.
678    ///
679    /// That number of code units is always either 1 or 2, for unicode scalar values in
680    /// the [basic multilingual plane] or [supplementary planes] respectively.
681    ///
682    /// See the documentation for [`len_utf8()`] for more explanation of this
683    /// concept. This function is a mirror, but for UTF-16 instead of UTF-8.
684    ///
685    /// [basic multilingual plane]: http://www.unicode.org/glossary/#basic_multilingual_plane
686    /// [supplementary planes]: http://www.unicode.org/glossary/#supplementary_planes
687    /// [`len_utf8()`]: #method.len_utf8
688    ///
689    /// # Examples
690    ///
691    /// Basic usage:
692    ///
693    /// ```
694    /// let n = 'ß'.len_utf16();
695    /// assert_eq!(n, 1);
696    ///
697    /// let len = '💣'.len_utf16();
698    /// assert_eq!(len, 2);
699    /// ```
700    #[stable(feature = "rust1", since = "1.0.0")]
701    #[rustc_const_stable(feature = "const_char_len_utf", since = "1.52.0")]
702    #[inline]
703    #[must_use]
704    pub const fn len_utf16(self) -> usize {
705        len_utf16(self as u32)
706    }
707
708    /// Encodes this character as UTF-8 into the provided byte buffer,
709    /// and then returns the subslice of the buffer that contains the encoded character.
710    ///
711    /// # Panics
712    ///
713    /// Panics if the buffer is not large enough.
714    /// A buffer of length four is large enough to encode any `char`.
715    ///
716    /// # Examples
717    ///
718    /// In both of these examples, 'ß' takes two bytes to encode.
719    ///
720    /// ```
721    /// let mut b = [0; 2];
722    ///
723    /// let result = 'ß'.encode_utf8(&mut b);
724    ///
725    /// assert_eq!(result, "ß");
726    ///
727    /// assert_eq!(result.len(), 2);
728    /// ```
729    ///
730    /// A buffer that's too small:
731    ///
732    /// ```should_panic
733    /// let mut b = [0; 1];
734    ///
735    /// // this panics
736    /// 'ß'.encode_utf8(&mut b);
737    /// ```
738    #[stable(feature = "unicode_encode_char", since = "1.15.0")]
739    #[rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0")]
740    #[inline]
741    #[ferrocene::prevalidated]
742    pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
743        // SAFETY: `char` is not a surrogate, so this is valid UTF-8.
744        unsafe { from_utf8_unchecked_mut(encode_utf8_raw(self as u32, dst)) }
745    }
746
747    /// Encodes this character as native endian UTF-16 into the provided `u16` buffer,
748    /// and then returns the subslice of the buffer that contains the encoded character.
749    ///
750    /// # Panics
751    ///
752    /// Panics if the buffer is not large enough.
753    /// A buffer of length 2 is large enough to encode any `char`.
754    ///
755    /// # Examples
756    ///
757    /// In both of these examples, '𝕊' takes two `u16`s to encode.
758    ///
759    /// ```
760    /// let mut b = [0; 2];
761    ///
762    /// let result = '𝕊'.encode_utf16(&mut b);
763    ///
764    /// assert_eq!(result.len(), 2);
765    /// ```
766    ///
767    /// A buffer that's too small:
768    ///
769    /// ```should_panic
770    /// let mut b = [0; 1];
771    ///
772    /// // this panics
773    /// '𝕊'.encode_utf16(&mut b);
774    /// ```
775    #[stable(feature = "unicode_encode_char", since = "1.15.0")]
776    #[rustc_const_stable(feature = "const_char_encode_utf16", since = "1.84.0")]
777    #[inline]
778    pub const fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] {
779        encode_utf16_raw(self as u32, dst)
780    }
781
782    /// Returns `true` if this `char` has the `Alphabetic` property.
783    ///
784    /// `Alphabetic` is [described] in Chapter 4 (Character Properties) of the Unicode Standard, and
785    /// [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
786    ///
787    /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G32524
788    /// [specified]: https://www.unicode.org/reports/tr44/#Alphabetic
789    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
790    ///
791    /// # Examples
792    ///
793    /// Basic usage:
794    ///
795    /// ```
796    /// assert!('a'.is_alphabetic());
797    /// assert!('京'.is_alphabetic());
798    ///
799    /// let c = '💝';
800    /// // love is many things, but it is not alphabetic
801    /// assert!(!c.is_alphabetic());
802    /// ```
803    #[must_use]
804    #[stable(feature = "rust1", since = "1.0.0")]
805    #[inline]
806    pub fn is_alphabetic(self) -> bool {
807        match self {
808            'a'..='z' | 'A'..='Z' => true,
809            '\0'..='\u{A9}' => false,
810            _ => unicode::Alphabetic(self),
811        }
812    }
813
814    /// Returns `true` if this `char` has the `Cased` property.
815    /// A character is cased if and only if it is uppercase, lowercase, or titlecase.
816    ///
817    /// `Cased` is [described] in Chapter 3 (Character Properties) of the Unicode Standard and
818    /// [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
819    ///
820    /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G44595
821    /// [specified]: https://www.unicode.org/reports/tr44/#Cased
822    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
823    ///
824    /// # Examples
825    ///
826    /// Basic usage:
827    ///
828    /// ```
829    /// #![feature(titlecase)]
830    /// assert!('A'.is_cased());
831    /// assert!('a'.is_cased());
832    /// assert!(!'京'.is_cased());
833    /// ```
834    #[must_use]
835    #[unstable(feature = "titlecase", issue = "153892")]
836    #[inline]
837    pub fn is_cased(self) -> bool {
838        match self {
839            'a'..='z' | 'A'..='Z' => true,
840            '\0'..='\u{A9}' => false,
841            _ => unicode::Lowercase(self) || unicode::Uppercase(self) || unicode::Lt(self),
842        }
843    }
844
845    /// Returns the case of this character:
846    /// [`Some(CharCase::Upper)`][`CharCase::Upper`] if [`self.is_uppercase()`][`char::is_uppercase`],
847    /// [`Some(CharCase::Lower)`][`CharCase::Lower`] if [`self.is_lowercase()`][`char::is_lowercase`],
848    /// [`Some(CharCase::Title)`][`CharCase::Title`] if [`self.is_titlecase()`][`char::is_titlecase`], and
849    /// `None` if [`!self.is_cased()`][`char::is_cased`].
850    ///
851    /// # Examples
852    ///
853    /// ```
854    /// #![feature(titlecase)]
855    /// use core::char::CharCase;
856    /// assert_eq!('a'.case(), Some(CharCase::Lower));
857    /// assert_eq!('δ'.case(), Some(CharCase::Lower));
858    /// assert_eq!('A'.case(), Some(CharCase::Upper));
859    /// assert_eq!('Δ'.case(), Some(CharCase::Upper));
860    /// assert_eq!('Dž'.case(), Some(CharCase::Title));
861    /// assert_eq!('中'.case(), None);
862    /// ```
863    #[must_use]
864    #[unstable(feature = "titlecase", issue = "153892")]
865    #[inline]
866    pub fn case(self) -> Option<CharCase> {
867        match self {
868            'a'..='z' => Some(CharCase::Lower),
869            'A'..='Z' => Some(CharCase::Upper),
870            '\0'..='\u{A9}' => None,
871            _ if unicode::Lowercase(self) => Some(CharCase::Lower),
872            _ if unicode::Uppercase(self) => Some(CharCase::Upper),
873            _ if unicode::Lt(self) => Some(CharCase::Title),
874            _ => None,
875        }
876    }
877
878    /// Returns `true` if this `char` has the `Lowercase` property.
879    ///
880    /// `Lowercase` is [described] in Chapter 4 (Character Properties) of the Unicode Standard, and
881    /// [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
882    ///
883    /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G136255
884    /// [specified]: https://www.unicode.org/reports/tr44/#Lowercase
885    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
886    ///
887    /// # Examples
888    ///
889    /// Basic usage:
890    ///
891    /// ```
892    /// assert!('a'.is_lowercase());
893    /// assert!('δ'.is_lowercase());
894    /// assert!(!'A'.is_lowercase());
895    /// assert!(!'Δ'.is_lowercase());
896    ///
897    /// // The various Chinese scripts and punctuation do not have case, and so:
898    /// assert!(!'中'.is_lowercase());
899    /// assert!(!' '.is_lowercase());
900    /// ```
901    ///
902    /// In a const context:
903    ///
904    /// ```
905    /// const CAPITAL_DELTA_IS_LOWERCASE: bool = 'Δ'.is_lowercase();
906    /// assert!(!CAPITAL_DELTA_IS_LOWERCASE);
907    /// ```
908    #[must_use]
909    #[stable(feature = "rust1", since = "1.0.0")]
910    #[rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0")]
911    #[inline]
912    pub const fn is_lowercase(self) -> bool {
913        match self {
914            'a'..='z' => true,
915            '\0'..='\u{A9}' => false,
916            _ => unicode::Lowercase(self),
917        }
918    }
919
920    /// Returns `true` if this `char` is in the general category for titlecase letters.
921    /// Conceptually, these characters consist of an uppercase portion followed by a lowercase portion.
922    ///
923    /// Titlecase letters (code points with the general category of `Lt`) are [described] in Chapter 4
924    /// (Character Properties) of the Unicode Standard, and [specified] in the Unicode Character
925    /// Database [`UnicodeData.txt`].
926    ///
927    /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G124722
928    /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table
929    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
930    ///
931    /// # Examples
932    ///
933    /// Basic usage:
934    ///
935    /// ```
936    /// #![feature(titlecase)]
937    /// assert!('Dž'.is_titlecase());
938    /// assert!('ῼ'.is_titlecase());
939    /// assert!(!'D'.is_titlecase());
940    /// assert!(!'z'.is_titlecase());
941    /// assert!(!'中'.is_titlecase());
942    /// assert!(!' '.is_titlecase());
943    /// ```
944    #[must_use]
945    #[unstable(feature = "titlecase", issue = "153892")]
946    #[inline]
947    pub fn is_titlecase(self) -> bool {
948        match self {
949            '\0'..='\u{01C4}' => false,
950            _ => unicode::Lt(self),
951        }
952    }
953
954    /// Returns `true` if this `char` has the `Uppercase` property.
955    ///
956    /// `Uppercase` is [described] in Chapter 4 (Character Properties) of the Unicode Standard, and
957    /// [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
958    ///
959    /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G136255
960    /// [specified]: https://www.unicode.org/reports/tr44/#Uppercase
961    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
962    ///
963    /// # Examples
964    ///
965    /// Basic usage:
966    ///
967    /// ```
968    /// assert!(!'a'.is_uppercase());
969    /// assert!(!'δ'.is_uppercase());
970    /// assert!('A'.is_uppercase());
971    /// assert!('Δ'.is_uppercase());
972    ///
973    /// // The various Chinese scripts and punctuation do not have case, and so:
974    /// assert!(!'中'.is_uppercase());
975    /// assert!(!' '.is_uppercase());
976    /// ```
977    ///
978    /// In a const context:
979    ///
980    /// ```
981    /// const CAPITAL_DELTA_IS_UPPERCASE: bool = 'Δ'.is_uppercase();
982    /// assert!(CAPITAL_DELTA_IS_UPPERCASE);
983    /// ```
984    #[must_use]
985    #[stable(feature = "rust1", since = "1.0.0")]
986    #[rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0")]
987    #[inline]
988    pub const fn is_uppercase(self) -> bool {
989        match self {
990            'A'..='Z' => true,
991            '\0'..='\u{BF}' => false,
992            _ => unicode::Uppercase(self),
993        }
994    }
995
996    /// Returns `true` if this `char` has one of the general categories for numbers.
997    ///
998    /// The general categories for numbers (`Nd` for decimal digits, `Nl` for letter-like numeric
999    /// characters, and `No` for other numeric characters) are [specified] in the Unicode Character
1000    /// Database [`UnicodeData.txt`].
1001    ///
1002    /// This method doesn't cover everything that could be considered a number, e.g. ideographic numbers like '三'.
1003    /// If you want everything including characters with overlapping purposes, then you might want to use
1004    /// a Unicode or language-processing library that exposes the appropriate character properties
1005    /// (e.g. [`Numeric_Type`]) instead of looking at the Unicode categories.
1006    ///
1007    /// If you want to parse ASCII decimal digits (0-9) or ASCII base-N, use
1008    /// `is_ascii_digit` or `is_digit` instead.
1009    ///
1010    /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table
1011    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1012    /// [`Numeric_Type`]: https://www.unicode.org/reports/tr44/#Numeric_Type
1013    ///
1014    /// # Examples
1015    ///
1016    /// Basic usage:
1017    ///
1018    /// ```
1019    /// assert!('٣'.is_numeric());
1020    /// assert!('7'.is_numeric());
1021    /// assert!('৬'.is_numeric());
1022    /// assert!('¾'.is_numeric());
1023    /// assert!('①'.is_numeric());
1024    /// assert!(!'K'.is_numeric());
1025    /// assert!(!'و'.is_numeric());
1026    /// assert!(!'藏'.is_numeric());
1027    /// assert!(!'三'.is_numeric());
1028    /// ```
1029    #[must_use]
1030    #[stable(feature = "rust1", since = "1.0.0")]
1031    #[inline]
1032    pub fn is_numeric(self) -> bool {
1033        match self {
1034            '0'..='9' => true,
1035            '\0'..='\u{B1}' => false,
1036            _ => unicode::N(self),
1037        }
1038    }
1039
1040    /// Returns `true` if this `char` satisfies either [`is_alphabetic()`] or [`is_numeric()`].
1041    ///
1042    /// [`is_alphabetic()`]: Self::is_alphabetic
1043    /// [`is_numeric()`]: Self::is_numeric
1044    ///
1045    /// # Examples
1046    ///
1047    /// Basic usage:
1048    ///
1049    /// ```
1050    /// assert!('٣'.is_alphanumeric());
1051    /// assert!('7'.is_alphanumeric());
1052    /// assert!('৬'.is_alphanumeric());
1053    /// assert!('¾'.is_alphanumeric());
1054    /// assert!('①'.is_alphanumeric());
1055    /// assert!('K'.is_alphanumeric());
1056    /// assert!('و'.is_alphanumeric());
1057    /// assert!('藏'.is_alphanumeric());
1058    /// ```
1059    #[must_use]
1060    #[stable(feature = "rust1", since = "1.0.0")]
1061    #[inline]
1062    pub fn is_alphanumeric(self) -> bool {
1063        match self {
1064            'a'..='z' | 'A'..='Z' | '0'..='9' => true,
1065            '\0'..='\u{A9}' => false,
1066            _ => unicode::Alphabetic(self) || unicode::N(self),
1067        }
1068    }
1069
1070    /// Returns `true` if this `char` has the `White_Space` property.
1071    ///
1072    /// `White_Space` is [specified] in the Unicode Character Database [`PropList.txt`].
1073    ///
1074    /// [specified]: https://www.unicode.org/reports/tr44/#White_Space
1075    /// [`PropList.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt
1076    ///
1077    /// # Examples
1078    ///
1079    /// Basic usage:
1080    ///
1081    /// ```
1082    /// assert!(' '.is_whitespace());
1083    ///
1084    /// // line break
1085    /// assert!('\n'.is_whitespace());
1086    ///
1087    /// // a non-breaking space
1088    /// assert!('\u{A0}'.is_whitespace());
1089    ///
1090    /// assert!(!'越'.is_whitespace());
1091    /// ```
1092    #[must_use]
1093    #[stable(feature = "rust1", since = "1.0.0")]
1094    #[rustc_const_stable(feature = "const_char_classify", since = "1.87.0")]
1095    #[inline]
1096    #[ferrocene::prevalidated]
1097    pub const fn is_whitespace(self) -> bool {
1098        match self {
1099            ' ' | '\x09'..='\x0d' => true,
1100            '\0'..='\u{84}' => false,
1101            _ => unicode::White_Space(self),
1102        }
1103    }
1104
1105    /// Returns `true` if this `char` has the general category for control codes.
1106    ///
1107    /// Control codes (code points with the general category of `Cc`) are [described] in Chapter 23
1108    /// (Special Areas and Format Characters) of the Unicode Standard, and [specified] in the Unicode Character
1109    /// Database [`UnicodeData.txt`]. The full set of Unicode control codes is
1110    /// `'\0'..='\x1f' | '\x7f'..='\u{9f}'`, and will never change.
1111    ///
1112    /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-23/#G20365
1113    /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table
1114    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1115    ///
1116    /// # Examples
1117    ///
1118    /// Basic usage:
1119    ///
1120    /// ```
1121    /// assert!('\t'.is_control());
1122    /// assert!('\n'.is_control());
1123    /// assert!('\u{9C}'.is_control()); // STRING TERMINATOR
1124    /// assert!(!'q'.is_control());
1125    /// ```
1126    #[ferrocene::prevalidated]
1127    #[must_use]
1128    #[stable(feature = "rust1", since = "1.0.0")]
1129    #[rustc_const_stable(feature = "const_is_control", since = "1.97.0")]
1130    #[inline]
1131    pub const fn is_control(self) -> bool {
1132        // According to
1133        // https://www.unicode.org/policies/stability_policy.html#Property_Value,
1134        // the set of codepoints in `Cc` will never change.
1135        // So we can just hard-code the patterns to match against instead of using a table.
1136        matches!(self, '\0'..='\x1f' | '\x7f'..='\u{9f}')
1137    }
1138
1139    /// Returns `true` if this `char` has the general category for [private-use characters].
1140    /// These characters do not have an interpretation specified by Unicode; individual programs
1141    /// and users are free to assign them whatever meaning they like.
1142    ///
1143    /// [private-use characters]: https://www.unicode.org/faq/private_use#private_use
1144    ///
1145    /// Private-use characters (code points with the general category of `Co`) are [described] in Chapter 23
1146    /// (Special Areas and Format Characters) of the Unicode Standard, and [specified] in the
1147    /// Unicode Character Database [`UnicodeData.txt`]. The full set of private-use characters is
1148    /// `'\u{E000}'..='\u{F8FF}' | '\u{F0000}'..='\u{FFFFD}' | '\u{100000}'..='\u{10FFFD}'`,
1149    /// and will never change.
1150    ///
1151    /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-23/#G19184
1152    /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table
1153    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1154    ///
1155    #[ferrocene::prevalidated]
1156    #[must_use]
1157    #[unstable(feature = "char_unassigned_private_use", issue = "158322")]
1158    #[inline]
1159    pub const fn is_private_use(self) -> bool {
1160        // According to
1161        // https://www.unicode.org/policies/stability_policy.html#Property_Value,
1162        // the set of codepoints in `Co` will never change.
1163        // So we can just hard-code the patterns to match against instead of using a table.
1164        matches!(self, '\u{E000}'..='\u{F8FF}' | '\u{F0000}'..='\u{FFFFD}' | '\u{100000}'..='\u{10FFFD}')
1165    }
1166
1167    /// Returns `true` if this `char` has the general category for format control characters.
1168    ///
1169    /// Format controls (code points with the general category of `Cf`) are [described] in Chapter 4
1170    /// (Character Properties) of the Unicode Standard, and [specified] in the Unicode Character
1171    /// Database [`UnicodeData.txt`].
1172    ///
1173    /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153
1174    /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table
1175    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1176    ///
1177    /// # Examples
1178    ///
1179    /// Basic usage:
1180    ///
1181    /// ```ignore(private)
1182    /// assert!('\u{AD}'.is_format_control()); // SOFT HYPHEN
1183    /// assert!('\u{200B}'.is_format_control()); // ZERO WIDTH SPACE
1184    /// assert!('\u{E0041}'.is_format_control()); // TAG LATIN CAPITAL LETTER A
1185    /// assert!('۝'.is_format_control()); // ARABIC END OF AYAH
1186    /// assert!('𓐲'.is_format_control()); // EGYPTIAN HIEROGLYPH INSERT AT TOP START
1187    /// assert!(!'q'.is_format_control());
1188    /// ```
1189    #[ferrocene::prevalidated]
1190    #[must_use]
1191    #[inline]
1192    fn is_format_control(self) -> bool {
1193        self > '\u{AC}' && unicode::Cf(self)
1194    }
1195
1196    /// Returns `true` if this `char` has been assigned a meaning by Unicode, as of
1197    /// [`UNICODE_VERSION`].
1198    ///
1199    /// [`UNICODE_VERSION`]: Self::UNICODE_VERSION
1200    ///
1201    /// Many of Unicode's [stability policies] apply only to assigned characters.
1202    ///
1203    /// [stability policies]: https://www.unicode.org/policies/stability_policy.html
1204    ///
1205    /// Currently unassigned characters (characters for which this method returns `false`)
1206    /// may have a meaning assigned in a future version of Unicode,
1207    /// except for the 66 [noncharacters] which will never be assigned a meaning.
1208    ///
1209    /// [noncharacters]: https://www.unicode.org/faq/private_use.html#noncharacters
1210    ///
1211    /// A character is considered assigned if it is present in [`UnicodeData.txt`].
1212    /// Unassigned characters have general category `Cn`, as [described] in Chapter 4
1213    /// (Character Properties) of the Unicode Standard.
1214    ///
1215    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1216    /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153
1217    ///
1218    /// # Examples
1219    ///
1220    /// Basic usage:
1221    ///
1222    /// ```
1223    /// #![feature(char_unassigned_private_use)]
1224    /// assert!('γ'.is_assigned()); // once a character is assigned, it stays assigned forever
1225    /// assert!(!'\u{FFFE}'.is_assigned()); // noncharacter, will never be assigned
1226    ///
1227    /// // Not currently assigned, but may be in the future,
1228    /// // so we shouldn't rely on the current status
1229    /// /* assert!(!'\u{7AAAA}'.is_assigned()); */
1230    /// ```
1231    #[ferrocene::prevalidated]
1232    #[must_use]
1233    #[unstable(feature = "char_unassigned_private_use", issue = "158322")]
1234    #[inline]
1235    pub fn is_assigned(self) -> bool {
1236        match self {
1237            '\0'..='\u{377}' => true,
1238            '\u{378}'..='\u{3FFFD}' => !unicode::Cn_planes_0_3(self),
1239            // Assigned character ranges in planes 4 and above.
1240            // `src/tools/unicode-table-generator/src/main.rs` asserts that this is correct
1241            '\u{E0001}'
1242            | '\u{E0020}'..='\u{E007F}'
1243            | '\u{E0100}'..='\u{E01EF}'
1244            | '\u{F0000}'..='\u{FFFFD}'
1245            | '\u{100000}'..='\u{10FFFD}' => true,
1246            _ => false,
1247        }
1248    }
1249
1250    /// Returns `true` if this `char` has the `Default_Ignorable_Code_Point` property.
1251    /// These characters [should be displayed as invisible in fallback rendering](https://www.unicode.org/faq/unsup_char#3).
1252    ///
1253    /// `Default_Ignorable_Code_Point` is [described] in Chapter 5 (Implementation Guidelines) of the Unicode Standard,
1254    /// and [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
1255    ///
1256    /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-5/#G40120
1257    /// [specified]: https://www.unicode.org/reports/tr44/#Default_Ignorable_Code_Point
1258    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
1259    ///
1260    /// # Examples
1261    ///
1262    /// Basic usage:
1263    ///
1264    /// ```ignore(private)
1265    /// assert!('\u{AD}'.is_default_ignorable()); // SOFT HYPHEN
1266    /// assert!('\u{115F}'.is_default_ignorable()); // HANGUL CHOSEONG FILLER
1267    /// assert!('\u{200B}'.is_default_ignorable()); // ZERO WIDTH SPACE
1268    /// assert!('\u{E0041}'.is_default_ignorable()); // TAG LATIN CAPITAL LETTER A
1269    /// assert!(!'۝'.is_default_ignorable()); // ARABIC END OF AYAH
1270    /// assert!(!'𓐲'.is_default_ignorable()); // EGYPTIAN HIEROGLYPH INSERT AT TOP START
1271    /// assert!(!' '.is_default_ignorable());
1272    /// assert!(!'\n'.is_default_ignorable());
1273    /// assert!(!'\0'.is_default_ignorable());
1274    /// assert!(!'q'.is_default_ignorable());
1275    #[ferrocene::prevalidated]
1276    #[must_use]
1277    #[inline]
1278    fn is_default_ignorable(self) -> bool {
1279        self > '\u{AC}' && unicode::Default_Ignorable_Code_Point(self)
1280    }
1281
1282    /// Returns `true` if this `char` has the `Grapheme_Extend` property.
1283    ///
1284    /// `Grapheme_Extend` is [described] in Chapter 3 (Conformance) of the Unicode Standard,
1285    /// and [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
1286    ///
1287    /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G41165
1288    /// [specified]: https://www.unicode.org/reports/tr44/#Grapheme_Extend
1289    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
1290    #[ferrocene::prevalidated]
1291    #[must_use]
1292    #[inline]
1293    fn is_grapheme_extender(self) -> bool {
1294        self > '\u{02FF}' && unicode::Grapheme_Extend(self)
1295    }
1296
1297    /// Returns `true` if this `char` has the `Case_Ignorable` property. This narrow-use property
1298    /// is used to implement context-dependent casing for the Greek letter sigma (uppercase 'Σ'),
1299    /// which has two lowercase forms.
1300    ///
1301    /// `Case_Ignorable` is [described] in Chapter 3 (Conformance) of the Unicode Core Specification,
1302    /// and [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`].
1303    /// See those resources, as well as [`to_lowercase()`]'s documentation, for more information.
1304    ///
1305    /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G63116
1306    /// [specified]: https://www.unicode.org/reports/tr44/#Case_Ignorable
1307    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
1308    /// [`to_lowercase()`]: Self::to_lowercase()
1309    #[must_use]
1310    #[inline]
1311    #[unstable(feature = "case_ignorable", issue = "154848")]
1312    pub fn is_case_ignorable(self) -> bool {
1313        if self.is_ascii() {
1314            matches!(self, '\'' | '.' | ':' | '^' | '`')
1315        } else {
1316            unicode::Case_Ignorable(self)
1317        }
1318    }
1319
1320    /// Returns an iterator that yields the lowercase mapping of this `char` as one or more
1321    /// `char`s.
1322    ///
1323    /// If this `char` does not have a lowercase mapping, the iterator yields the same `char`.
1324    ///
1325    /// If this `char` has a one-to-one lowercase mapping given by the [Unicode Character
1326    /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
1327    ///
1328    /// [ucd]: https://www.unicode.org/reports/tr44/
1329    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1330    ///
1331    /// If this `char` expands to multiple `char`s, the iterator yields the `char`s given by
1332    /// [`SpecialCasing.txt`]. The maximum number of `char`s in a case mapping is 3.
1333    ///
1334    /// This operation performs an unconditional mapping without tailoring. That is, the conversion
1335    /// is independent of context and language. See [below](#notes-on-context-and-locale)
1336    /// for more information.
1337    ///
1338    /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
1339    /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
1340    ///
1341    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
1342    ///
1343    /// # Examples
1344    ///
1345    /// As an iterator:
1346    ///
1347    /// ```
1348    /// for c in 'İ'.to_lowercase() {
1349    ///     print!("{c}");
1350    /// }
1351    /// println!();
1352    /// ```
1353    ///
1354    /// Using `println!` directly:
1355    ///
1356    /// ```
1357    /// println!("{}", 'İ'.to_lowercase());
1358    /// ```
1359    ///
1360    /// Both are equivalent to:
1361    ///
1362    /// ```
1363    /// println!("i\u{307}");
1364    /// ```
1365    ///
1366    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
1367    ///
1368    /// ```
1369    /// assert_eq!('C'.to_lowercase().to_string(), "c");
1370    ///
1371    /// // Sometimes the result is more than one character:
1372    /// assert_eq!('İ'.to_lowercase().to_string(), "i\u{307}");
1373    ///
1374    /// // Characters that do not have both uppercase and lowercase
1375    /// // convert into themselves.
1376    /// assert_eq!('山'.to_lowercase().to_string(), "山");
1377    /// ```
1378    /// # Notes on context and locale
1379    ///
1380    /// As stated earlier, this method does not take into account language or context.
1381    /// Below is a non-exhaustive list of situations where this can be relevant.
1382    /// If you need to handle locale-depedendent casing in your code, consider using
1383    /// an external crate, like [`icu_casemap`](https://crates.io/crates/icu_casemap)
1384    /// which is developed by Unicode.
1385    ///
1386    /// ## Greek sigma
1387    ///
1388    /// In Greek, the letter simga (uppercase 'Σ') has two lowercase forms:
1389    /// 'σ' which is used in most situations, and 'ς' which appears only
1390    /// at the end of a word. [`char::to_lowercase()`] always uses the first form:
1391    ///
1392    /// ```
1393    /// assert_eq!('Σ'.to_lowercase().to_string(), "σ");
1394    /// ```
1395    ///
1396    /// `str::to_lowercase()` (only available with the `alloc` crate)
1397    /// *does* properly handle this contextual mapping,
1398    /// so prefer using that method if you can. Alternatively, you can use
1399    /// [`is_cased()`] and [`is_case_ignorable()`] to implement it yourself.
1400    /// See `Final_Sigma` in [Table 3.17] of the Unicode Standard,
1401    /// along with [`SpecialCasing.txt`], for more details.
1402    ///
1403    /// [`is_cased()`]: Self::is_cased()
1404    /// [`is_case_ignorable()`]: Self::is_case_ignorable()
1405    /// [Table 3.17]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G54277
1406    ///
1407    /// ## Turkish and Azeri I/ı/İ/i
1408    ///
1409    /// In Turkish and Azeri, the equivalent of 'i' in Latin has five forms instead of two:
1410    ///
1411    /// * 'Dotless': I / ı, sometimes written ï
1412    /// * 'Dotted': İ / i
1413    ///
1414    /// Note that the uppercase undotted 'I' is the same codepoint as the Latin. Therefore:
1415    ///
1416    /// ```
1417    /// let lower_i = 'I'.to_lowercase().to_string();
1418    /// ```
1419    ///
1420    /// `'I'`'s correct lowercase relies on the language of the text: if we're
1421    /// in `en-US`, it should be `"i"`, but if we're in `tr-TR` or `az-AZ`, it should
1422    /// be `"ı"`. `to_lowercase()` does not take this into account, and so:
1423    ///
1424    /// ```
1425    /// let lower_i = 'I'.to_lowercase().to_string();
1426    ///
1427    /// assert_eq!(lower_i, "i");
1428    /// ```
1429    ///
1430    /// holds across languages.
1431    ///
1432    /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
1433    #[must_use = "this returns the lowercased character as a new iterator, \
1434                  without modifying the original"]
1435    #[stable(feature = "rust1", since = "1.0.0")]
1436    #[inline]
1437    pub fn to_lowercase(self) -> ToLowercase {
1438        ToLowercase(CaseMappingIter::new(conversions::to_lower(self)))
1439    }
1440
1441    /// Returns an iterator that yields the titlecase mapping of this `char` as one or more
1442    /// `char`s.
1443    ///
1444    /// This is usually, but not always, equivalent to the uppercase mapping
1445    /// returned by [`to_uppercase()`]. Prefer this method when seeking to capitalize
1446    /// Only The First Letter of a word, but use [`to_uppercase()`] for ALL CAPS.
1447    /// See [below](#difference-from-uppercase) for a thorough explanation
1448    /// of the difference between the two methods.
1449    ///
1450    /// If this `char` does not have a titlecase mapping, the iterator yields the same `char`.
1451    ///
1452    /// If this `char` has a one-to-one titlecase mapping given by the [Unicode Character
1453    /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
1454    ///
1455    /// [ucd]: https://www.unicode.org/reports/tr44/
1456    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1457    ///
1458    /// If this `char` expands to multiple `char`s, the iterator yields the `char`s given by
1459    /// [`SpecialCasing.txt`]. The maximum number of `char`s in a case mapping is 3.
1460    ///
1461    /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
1462    ///
1463    /// This operation performs an unconditional mapping without tailoring. That is, the conversion
1464    /// is independent of context and language. See [below](#note-on-locale)
1465    /// for more information.
1466    ///
1467    /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
1468    /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
1469    ///
1470    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
1471    ///
1472    /// # Examples
1473    ///
1474    /// As an iterator:
1475    ///
1476    /// ```
1477    /// #![feature(titlecase)]
1478    /// for c in 'ß'.to_titlecase() {
1479    ///     print!("{c}");
1480    /// }
1481    /// println!();
1482    /// ```
1483    ///
1484    /// Using `println!` directly:
1485    ///
1486    /// ```
1487    /// #![feature(titlecase)]
1488    /// println!("{}", 'ß'.to_titlecase());
1489    /// ```
1490    ///
1491    /// Both are equivalent to:
1492    ///
1493    /// ```
1494    /// println!("Ss");
1495    /// ```
1496    ///
1497    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
1498    ///
1499    /// ```
1500    /// #![feature(titlecase)]
1501    /// assert_eq!('c'.to_titlecase().to_string(), "C");
1502    /// assert_eq!('ა'.to_titlecase().to_string(), "ა");
1503    /// assert_eq!('dž'.to_titlecase().to_string(), "Dž");
1504    /// assert_eq!('ᾨ'.to_titlecase().to_string(), "ᾨ");
1505    ///
1506    /// // Sometimes the result is more than one character:
1507    /// assert_eq!('ß'.to_titlecase().to_string(), "Ss");
1508    ///
1509    /// // Characters that do not have separate cased forms
1510    /// // convert into themselves.
1511    /// assert_eq!('山'.to_titlecase().to_string(), "山");
1512    /// ```
1513    ///
1514    /// # Difference from uppercase
1515    ///
1516    /// Currently, there are three classes of characters where [`to_uppercase()`]
1517    /// and `to_titlecase()` give different results:
1518    ///
1519    /// ## Georgian script
1520    ///
1521    /// Each letter in the modern Georgian alphabet can be written in one of two forms:
1522    /// the typical lowercase-like "mkhedruli" form, and a variant uppercase-like "mtavruli"
1523    /// form. However, unlike uppercase in most cased scripts, mtavruli is not typically used
1524    /// to start sentences, denote proper nouns, or for any other purpose
1525    /// in running text. It is instead confined to titles and headings, which are written entirely
1526    /// in mtavruli. For this reason, [`to_uppercase()`] applied to a Georgian letter
1527    /// will return the mtavruli form, but `to_titlecase()` will return the mkhedruli form.
1528    ///
1529    /// ```
1530    /// #![feature(titlecase)]
1531    /// let ani = 'ა'; // First letter of the Georgian alphabet, in mkhedruli form
1532    ///
1533    /// // Titlecasing mkhedruli maps it to itself...
1534    /// assert_eq!(ani.to_titlecase().to_string(), ani.to_string());
1535    ///
1536    /// // but uppercasing it maps it to mtavruli
1537    /// assert_eq!(ani.to_uppercase().to_string(), "Ა");
1538    /// ```
1539    ///
1540    /// ## Compatibility digraphs for Latin-alphabet Serbo-Croatian
1541    ///
1542    /// The standard Latin alphabet for the Serbo-Croatian language
1543    /// (Bosnian, Croatian, Montenegrin, and Serbian) contains
1544    /// three digraphs: Dž, Lj, and Nj. These are usually represented as
1545    /// two characters. However, for compatibility with older character sets,
1546    /// Unicode includes single-character versions of these digraphs.
1547    /// Each has a uppercase, titlecase, and lowercase version:
1548    ///
1549    /// - `'DŽ'`, `'Dž'`, `'dž'`
1550    /// - `'LJ'`, `'Lj'`, `'lj'`
1551    /// - `'NJ'`, `'Nj'`, `'nj'`
1552    ///
1553    /// Unicode additionally encodes a casing triad for the Dz digraph
1554    /// without the caron: `'DZ'`, `'Dz'`, `'dz'`.
1555    ///
1556    /// ## Iota-subscritped Greek vowels
1557    ///
1558    /// In ancient Greek, the long vowels alpha (α), eta (η), and omega (ω)
1559    /// were sometimes followed by an iota (ι), forming a diphthong. Over time,
1560    /// the diphthong pronunciation was slowly lost, with the iota becoming mute.
1561    /// Eventually, the ι disappeared from the spelling as well.
1562    /// However, there remains a need to represent ancient texts faithfully.
1563    ///
1564    /// Modern editions of ancient Greek texts commonly use a reduced-sized
1565    /// ι symbol to denote mute iotas, while distinguishing them from ιs
1566    /// which continued to affect pronunciation. The exact standard differs
1567    /// between different publications. Some render the mute ι below its associated
1568    /// vowel (subscript), while others place it to the right of said vowel (adscript).
1569    /// The interaction of mute ι symbols with casing also varies.
1570    ///
1571    /// The Unicode Standard, for its default casing rules, chose to make lowercase
1572    /// Greek vowels with iota subscipt (e.g. `'ᾠ'`) titlecase to the uppercase vowel
1573    /// with iota subscript (`'ᾨ'`) but uppercase to the uppercase vowel followed by
1574    /// full-size uppercase iota (`"ὨΙ"`). This is just one convention among many
1575    /// in common use, but it is the one Unicode settled on,
1576    /// so it is what this method does also.
1577    ///
1578    /// # Note on locale
1579    ///
1580    /// As stated above, this method is locale-insensitive.
1581    /// If you need locale support, consider using an external crate,
1582    /// like [`icu_casemap`](https://crates.io/crates/icu_casemap)
1583    /// which is developed by Unicode. A description of one common
1584    /// locale-dependent casing issue follows (there are others):
1585    ///
1586    /// In Turkish and Azeri, the equivalent of 'i' in Latin has five forms instead of two:
1587    ///
1588    /// * 'Dotless': I / ı, sometimes written ï
1589    /// * 'Dotted': İ / i
1590    ///
1591    /// Note that the lowercase dotted 'i' is the same codepoint as the Latin. Therefore:
1592    ///
1593    /// ```
1594    /// #![feature(titlecase)]
1595    /// let upper_i = 'i'.to_titlecase().to_string();
1596    /// ```
1597    ///
1598    /// `'i'`'s correct titlecase relies on the language of the text: if we're
1599    /// in `en-US`, it should be `"I"`, but if we're in `tr-TR` or `az-AZ`, it should
1600    /// be `"İ"`. `to_titlecase()` does not take this into account, and so:
1601    ///
1602    /// ```
1603    /// #![feature(titlecase)]
1604    /// let upper_i = 'i'.to_titlecase().to_string();
1605    ///
1606    /// assert_eq!(upper_i, "I");
1607    /// ```
1608    ///
1609    /// holds across languages.
1610    ///
1611    /// [`to_uppercase()`]: Self::to_uppercase()
1612    #[must_use = "this returns the titlecased character as a new iterator, \
1613                  without modifying the original"]
1614    #[unstable(feature = "titlecase", issue = "153892")]
1615    #[inline]
1616    pub fn to_titlecase(self) -> ToTitlecase {
1617        ToTitlecase(CaseMappingIter::new(conversions::to_title(self)))
1618    }
1619
1620    /// Returns an iterator that yields the uppercase mapping of this `char` as one or more
1621    /// `char`s.
1622    ///
1623    /// Prefer this method when converting a word into ALL CAPS, but consider [`to_titlecase()`]
1624    /// instead if you seek to capitalize Only The First Letter. See that method's documentation
1625    /// for more information on the difference between the two.
1626    ///
1627    /// If this `char` does not have an uppercase mapping, the iterator yields the same `char`.
1628    ///
1629    /// If this `char` has a one-to-one uppercase mapping given by the [Unicode Character
1630    /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
1631    ///
1632    /// [ucd]: https://www.unicode.org/reports/tr44/
1633    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
1634    ///
1635    /// If this `char` expands to multiple `char`s, the iterator yields the `char`s given by
1636    /// [`SpecialCasing.txt`]. The maximum number of `char`s in a case mapping is 3.
1637    ///
1638    /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
1639    ///
1640    /// This operation performs an unconditional mapping without tailoring. That is, the conversion
1641    /// is independent of context and language. See [below](#note-on-locale)
1642    /// for more information.
1643    ///
1644    /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
1645    /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
1646    ///
1647    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
1648    ///
1649    /// # Examples
1650    ///
1651    /// `'ſt'` (U+FB05) is a single Unicode code point (a ligature) that maps to "ST" in uppercase.
1652    ///
1653    /// As an iterator:
1654    ///
1655    /// ```
1656    /// for c in 'ſt'.to_uppercase() {
1657    ///     print!("{c}");
1658    /// }
1659    /// println!();
1660    /// ```
1661    ///
1662    /// Using `println!` directly:
1663    ///
1664    /// ```
1665    /// println!("{}", 'ſt'.to_uppercase());
1666    /// ```
1667    ///
1668    /// Both are equivalent to:
1669    ///
1670    /// ```
1671    /// println!("ST");
1672    /// ```
1673    ///
1674    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
1675    ///
1676    /// ```
1677    /// assert_eq!('c'.to_uppercase().to_string(), "C");
1678    /// assert_eq!('ა'.to_uppercase().to_string(), "Ა");
1679    /// assert_eq!('dž'.to_uppercase().to_string(), "DŽ");
1680    ///
1681    /// // Sometimes the result is more than one character:
1682    /// assert_eq!('ſt'.to_uppercase().to_string(), "ST");
1683    /// assert_eq!('ᾨ'.to_uppercase().to_string(), "ὨΙ");
1684    ///
1685    /// // Characters that do not have both uppercase and lowercase
1686    /// // convert into themselves.
1687    /// assert_eq!('山'.to_uppercase().to_string(), "山");
1688    /// ```
1689    ///
1690    /// # Note on locale
1691    ///
1692    /// As stated above, this method is locale-insensitive.
1693    /// If you need locale support, consider using an external crate,
1694    /// like [`icu_casemap`](https://crates.io/crates/icu_casemap)
1695    /// which is developed by Unicode. A description of one common
1696    /// locale-dependent casing issue follows (there are others):
1697    ///
1698    /// In Turkish and Azeri, the equivalent of 'i' in Latin has five forms instead of two:
1699    ///
1700    /// * 'Dotless': I / ı, sometimes written ï
1701    /// * 'Dotted': İ / i
1702    ///
1703    /// Note that the lowercase dotted 'i' is the same codepoint as the Latin. Therefore:
1704    ///
1705    /// ```
1706    /// let upper_i = 'i'.to_uppercase().to_string();
1707    /// ```
1708    ///
1709    /// `'i'`'s correct uppercase relies on the language of the text: if we're
1710    /// in `en-US`, it should be `"I"`, but if we're in `tr-TR` or `az-AZ`, it should
1711    /// be `"İ"`. `to_uppercase()` does not take this into account, and so:
1712    ///
1713    /// ```
1714    /// let upper_i = 'i'.to_uppercase().to_string();
1715    ///
1716    /// assert_eq!(upper_i, "I");
1717    /// ```
1718    ///
1719    /// holds across languages.
1720    ///
1721    /// [`to_titlecase()`]: Self::to_titlecase()
1722    #[must_use = "this returns the uppercased character as a new iterator, \
1723                  without modifying the original"]
1724    #[stable(feature = "rust1", since = "1.0.0")]
1725    #[inline]
1726    pub fn to_uppercase(self) -> ToUppercase {
1727        ToUppercase(CaseMappingIter::new(conversions::to_upper(self)))
1728    }
1729
1730    /// Returns an iterator that yields the case folding of this `char` as one or more
1731    /// `char`s.
1732    ///
1733    /// Case folding is meant to be used when performing case-insensitive string comparisons.
1734    /// Case-folded strings should not usually be exposed directly to users. For most,
1735    /// but not all, characters, the casefold mapping is identical to the lowercase one.
1736    ///
1737    /// This iterator yields the `char`(s) in the common or full case folding for this `char`,
1738    /// as given by the [Unicode Character Database][ucd] [`CaseFolding.txt`].
1739    /// The maximum number of `char`s in a case folding is 3.
1740    ///
1741    /// [ucd]: https://www.unicode.org/reports/tr44/
1742    /// [`CaseFolding.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/CaseFolding.txt
1743    ///
1744    ///
1745    /// No [normalization] (e.g. NFC) is performed, so visually and semantically identical characters
1746    /// might still casefold differently. For example, `'ά'` (U+03AC GREEK SMALL LETTER ALPHA WITH TONOS)
1747    /// is considered distinct from `'ά'` (U+1F71 GREEK SMALL LETTER ALPHA WITH OXIA),
1748    /// even though Unicode considers them canonically equivalent.
1749    ///
1750    /// In addition, this method is independent of language/locale,
1751    /// so the special behavior of I/ı/İ/i in Turkish and Azeri is not handled.
1752    ///
1753    /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case folding in
1754    /// general and Chapter 3 (Conformance) discusses the default algorithm for case folding.
1755    ///
1756    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
1757    ///
1758    /// # Examples
1759    ///
1760    /// The German sharp S `'ß'` (U+DF) is a single Unicode code point
1761    /// that casefolds to `"ss"`. Its uppercase variant '`ẞ`' (U+1E9E)
1762    /// has the same case-folding.
1763    ///
1764    /// As an iterator:
1765    ///
1766    /// ```
1767    /// #![feature(casefold)]
1768    /// assert!('ß'.to_casefold_unnormalized().eq(['s', 's']));
1769    /// assert!('ẞ'.to_casefold_unnormalized().eq(['s', 's']));
1770    /// ```
1771    ///
1772    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
1773    ///
1774    /// ```
1775    /// #![feature(casefold)]
1776    /// assert_eq!('ß'.to_casefold_unnormalized().to_string(), "ss");
1777    /// assert_eq!('ẞ'.to_casefold_unnormalized().to_string(), "ss");
1778    /// ```
1779    ///
1780    /// No [normalization] is performed:
1781    ///
1782    /// ```rust
1783    /// #![feature(casefold)]
1784    /// // These two characters are visually and semantically identical;
1785    /// // Unicode considers them to be canonically equivalent.
1786    /// let alpha_tonos = 'ά';
1787    /// let alpha_oxia = 'ά';
1788    ///
1789    /// // However, they are different codepoints:
1790    /// assert_eq!(alpha_tonos, '\u{03AC}');
1791    /// assert_eq!(alpha_oxia, '\u{1F71}');
1792    ///
1793    /// // Their case-foldings are likewise unequal:
1794    /// assert!(alpha_tonos.to_casefold_unnormalized().eq(['\u{03AC}']));
1795    /// assert!(alpha_oxia.to_casefold_unnormalized().eq(['\u{1F71}']));
1796    /// ```
1797    ///
1798    /// # Note on locale
1799    ///
1800    /// In Turkish and Azeri, the equivalent of 'i' in Latin has five forms instead of two:
1801    ///
1802    /// * 'Dotless': I / ı, sometimes written ï
1803    /// * 'Dotted': İ / i
1804    ///
1805    /// Note that the uppercase undotted 'I' is the same codepoint as the Latin. Therefore:
1806    ///
1807    /// ```
1808    /// #![feature(casefold)]
1809    /// let casefold_i = 'I'.to_casefold_unnormalized().to_string();
1810    /// ```
1811    ///
1812    /// `'I'`'s correct case folding relies on the language of the text: if we're
1813    /// in `en-US`, it should be `"i"`, but if we're in `tr-TR` or `az-AZ`, it should
1814    /// be `"ı"`. `to_casefold_unnormalized()` does not take this into account, and so:
1815    ///
1816    /// ```
1817    /// #![feature(casefold)]
1818    /// let casefold_i = 'I'.to_casefold_unnormalized().to_string();
1819    ///
1820    /// assert_eq!(casefold_i, "i");
1821    /// ```
1822    ///
1823    /// holds across languages.
1824    ///
1825    /// [normalization]: https://www.unicode.org/faq/normalization.html
1826    #[must_use = "this returns the case-folded character as a new iterator, \
1827                  without modifying the original"]
1828    #[unstable(feature = "casefold", issue = "157000")]
1829    #[inline]
1830    pub fn to_casefold_unnormalized(self) -> ToCasefold {
1831        ToCasefold(CaseMappingIter::new(conversions::to_casefold(self)))
1832    }
1833
1834    /// Returns the code point value as a `u32`.
1835    ///
1836    /// # Examples
1837    ///
1838    /// ```
1839    /// #![feature(char_to_u32)]
1840    ///
1841    /// let ascii = 'a';
1842    /// let heart = '❤';
1843    ///
1844    /// assert_eq!(ascii.to_u32(), 97_u32);
1845    /// assert_eq!(heart.to_u32(), 0x2764_u32);
1846    /// ```
1847    #[must_use = "this returns the result of the operation, \
1848                  without modifying the original"]
1849    #[unstable(feature = "char_to_u32", issue = "158938")]
1850    #[rustc_const_unstable(feature = "char_to_u32", issue = "158938")]
1851    #[inline(always)]
1852    pub const fn to_u32(self) -> u32 {
1853        self as u32
1854    }
1855
1856    /// Checks if the value is within the ASCII range.
1857    ///
1858    /// # Examples
1859    ///
1860    /// ```
1861    /// let ascii = 'a';
1862    /// let non_ascii = '❤';
1863    ///
1864    /// assert!(ascii.is_ascii());
1865    /// assert!(!non_ascii.is_ascii());
1866    /// ```
1867    #[must_use]
1868    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
1869    #[rustc_const_stable(feature = "const_char_is_ascii", since = "1.32.0")]
1870    #[rustc_diagnostic_item = "char_is_ascii"]
1871    #[inline]
1872    #[ferrocene::prevalidated]
1873    pub const fn is_ascii(&self) -> bool {
1874        *self as u32 <= 0x7F
1875    }
1876
1877    /// Returns `Some` if the value is within the ASCII range,
1878    /// or `None` if it's not.
1879    ///
1880    /// This is preferred to [`Self::is_ascii`] when you're passing the value
1881    /// along to something else that can take [`ascii::Char`] rather than
1882    /// needing to check again for itself whether the value is in ASCII.
1883    #[must_use]
1884    #[unstable(feature = "ascii_char", issue = "110998")]
1885    #[inline]
1886    #[ferrocene::prevalidated]
1887    pub const fn as_ascii(&self) -> Option<ascii::Char> {
1888        if self.is_ascii() {
1889            // SAFETY: Just checked that this is ASCII.
1890            Some(unsafe { ascii::Char::from_u8_unchecked(*self as u8) })
1891        } else {
1892            None
1893        }
1894    }
1895
1896    /// Converts this char into an [ASCII character](`ascii::Char`), without
1897    /// checking whether it is valid.
1898    ///
1899    /// # Safety
1900    ///
1901    /// This char must be within the ASCII range, or else this is UB.
1902    #[must_use]
1903    #[unstable(feature = "ascii_char", issue = "110998")]
1904    #[inline]
1905    pub const unsafe fn as_ascii_unchecked(&self) -> ascii::Char {
1906        assert_unsafe_precondition!(
1907            check_library_ub,
1908            "as_ascii_unchecked requires that the char is valid ASCII",
1909            (it: &char = self) => it.is_ascii()
1910        );
1911
1912        // SAFETY: the caller promised that this char is ASCII.
1913        unsafe { ascii::Char::from_u8_unchecked(*self as u8) }
1914    }
1915
1916    /// Makes a copy of the value in its ASCII upper case equivalent.
1917    ///
1918    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
1919    /// but non-ASCII letters are unchanged.
1920    ///
1921    /// To uppercase the value in-place, use [`make_ascii_uppercase()`].
1922    ///
1923    /// To uppercase ASCII characters in addition to non-ASCII characters, use
1924    /// [`to_uppercase()`].
1925    ///
1926    /// # Examples
1927    ///
1928    /// ```
1929    /// let ascii = 'a';
1930    /// let non_ascii = '❤';
1931    ///
1932    /// assert_eq!('A', ascii.to_ascii_uppercase());
1933    /// assert_eq!('❤', non_ascii.to_ascii_uppercase());
1934    /// ```
1935    ///
1936    /// [`make_ascii_uppercase()`]: #method.make_ascii_uppercase
1937    /// [`to_uppercase()`]: #method.to_uppercase
1938    #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"]
1939    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
1940    #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
1941    #[inline]
1942    pub const fn to_ascii_uppercase(&self) -> char {
1943        if self.is_ascii_lowercase() {
1944            (*self as u8).ascii_change_case_unchecked() as char
1945        } else {
1946            *self
1947        }
1948    }
1949
1950    /// Makes a copy of the value in its ASCII lower case equivalent.
1951    ///
1952    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
1953    /// but non-ASCII letters are unchanged.
1954    ///
1955    /// To lowercase the value in-place, use [`make_ascii_lowercase()`].
1956    ///
1957    /// To lowercase ASCII characters in addition to non-ASCII characters, use
1958    /// [`to_lowercase()`].
1959    ///
1960    /// # Examples
1961    ///
1962    /// ```
1963    /// let ascii = 'A';
1964    /// let non_ascii = '❤';
1965    ///
1966    /// assert_eq!('a', ascii.to_ascii_lowercase());
1967    /// assert_eq!('❤', non_ascii.to_ascii_lowercase());
1968    /// ```
1969    ///
1970    /// [`make_ascii_lowercase()`]: #method.make_ascii_lowercase
1971    /// [`to_lowercase()`]: #method.to_lowercase
1972    #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"]
1973    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
1974    #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
1975    #[inline]
1976    pub const fn to_ascii_lowercase(&self) -> char {
1977        if self.is_ascii_uppercase() {
1978            (*self as u8).ascii_change_case_unchecked() as char
1979        } else {
1980            *self
1981        }
1982    }
1983
1984    /// Checks that two values are an ASCII case-insensitive match.
1985    ///
1986    /// Equivalent to <code>[to_ascii_lowercase]\(a) == [to_ascii_lowercase]\(b)</code>.
1987    ///
1988    /// # Examples
1989    ///
1990    /// ```
1991    /// let upper_a = 'A';
1992    /// let lower_a = 'a';
1993    /// let lower_z = 'z';
1994    ///
1995    /// assert!(upper_a.eq_ignore_ascii_case(&lower_a));
1996    /// assert!(upper_a.eq_ignore_ascii_case(&upper_a));
1997    /// assert!(!upper_a.eq_ignore_ascii_case(&lower_z));
1998    /// ```
1999    ///
2000    /// [to_ascii_lowercase]: #method.to_ascii_lowercase
2001    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
2002    #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
2003    #[inline]
2004    pub const fn eq_ignore_ascii_case(&self, other: &char) -> bool {
2005        self.to_ascii_lowercase() == other.to_ascii_lowercase()
2006    }
2007
2008    /// Converts this type to its ASCII upper case equivalent in-place.
2009    ///
2010    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
2011    /// but non-ASCII letters are unchanged.
2012    ///
2013    /// To return a new uppercased value without modifying the existing one, use
2014    /// [`to_ascii_uppercase()`].
2015    ///
2016    /// # Examples
2017    ///
2018    /// ```
2019    /// let mut ascii = 'a';
2020    ///
2021    /// ascii.make_ascii_uppercase();
2022    ///
2023    /// assert_eq!('A', ascii);
2024    /// ```
2025    ///
2026    /// [`to_ascii_uppercase()`]: #method.to_ascii_uppercase
2027    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
2028    #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")]
2029    #[inline]
2030    pub const fn make_ascii_uppercase(&mut self) {
2031        *self = self.to_ascii_uppercase();
2032    }
2033
2034    /// Converts this type to its ASCII lower case equivalent in-place.
2035    ///
2036    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
2037    /// but non-ASCII letters are unchanged.
2038    ///
2039    /// To return a new lowercased value without modifying the existing one, use
2040    /// [`to_ascii_lowercase()`].
2041    ///
2042    /// # Examples
2043    ///
2044    /// ```
2045    /// let mut ascii = 'A';
2046    ///
2047    /// ascii.make_ascii_lowercase();
2048    ///
2049    /// assert_eq!('a', ascii);
2050    /// ```
2051    ///
2052    /// [`to_ascii_lowercase()`]: #method.to_ascii_lowercase
2053    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
2054    #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")]
2055    #[inline]
2056    pub const fn make_ascii_lowercase(&mut self) {
2057        *self = self.to_ascii_lowercase();
2058    }
2059
2060    /// Checks if the value is an ASCII alphabetic character:
2061    ///
2062    /// - U+0041 'A' ..= U+005A 'Z', or
2063    /// - U+0061 'a' ..= U+007A 'z'.
2064    ///
2065    /// # Examples
2066    ///
2067    /// ```
2068    /// let uppercase_a = 'A';
2069    /// let uppercase_g = 'G';
2070    /// let a = 'a';
2071    /// let g = 'g';
2072    /// let zero = '0';
2073    /// let percent = '%';
2074    /// let space = ' ';
2075    /// let lf = '\n';
2076    /// let esc = '\x1b';
2077    ///
2078    /// assert!(uppercase_a.is_ascii_alphabetic());
2079    /// assert!(uppercase_g.is_ascii_alphabetic());
2080    /// assert!(a.is_ascii_alphabetic());
2081    /// assert!(g.is_ascii_alphabetic());
2082    /// assert!(!zero.is_ascii_alphabetic());
2083    /// assert!(!percent.is_ascii_alphabetic());
2084    /// assert!(!space.is_ascii_alphabetic());
2085    /// assert!(!lf.is_ascii_alphabetic());
2086    /// assert!(!esc.is_ascii_alphabetic());
2087    /// ```
2088    #[must_use]
2089    #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2090    #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2091    #[inline]
2092    pub const fn is_ascii_alphabetic(&self) -> bool {
2093        matches!(*self, 'a'..='z' | 'A'..='Z')
2094    }
2095
2096    /// Checks if the value is an ASCII uppercase character:
2097    /// U+0041 'A' ..= U+005A 'Z'.
2098    ///
2099    /// # Examples
2100    ///
2101    /// ```
2102    /// let uppercase_a = 'A';
2103    /// let uppercase_g = 'G';
2104    /// let a = 'a';
2105    /// let g = 'g';
2106    /// let zero = '0';
2107    /// let percent = '%';
2108    /// let space = ' ';
2109    /// let lf = '\n';
2110    /// let esc = '\x1b';
2111    ///
2112    /// assert!(uppercase_a.is_ascii_uppercase());
2113    /// assert!(uppercase_g.is_ascii_uppercase());
2114    /// assert!(!a.is_ascii_uppercase());
2115    /// assert!(!g.is_ascii_uppercase());
2116    /// assert!(!zero.is_ascii_uppercase());
2117    /// assert!(!percent.is_ascii_uppercase());
2118    /// assert!(!space.is_ascii_uppercase());
2119    /// assert!(!lf.is_ascii_uppercase());
2120    /// assert!(!esc.is_ascii_uppercase());
2121    /// ```
2122    #[must_use]
2123    #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2124    #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2125    #[inline]
2126    pub const fn is_ascii_uppercase(&self) -> bool {
2127        matches!(*self, 'A'..='Z')
2128    }
2129
2130    /// Checks if the value is an ASCII lowercase character:
2131    /// U+0061 'a' ..= U+007A 'z'.
2132    ///
2133    /// # Examples
2134    ///
2135    /// ```
2136    /// let uppercase_a = 'A';
2137    /// let uppercase_g = 'G';
2138    /// let a = 'a';
2139    /// let g = 'g';
2140    /// let zero = '0';
2141    /// let percent = '%';
2142    /// let space = ' ';
2143    /// let lf = '\n';
2144    /// let esc = '\x1b';
2145    ///
2146    /// assert!(!uppercase_a.is_ascii_lowercase());
2147    /// assert!(!uppercase_g.is_ascii_lowercase());
2148    /// assert!(a.is_ascii_lowercase());
2149    /// assert!(g.is_ascii_lowercase());
2150    /// assert!(!zero.is_ascii_lowercase());
2151    /// assert!(!percent.is_ascii_lowercase());
2152    /// assert!(!space.is_ascii_lowercase());
2153    /// assert!(!lf.is_ascii_lowercase());
2154    /// assert!(!esc.is_ascii_lowercase());
2155    /// ```
2156    #[must_use]
2157    #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2158    #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2159    #[inline]
2160    pub const fn is_ascii_lowercase(&self) -> bool {
2161        matches!(*self, 'a'..='z')
2162    }
2163
2164    /// Checks if the value is an ASCII alphanumeric character:
2165    ///
2166    /// - U+0041 'A' ..= U+005A 'Z', or
2167    /// - U+0061 'a' ..= U+007A 'z', or
2168    /// - U+0030 '0' ..= U+0039 '9'.
2169    ///
2170    /// # Examples
2171    ///
2172    /// ```
2173    /// let uppercase_a = 'A';
2174    /// let uppercase_g = 'G';
2175    /// let a = 'a';
2176    /// let g = 'g';
2177    /// let zero = '0';
2178    /// let percent = '%';
2179    /// let space = ' ';
2180    /// let lf = '\n';
2181    /// let esc = '\x1b';
2182    ///
2183    /// assert!(uppercase_a.is_ascii_alphanumeric());
2184    /// assert!(uppercase_g.is_ascii_alphanumeric());
2185    /// assert!(a.is_ascii_alphanumeric());
2186    /// assert!(g.is_ascii_alphanumeric());
2187    /// assert!(zero.is_ascii_alphanumeric());
2188    /// assert!(!percent.is_ascii_alphanumeric());
2189    /// assert!(!space.is_ascii_alphanumeric());
2190    /// assert!(!lf.is_ascii_alphanumeric());
2191    /// assert!(!esc.is_ascii_alphanumeric());
2192    /// ```
2193    #[must_use]
2194    #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2195    #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2196    #[inline]
2197    pub const fn is_ascii_alphanumeric(&self) -> bool {
2198        matches!(*self, '0'..='9') | matches!(*self, 'A'..='Z') | matches!(*self, 'a'..='z')
2199    }
2200
2201    /// Checks if the value is an ASCII decimal digit:
2202    /// U+0030 '0' ..= U+0039 '9'.
2203    ///
2204    /// # Examples
2205    ///
2206    /// ```
2207    /// let uppercase_a = 'A';
2208    /// let uppercase_g = 'G';
2209    /// let a = 'a';
2210    /// let g = 'g';
2211    /// let zero = '0';
2212    /// let percent = '%';
2213    /// let space = ' ';
2214    /// let lf = '\n';
2215    /// let esc = '\x1b';
2216    ///
2217    /// assert!(!uppercase_a.is_ascii_digit());
2218    /// assert!(!uppercase_g.is_ascii_digit());
2219    /// assert!(!a.is_ascii_digit());
2220    /// assert!(!g.is_ascii_digit());
2221    /// assert!(zero.is_ascii_digit());
2222    /// assert!(!percent.is_ascii_digit());
2223    /// assert!(!space.is_ascii_digit());
2224    /// assert!(!lf.is_ascii_digit());
2225    /// assert!(!esc.is_ascii_digit());
2226    /// ```
2227    #[must_use]
2228    #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2229    #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2230    #[inline]
2231    pub const fn is_ascii_digit(&self) -> bool {
2232        matches!(*self, '0'..='9')
2233    }
2234
2235    /// Checks if the value is an ASCII octal digit:
2236    /// U+0030 '0' ..= U+0037 '7'.
2237    ///
2238    /// # Examples
2239    ///
2240    /// ```
2241    /// #![feature(is_ascii_octdigit)]
2242    ///
2243    /// let uppercase_a = 'A';
2244    /// let a = 'a';
2245    /// let zero = '0';
2246    /// let seven = '7';
2247    /// let nine = '9';
2248    /// let percent = '%';
2249    /// let lf = '\n';
2250    ///
2251    /// assert!(!uppercase_a.is_ascii_octdigit());
2252    /// assert!(!a.is_ascii_octdigit());
2253    /// assert!(zero.is_ascii_octdigit());
2254    /// assert!(seven.is_ascii_octdigit());
2255    /// assert!(!nine.is_ascii_octdigit());
2256    /// assert!(!percent.is_ascii_octdigit());
2257    /// assert!(!lf.is_ascii_octdigit());
2258    /// ```
2259    #[must_use]
2260    #[unstable(feature = "is_ascii_octdigit", issue = "101288")]
2261    #[inline]
2262    pub const fn is_ascii_octdigit(&self) -> bool {
2263        matches!(*self, '0'..='7')
2264    }
2265
2266    /// Checks if the value is an ASCII hexadecimal digit:
2267    ///
2268    /// - U+0030 '0' ..= U+0039 '9', or
2269    /// - U+0041 'A' ..= U+0046 'F', or
2270    /// - U+0061 'a' ..= U+0066 'f'.
2271    ///
2272    /// # Examples
2273    ///
2274    /// ```
2275    /// let uppercase_a = 'A';
2276    /// let uppercase_g = 'G';
2277    /// let a = 'a';
2278    /// let g = 'g';
2279    /// let zero = '0';
2280    /// let percent = '%';
2281    /// let space = ' ';
2282    /// let lf = '\n';
2283    /// let esc = '\x1b';
2284    ///
2285    /// assert!(uppercase_a.is_ascii_hexdigit());
2286    /// assert!(!uppercase_g.is_ascii_hexdigit());
2287    /// assert!(a.is_ascii_hexdigit());
2288    /// assert!(!g.is_ascii_hexdigit());
2289    /// assert!(zero.is_ascii_hexdigit());
2290    /// assert!(!percent.is_ascii_hexdigit());
2291    /// assert!(!space.is_ascii_hexdigit());
2292    /// assert!(!lf.is_ascii_hexdigit());
2293    /// assert!(!esc.is_ascii_hexdigit());
2294    /// ```
2295    #[must_use]
2296    #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2297    #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2298    #[inline]
2299    pub const fn is_ascii_hexdigit(&self) -> bool {
2300        matches!(*self, '0'..='9') | matches!(*self, 'A'..='F') | matches!(*self, 'a'..='f')
2301    }
2302
2303    /// Checks if the value is an ASCII punctuation or symbol character
2304    /// (i.e. not alphanumeric, whitespace, or control):
2305    ///
2306    /// - U+0021 ..= U+002F `! " # $ % & ' ( ) * + , - . /`, or
2307    /// - U+003A ..= U+0040 `: ; < = > ? @`, or
2308    /// - U+005B ..= U+0060 ``[ \ ] ^ _ ` ``, or
2309    /// - U+007B ..= U+007E `{ | } ~`
2310    ///
2311    /// # Examples
2312    ///
2313    /// ```
2314    /// let uppercase_a = 'A';
2315    /// let uppercase_g = 'G';
2316    /// let a = 'a';
2317    /// let g = 'g';
2318    /// let zero = '0';
2319    /// let percent = '%';
2320    /// let space = ' ';
2321    /// let lf = '\n';
2322    /// let esc = '\x1b';
2323    ///
2324    /// assert!(!uppercase_a.is_ascii_punctuation());
2325    /// assert!(!uppercase_g.is_ascii_punctuation());
2326    /// assert!(!a.is_ascii_punctuation());
2327    /// assert!(!g.is_ascii_punctuation());
2328    /// assert!(!zero.is_ascii_punctuation());
2329    /// assert!(percent.is_ascii_punctuation());
2330    /// assert!(!space.is_ascii_punctuation());
2331    /// assert!(!lf.is_ascii_punctuation());
2332    /// assert!(!esc.is_ascii_punctuation());
2333    /// ```
2334    #[must_use]
2335    #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2336    #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2337    #[inline]
2338    pub const fn is_ascii_punctuation(&self) -> bool {
2339        matches!(*self, '!'..='/')
2340            | matches!(*self, ':'..='@')
2341            | matches!(*self, '['..='`')
2342            | matches!(*self, '{'..='~')
2343    }
2344
2345    /// Checks if the value is an ASCII graphic character
2346    /// (i.e. not whitespace or control):
2347    /// U+0021 '!' ..= U+007E '~'.
2348    ///
2349    /// # Examples
2350    ///
2351    /// ```
2352    /// let uppercase_a = 'A';
2353    /// let uppercase_g = 'G';
2354    /// let a = 'a';
2355    /// let g = 'g';
2356    /// let zero = '0';
2357    /// let percent = '%';
2358    /// let space = ' ';
2359    /// let lf = '\n';
2360    /// let esc = '\x1b';
2361    ///
2362    /// assert!(uppercase_a.is_ascii_graphic());
2363    /// assert!(uppercase_g.is_ascii_graphic());
2364    /// assert!(a.is_ascii_graphic());
2365    /// assert!(g.is_ascii_graphic());
2366    /// assert!(zero.is_ascii_graphic());
2367    /// assert!(percent.is_ascii_graphic());
2368    /// assert!(!space.is_ascii_graphic());
2369    /// assert!(!lf.is_ascii_graphic());
2370    /// assert!(!esc.is_ascii_graphic());
2371    /// ```
2372    #[must_use]
2373    #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2374    #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2375    #[inline]
2376    pub const fn is_ascii_graphic(&self) -> bool {
2377        matches!(*self, '!'..='~')
2378    }
2379
2380    /// Checks if the value is an ASCII whitespace character:
2381    /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
2382    /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
2383    ///
2384    /// **Warning:** Because the list above excludes U+000B VERTICAL TAB,
2385    /// `c.is_ascii_whitespace()` is **not** equivalent to `c.is_ascii() && c.is_whitespace()`.
2386    ///
2387    /// Rust uses the WhatWG Infra Standard's [definition of ASCII
2388    /// whitespace][infra-aw]. There are several other definitions in
2389    /// wide use. For instance, [the POSIX locale][pct] includes
2390    /// U+000B VERTICAL TAB as well as all the above characters,
2391    /// but—from the very same specification—[the default rule for
2392    /// "field splitting" in the Bourne shell][bfs] considers *only*
2393    /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
2394    ///
2395    /// If you are writing a program that will process an existing
2396    /// file format, check what that format's definition of whitespace is
2397    /// before using this function.
2398    ///
2399    /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
2400    /// [pct]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01
2401    /// [bfs]: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_06_05
2402    ///
2403    /// # Examples
2404    ///
2405    /// ```
2406    /// let uppercase_a = 'A';
2407    /// let uppercase_g = 'G';
2408    /// let a = 'a';
2409    /// let g = 'g';
2410    /// let zero = '0';
2411    /// let percent = '%';
2412    /// let space = ' ';
2413    /// let lf = '\n';
2414    /// let esc = '\x1b';
2415    ///
2416    /// assert!(!uppercase_a.is_ascii_whitespace());
2417    /// assert!(!uppercase_g.is_ascii_whitespace());
2418    /// assert!(!a.is_ascii_whitespace());
2419    /// assert!(!g.is_ascii_whitespace());
2420    /// assert!(!zero.is_ascii_whitespace());
2421    /// assert!(!percent.is_ascii_whitespace());
2422    /// assert!(space.is_ascii_whitespace());
2423    /// assert!(lf.is_ascii_whitespace());
2424    /// assert!(!esc.is_ascii_whitespace());
2425    /// ```
2426    #[must_use]
2427    #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2428    #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2429    #[inline]
2430    #[ferrocene::prevalidated]
2431    pub const fn is_ascii_whitespace(&self) -> bool {
2432        matches!(*self, '\t' | '\n' | '\x0C' | '\r' | ' ')
2433    }
2434
2435    /// Checks if the value is an ASCII control character:
2436    /// U+0000 NUL ..= U+001F UNIT SEPARATOR, or U+007F DELETE.
2437    /// Note that most ASCII whitespace characters are control
2438    /// characters, but SPACE is not.
2439    ///
2440    /// # Examples
2441    ///
2442    /// ```
2443    /// let uppercase_a = 'A';
2444    /// let uppercase_g = 'G';
2445    /// let a = 'a';
2446    /// let g = 'g';
2447    /// let zero = '0';
2448    /// let percent = '%';
2449    /// let space = ' ';
2450    /// let lf = '\n';
2451    /// let esc = '\x1b';
2452    ///
2453    /// assert!(!uppercase_a.is_ascii_control());
2454    /// assert!(!uppercase_g.is_ascii_control());
2455    /// assert!(!a.is_ascii_control());
2456    /// assert!(!g.is_ascii_control());
2457    /// assert!(!zero.is_ascii_control());
2458    /// assert!(!percent.is_ascii_control());
2459    /// assert!(!space.is_ascii_control());
2460    /// assert!(lf.is_ascii_control());
2461    /// assert!(esc.is_ascii_control());
2462    /// ```
2463    #[must_use]
2464    #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
2465    #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
2466    #[inline]
2467    pub const fn is_ascii_control(&self) -> bool {
2468        matches!(*self, '\0'..='\x1F' | '\x7F')
2469    }
2470}
2471
2472#[ferrocene::prevalidated]
2473pub(crate) struct EscapeDebugExtArgs {
2474    /// Escape Grapheme Extender codepoints?
2475    ///
2476    /// Note that this excludes
2477    /// U+FF9E HALFWIDTH KATAKANA VOICED SOUND MARK
2478    /// and U+FF9F HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK,
2479    /// which are never escaped, as graphically
2480    /// they are not combining. See <https://github.com/microsoft/terminal/issues/18087>
2481    /// for background on these characters.
2482    pub(crate) escape_grapheme_extender: bool,
2483
2484    /// Escape single quotes?
2485    pub(crate) escape_single_quote: bool,
2486
2487    /// Escape double quotes?
2488    pub(crate) escape_double_quote: bool,
2489}
2490
2491impl EscapeDebugExtArgs {
2492    pub(crate) const ESCAPE_ALL: Self = Self {
2493        escape_grapheme_extender: true,
2494        escape_single_quote: true,
2495        escape_double_quote: true,
2496    };
2497}
2498
2499#[inline]
2500#[must_use]
2501#[ferrocene::prevalidated]
2502const fn len_utf8(code: u32) -> usize {
2503    match code {
2504        ..MAX_ONE_B => 1,
2505        ..MAX_TWO_B => 2,
2506        ..MAX_THREE_B => 3,
2507        _ => 4,
2508    }
2509}
2510
2511#[inline]
2512#[must_use]
2513const fn len_utf16(code: u32) -> usize {
2514    if (code & 0xFFFF) == code { 1 } else { 2 }
2515}
2516
2517/// Encodes a raw `u32` value as UTF-8 into the provided byte buffer,
2518/// and then returns the subslice of the buffer that contains the encoded character.
2519///
2520/// Unlike `char::encode_utf8`, this method also handles codepoints in the surrogate range.
2521/// (Creating a `char` in the surrogate range is UB.)
2522/// The result is valid [generalized UTF-8] but not valid UTF-8.
2523///
2524/// [generalized UTF-8]: https://simonsapin.github.io/wtf-8/#generalized-utf8
2525///
2526/// # Panics
2527///
2528/// Panics if the buffer is not large enough.
2529/// A buffer of length four is large enough to encode any `char`.
2530#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
2531#[doc(hidden)]
2532#[inline]
2533#[ferrocene::prevalidated]
2534pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] {
2535    let len = len_utf8(code);
2536    if dst.len() < len {
2537        const_panic!(
2538            "encode_utf8: buffer does not have enough bytes to encode code point",
2539            "encode_utf8: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}",
2540            code: u32 = code,
2541            len: usize = len,
2542            dst_len: usize = dst.len(),
2543        );
2544    }
2545
2546    // SAFETY: `dst` is checked to be at least the length needed to encode the codepoint.
2547    unsafe { encode_utf8_raw_unchecked(code, dst.as_mut_ptr()) };
2548
2549    // SAFETY: `<&mut [u8]>::as_mut_ptr` is guaranteed to return a valid pointer and `len` has been tested to be within bounds.
2550    unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) }
2551}
2552
2553/// Encodes a raw `u32` value as UTF-8 into the byte buffer pointed to by `dst`.
2554///
2555/// Unlike `char::encode_utf8`, this method also handles codepoints in the surrogate range.
2556/// (Creating a `char` in the surrogate range is UB.)
2557/// The result is valid [generalized UTF-8] but not valid UTF-8.
2558///
2559/// [generalized UTF-8]: https://simonsapin.github.io/wtf-8/#generalized-utf8
2560///
2561/// # Safety
2562///
2563/// The behavior is undefined if the buffer pointed to by `dst` is not
2564/// large enough to hold the encoded codepoint. A buffer of length four
2565/// is large enough to encode any `char`.
2566///
2567/// For a safe version of this function, see the [`encode_utf8_raw`] function.
2568#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
2569#[doc(hidden)]
2570#[inline]
2571#[ferrocene::prevalidated]
2572pub const unsafe fn encode_utf8_raw_unchecked(code: u32, dst: *mut u8) {
2573    let len = len_utf8(code);
2574    // SAFETY: The caller must guarantee that the buffer pointed to by `dst`
2575    // is at least `len` bytes long.
2576    unsafe {
2577        if len == 1 {
2578            *dst = code as u8;
2579            return;
2580        }
2581
2582        let last1 = (code >> 0 & 0x3F) as u8 | TAG_CONT;
2583        let last2 = (code >> 6 & 0x3F) as u8 | TAG_CONT;
2584        let last3 = (code >> 12 & 0x3F) as u8 | TAG_CONT;
2585        let last4 = (code >> 18 & 0x3F) as u8 | TAG_FOUR_B;
2586
2587        if len == 2 {
2588            *dst = last2 | TAG_TWO_B;
2589            *dst.add(1) = last1;
2590            return;
2591        }
2592
2593        if len == 3 {
2594            *dst = last3 | TAG_THREE_B;
2595            *dst.add(1) = last2;
2596            *dst.add(2) = last1;
2597            return;
2598        }
2599
2600        *dst = last4;
2601        *dst.add(1) = last3;
2602        *dst.add(2) = last2;
2603        *dst.add(3) = last1;
2604    }
2605}
2606
2607/// Encodes a raw `u32` value as native endian UTF-16 into the provided `u16` buffer,
2608/// and then returns the subslice of the buffer that contains the encoded character.
2609///
2610/// Unlike `char::encode_utf16`, this method also handles codepoints in the surrogate range.
2611/// (Creating a `char` in the surrogate range is UB.)
2612///
2613/// # Panics
2614///
2615/// Panics if the buffer is not large enough.
2616/// A buffer of length 2 is large enough to encode any `char`.
2617#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
2618#[doc(hidden)]
2619#[inline]
2620pub const fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] {
2621    let len = len_utf16(code);
2622    match (len, &mut *dst) {
2623        (1, [a, ..]) => {
2624            *a = code as u16;
2625        }
2626        (2, [a, b, ..]) => {
2627            code -= 0x1_0000;
2628            *a = (code >> 10) as u16 | 0xD800;
2629            *b = (code & 0x3FF) as u16 | 0xDC00;
2630        }
2631        _ => {
2632            const_panic!(
2633                "encode_utf16: buffer does not have enough bytes to encode code point",
2634                "encode_utf16: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}",
2635                code: u32 = code,
2636                len: usize = len,
2637                dst_len: usize = dst.len(),
2638            )
2639        }
2640    };
2641    // SAFETY: `<&mut [u16]>::as_mut_ptr` is guaranteed to return a valid pointer and `len` has been tested to be within bounds.
2642    unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) }
2643}