| //! Utilities for the `char` primitive type. | |
| //! | |
| //! *[See also the `char` primitive type](primitive@char).* | |
| //! | |
| //! The `char` type represents a single character. More specifically, since | |
| //! 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode | |
| //! scalar value]', which is similar to, but not the same as, a '[Unicode code | |
| //! point]'. | |
| //! | |
| //! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value | |
| //! [Unicode code point]: https://www.unicode.org/glossary/#code_point | |
| //! | |
| //! This module exists for technical reasons, the primary documentation for | |
| //! `char` is directly on [the `char` primitive type][char] itself. | |
| //! | |
| //! This module is the home of the iterator implementations for the iterators | |
| //! implemented on `char`, as well as some useful constants and conversion | |
| //! functions that convert various types to `char`. | |
| #![allow(non_snake_case)] | |
| #![stable(feature = "rust1", since = "1.0.0")] | |
| mod convert; | |
| mod decode; | |
| mod methods; | |
| // stable re-exports | |
| #[rustfmt::skip] | |
| #[stable(feature = "try_from", since = "1.34.0")] | |
| pub use self::convert::CharTryFromError; | |
| #[stable(feature = "char_from_str", since = "1.20.0")] | |
| pub use self::convert::ParseCharError; | |
| #[stable(feature = "decode_utf16", since = "1.9.0")] | |
| pub use self::decode::{DecodeUtf16, DecodeUtf16Error}; | |
| // perma-unstable re-exports | |
| #[rustfmt::skip] | |
| #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] | |
| pub use self::methods::encode_utf16_raw; // perma-unstable | |
| #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] | |
| pub use self::methods::{encode_utf8_raw, encode_utf8_raw_unchecked}; // perma-unstable | |
| #[rustfmt::skip] | |
| use crate::ascii; | |
| pub(crate) use self::methods::EscapeDebugExtArgs; | |
| use crate::error::Error; | |
| use crate::escape::{AlwaysEscaped, EscapeIterInner, MaybeEscaped}; | |
| use crate::fmt::{self, Write}; | |
| use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; | |
| use crate::num::NonZero; | |
| // UTF-8 ranges and tags for encoding characters | |
| const TAG_CONT: u8 = 0b1000_0000; | |
| const TAG_TWO_B: u8 = 0b1100_0000; | |
| const TAG_THREE_B: u8 = 0b1110_0000; | |
| const TAG_FOUR_B: u8 = 0b1111_0000; | |
| const MAX_ONE_B: u32 = 0x80; | |
| const MAX_TWO_B: u32 = 0x800; | |
| const MAX_THREE_B: u32 = 0x10000; | |
| /* | |
| Lu Uppercase_Letter an uppercase letter | |
| Ll Lowercase_Letter a lowercase letter | |
| Lt Titlecase_Letter a digraphic character, with first part uppercase | |
| Lm Modifier_Letter a modifier letter | |
| Lo Other_Letter other letters, including syllables and ideographs | |
| Mn Nonspacing_Mark a nonspacing combining mark (zero advance width) | |
| Mc Spacing_Mark a spacing combining mark (positive advance width) | |
| Me Enclosing_Mark an enclosing combining mark | |
| Nd Decimal_Number a decimal digit | |
| Nl Letter_Number a letterlike numeric character | |
| No Other_Number a numeric character of other type | |
| Pc Connector_Punctuation a connecting punctuation mark, like a tie | |
| Pd Dash_Punctuation a dash or hyphen punctuation mark | |
| Ps Open_Punctuation an opening punctuation mark (of a pair) | |
| Pe Close_Punctuation a closing punctuation mark (of a pair) | |
| Pi Initial_Punctuation an initial quotation mark | |
| Pf Final_Punctuation a final quotation mark | |
| Po Other_Punctuation a punctuation mark of other type | |
| Sm Math_Symbol a symbol of primarily mathematical use | |
| Sc Currency_Symbol a currency sign | |
| Sk Modifier_Symbol a non-letterlike modifier symbol | |
| So Other_Symbol a symbol of other type | |
| Zs Space_Separator a space character (of various non-zero widths) | |
| Zl Line_Separator U+2028 LINE SEPARATOR only | |
| Zp Paragraph_Separator U+2029 PARAGRAPH SEPARATOR only | |
| Cc Control a C0 or C1 control code | |
| Cf Format a format control character | |
| Cs Surrogate a surrogate code point | |
| Co Private_Use a private-use character | |
| Cn Unassigned a reserved unassigned code point or a noncharacter | |
| */ | |
| /// The highest valid code point a `char` can have, `'\u{10FFFF}'`. Use [`char::MAX`] instead. | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| #[deprecated(since = "TBD", note = "replaced by the `MAX` associated constant on `char`")] | |
| pub const MAX: char = char::MAX; | |
| /// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a | |
| /// decoding error. Use [`char::REPLACEMENT_CHARACTER`] instead. | |
| #[stable(feature = "decode_utf16", since = "1.9.0")] | |
| #[deprecated( | |
| since = "TBD", | |
| note = "replaced by the `REPLACEMENT_CHARACTER` associated constant on `char`" | |
| )] | |
| pub const REPLACEMENT_CHARACTER: char = char::REPLACEMENT_CHARACTER; | |
| /// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of | |
| /// `char` and `str` methods are based on. Use [`char::UNICODE_VERSION`] instead. | |
| #[stable(feature = "unicode_version", since = "1.45.0")] | |
| #[deprecated( | |
| since = "TBD", | |
| note = "replaced by the `UNICODE_VERSION` associated constant on `char`" | |
| )] | |
| pub const UNICODE_VERSION: (u8, u8, u8) = char::UNICODE_VERSION; | |
| /// Creates an iterator over the UTF-16 encoded code points in `iter`, returning | |
| /// unpaired surrogates as `Err`s. Use [`char::decode_utf16`] instead. | |
| #[stable(feature = "decode_utf16", since = "1.9.0")] | |
| #[deprecated(since = "TBD", note = "replaced by the `decode_utf16` method on `char`")] | |
| #[inline] | |
| pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> { | |
| self::decode::decode_utf16(iter) | |
| } | |
| /// Converts a `u32` to a `char`. Use [`char::from_u32`] instead. | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] | |
| #[deprecated(since = "TBD", note = "replaced by the `from_u32` method on `char`")] | |
| #[must_use] | |
| #[inline] | |
| pub const fn from_u32(i: u32) -> Option<char> { | |
| self::convert::from_u32(i) | |
| } | |
| /// Converts a `u32` to a `char`, ignoring validity. Use [`char::from_u32_unchecked`] | |
| /// instead. | |
| #[stable(feature = "char_from_unchecked", since = "1.5.0")] | |
| #[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")] | |
| #[deprecated(since = "TBD", note = "replaced by the `from_u32_unchecked` method on `char`")] | |
| #[must_use] | |
| #[inline] | |
| pub const unsafe fn from_u32_unchecked(i: u32) -> char { | |
| // SAFETY: the safety contract must be upheld by the caller. | |
| unsafe { self::convert::from_u32_unchecked(i) } | |
| } | |
| /// Converts a digit in the given radix to a `char`. Use [`char::from_digit`] instead. | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] | |
| #[deprecated(since = "TBD", note = "replaced by the `from_digit` method on `char`")] | |
| #[must_use] | |
| #[inline] | |
| pub const fn from_digit(num: u32, radix: u32) -> Option<char> { | |
| self::convert::from_digit(num, radix) | |
| } | |
| /// Returns an iterator that yields the hexadecimal Unicode escape of a | |
| /// character, as `char`s. | |
| /// | |
| /// This `struct` is created by the [`escape_unicode`] method on [`char`]. See | |
| /// its documentation for more. | |
| /// | |
| /// [`escape_unicode`]: char::escape_unicode | |
| #[derive(Clone, Debug)] | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub struct EscapeUnicode(EscapeIterInner<10, AlwaysEscaped>); | |
| impl EscapeUnicode { | |
| #[inline] | |
| const fn new(c: char) -> Self { | |
| Self(EscapeIterInner::unicode(c)) | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl Iterator for EscapeUnicode { | |
| type Item = char; | |
| #[inline] | |
| fn next(&mut self) -> Option<char> { | |
| self.0.next().map(char::from) | |
| } | |
| #[inline] | |
| fn size_hint(&self) -> (usize, Option<usize>) { | |
| let n = self.0.len(); | |
| (n, Some(n)) | |
| } | |
| #[inline] | |
| fn count(self) -> usize { | |
| self.0.len() | |
| } | |
| #[inline] | |
| fn last(mut self) -> Option<char> { | |
| self.0.next_back().map(char::from) | |
| } | |
| #[inline] | |
| fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { | |
| self.0.advance_by(n) | |
| } | |
| } | |
| #[stable(feature = "exact_size_escape", since = "1.11.0")] | |
| impl ExactSizeIterator for EscapeUnicode { | |
| #[inline] | |
| fn len(&self) -> usize { | |
| self.0.len() | |
| } | |
| } | |
| #[stable(feature = "fused", since = "1.26.0")] | |
| impl FusedIterator for EscapeUnicode {} | |
| #[stable(feature = "char_struct_display", since = "1.16.0")] | |
| impl fmt::Display for EscapeUnicode { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| fmt::Display::fmt(&self.0, f) | |
| } | |
| } | |
| /// An iterator that yields the literal escape code of a `char`. | |
| /// | |
| /// This `struct` is created by the [`escape_default`] method on [`char`]. See | |
| /// its documentation for more. | |
| /// | |
| /// [`escape_default`]: char::escape_default | |
| #[derive(Clone, Debug)] | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub struct EscapeDefault(EscapeIterInner<10, AlwaysEscaped>); | |
| impl EscapeDefault { | |
| #[inline] | |
| const fn printable(c: ascii::Char) -> Self { | |
| Self(EscapeIterInner::ascii(c.to_u8())) | |
| } | |
| #[inline] | |
| const fn backslash(c: ascii::Char) -> Self { | |
| Self(EscapeIterInner::backslash(c)) | |
| } | |
| #[inline] | |
| const fn unicode(c: char) -> Self { | |
| Self(EscapeIterInner::unicode(c)) | |
| } | |
| } | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| impl Iterator for EscapeDefault { | |
| type Item = char; | |
| #[inline] | |
| fn next(&mut self) -> Option<char> { | |
| self.0.next().map(char::from) | |
| } | |
| #[inline] | |
| fn size_hint(&self) -> (usize, Option<usize>) { | |
| let n = self.0.len(); | |
| (n, Some(n)) | |
| } | |
| #[inline] | |
| fn count(self) -> usize { | |
| self.0.len() | |
| } | |
| #[inline] | |
| fn last(mut self) -> Option<char> { | |
| self.0.next_back().map(char::from) | |
| } | |
| #[inline] | |
| fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { | |
| self.0.advance_by(n) | |
| } | |
| } | |
| #[stable(feature = "exact_size_escape", since = "1.11.0")] | |
| impl ExactSizeIterator for EscapeDefault { | |
| #[inline] | |
| fn len(&self) -> usize { | |
| self.0.len() | |
| } | |
| } | |
| #[stable(feature = "fused", since = "1.26.0")] | |
| impl FusedIterator for EscapeDefault {} | |
| #[stable(feature = "char_struct_display", since = "1.16.0")] | |
| impl fmt::Display for EscapeDefault { | |
| #[inline] | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| fmt::Display::fmt(&self.0, f) | |
| } | |
| } | |
| /// An iterator that yields the literal escape code of a `char`. | |
| /// | |
| /// This `struct` is created by the [`escape_debug`] method on [`char`]. See its | |
| /// documentation for more. | |
| /// | |
| /// [`escape_debug`]: char::escape_debug | |
| #[stable(feature = "char_escape_debug", since = "1.20.0")] | |
| #[derive(Clone, Debug)] | |
| pub struct EscapeDebug(EscapeIterInner<10, MaybeEscaped>); | |
| impl EscapeDebug { | |
| #[inline] | |
| const fn printable(chr: char) -> Self { | |
| Self(EscapeIterInner::printable(chr)) | |
| } | |
| #[inline] | |
| const fn backslash(c: ascii::Char) -> Self { | |
| Self(EscapeIterInner::backslash(c)) | |
| } | |
| #[inline] | |
| const fn unicode(c: char) -> Self { | |
| Self(EscapeIterInner::unicode(c)) | |
| } | |
| } | |
| #[stable(feature = "char_escape_debug", since = "1.20.0")] | |
| impl Iterator for EscapeDebug { | |
| type Item = char; | |
| #[inline] | |
| fn next(&mut self) -> Option<char> { | |
| self.0.next() | |
| } | |
| #[inline] | |
| fn size_hint(&self) -> (usize, Option<usize>) { | |
| let n = self.len(); | |
| (n, Some(n)) | |
| } | |
| #[inline] | |
| fn count(self) -> usize { | |
| self.len() | |
| } | |
| } | |
| #[stable(feature = "char_escape_debug", since = "1.20.0")] | |
| impl ExactSizeIterator for EscapeDebug { | |
| fn len(&self) -> usize { | |
| self.0.len() | |
| } | |
| } | |
| #[stable(feature = "fused", since = "1.26.0")] | |
| impl FusedIterator for EscapeDebug {} | |
| #[stable(feature = "char_escape_debug", since = "1.20.0")] | |
| impl fmt::Display for EscapeDebug { | |
| #[inline] | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| fmt::Display::fmt(&self.0, f) | |
| } | |
| } | |
| macro_rules! casemappingiter_impls { | |
| ( | |
| #[$stab:meta] | |
| #[$dendstab:meta] | |
| #[$fusedstab:meta] | |
| #[$exactstab:meta] | |
| #[$displaystab:meta] | |
| $(#[$attr:meta])* | |
| $ITER_NAME:ident | |
| ) => { | |
| $(#[$attr])* | |
| #[$stab] | |
| #[derive(Debug, Clone)] | |
| pub struct $ITER_NAME(CaseMappingIter); | |
| #[$stab] | |
| impl Iterator for $ITER_NAME { | |
| type Item = char; | |
| fn next(&mut self) -> Option<char> { | |
| self.0.next() | |
| } | |
| fn size_hint(&self) -> (usize, Option<usize>) { | |
| self.0.size_hint() | |
| } | |
| fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc | |
| where | |
| Fold: FnMut(Acc, Self::Item) -> Acc, | |
| { | |
| self.0.fold(init, fold) | |
| } | |
| fn count(self) -> usize { | |
| self.0.count() | |
| } | |
| fn last(self) -> Option<Self::Item> { | |
| self.0.last() | |
| } | |
| fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { | |
| self.0.advance_by(n) | |
| } | |
| unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { | |
| // SAFETY: just forwarding requirements to caller | |
| unsafe { self.0.__iterator_get_unchecked(idx) } | |
| } | |
| } | |
| #[$dendstab] | |
| impl DoubleEndedIterator for $ITER_NAME { | |
| fn next_back(&mut self) -> Option<char> { | |
| self.0.next_back() | |
| } | |
| fn rfold<Acc, Fold>(self, init: Acc, rfold: Fold) -> Acc | |
| where | |
| Fold: FnMut(Acc, Self::Item) -> Acc, | |
| { | |
| self.0.rfold(init, rfold) | |
| } | |
| fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { | |
| self.0.advance_back_by(n) | |
| } | |
| } | |
| #[$fusedstab] | |
| impl FusedIterator for $ITER_NAME {} | |
| #[$exactstab] | |
| impl ExactSizeIterator for $ITER_NAME { | |
| fn len(&self) -> usize { | |
| self.0.len() | |
| } | |
| fn is_empty(&self) -> bool { | |
| self.0.is_empty() | |
| } | |
| } | |
| // SAFETY: forwards to inner `array::IntoIter` | |
| #[unstable(feature = "trusted_len", issue = "37572")] | |
| unsafe impl TrustedLen for $ITER_NAME {} | |
| // SAFETY: forwards to inner `array::IntoIter` | |
| #[doc(hidden)] | |
| #[unstable(feature = "std_internals", issue = "none")] | |
| unsafe impl TrustedRandomAccessNoCoerce for $ITER_NAME { | |
| const MAY_HAVE_SIDE_EFFECT: bool = false; | |
| } | |
| // SAFETY: this iter has no subtypes/supertypes | |
| #[doc(hidden)] | |
| #[unstable(feature = "std_internals", issue = "none")] | |
| unsafe impl TrustedRandomAccess for $ITER_NAME {} | |
| #[$displaystab] | |
| impl fmt::Display for $ITER_NAME { | |
| #[inline] | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| fmt::Display::fmt(&self.0, f) | |
| } | |
| } | |
| } | |
| } | |
| casemappingiter_impls! { | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| #[stable(feature = "case_mapping_double_ended", since = "1.59.0")] | |
| #[stable(feature = "fused", since = "1.26.0")] | |
| #[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")] | |
| #[stable(feature = "char_struct_display", since = "1.16.0")] | |
| /// Returns an iterator that yields the uppercase equivalent of a `char`. | |
| /// | |
| /// This `struct` is created by the [`to_uppercase`] method on [`char`]. See | |
| /// its documentation for more. | |
| /// | |
| /// [`to_uppercase`]: char::to_uppercase | |
| ToUppercase | |
| } | |
| casemappingiter_impls! { | |
| #[unstable(feature = "titlecase", issue = "153892")] | |
| #[unstable(feature = "titlecase", issue = "153892")] | |
| #[unstable(feature = "titlecase", issue = "153892")] | |
| #[unstable(feature = "titlecase", issue = "153892")] | |
| #[unstable(feature = "titlecase", issue = "153892")] | |
| /// Returns an iterator that yields the titlecase equivalent of a `char`. | |
| /// | |
| /// This `struct` is created by the [`to_titlecase`] method on [`char`]. See | |
| /// its documentation for more. | |
| /// | |
| /// [`to_titlecase`]: char::to_titlecase | |
| ToTitlecase | |
| } | |
| casemappingiter_impls! { | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| #[stable(feature = "case_mapping_double_ended", since = "1.59.0")] | |
| #[stable(feature = "fused", since = "1.26.0")] | |
| #[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")] | |
| #[stable(feature = "char_struct_display", since = "1.16.0")] | |
| /// Returns an iterator that yields the lowercase equivalent of a `char`. | |
| /// | |
| /// This `struct` is created by the [`to_lowercase`] method on [`char`]. See | |
| /// its documentation for more. | |
| /// | |
| /// [`to_lowercase`]: char::to_lowercase | |
| ToLowercase | |
| } | |
| #[derive(Debug, Clone)] | |
| struct CaseMappingIter(core::array::IntoIter<char, 3>); | |
| impl CaseMappingIter { | |
| #[inline] | |
| fn new(chars: [char; 3]) -> CaseMappingIter { | |
| let mut iter = chars.into_iter(); | |
| if chars[2] == '\0' { | |
| iter.next_back(); | |
| if chars[1] == '\0' { | |
| iter.next_back(); | |
| // Deliberately don't check `chars[0]`, | |
| // as '\0' lowercases to itself | |
| } | |
| } | |
| CaseMappingIter(iter) | |
| } | |
| } | |
| impl Iterator for CaseMappingIter { | |
| type Item = char; | |
| fn next(&mut self) -> Option<char> { | |
| self.0.next() | |
| } | |
| fn size_hint(&self) -> (usize, Option<usize>) { | |
| self.0.size_hint() | |
| } | |
| fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc | |
| where | |
| Fold: FnMut(Acc, Self::Item) -> Acc, | |
| { | |
| self.0.fold(init, fold) | |
| } | |
| fn count(self) -> usize { | |
| self.0.count() | |
| } | |
| fn last(self) -> Option<Self::Item> { | |
| self.0.last() | |
| } | |
| fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { | |
| self.0.advance_by(n) | |
| } | |
| unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { | |
| // SAFETY: just forwarding requirements to caller | |
| unsafe { self.0.__iterator_get_unchecked(idx) } | |
| } | |
| } | |
| impl DoubleEndedIterator for CaseMappingIter { | |
| fn next_back(&mut self) -> Option<char> { | |
| self.0.next_back() | |
| } | |
| fn rfold<Acc, Fold>(self, init: Acc, rfold: Fold) -> Acc | |
| where | |
| Fold: FnMut(Acc, Self::Item) -> Acc, | |
| { | |
| self.0.rfold(init, rfold) | |
| } | |
| fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { | |
| self.0.advance_back_by(n) | |
| } | |
| } | |
| impl ExactSizeIterator for CaseMappingIter { | |
| fn len(&self) -> usize { | |
| self.0.len() | |
| } | |
| fn is_empty(&self) -> bool { | |
| self.0.is_empty() | |
| } | |
| } | |
| impl FusedIterator for CaseMappingIter {} | |
| // SAFETY: forwards to inner `array::IntoIter` | |
| unsafe impl TrustedLen for CaseMappingIter {} | |
| // SAFETY: forwards to inner `array::IntoIter` | |
| unsafe impl TrustedRandomAccessNoCoerce for CaseMappingIter { | |
| const MAY_HAVE_SIDE_EFFECT: bool = false; | |
| } | |
| // SAFETY: `CaseMappingIter` has no subtypes/supertypes | |
| unsafe impl TrustedRandomAccess for CaseMappingIter {} | |
| impl fmt::Display for CaseMappingIter { | |
| #[inline] | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| for c in self.0.clone() { | |
| f.write_char(c)?; | |
| } | |
| Ok(()) | |
| } | |
| } | |
| /// The error type returned when a checked char conversion fails. | |
| #[stable(feature = "u8_from_char", since = "1.59.0")] | |
| #[derive(Debug, Copy, Clone, PartialEq, Eq)] | |
| pub struct TryFromCharError(pub(crate) ()); | |
| #[stable(feature = "u8_from_char", since = "1.59.0")] | |
| impl fmt::Display for TryFromCharError { | |
| fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| "unicode code point out of range".fmt(fmt) | |
| } | |
| } | |
| #[stable(feature = "u8_from_char", since = "1.59.0")] | |
| impl Error for TryFromCharError {} | |
| /// The case of a cased character, | |
| /// as returned by [`char::case`]. | |
| /// | |
| /// Titlecase characters conceptually are composed of an uppercase portion | |
| /// followed by a lowercase portion. | |
| /// The variant discriminants represent this: | |
| /// the most significant bit represents whether the case | |
| /// conceptually starts as uppercase, while the least significant bit | |
| /// represents whether it conceptually ends as uppercase. | |
| #[unstable(feature = "titlecase", issue = "153892")] | |
| #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | |
| pub enum CharCase { | |
| /// Lowercase. Corresponds to the `Lowercase` Unicode property. | |
| Lower = 0b00, | |
| /// Titlecase. Corresponds to the `Titlecase_Letter` Unicode general category. | |
| Title = 0b10, | |
| /// Uppercase. Corresponds to the `Uppercase` Unicode property. | |
| Upper = 0b11, | |
| } |