1#[cfg(not(feature = "ferrocene_certified"))]
4use crate::char::TryFromCharError;
5#[cfg(not(feature = "ferrocene_certified"))]
6use crate::error::Error;
7#[cfg(not(feature = "ferrocene_certified"))]
8use crate::fmt;
9use crate::mem::transmute;
10#[cfg(not(feature = "ferrocene_certified"))]
11use crate::str::FromStr;
12use crate::ub_checks::assert_unsafe_precondition;
13
14#[cfg(not(feature = "ferrocene_certified"))]
16#[must_use]
17#[inline]
18pub(super) const fn from_u32(i: u32) -> Option<char> {
19 match char_try_from_u32(i) {
21 Ok(c) => Some(c),
22 Err(_) => None,
23 }
24}
25
26#[inline]
28#[must_use]
29#[allow(unnecessary_transmutes)]
30#[track_caller]
31pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char {
32 unsafe {
34 assert_unsafe_precondition!(
35 check_language_ub,
36 "invalid value for `char`",
37 (i: u32 = i) => char_try_from_u32(i).is_ok()
38 );
39 transmute(i)
40 }
41}
42
43#[cfg(not(feature = "ferrocene_certified"))]
44#[stable(feature = "char_convert", since = "1.13.0")]
45#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
46impl const From<char> for u32 {
47 #[inline]
57 fn from(c: char) -> Self {
58 c as u32
59 }
60}
61
62#[cfg(not(feature = "ferrocene_certified"))]
63#[stable(feature = "more_char_conversions", since = "1.51.0")]
64#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
65impl const From<char> for u64 {
66 #[inline]
76 fn from(c: char) -> Self {
77 c as u64
80 }
81}
82
83#[cfg(not(feature = "ferrocene_certified"))]
84#[stable(feature = "more_char_conversions", since = "1.51.0")]
85#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
86impl const From<char> for u128 {
87 #[inline]
97 fn from(c: char) -> Self {
98 c as u128
101 }
102}
103
104#[cfg(not(feature = "ferrocene_certified"))]
109#[stable(feature = "u8_from_char", since = "1.59.0")]
110#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
111impl const TryFrom<char> for u8 {
112 type Error = TryFromCharError;
113
114 #[inline]
125 fn try_from(c: char) -> Result<u8, Self::Error> {
126 match u8::try_from(u32::from(c)) {
128 Ok(b) => Ok(b),
129 Err(_) => Err(TryFromCharError(())),
130 }
131 }
132}
133
134#[cfg(not(feature = "ferrocene_certified"))]
139#[stable(feature = "u16_from_char", since = "1.74.0")]
140#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
141impl const TryFrom<char> for u16 {
142 type Error = TryFromCharError;
143
144 #[inline]
155 fn try_from(c: char) -> Result<u16, Self::Error> {
156 match u16::try_from(u32::from(c)) {
158 Ok(x) => Ok(x),
159 Err(_) => Err(TryFromCharError(())),
160 }
161 }
162}
163
164#[cfg(not(feature = "ferrocene_certified"))]
183#[stable(feature = "char_convert", since = "1.13.0")]
184#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
185impl const From<u8> for char {
186 #[inline]
196 fn from(i: u8) -> Self {
197 i as char
198 }
199}
200
201#[cfg(not(feature = "ferrocene_certified"))]
205#[stable(feature = "char_from_str", since = "1.20.0")]
206#[derive(Clone, Debug, PartialEq, Eq)]
207pub struct ParseCharError {
208 kind: CharErrorKind,
209}
210
211#[cfg(not(feature = "ferrocene_certified"))]
212#[derive(Copy, Clone, Debug, PartialEq, Eq)]
213enum CharErrorKind {
214 EmptyString,
215 TooManyChars,
216}
217
218#[cfg(not(feature = "ferrocene_certified"))]
219#[stable(feature = "char_from_str", since = "1.20.0")]
220impl Error for ParseCharError {}
221
222#[cfg(not(feature = "ferrocene_certified"))]
223#[stable(feature = "char_from_str", since = "1.20.0")]
224impl fmt::Display for ParseCharError {
225 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226 match self.kind {
227 CharErrorKind::EmptyString => "cannot parse char from empty string",
228 CharErrorKind::TooManyChars => "too many characters in string",
229 }
230 .fmt(f)
231 }
232}
233
234#[cfg(not(feature = "ferrocene_certified"))]
235#[stable(feature = "char_from_str", since = "1.20.0")]
236impl FromStr for char {
237 type Err = ParseCharError;
238
239 #[inline]
240 fn from_str(s: &str) -> Result<Self, Self::Err> {
241 let mut chars = s.chars();
242 match (chars.next(), chars.next()) {
243 (None, _) => Err(ParseCharError { kind: CharErrorKind::EmptyString }),
244 (Some(c), None) => Ok(c),
245 _ => Err(ParseCharError { kind: CharErrorKind::TooManyChars }),
246 }
247 }
248}
249
250#[inline]
251#[allow(unnecessary_transmutes)]
252const fn char_try_from_u32(i: u32) -> Result<char, CharTryFromError> {
253 if (i ^ 0xD800).wrapping_sub(0x800) >= 0x110000 - 0x800 {
267 Err(CharTryFromError(()))
268 } else {
269 Ok(unsafe { transmute(i) })
271 }
272}
273
274#[cfg(not(feature = "ferrocene_certified"))]
275#[stable(feature = "try_from", since = "1.34.0")]
276#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
277impl const TryFrom<u32> for char {
278 type Error = CharTryFromError;
279
280 #[inline]
281 fn try_from(i: u32) -> Result<Self, Self::Error> {
282 char_try_from_u32(i)
283 }
284}
285
286#[stable(feature = "try_from", since = "1.34.0")]
291#[cfg_attr(not(feature = "ferrocene_certified"), derive(Copy, Clone, Debug, PartialEq, Eq))]
292pub struct CharTryFromError(());
293
294#[cfg(not(feature = "ferrocene_certified"))]
295#[stable(feature = "try_from", since = "1.34.0")]
296impl fmt::Display for CharTryFromError {
297 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
298 "converted integer out of range for `char`".fmt(f)
299 }
300}
301
302#[cfg(not(feature = "ferrocene_certified"))]
304#[inline]
305#[must_use]
306pub(super) const fn from_digit(num: u32, radix: u32) -> Option<char> {
307 if radix > 36 {
308 panic!("from_digit: radix is too high (maximum 36)");
309 }
310 if num < radix {
311 let num = num as u8;
312 if num < 10 { Some((b'0' + num) as char) } else { Some((b'a' + num - 10) as char) }
313 } else {
314 None
315 }
316}