1 //! Character conversions.
3 use crate::char::TryFromCharError
;
4 use crate::convert
::TryFrom
;
6 use crate::mem
::transmute
;
7 use crate::str::FromStr
;
9 /// Converts a `u32` to a `char`. See [`char::from_u32`].
12 pub(super) const fn from_u32(i
: u32) -> Option
<char> {
13 // FIXME: once Result::ok is const fn, use it here
14 match char_try_from_u32(i
) {
20 /// Converts a `u32` to a `char`, ignoring validity. See [`char::from_u32_unchecked`].
23 pub(super) const unsafe fn from_u32_unchecked(i
: u32) -> char {
24 // SAFETY: the caller must guarantee that `i` is a valid char value.
25 if cfg
!(debug_assertions
) { char::from_u32(i).unwrap() }
else { unsafe { transmute(i) }
}
28 #[stable(feature = "char_convert", since = "1.13.0")]
29 #[rustc_const_unstable(feature = "const_convert", issue = "88674")]
30 impl const From
<char> for u32 {
31 /// Converts a [`char`] into a [`u32`].
39 /// let u = u32::from(c);
40 /// assert!(4 == mem::size_of_val(&u))
43 fn from(c
: char) -> Self {
48 #[stable(feature = "more_char_conversions", since = "1.51.0")]
49 #[rustc_const_unstable(feature = "const_convert", issue = "88674")]
50 impl const From
<char> for u64 {
51 /// Converts a [`char`] into a [`u64`].
59 /// let u = u64::from(c);
60 /// assert!(8 == mem::size_of_val(&u))
63 fn from(c
: char) -> Self {
64 // The char is casted to the value of the code point, then zero-extended to 64 bit.
65 // See [https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics]
70 #[stable(feature = "more_char_conversions", since = "1.51.0")]
71 #[rustc_const_unstable(feature = "const_convert", issue = "88674")]
72 impl const From
<char> for u128
{
73 /// Converts a [`char`] into a [`u128`].
81 /// let u = u128::from(c);
82 /// assert!(16 == mem::size_of_val(&u))
85 fn from(c
: char) -> Self {
86 // The char is casted to the value of the code point, then zero-extended to 128 bit.
87 // See [https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics]
92 /// Map `char` with code point in U+0000..=U+00FF to byte in 0x00..=0xFF with same value, failing
93 /// if the code point is greater than U+00FF.
95 /// See [`impl From<u8> for char`](char#impl-From<u8>-for-char) for details on the encoding.
96 #[stable(feature = "u8_from_char", since = "1.59.0")]
97 impl TryFrom
<char> for u8 {
98 type Error
= TryFromCharError
;
101 fn try_from(c
: char) -> Result
<u8, Self::Error
> {
102 u8::try_from(u32::from(c
)).map_err(|_
| TryFromCharError(()))
106 /// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
108 /// Unicode is designed such that this effectively decodes bytes
109 /// with the character encoding that IANA calls ISO-8859-1.
110 /// This encoding is compatible with ASCII.
112 /// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hyphen),
113 /// which leaves some "blanks", byte values that are not assigned to any character.
114 /// ISO-8859-1 (the IANA one) assigns them to the C0 and C1 control codes.
116 /// Note that this is *also* different from Windows-1252 a.k.a. code page 1252,
117 /// which is a superset ISO/IEC 8859-1 that assigns some (not all!) blanks
118 /// to punctuation and various Latin characters.
120 /// To confuse things further, [on the Web](https://encoding.spec.whatwg.org/)
121 /// `ascii`, `iso-8859-1`, and `windows-1252` are all aliases
122 /// for a superset of Windows-1252 that fills the remaining blanks with corresponding
123 /// C0 and C1 control codes.
124 #[stable(feature = "char_convert", since = "1.13.0")]
125 #[rustc_const_unstable(feature = "const_convert", issue = "88674")]
126 impl const From
<u8> for char {
127 /// Converts a [`u8`] into a [`char`].
134 /// let u = 32 as u8;
135 /// let c = char::from(u);
136 /// assert!(4 == mem::size_of_val(&c))
139 fn from(i
: u8) -> Self {
144 /// An error which can be returned when parsing a char.
146 /// This `struct` is created when using the [`char::from_str`] method.
147 #[stable(feature = "char_from_str", since = "1.20.0")]
148 #[derive(Clone, Debug, PartialEq, Eq)]
149 pub struct ParseCharError
{
153 impl ParseCharError
{
155 feature
= "char_error_internals",
156 reason
= "this method should not be available publicly",
160 pub fn __description(&self) -> &str {
162 CharErrorKind
::EmptyString
=> "cannot parse char from empty string",
163 CharErrorKind
::TooManyChars
=> "too many characters in string",
168 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
174 #[stable(feature = "char_from_str", since = "1.20.0")]
175 impl fmt
::Display
for ParseCharError
{
176 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
177 self.__description().fmt(f
)
181 #[stable(feature = "char_from_str", since = "1.20.0")]
182 impl FromStr
for char {
183 type Err
= ParseCharError
;
186 fn from_str(s
: &str) -> Result
<Self, Self::Err
> {
187 let mut chars
= s
.chars();
188 match (chars
.next(), chars
.next()) {
189 (None
, _
) => Err(ParseCharError { kind: CharErrorKind::EmptyString }
),
190 (Some(c
), None
) => Ok(c
),
191 _
=> Err(ParseCharError { kind: CharErrorKind::TooManyChars }
),
197 const fn char_try_from_u32(i
: u32) -> Result
<char, CharTryFromError
> {
198 // This is an optimized version of the check
199 // (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF),
200 // which can also be written as
201 // i >= 0x110000 || (i >= 0xD800 && i < 0xE000).
203 // The XOR with 0xD800 permutes the ranges such that 0xD800..0xE000 is
204 // mapped to 0x0000..0x0800, while keeping all the high bits outside 0xFFFF the same.
205 // In particular, numbers >= 0x110000 stay in this range.
207 // Subtracting 0x800 causes 0x0000..0x0800 to wrap, meaning that a single
208 // unsigned comparison against 0x110000 - 0x800 will detect both the wrapped
209 // surrogate range as well as the numbers originally larger than 0x110000.
211 if (i ^
0xD800).wrapping_sub(0x800) >= 0x110000 - 0x800 {
212 Err(CharTryFromError(()))
214 // SAFETY: checked that it's a legal unicode value
215 Ok(unsafe { transmute(i) }
)
219 #[stable(feature = "try_from", since = "1.34.0")]
220 impl TryFrom
<u32> for char {
221 type Error
= CharTryFromError
;
224 fn try_from(i
: u32) -> Result
<Self, Self::Error
> {
229 /// The error type returned when a conversion from [`prim@u32`] to [`prim@char`] fails.
231 /// This `struct` is created by the [`char::try_from<u32>`](char#impl-TryFrom<u32>-for-char) method.
232 /// See its documentation for more.
233 #[stable(feature = "try_from", since = "1.34.0")]
234 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
235 pub struct CharTryFromError(());
237 #[stable(feature = "try_from", since = "1.34.0")]
238 impl fmt
::Display
for CharTryFromError
{
239 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
240 "converted integer out of range for `char`".fmt(f
)
244 /// Converts a digit in the given radix to a `char`. See [`char::from_digit`].
247 pub(super) const fn from_digit(num
: u32, radix
: u32) -> Option
<char> {
249 panic
!("from_digit: radix is too high (maximum 36)");
253 if num
< 10 { Some((b'0' + num) as char) }
else { Some((b'a' + num - 10) as char) }