core/char/
mod.rs

1//! Utilities for the `char` primitive type.
2//!
3//! *[See also the `char` primitive type](primitive@char).*
4//!
5//! The `char` type represents a single character. More specifically, since
6//! 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode
7//! scalar value]', which is similar to, but not the same as, a '[Unicode code
8//! point]'.
9//!
10//! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
11//! [Unicode code point]: https://www.unicode.org/glossary/#code_point
12//!
13//! This module exists for technical reasons, the primary documentation for
14//! `char` is directly on [the `char` primitive type][char] itself.
15//!
16//! This module is the home of the iterator implementations for the iterators
17//! implemented on `char`, as well as some useful constants and conversion
18//! functions that convert various types to `char`.
19
20#![allow(non_snake_case)]
21#![stable(feature = "rust1", since = "1.0.0")]
22
23mod convert;
24#[cfg(not(feature = "ferrocene_certified"))]
25mod decode;
26mod methods;
27
28// stable re-exports
29#[rustfmt::skip]
30#[stable(feature = "try_from", since = "1.34.0")]
31pub use self::convert::CharTryFromError;
32#[stable(feature = "char_from_str", since = "1.20.0")]
33#[cfg(not(feature = "ferrocene_certified"))]
34pub use self::convert::ParseCharError;
35#[stable(feature = "decode_utf16", since = "1.9.0")]
36#[cfg(not(feature = "ferrocene_certified"))]
37pub use self::decode::{DecodeUtf16, DecodeUtf16Error};
38
39// perma-unstable re-exports
40#[rustfmt::skip]
41#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
42#[cfg(not(feature = "ferrocene_certified"))]
43pub use self::methods::encode_utf16_raw; // perma-unstable
44#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
45#[cfg(not(feature = "ferrocene_certified"))]
46pub use self::methods::{encode_utf8_raw, encode_utf8_raw_unchecked}; // perma-unstable
47
48#[rustfmt::skip]
49#[cfg(not(feature = "ferrocene_certified"))]
50use crate::ascii;
51#[cfg(not(feature = "ferrocene_certified"))]
52pub(crate) use self::methods::EscapeDebugExtArgs;
53#[cfg(not(feature = "ferrocene_certified"))]
54use crate::error::Error;
55#[cfg(not(feature = "ferrocene_certified"))]
56use crate::escape::{AlwaysEscaped, EscapeIterInner, MaybeEscaped};
57#[cfg(not(feature = "ferrocene_certified"))]
58use crate::fmt::{self, Write};
59#[cfg(not(feature = "ferrocene_certified"))]
60use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
61#[cfg(not(feature = "ferrocene_certified"))]
62use crate::num::NonZero;
63
64// UTF-8 ranges and tags for encoding characters
65#[cfg(not(feature = "ferrocene_certified"))]
66const TAG_CONT: u8 = 0b1000_0000;
67#[cfg(not(feature = "ferrocene_certified"))]
68const TAG_TWO_B: u8 = 0b1100_0000;
69#[cfg(not(feature = "ferrocene_certified"))]
70const TAG_THREE_B: u8 = 0b1110_0000;
71#[cfg(not(feature = "ferrocene_certified"))]
72const TAG_FOUR_B: u8 = 0b1111_0000;
73const MAX_ONE_B: u32 = 0x80;
74const MAX_TWO_B: u32 = 0x800;
75const MAX_THREE_B: u32 = 0x10000;
76
77/*
78    Lu  Uppercase_Letter        an uppercase letter
79    Ll  Lowercase_Letter        a lowercase letter
80    Lt  Titlecase_Letter        a digraphic character, with first part uppercase
81    Lm  Modifier_Letter         a modifier letter
82    Lo  Other_Letter            other letters, including syllables and ideographs
83    Mn  Nonspacing_Mark         a nonspacing combining mark (zero advance width)
84    Mc  Spacing_Mark            a spacing combining mark (positive advance width)
85    Me  Enclosing_Mark          an enclosing combining mark
86    Nd  Decimal_Number          a decimal digit
87    Nl  Letter_Number           a letterlike numeric character
88    No  Other_Number            a numeric character of other type
89    Pc  Connector_Punctuation   a connecting punctuation mark, like a tie
90    Pd  Dash_Punctuation        a dash or hyphen punctuation mark
91    Ps  Open_Punctuation        an opening punctuation mark (of a pair)
92    Pe  Close_Punctuation       a closing punctuation mark (of a pair)
93    Pi  Initial_Punctuation     an initial quotation mark
94    Pf  Final_Punctuation       a final quotation mark
95    Po  Other_Punctuation       a punctuation mark of other type
96    Sm  Math_Symbol             a symbol of primarily mathematical use
97    Sc  Currency_Symbol         a currency sign
98    Sk  Modifier_Symbol         a non-letterlike modifier symbol
99    So  Other_Symbol            a symbol of other type
100    Zs  Space_Separator         a space character (of various non-zero widths)
101    Zl  Line_Separator          U+2028 LINE SEPARATOR only
102    Zp  Paragraph_Separator     U+2029 PARAGRAPH SEPARATOR only
103    Cc  Control                 a C0 or C1 control code
104    Cf  Format                  a format control character
105    Cs  Surrogate               a surrogate code point
106    Co  Private_Use             a private-use character
107    Cn  Unassigned              a reserved unassigned code point or a noncharacter
108*/
109
110/// The highest valid code point a `char` can have, `'\u{10FFFF}'`. Use [`char::MAX`] instead.
111#[stable(feature = "rust1", since = "1.0.0")]
112#[cfg(not(feature = "ferrocene_certified"))]
113pub const MAX: char = char::MAX;
114
115/// The maximum number of bytes required to [encode](char::encode_utf8) a `char` to
116/// UTF-8 encoding.
117#[unstable(feature = "char_max_len", issue = "121714")]
118#[cfg(not(feature = "ferrocene_certified"))]
119pub const MAX_LEN_UTF8: usize = char::MAX_LEN_UTF8;
120
121/// The maximum number of two-byte units required to [encode](char::encode_utf16) a `char`
122/// to UTF-16 encoding.
123#[unstable(feature = "char_max_len", issue = "121714")]
124#[cfg(not(feature = "ferrocene_certified"))]
125pub const MAX_LEN_UTF16: usize = char::MAX_LEN_UTF16;
126
127/// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
128/// decoding error. Use [`char::REPLACEMENT_CHARACTER`] instead.
129#[stable(feature = "decode_utf16", since = "1.9.0")]
130#[cfg(not(feature = "ferrocene_certified"))]
131pub const REPLACEMENT_CHARACTER: char = char::REPLACEMENT_CHARACTER;
132
133/// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of
134/// `char` and `str` methods are based on. Use [`char::UNICODE_VERSION`] instead.
135#[stable(feature = "unicode_version", since = "1.45.0")]
136#[cfg(not(feature = "ferrocene_certified"))]
137pub const UNICODE_VERSION: (u8, u8, u8) = char::UNICODE_VERSION;
138
139/// Creates an iterator over the UTF-16 encoded code points in `iter`, returning
140/// unpaired surrogates as `Err`s. Use [`char::decode_utf16`] instead.
141#[stable(feature = "decode_utf16", since = "1.9.0")]
142#[inline]
143#[cfg(not(feature = "ferrocene_certified"))]
144pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
145    self::decode::decode_utf16(iter)
146}
147
148/// Converts a `u32` to a `char`. Use [`char::from_u32`] instead.
149#[stable(feature = "rust1", since = "1.0.0")]
150#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
151#[must_use]
152#[inline]
153#[cfg(not(feature = "ferrocene_certified"))]
154pub const fn from_u32(i: u32) -> Option<char> {
155    self::convert::from_u32(i)
156}
157
158/// Converts a `u32` to a `char`, ignoring validity. Use [`char::from_u32_unchecked`]
159/// instead.
160#[stable(feature = "char_from_unchecked", since = "1.5.0")]
161#[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")]
162#[must_use]
163#[inline]
164#[cfg(not(feature = "ferrocene_certified"))]
165pub const unsafe fn from_u32_unchecked(i: u32) -> char {
166    // SAFETY: the safety contract must be upheld by the caller.
167    unsafe { self::convert::from_u32_unchecked(i) }
168}
169
170/// Converts a digit in the given radix to a `char`. Use [`char::from_digit`] instead.
171#[stable(feature = "rust1", since = "1.0.0")]
172#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
173#[must_use]
174#[inline]
175#[cfg(not(feature = "ferrocene_certified"))]
176pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
177    self::convert::from_digit(num, radix)
178}
179
180/// Returns an iterator that yields the hexadecimal Unicode escape of a
181/// character, as `char`s.
182///
183/// This `struct` is created by the [`escape_unicode`] method on [`char`]. See
184/// its documentation for more.
185///
186/// [`escape_unicode`]: char::escape_unicode
187#[derive(Clone, Debug)]
188#[stable(feature = "rust1", since = "1.0.0")]
189#[cfg(not(feature = "ferrocene_certified"))]
190pub struct EscapeUnicode(EscapeIterInner<10, AlwaysEscaped>);
191
192#[cfg(not(feature = "ferrocene_certified"))]
193impl EscapeUnicode {
194    #[inline]
195    const fn new(c: char) -> Self {
196        Self(EscapeIterInner::unicode(c))
197    }
198}
199
200#[stable(feature = "rust1", since = "1.0.0")]
201#[cfg(not(feature = "ferrocene_certified"))]
202impl Iterator for EscapeUnicode {
203    type Item = char;
204
205    #[inline]
206    fn next(&mut self) -> Option<char> {
207        self.0.next().map(char::from)
208    }
209
210    #[inline]
211    fn size_hint(&self) -> (usize, Option<usize>) {
212        let n = self.0.len();
213        (n, Some(n))
214    }
215
216    #[inline]
217    fn count(self) -> usize {
218        self.0.len()
219    }
220
221    #[inline]
222    fn last(mut self) -> Option<char> {
223        self.0.next_back().map(char::from)
224    }
225
226    #[inline]
227    fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
228        self.0.advance_by(n)
229    }
230}
231
232#[stable(feature = "exact_size_escape", since = "1.11.0")]
233#[cfg(not(feature = "ferrocene_certified"))]
234impl ExactSizeIterator for EscapeUnicode {
235    #[inline]
236    fn len(&self) -> usize {
237        self.0.len()
238    }
239}
240
241#[stable(feature = "fused", since = "1.26.0")]
242#[cfg(not(feature = "ferrocene_certified"))]
243impl FusedIterator for EscapeUnicode {}
244
245#[stable(feature = "char_struct_display", since = "1.16.0")]
246#[cfg(not(feature = "ferrocene_certified"))]
247impl fmt::Display for EscapeUnicode {
248    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
249        fmt::Display::fmt(&self.0, f)
250    }
251}
252
253/// An iterator that yields the literal escape code of a `char`.
254///
255/// This `struct` is created by the [`escape_default`] method on [`char`]. See
256/// its documentation for more.
257///
258/// [`escape_default`]: char::escape_default
259#[derive(Clone, Debug)]
260#[stable(feature = "rust1", since = "1.0.0")]
261#[cfg(not(feature = "ferrocene_certified"))]
262pub struct EscapeDefault(EscapeIterInner<10, AlwaysEscaped>);
263
264#[cfg(not(feature = "ferrocene_certified"))]
265impl EscapeDefault {
266    #[inline]
267    const fn printable(c: ascii::Char) -> Self {
268        Self(EscapeIterInner::ascii(c.to_u8()))
269    }
270
271    #[inline]
272    const fn backslash(c: ascii::Char) -> Self {
273        Self(EscapeIterInner::backslash(c))
274    }
275
276    #[inline]
277    const fn unicode(c: char) -> Self {
278        Self(EscapeIterInner::unicode(c))
279    }
280}
281
282#[stable(feature = "rust1", since = "1.0.0")]
283#[cfg(not(feature = "ferrocene_certified"))]
284impl Iterator for EscapeDefault {
285    type Item = char;
286
287    #[inline]
288    fn next(&mut self) -> Option<char> {
289        self.0.next().map(char::from)
290    }
291
292    #[inline]
293    fn size_hint(&self) -> (usize, Option<usize>) {
294        let n = self.0.len();
295        (n, Some(n))
296    }
297
298    #[inline]
299    fn count(self) -> usize {
300        self.0.len()
301    }
302
303    #[inline]
304    fn last(mut self) -> Option<char> {
305        self.0.next_back().map(char::from)
306    }
307
308    #[inline]
309    fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
310        self.0.advance_by(n)
311    }
312}
313
314#[stable(feature = "exact_size_escape", since = "1.11.0")]
315#[cfg(not(feature = "ferrocene_certified"))]
316impl ExactSizeIterator for EscapeDefault {
317    #[inline]
318    fn len(&self) -> usize {
319        self.0.len()
320    }
321}
322
323#[stable(feature = "fused", since = "1.26.0")]
324#[cfg(not(feature = "ferrocene_certified"))]
325impl FusedIterator for EscapeDefault {}
326
327#[stable(feature = "char_struct_display", since = "1.16.0")]
328#[cfg(not(feature = "ferrocene_certified"))]
329impl fmt::Display for EscapeDefault {
330    #[inline]
331    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
332        fmt::Display::fmt(&self.0, f)
333    }
334}
335
336/// An iterator that yields the literal escape code of a `char`.
337///
338/// This `struct` is created by the [`escape_debug`] method on [`char`]. See its
339/// documentation for more.
340///
341/// [`escape_debug`]: char::escape_debug
342#[stable(feature = "char_escape_debug", since = "1.20.0")]
343#[derive(Clone, Debug)]
344#[cfg(not(feature = "ferrocene_certified"))]
345pub struct EscapeDebug(EscapeIterInner<10, MaybeEscaped>);
346
347#[cfg(not(feature = "ferrocene_certified"))]
348impl EscapeDebug {
349    #[inline]
350    const fn printable(chr: char) -> Self {
351        Self(EscapeIterInner::printable(chr))
352    }
353
354    #[inline]
355    const fn backslash(c: ascii::Char) -> Self {
356        Self(EscapeIterInner::backslash(c))
357    }
358
359    #[inline]
360    const fn unicode(c: char) -> Self {
361        Self(EscapeIterInner::unicode(c))
362    }
363}
364
365#[stable(feature = "char_escape_debug", since = "1.20.0")]
366#[cfg(not(feature = "ferrocene_certified"))]
367impl Iterator for EscapeDebug {
368    type Item = char;
369
370    #[inline]
371    fn next(&mut self) -> Option<char> {
372        self.0.next()
373    }
374
375    #[inline]
376    fn size_hint(&self) -> (usize, Option<usize>) {
377        let n = self.len();
378        (n, Some(n))
379    }
380
381    #[inline]
382    fn count(self) -> usize {
383        self.len()
384    }
385}
386
387#[stable(feature = "char_escape_debug", since = "1.20.0")]
388#[cfg(not(feature = "ferrocene_certified"))]
389impl ExactSizeIterator for EscapeDebug {
390    fn len(&self) -> usize {
391        self.0.len()
392    }
393}
394
395#[stable(feature = "fused", since = "1.26.0")]
396#[cfg(not(feature = "ferrocene_certified"))]
397impl FusedIterator for EscapeDebug {}
398
399#[stable(feature = "char_escape_debug", since = "1.20.0")]
400#[cfg(not(feature = "ferrocene_certified"))]
401impl fmt::Display for EscapeDebug {
402    #[inline]
403    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
404        fmt::Display::fmt(&self.0, f)
405    }
406}
407
408#[cfg(not(feature = "ferrocene_certified"))]
409macro_rules! casemappingiter_impls {
410    ($(#[$attr:meta])* $ITER_NAME:ident) => {
411        $(#[$attr])*
412        #[stable(feature = "rust1", since = "1.0.0")]
413        #[derive(Debug, Clone)]
414        pub struct $ITER_NAME(CaseMappingIter);
415
416        #[stable(feature = "rust1", since = "1.0.0")]
417        impl Iterator for $ITER_NAME {
418            type Item = char;
419            fn next(&mut self) -> Option<char> {
420                self.0.next()
421            }
422
423            fn size_hint(&self) -> (usize, Option<usize>) {
424                self.0.size_hint()
425            }
426
427            fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
428            where
429                Fold: FnMut(Acc, Self::Item) -> Acc,
430            {
431                self.0.fold(init, fold)
432            }
433
434            fn count(self) -> usize {
435                self.0.count()
436            }
437
438            fn last(self) -> Option<Self::Item> {
439                self.0.last()
440            }
441
442            fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
443                self.0.advance_by(n)
444            }
445
446            unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
447                // SAFETY: just forwarding requirements to caller
448                unsafe { self.0.__iterator_get_unchecked(idx) }
449            }
450        }
451
452        #[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
453        impl DoubleEndedIterator for $ITER_NAME {
454            fn next_back(&mut self) -> Option<char> {
455                self.0.next_back()
456            }
457
458            fn rfold<Acc, Fold>(self, init: Acc, rfold: Fold) -> Acc
459            where
460                Fold: FnMut(Acc, Self::Item) -> Acc,
461            {
462                self.0.rfold(init, rfold)
463            }
464
465            fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
466                self.0.advance_back_by(n)
467            }
468        }
469
470        #[stable(feature = "fused", since = "1.26.0")]
471        impl FusedIterator for $ITER_NAME {}
472
473        #[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
474        impl ExactSizeIterator for $ITER_NAME {
475            fn len(&self) -> usize {
476                self.0.len()
477            }
478
479            fn is_empty(&self) -> bool {
480                self.0.is_empty()
481            }
482        }
483
484        // SAFETY: forwards to inner `array::IntoIter`
485        #[unstable(feature = "trusted_len", issue = "37572")]
486        unsafe impl TrustedLen for $ITER_NAME {}
487
488        // SAFETY: forwards to inner `array::IntoIter`
489        #[doc(hidden)]
490        #[unstable(feature = "std_internals", issue = "none")]
491        unsafe impl TrustedRandomAccessNoCoerce for $ITER_NAME {
492            const MAY_HAVE_SIDE_EFFECT: bool = false;
493        }
494
495        // SAFETY: this iter has no subtypes/supertypes
496        #[doc(hidden)]
497        #[unstable(feature = "std_internals", issue = "none")]
498        unsafe impl TrustedRandomAccess for $ITER_NAME {}
499
500        #[stable(feature = "char_struct_display", since = "1.16.0")]
501        impl fmt::Display for $ITER_NAME {
502            #[inline]
503            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
504                fmt::Display::fmt(&self.0, f)
505            }
506        }
507    }
508}
509
510#[cfg(not(feature = "ferrocene_certified"))]
511casemappingiter_impls! {
512    /// Returns an iterator that yields the lowercase equivalent of a `char`.
513    ///
514    /// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
515    /// its documentation for more.
516    ///
517    /// [`to_lowercase`]: char::to_lowercase
518    ToLowercase
519}
520
521#[cfg(not(feature = "ferrocene_certified"))]
522casemappingiter_impls! {
523    /// Returns an iterator that yields the uppercase equivalent of a `char`.
524    ///
525    /// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
526    /// its documentation for more.
527    ///
528    /// [`to_uppercase`]: char::to_uppercase
529    ToUppercase
530}
531
532#[derive(Debug, Clone)]
533#[cfg(not(feature = "ferrocene_certified"))]
534struct CaseMappingIter(core::array::IntoIter<char, 3>);
535
536#[cfg(not(feature = "ferrocene_certified"))]
537impl CaseMappingIter {
538    #[inline]
539    fn new(chars: [char; 3]) -> CaseMappingIter {
540        let mut iter = chars.into_iter();
541        if chars[2] == '\0' {
542            iter.next_back();
543            if chars[1] == '\0' {
544                iter.next_back();
545
546                // Deliberately don't check `chars[0]`,
547                // as '\0' lowercases to itself
548            }
549        }
550        CaseMappingIter(iter)
551    }
552}
553
554#[cfg(not(feature = "ferrocene_certified"))]
555impl Iterator for CaseMappingIter {
556    type Item = char;
557
558    fn next(&mut self) -> Option<char> {
559        self.0.next()
560    }
561
562    fn size_hint(&self) -> (usize, Option<usize>) {
563        self.0.size_hint()
564    }
565
566    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
567    where
568        Fold: FnMut(Acc, Self::Item) -> Acc,
569    {
570        self.0.fold(init, fold)
571    }
572
573    fn count(self) -> usize {
574        self.0.count()
575    }
576
577    fn last(self) -> Option<Self::Item> {
578        self.0.last()
579    }
580
581    fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
582        self.0.advance_by(n)
583    }
584
585    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
586        // SAFETY: just forwarding requirements to caller
587        unsafe { self.0.__iterator_get_unchecked(idx) }
588    }
589}
590
591#[cfg(not(feature = "ferrocene_certified"))]
592impl DoubleEndedIterator for CaseMappingIter {
593    fn next_back(&mut self) -> Option<char> {
594        self.0.next_back()
595    }
596
597    fn rfold<Acc, Fold>(self, init: Acc, rfold: Fold) -> Acc
598    where
599        Fold: FnMut(Acc, Self::Item) -> Acc,
600    {
601        self.0.rfold(init, rfold)
602    }
603
604    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
605        self.0.advance_back_by(n)
606    }
607}
608
609#[cfg(not(feature = "ferrocene_certified"))]
610impl ExactSizeIterator for CaseMappingIter {
611    fn len(&self) -> usize {
612        self.0.len()
613    }
614
615    fn is_empty(&self) -> bool {
616        self.0.is_empty()
617    }
618}
619
620#[cfg(not(feature = "ferrocene_certified"))]
621impl FusedIterator for CaseMappingIter {}
622
623// SAFETY: forwards to inner `array::IntoIter`
624#[cfg(not(feature = "ferrocene_certified"))]
625unsafe impl TrustedLen for CaseMappingIter {}
626
627// SAFETY: forwards to inner `array::IntoIter`
628#[cfg(not(feature = "ferrocene_certified"))]
629unsafe impl TrustedRandomAccessNoCoerce for CaseMappingIter {
630    const MAY_HAVE_SIDE_EFFECT: bool = false;
631}
632
633// SAFETY: `CaseMappingIter` has no subtypes/supertypes
634#[cfg(not(feature = "ferrocene_certified"))]
635unsafe impl TrustedRandomAccess for CaseMappingIter {}
636
637#[cfg(not(feature = "ferrocene_certified"))]
638impl fmt::Display for CaseMappingIter {
639    #[inline]
640    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
641        for c in self.0.clone() {
642            f.write_char(c)?;
643        }
644        Ok(())
645    }
646}
647
648/// The error type returned when a checked char conversion fails.
649#[stable(feature = "u8_from_char", since = "1.59.0")]
650#[derive(Debug, Copy, Clone, PartialEq, Eq)]
651#[cfg(not(feature = "ferrocene_certified"))]
652pub struct TryFromCharError(pub(crate) ());
653
654#[stable(feature = "u8_from_char", since = "1.59.0")]
655#[cfg(not(feature = "ferrocene_certified"))]
656impl fmt::Display for TryFromCharError {
657    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
658        "unicode code point out of range".fmt(fmt)
659    }
660}
661
662#[stable(feature = "u8_from_char", since = "1.59.0")]
663#[cfg(not(feature = "ferrocene_certified"))]
664impl Error for TryFromCharError {}