1 //! Character conversions.
3 use crate::char::TryFromCharError;
4 use crate::convert::TryFrom;
6 use crate::mem::transmute;
7 use crate::str::FromStr;
11 /// Converts a `u32` to a `char`.
13 /// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
20 /// assert_eq!(128175, i);
23 /// However, the reverse is not true: not all valid [`u32`]s are valid
24 /// [`char`]s. `from_u32()` will return `None` if the input is not a valid value
27 /// For an unsafe version of this function which ignores these checks, see
28 /// [`from_u32_unchecked`].
37 /// let c = char::from_u32(0x2764);
39 /// assert_eq!(Some('❤'), c);
42 /// Returning `None` when the input is not a valid [`char`]:
47 /// let c = char::from_u32(0x110000);
49 /// assert_eq!(None, c);
54 #[stable(feature = "rust1", since = "1.0.0")]
55 #[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
56 pub const fn from_u32(i: u32) -> Option<char> {
57 // FIXME: once Result::ok is const fn, use it here
58 match char_try_from_u32(i) {
64 /// Converts a `u32` to a `char`, ignoring validity.
66 /// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
73 /// assert_eq!(128175, i);
76 /// However, the reverse is not true: not all valid [`u32`]s are valid
77 /// [`char`]s. `from_u32_unchecked()` will ignore this, and blindly cast to
78 /// [`char`], possibly creating an invalid one.
82 /// This function is unsafe, as it may construct invalid `char` values.
84 /// For a safe version of this function, see the [`from_u32`] function.
93 /// let c = unsafe { char::from_u32_unchecked(0x2764) };
95 /// assert_eq!('❤', c);
99 #[stable(feature = "char_from_unchecked", since = "1.5.0")]
100 #[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
101 pub const unsafe fn from_u32_unchecked(i: u32) -> char {
102 // SAFETY: the caller must guarantee that `i` is a valid char value.
103 if cfg!(debug_assertions) { char::from_u32(i).unwrap() } else { unsafe { transmute(i) } }
106 #[stable(feature = "char_convert", since = "1.13.0")]
107 #[rustc_const_unstable(feature = "const_convert", issue = "88674")]
108 impl const From<char> for u32 {
109 /// Converts a [`char`] into a [`u32`].
117 /// let u = u32::from(c);
118 /// assert!(4 == mem::size_of_val(&u))
121 fn from(c: char) -> Self {
126 #[stable(feature = "more_char_conversions", since = "1.51.0")]
127 #[rustc_const_unstable(feature = "const_convert", issue = "88674")]
128 impl const From<char> for u64 {
129 /// Converts a [`char`] into a [`u64`].
137 /// let u = u64::from(c);
138 /// assert!(8 == mem::size_of_val(&u))
141 fn from(c: char) -> Self {
142 // The char is casted to the value of the code point, then zero-extended to 64 bit.
143 // See [https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics]
148 #[stable(feature = "more_char_conversions", since = "1.51.0")]
149 #[rustc_const_unstable(feature = "const_convert", issue = "88674")]
150 impl const From<char> for u128 {
151 /// Converts a [`char`] into a [`u128`].
159 /// let u = u128::from(c);
160 /// assert!(16 == mem::size_of_val(&u))
163 fn from(c: char) -> Self {
164 // The char is casted to the value of the code point, then zero-extended to 128 bit.
165 // See [https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics]
170 /// Map `char` with code point in U+0000..=U+00FF to byte in 0x00..=0xFF with same value, failing
171 /// if the code point is greater than U+00FF.
173 /// See [`impl From<u8> for char`](char#impl-From<u8>) for details on the encoding.
174 #[stable(feature = "u8_from_char", since = "1.59.0")]
175 impl TryFrom<char> for u8 {
176 type Error = TryFromCharError;
179 fn try_from(c: char) -> Result<u8, Self::Error> {
180 u8::try_from(u32::from(c)).map_err(|_| TryFromCharError(()))
184 /// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
186 /// Unicode is designed such that this effectively decodes bytes
187 /// with the character encoding that IANA calls ISO-8859-1.
188 /// This encoding is compatible with ASCII.
190 /// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hyphen),
191 /// which leaves some "blanks", byte values that are not assigned to any character.
192 /// ISO-8859-1 (the IANA one) assigns them to the C0 and C1 control codes.
194 /// Note that this is *also* different from Windows-1252 a.k.a. code page 1252,
195 /// which is a superset ISO/IEC 8859-1 that assigns some (not all!) blanks
196 /// to punctuation and various Latin characters.
198 /// To confuse things further, [on the Web](https://encoding.spec.whatwg.org/)
199 /// `ascii`, `iso-8859-1`, and `windows-1252` are all aliases
200 /// for a superset of Windows-1252 that fills the remaining blanks with corresponding
201 /// C0 and C1 control codes.
202 #[stable(feature = "char_convert", since = "1.13.0")]
203 #[rustc_const_unstable(feature = "const_convert", issue = "88674")]
204 impl const From<u8> for char {
205 /// Converts a [`u8`] into a [`char`].
212 /// let u = 32 as u8;
213 /// let c = char::from(u);
214 /// assert!(4 == mem::size_of_val(&c))
217 fn from(i: u8) -> Self {
222 /// An error which can be returned when parsing a char.
223 #[stable(feature = "char_from_str", since = "1.20.0")]
224 #[derive(Clone, Debug, PartialEq, Eq)]
225 pub struct ParseCharError {
229 impl ParseCharError {
231 feature = "char_error_internals",
232 reason = "this method should not be available publicly",
236 pub fn __description(&self) -> &str {
238 CharErrorKind::EmptyString => "cannot parse char from empty string",
239 CharErrorKind::TooManyChars => "too many characters in string",
244 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
250 #[stable(feature = "char_from_str", since = "1.20.0")]
251 impl fmt::Display for ParseCharError {
252 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
253 self.__description().fmt(f)
257 #[stable(feature = "char_from_str", since = "1.20.0")]
258 impl FromStr for char {
259 type Err = ParseCharError;
262 fn from_str(s: &str) -> Result<Self, Self::Err> {
263 let mut chars = s.chars();
264 match (chars.next(), chars.next()) {
265 (None, _) => Err(ParseCharError { kind: CharErrorKind::EmptyString }),
266 (Some(c), None) => Ok(c),
267 _ => Err(ParseCharError { kind: CharErrorKind::TooManyChars }),
273 const fn char_try_from_u32(i: u32) -> Result<char, CharTryFromError> {
274 if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
275 Err(CharTryFromError(()))
277 // SAFETY: checked that it's a legal unicode value
278 Ok(unsafe { transmute(i) })
282 #[stable(feature = "try_from", since = "1.34.0")]
283 impl TryFrom<u32> for char {
284 type Error = CharTryFromError;
287 fn try_from(i: u32) -> Result<Self, Self::Error> {
292 /// The error type returned when a conversion from u32 to char fails.
293 #[stable(feature = "try_from", since = "1.34.0")]
294 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
295 pub struct CharTryFromError(());
297 #[stable(feature = "try_from", since = "1.34.0")]
298 impl fmt::Display for CharTryFromError {
299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300 "converted integer out of range for `char`".fmt(f)
304 /// Converts a digit in the given radix to a `char`.
306 /// A 'radix' here is sometimes also called a 'base'. A radix of two
307 /// indicates a binary number, a radix of ten, decimal, and a radix of
308 /// sixteen, hexadecimal, to give some common values. Arbitrary
309 /// radices are supported.
311 /// `from_digit()` will return `None` if the input is not a digit in
316 /// Panics if given a radix larger than 36.
325 /// let c = char::from_digit(4, 10);
327 /// assert_eq!(Some('4'), c);
329 /// // Decimal 11 is a single digit in base 16
330 /// let c = char::from_digit(11, 16);
332 /// assert_eq!(Some('b'), c);
335 /// Returning `None` when the input is not a digit:
340 /// let c = char::from_digit(20, 10);
342 /// assert_eq!(None, c);
345 /// Passing a large radix, causing a panic:
351 /// let c = char::from_digit(1, 37);
355 #[stable(feature = "rust1", since = "1.0.0")]
356 #[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
357 pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
359 panic!("from_digit: radix is too high (maximum 36)");
363 if num < 10 { Some((b'0' + num) as char) } else { Some((b'a' + num - 10) as char) }