Skip to main content

core/ascii/
ascii_char.rs

1//! This uses the name `AsciiChar`, even though it's not exposed that way right now,
2//! because it avoids a whole bunch of "are you sure you didn't mean `char`?"
3//! suggestions from rustc if you get anything slightly wrong in here, and overall
4//! helps with clarity as we're also referring to `char` intentionally in here.
5
6use crate::mem::transmute;
7use crate::{assert_unsafe_precondition, fmt};
8
9/// One of the 128 Unicode characters from U+0000 through U+007F,
10/// often known as the [ASCII] subset.
11///
12/// Officially, this is the first [block] in Unicode, _Basic Latin_.
13/// For details, see the [*C0 Controls and Basic Latin*][chart] code chart.
14///
15/// This block was based on older 7-bit character code standards such as
16/// ANSI X3.4-1977, ISO 646-1973, and [NIST FIPS 1-2].
17///
18/// # When to use this
19///
20/// The main advantage of this subset is that it's always valid UTF-8.  As such,
21/// the `&[ascii::Char]` -> `&str` conversion function (as well as other related
22/// ones) are O(1): *no* runtime checks are needed.
23///
24/// If you're consuming strings, you should usually handle Unicode and thus
25/// accept `str`s, not limit yourself to `ascii::Char`s.
26///
27/// However, certain formats are intentionally designed to produce ASCII-only
28/// output in order to be 8-bit-clean.  In those cases, it can be simpler and
29/// faster to generate `ascii::Char`s instead of dealing with the variable width
30/// properties of general UTF-8 encoded strings, while still allowing the result
31/// to be used freely with other Rust things that deal in general `str`s.
32///
33/// For example, a UUID library might offer a way to produce the string
34/// representation of a UUID as an `[ascii::Char; 36]` to avoid memory
35/// allocation yet still allow it to be used as UTF-8 via `as_str` without
36/// paying for validation (or needing `unsafe` code) the way it would if it
37/// were provided as a `[u8; 36]`.
38///
39/// # Layout
40///
41/// This type is guaranteed to have a size and alignment of 1 byte.
42///
43/// # Names
44///
45/// The variants on this type are [Unicode names][NamesList] of the characters
46/// in upper camel case, with a few tweaks:
47/// - For `<control>` characters, the primary alias name is used.
48/// - `LATIN` is dropped, as this block has no non-latin letters.
49/// - `LETTER` is dropped, as `CAPITAL`/`SMALL` suffices in this block.
50/// - `DIGIT`s use a single digit rather than writing out `ZERO`, `ONE`, etc.
51///
52/// [ASCII]: https://www.unicode.org/glossary/index.html#ASCII
53/// [block]: https://www.unicode.org/glossary/index.html#block
54/// [chart]: https://www.unicode.org/charts/PDF/U0000.pdf
55/// [NIST FIPS 1-2]: https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub1-2-1977.pdf
56/// [NamesList]: https://www.unicode.org/Public/15.0.0/ucd/NamesList.txt
57#[derive(Copy, Hash)]
58#[derive_const(Clone, Eq, PartialEq, Ord, PartialOrd)]
59#[unstable(feature = "ascii_char", issue = "110998")]
60#[repr(u8)]
61pub enum AsciiChar {
62    /// U+0000 (The default variant)
63    #[unstable(feature = "ascii_char_variants", issue = "110998")]
64    Null = 0,
65    /// U+0001
66    #[unstable(feature = "ascii_char_variants", issue = "110998")]
67    StartOfHeading = 1,
68    /// U+0002
69    #[unstable(feature = "ascii_char_variants", issue = "110998")]
70    StartOfText = 2,
71    /// U+0003
72    #[unstable(feature = "ascii_char_variants", issue = "110998")]
73    EndOfText = 3,
74    /// U+0004
75    #[unstable(feature = "ascii_char_variants", issue = "110998")]
76    EndOfTransmission = 4,
77    /// U+0005
78    #[unstable(feature = "ascii_char_variants", issue = "110998")]
79    Enquiry = 5,
80    /// U+0006
81    #[unstable(feature = "ascii_char_variants", issue = "110998")]
82    Acknowledge = 6,
83    /// U+0007
84    #[unstable(feature = "ascii_char_variants", issue = "110998")]
85    Bell = 7,
86    /// U+0008
87    #[unstable(feature = "ascii_char_variants", issue = "110998")]
88    Backspace = 8,
89    /// U+0009
90    #[unstable(feature = "ascii_char_variants", issue = "110998")]
91    CharacterTabulation = 9,
92    /// U+000A
93    #[unstable(feature = "ascii_char_variants", issue = "110998")]
94    LineFeed = 10,
95    /// U+000B
96    #[unstable(feature = "ascii_char_variants", issue = "110998")]
97    LineTabulation = 11,
98    /// U+000C
99    #[unstable(feature = "ascii_char_variants", issue = "110998")]
100    FormFeed = 12,
101    /// U+000D
102    #[unstable(feature = "ascii_char_variants", issue = "110998")]
103    CarriageReturn = 13,
104    /// U+000E
105    #[unstable(feature = "ascii_char_variants", issue = "110998")]
106    ShiftOut = 14,
107    /// U+000F
108    #[unstable(feature = "ascii_char_variants", issue = "110998")]
109    ShiftIn = 15,
110    /// U+0010
111    #[unstable(feature = "ascii_char_variants", issue = "110998")]
112    DataLinkEscape = 16,
113    /// U+0011
114    #[unstable(feature = "ascii_char_variants", issue = "110998")]
115    DeviceControlOne = 17,
116    /// U+0012
117    #[unstable(feature = "ascii_char_variants", issue = "110998")]
118    DeviceControlTwo = 18,
119    /// U+0013
120    #[unstable(feature = "ascii_char_variants", issue = "110998")]
121    DeviceControlThree = 19,
122    /// U+0014
123    #[unstable(feature = "ascii_char_variants", issue = "110998")]
124    DeviceControlFour = 20,
125    /// U+0015
126    #[unstable(feature = "ascii_char_variants", issue = "110998")]
127    NegativeAcknowledge = 21,
128    /// U+0016
129    #[unstable(feature = "ascii_char_variants", issue = "110998")]
130    SynchronousIdle = 22,
131    /// U+0017
132    #[unstable(feature = "ascii_char_variants", issue = "110998")]
133    EndOfTransmissionBlock = 23,
134    /// U+0018
135    #[unstable(feature = "ascii_char_variants", issue = "110998")]
136    Cancel = 24,
137    /// U+0019
138    #[unstable(feature = "ascii_char_variants", issue = "110998")]
139    EndOfMedium = 25,
140    /// U+001A
141    #[unstable(feature = "ascii_char_variants", issue = "110998")]
142    Substitute = 26,
143    /// U+001B
144    #[unstable(feature = "ascii_char_variants", issue = "110998")]
145    Escape = 27,
146    /// U+001C
147    #[unstable(feature = "ascii_char_variants", issue = "110998")]
148    InformationSeparatorFour = 28,
149    /// U+001D
150    #[unstable(feature = "ascii_char_variants", issue = "110998")]
151    InformationSeparatorThree = 29,
152    /// U+001E
153    #[unstable(feature = "ascii_char_variants", issue = "110998")]
154    InformationSeparatorTwo = 30,
155    /// U+001F
156    #[unstable(feature = "ascii_char_variants", issue = "110998")]
157    InformationSeparatorOne = 31,
158    /// U+0020
159    #[unstable(feature = "ascii_char_variants", issue = "110998")]
160    Space = 32,
161    /// U+0021
162    #[unstable(feature = "ascii_char_variants", issue = "110998")]
163    ExclamationMark = 33,
164    /// U+0022
165    #[unstable(feature = "ascii_char_variants", issue = "110998")]
166    QuotationMark = 34,
167    /// U+0023
168    #[unstable(feature = "ascii_char_variants", issue = "110998")]
169    NumberSign = 35,
170    /// U+0024
171    #[unstable(feature = "ascii_char_variants", issue = "110998")]
172    DollarSign = 36,
173    /// U+0025
174    #[unstable(feature = "ascii_char_variants", issue = "110998")]
175    PercentSign = 37,
176    /// U+0026
177    #[unstable(feature = "ascii_char_variants", issue = "110998")]
178    Ampersand = 38,
179    /// U+0027
180    #[unstable(feature = "ascii_char_variants", issue = "110998")]
181    Apostrophe = 39,
182    /// U+0028
183    #[unstable(feature = "ascii_char_variants", issue = "110998")]
184    LeftParenthesis = 40,
185    /// U+0029
186    #[unstable(feature = "ascii_char_variants", issue = "110998")]
187    RightParenthesis = 41,
188    /// U+002A
189    #[unstable(feature = "ascii_char_variants", issue = "110998")]
190    Asterisk = 42,
191    /// U+002B
192    #[unstable(feature = "ascii_char_variants", issue = "110998")]
193    PlusSign = 43,
194    /// U+002C
195    #[unstable(feature = "ascii_char_variants", issue = "110998")]
196    Comma = 44,
197    /// U+002D
198    #[unstable(feature = "ascii_char_variants", issue = "110998")]
199    HyphenMinus = 45,
200    /// U+002E
201    #[unstable(feature = "ascii_char_variants", issue = "110998")]
202    FullStop = 46,
203    /// U+002F
204    #[unstable(feature = "ascii_char_variants", issue = "110998")]
205    Solidus = 47,
206    /// U+0030
207    #[unstable(feature = "ascii_char_variants", issue = "110998")]
208    Digit0 = 48,
209    /// U+0031
210    #[unstable(feature = "ascii_char_variants", issue = "110998")]
211    Digit1 = 49,
212    /// U+0032
213    #[unstable(feature = "ascii_char_variants", issue = "110998")]
214    Digit2 = 50,
215    /// U+0033
216    #[unstable(feature = "ascii_char_variants", issue = "110998")]
217    Digit3 = 51,
218    /// U+0034
219    #[unstable(feature = "ascii_char_variants", issue = "110998")]
220    Digit4 = 52,
221    /// U+0035
222    #[unstable(feature = "ascii_char_variants", issue = "110998")]
223    Digit5 = 53,
224    /// U+0036
225    #[unstable(feature = "ascii_char_variants", issue = "110998")]
226    Digit6 = 54,
227    /// U+0037
228    #[unstable(feature = "ascii_char_variants", issue = "110998")]
229    Digit7 = 55,
230    /// U+0038
231    #[unstable(feature = "ascii_char_variants", issue = "110998")]
232    Digit8 = 56,
233    /// U+0039
234    #[unstable(feature = "ascii_char_variants", issue = "110998")]
235    Digit9 = 57,
236    /// U+003A
237    #[unstable(feature = "ascii_char_variants", issue = "110998")]
238    Colon = 58,
239    /// U+003B
240    #[unstable(feature = "ascii_char_variants", issue = "110998")]
241    Semicolon = 59,
242    /// U+003C
243    #[unstable(feature = "ascii_char_variants", issue = "110998")]
244    LessThanSign = 60,
245    /// U+003D
246    #[unstable(feature = "ascii_char_variants", issue = "110998")]
247    EqualsSign = 61,
248    /// U+003E
249    #[unstable(feature = "ascii_char_variants", issue = "110998")]
250    GreaterThanSign = 62,
251    /// U+003F
252    #[unstable(feature = "ascii_char_variants", issue = "110998")]
253    QuestionMark = 63,
254    /// U+0040
255    #[unstable(feature = "ascii_char_variants", issue = "110998")]
256    CommercialAt = 64,
257    /// U+0041
258    #[unstable(feature = "ascii_char_variants", issue = "110998")]
259    CapitalA = 65,
260    /// U+0042
261    #[unstable(feature = "ascii_char_variants", issue = "110998")]
262    CapitalB = 66,
263    /// U+0043
264    #[unstable(feature = "ascii_char_variants", issue = "110998")]
265    CapitalC = 67,
266    /// U+0044
267    #[unstable(feature = "ascii_char_variants", issue = "110998")]
268    CapitalD = 68,
269    /// U+0045
270    #[unstable(feature = "ascii_char_variants", issue = "110998")]
271    CapitalE = 69,
272    /// U+0046
273    #[unstable(feature = "ascii_char_variants", issue = "110998")]
274    CapitalF = 70,
275    /// U+0047
276    #[unstable(feature = "ascii_char_variants", issue = "110998")]
277    CapitalG = 71,
278    /// U+0048
279    #[unstable(feature = "ascii_char_variants", issue = "110998")]
280    CapitalH = 72,
281    /// U+0049
282    #[unstable(feature = "ascii_char_variants", issue = "110998")]
283    CapitalI = 73,
284    /// U+004A
285    #[unstable(feature = "ascii_char_variants", issue = "110998")]
286    CapitalJ = 74,
287    /// U+004B
288    #[unstable(feature = "ascii_char_variants", issue = "110998")]
289    CapitalK = 75,
290    /// U+004C
291    #[unstable(feature = "ascii_char_variants", issue = "110998")]
292    CapitalL = 76,
293    /// U+004D
294    #[unstable(feature = "ascii_char_variants", issue = "110998")]
295    CapitalM = 77,
296    /// U+004E
297    #[unstable(feature = "ascii_char_variants", issue = "110998")]
298    CapitalN = 78,
299    /// U+004F
300    #[unstable(feature = "ascii_char_variants", issue = "110998")]
301    CapitalO = 79,
302    /// U+0050
303    #[unstable(feature = "ascii_char_variants", issue = "110998")]
304    CapitalP = 80,
305    /// U+0051
306    #[unstable(feature = "ascii_char_variants", issue = "110998")]
307    CapitalQ = 81,
308    /// U+0052
309    #[unstable(feature = "ascii_char_variants", issue = "110998")]
310    CapitalR = 82,
311    /// U+0053
312    #[unstable(feature = "ascii_char_variants", issue = "110998")]
313    CapitalS = 83,
314    /// U+0054
315    #[unstable(feature = "ascii_char_variants", issue = "110998")]
316    CapitalT = 84,
317    /// U+0055
318    #[unstable(feature = "ascii_char_variants", issue = "110998")]
319    CapitalU = 85,
320    /// U+0056
321    #[unstable(feature = "ascii_char_variants", issue = "110998")]
322    CapitalV = 86,
323    /// U+0057
324    #[unstable(feature = "ascii_char_variants", issue = "110998")]
325    CapitalW = 87,
326    /// U+0058
327    #[unstable(feature = "ascii_char_variants", issue = "110998")]
328    CapitalX = 88,
329    /// U+0059
330    #[unstable(feature = "ascii_char_variants", issue = "110998")]
331    CapitalY = 89,
332    /// U+005A
333    #[unstable(feature = "ascii_char_variants", issue = "110998")]
334    CapitalZ = 90,
335    /// U+005B
336    #[unstable(feature = "ascii_char_variants", issue = "110998")]
337    LeftSquareBracket = 91,
338    /// U+005C
339    #[unstable(feature = "ascii_char_variants", issue = "110998")]
340    ReverseSolidus = 92,
341    /// U+005D
342    #[unstable(feature = "ascii_char_variants", issue = "110998")]
343    RightSquareBracket = 93,
344    /// U+005E
345    #[unstable(feature = "ascii_char_variants", issue = "110998")]
346    CircumflexAccent = 94,
347    /// U+005F
348    #[unstable(feature = "ascii_char_variants", issue = "110998")]
349    LowLine = 95,
350    /// U+0060
351    #[unstable(feature = "ascii_char_variants", issue = "110998")]
352    GraveAccent = 96,
353    /// U+0061
354    #[unstable(feature = "ascii_char_variants", issue = "110998")]
355    SmallA = 97,
356    /// U+0062
357    #[unstable(feature = "ascii_char_variants", issue = "110998")]
358    SmallB = 98,
359    /// U+0063
360    #[unstable(feature = "ascii_char_variants", issue = "110998")]
361    SmallC = 99,
362    /// U+0064
363    #[unstable(feature = "ascii_char_variants", issue = "110998")]
364    SmallD = 100,
365    /// U+0065
366    #[unstable(feature = "ascii_char_variants", issue = "110998")]
367    SmallE = 101,
368    /// U+0066
369    #[unstable(feature = "ascii_char_variants", issue = "110998")]
370    SmallF = 102,
371    /// U+0067
372    #[unstable(feature = "ascii_char_variants", issue = "110998")]
373    SmallG = 103,
374    /// U+0068
375    #[unstable(feature = "ascii_char_variants", issue = "110998")]
376    SmallH = 104,
377    /// U+0069
378    #[unstable(feature = "ascii_char_variants", issue = "110998")]
379    SmallI = 105,
380    /// U+006A
381    #[unstable(feature = "ascii_char_variants", issue = "110998")]
382    SmallJ = 106,
383    /// U+006B
384    #[unstable(feature = "ascii_char_variants", issue = "110998")]
385    SmallK = 107,
386    /// U+006C
387    #[unstable(feature = "ascii_char_variants", issue = "110998")]
388    SmallL = 108,
389    /// U+006D
390    #[unstable(feature = "ascii_char_variants", issue = "110998")]
391    SmallM = 109,
392    /// U+006E
393    #[unstable(feature = "ascii_char_variants", issue = "110998")]
394    SmallN = 110,
395    /// U+006F
396    #[unstable(feature = "ascii_char_variants", issue = "110998")]
397    SmallO = 111,
398    /// U+0070
399    #[unstable(feature = "ascii_char_variants", issue = "110998")]
400    SmallP = 112,
401    /// U+0071
402    #[unstable(feature = "ascii_char_variants", issue = "110998")]
403    SmallQ = 113,
404    /// U+0072
405    #[unstable(feature = "ascii_char_variants", issue = "110998")]
406    SmallR = 114,
407    /// U+0073
408    #[unstable(feature = "ascii_char_variants", issue = "110998")]
409    SmallS = 115,
410    /// U+0074
411    #[unstable(feature = "ascii_char_variants", issue = "110998")]
412    SmallT = 116,
413    /// U+0075
414    #[unstable(feature = "ascii_char_variants", issue = "110998")]
415    SmallU = 117,
416    /// U+0076
417    #[unstable(feature = "ascii_char_variants", issue = "110998")]
418    SmallV = 118,
419    /// U+0077
420    #[unstable(feature = "ascii_char_variants", issue = "110998")]
421    SmallW = 119,
422    /// U+0078
423    #[unstable(feature = "ascii_char_variants", issue = "110998")]
424    SmallX = 120,
425    /// U+0079
426    #[unstable(feature = "ascii_char_variants", issue = "110998")]
427    SmallY = 121,
428    /// U+007A
429    #[unstable(feature = "ascii_char_variants", issue = "110998")]
430    SmallZ = 122,
431    /// U+007B
432    #[unstable(feature = "ascii_char_variants", issue = "110998")]
433    LeftCurlyBracket = 123,
434    /// U+007C
435    #[unstable(feature = "ascii_char_variants", issue = "110998")]
436    VerticalLine = 124,
437    /// U+007D
438    #[unstable(feature = "ascii_char_variants", issue = "110998")]
439    RightCurlyBracket = 125,
440    /// U+007E
441    #[unstable(feature = "ascii_char_variants", issue = "110998")]
442    Tilde = 126,
443    /// U+007F
444    #[unstable(feature = "ascii_char_variants", issue = "110998")]
445    Delete = 127,
446}
447
448impl AsciiChar {
449    /// The character with the lowest ASCII code.
450    #[unstable(feature = "ascii_char", issue = "110998")]
451    pub const MIN: Self = Self::Null;
452
453    /// The character with the highest ASCII code.
454    #[unstable(feature = "ascii_char", issue = "110998")]
455    pub const MAX: Self = Self::Delete;
456
457    /// Creates an ASCII character from the byte `b`,
458    /// or returns `None` if it's too large.
459    #[unstable(feature = "ascii_char", issue = "110998")]
460    #[inline]
461    pub const fn from_u8(b: u8) -> Option<Self> {
462        if b <= 127 {
463            // SAFETY: Just checked that `b` is in-range
464            Some(unsafe { Self::from_u8_unchecked(b) })
465        } else {
466            None
467        }
468    }
469
470    /// Creates an ASCII character from the byte `b`,
471    /// without checking whether it's valid.
472    ///
473    /// # Safety
474    ///
475    /// `b` must be in `0..=127`, or else this is UB.
476    #[unstable(feature = "ascii_char", issue = "110998")]
477    #[inline]
478    pub const unsafe fn from_u8_unchecked(b: u8) -> Self {
479        assert_unsafe_precondition!(
480            check_library_ub,
481            "`ascii::Char::from_u8_unchecked` input cannot exceed 127.",
482            (b: u8 = b) => b <= 127,
483        );
484        // SAFETY: Our safety precondition is that `b` is in-range.
485        unsafe { transmute(b) }
486    }
487
488    /// When passed the *number* `0`, `1`, …, `9`, returns the *character*
489    /// `'0'`, `'1'`, …, `'9'` respectively.
490    ///
491    /// If `d >= 10`, returns `None`.
492    #[unstable(feature = "ascii_char", issue = "110998")]
493    #[inline]
494    pub const fn digit(d: u8) -> Option<Self> {
495        if d < 10 {
496            // SAFETY: Just checked it's in-range.
497            Some(unsafe { Self::digit_unchecked(d) })
498        } else {
499            None
500        }
501    }
502
503    /// When passed the *number* `0`, `1`, …, `9`, returns the *character*
504    /// `'0'`, `'1'`, …, `'9'` respectively, without checking that it's in-range.
505    ///
506    /// # Safety
507    ///
508    /// This is immediate UB if called with `d > 64`.
509    ///
510    /// If `d >= 10` and `d <= 64`, this is allowed to return any value or panic.
511    /// Notably, it should not be expected to return hex digits, or any other
512    /// reasonable extension of the decimal digits.
513    ///
514    /// (This loose safety condition is intended to simplify soundness proofs
515    /// when writing code using this method, since the implementation doesn't
516    /// need something really specific, not to make those other arguments do
517    /// something useful. It might be tightened before stabilization.)
518    #[unstable(feature = "ascii_char", issue = "110998")]
519    #[inline]
520    #[track_caller]
521    pub const unsafe fn digit_unchecked(d: u8) -> Self {
522        assert_unsafe_precondition!(
523            check_library_ub,
524            "`ascii::Char::digit_unchecked` input cannot exceed 9.",
525            (d: u8 = d) => d < 10
526        );
527
528        // SAFETY: `'0'` through `'9'` are U+00030 through U+0039,
529        // so because `d` must be 64 or less the addition can return at most
530        // 112 (0x70), which doesn't overflow and is within the ASCII range.
531        unsafe {
532            let byte = b'0'.unchecked_add(d);
533            Self::from_u8_unchecked(byte)
534        }
535    }
536
537    /// Gets this ASCII character as a byte.
538    #[unstable(feature = "ascii_char", issue = "110998")]
539    #[inline]
540    pub const fn to_u8(self) -> u8 {
541        self as u8
542    }
543
544    /// Gets this ASCII character as a `char` Unicode Scalar Value.
545    #[unstable(feature = "ascii_char", issue = "110998")]
546    #[inline]
547    pub const fn to_char(self) -> char {
548        self as u8 as char
549    }
550
551    /// Views this ASCII character as a one-code-unit UTF-8 `str`.
552    #[unstable(feature = "ascii_char", issue = "110998")]
553    #[inline]
554    pub const fn as_str(&self) -> &str {
555        crate::slice::from_ref(self).as_str()
556    }
557
558    /// Makes a copy of the value in its upper case equivalent.
559    ///
560    /// Letters 'a' to 'z' are mapped to 'A' to 'Z'.
561    ///
562    /// To uppercase the value in-place, use [`make_uppercase`].
563    ///
564    /// # Examples
565    ///
566    /// ```
567    /// #![feature(ascii_char, ascii_char_variants)]
568    /// use std::ascii;
569    ///
570    /// let lowercase_a = ascii::Char::SmallA;
571    ///
572    /// assert_eq!(
573    ///     ascii::Char::CapitalA,
574    ///     lowercase_a.to_uppercase(),
575    /// );
576    /// ```
577    ///
578    /// [`make_uppercase`]: Self::make_uppercase
579    #[must_use = "to uppercase the value in-place, use `make_uppercase()`"]
580    #[unstable(feature = "ascii_char", issue = "110998")]
581    #[inline]
582    pub const fn to_uppercase(self) -> Self {
583        let uppercase_byte = self.to_u8().to_ascii_uppercase();
584        // SAFETY: Toggling the 6th bit won't convert ASCII to non-ASCII.
585        unsafe { Self::from_u8_unchecked(uppercase_byte) }
586    }
587
588    /// Makes a copy of the value in its lower case equivalent.
589    ///
590    /// Letters 'A' to 'Z' are mapped to 'a' to 'z'.
591    ///
592    /// To lowercase the value in-place, use [`make_lowercase`].
593    ///
594    /// # Examples
595    ///
596    /// ```
597    /// #![feature(ascii_char, ascii_char_variants)]
598    /// use std::ascii;
599    ///
600    /// let uppercase_a = ascii::Char::CapitalA;
601    ///
602    /// assert_eq!(
603    ///     ascii::Char::SmallA,
604    ///     uppercase_a.to_lowercase(),
605    /// );
606    /// ```
607    ///
608    /// [`make_lowercase`]: Self::make_lowercase
609    #[must_use = "to lowercase the value in-place, use `make_lowercase()`"]
610    #[unstable(feature = "ascii_char", issue = "110998")]
611    #[inline]
612    pub const fn to_lowercase(self) -> Self {
613        let lowercase_byte = self.to_u8().to_ascii_lowercase();
614        // SAFETY: Setting the 6th bit won't convert ASCII to non-ASCII.
615        unsafe { Self::from_u8_unchecked(lowercase_byte) }
616    }
617
618    /// Checks that two values are a case-insensitive match.
619    ///
620    /// This is equivalent to `to_lowercase(a) == to_lowercase(b)`.
621    ///
622    /// # Examples
623    ///
624    /// ```
625    /// #![feature(ascii_char, ascii_char_variants)]
626    /// use std::ascii;
627    ///
628    /// let lowercase_a = ascii::Char::SmallA;
629    /// let uppercase_a = ascii::Char::CapitalA;
630    ///
631    /// assert!(lowercase_a.eq_ignore_case(uppercase_a));
632    /// ```
633    #[unstable(feature = "ascii_char", issue = "110998")]
634    #[inline]
635    pub const fn eq_ignore_case(self, other: Self) -> bool {
636        // FIXME(const-hack) `arg.to_u8().to_ascii_lowercase()` -> `arg.to_lowercase()`
637        // once `PartialEq` is const for `Self`.
638        self.to_u8().to_ascii_lowercase() == other.to_u8().to_ascii_lowercase()
639    }
640
641    /// Converts this value to its upper case equivalent in-place.
642    ///
643    /// Letters 'a' to 'z' are mapped to 'A' to 'Z'.
644    ///
645    /// To return a new uppercased value without modifying the existing one, use
646    /// [`to_uppercase`].
647    ///
648    /// # Examples
649    ///
650    /// ```
651    /// #![feature(ascii_char, ascii_char_variants)]
652    /// use std::ascii;
653    ///
654    /// let mut letter_a = ascii::Char::SmallA;
655    ///
656    /// letter_a.make_uppercase();
657    ///
658    /// assert_eq!(ascii::Char::CapitalA, letter_a);
659    /// ```
660    ///
661    /// [`to_uppercase`]: Self::to_uppercase
662    #[unstable(feature = "ascii_char", issue = "110998")]
663    #[inline]
664    pub const fn make_uppercase(&mut self) {
665        *self = self.to_uppercase();
666    }
667
668    /// Converts this value to its lower case equivalent in-place.
669    ///
670    /// Letters 'A' to 'Z' are mapped to 'a' to 'z'.
671    ///
672    /// To return a new lowercased value without modifying the existing one, use
673    /// [`to_lowercase`].
674    ///
675    /// # Examples
676    ///
677    /// ```
678    /// #![feature(ascii_char, ascii_char_variants)]
679    /// use std::ascii;
680    ///
681    /// let mut letter_a = ascii::Char::CapitalA;
682    ///
683    /// letter_a.make_lowercase();
684    ///
685    /// assert_eq!(ascii::Char::SmallA, letter_a);
686    /// ```
687    ///
688    /// [`to_lowercase`]: Self::to_lowercase
689    #[unstable(feature = "ascii_char", issue = "110998")]
690    #[inline]
691    pub const fn make_lowercase(&mut self) {
692        *self = self.to_lowercase();
693    }
694
695    /// Checks if the value is an alphabetic character:
696    ///
697    /// - 0x41 'A' ..= 0x5A 'Z', or
698    /// - 0x61 'a' ..= 0x7A 'z'.
699    ///
700    /// # Examples
701    ///
702    /// ```
703    /// #![feature(ascii_char, ascii_char_variants)]
704    /// use std::ascii;
705    ///
706    /// let uppercase_a = ascii::Char::CapitalA;
707    /// let uppercase_g = ascii::Char::CapitalG;
708    /// let a = ascii::Char::SmallA;
709    /// let g = ascii::Char::SmallG;
710    /// let zero = ascii::Char::Digit0;
711    /// let percent = ascii::Char::PercentSign;
712    /// let space = ascii::Char::Space;
713    /// let lf = ascii::Char::LineFeed;
714    /// let esc = ascii::Char::Escape;
715    ///
716    /// assert!(uppercase_a.is_alphabetic());
717    /// assert!(uppercase_g.is_alphabetic());
718    /// assert!(a.is_alphabetic());
719    /// assert!(g.is_alphabetic());
720    /// assert!(!zero.is_alphabetic());
721    /// assert!(!percent.is_alphabetic());
722    /// assert!(!space.is_alphabetic());
723    /// assert!(!lf.is_alphabetic());
724    /// assert!(!esc.is_alphabetic());
725    /// ```
726    #[must_use]
727    #[unstable(feature = "ascii_char", issue = "110998")]
728    #[inline]
729    pub const fn is_alphabetic(self) -> bool {
730        self.to_u8().is_ascii_alphabetic()
731    }
732
733    /// Checks if the value is an uppercase character:
734    /// 0x41 'A' ..= 0x5A 'Z'.
735    ///
736    /// # Examples
737    ///
738    /// ```
739    /// #![feature(ascii_char, ascii_char_variants)]
740    /// use std::ascii;
741    ///
742    /// let uppercase_a = ascii::Char::CapitalA;
743    /// let uppercase_g = ascii::Char::CapitalG;
744    /// let a = ascii::Char::SmallA;
745    /// let g = ascii::Char::SmallG;
746    /// let zero = ascii::Char::Digit0;
747    /// let percent = ascii::Char::PercentSign;
748    /// let space = ascii::Char::Space;
749    /// let lf = ascii::Char::LineFeed;
750    /// let esc = ascii::Char::Escape;
751    ///
752    /// assert!(uppercase_a.is_uppercase());
753    /// assert!(uppercase_g.is_uppercase());
754    /// assert!(!a.is_uppercase());
755    /// assert!(!g.is_uppercase());
756    /// assert!(!zero.is_uppercase());
757    /// assert!(!percent.is_uppercase());
758    /// assert!(!space.is_uppercase());
759    /// assert!(!lf.is_uppercase());
760    /// assert!(!esc.is_uppercase());
761    /// ```
762    #[must_use]
763    #[unstable(feature = "ascii_char", issue = "110998")]
764    #[inline]
765    pub const fn is_uppercase(self) -> bool {
766        self.to_u8().is_ascii_uppercase()
767    }
768
769    /// Checks if the value is a lowercase character:
770    /// 0x61 'a' ..= 0x7A 'z'.
771    ///
772    /// # Examples
773    ///
774    /// ```
775    /// #![feature(ascii_char, ascii_char_variants)]
776    /// use std::ascii;
777    ///
778    /// let uppercase_a = ascii::Char::CapitalA;
779    /// let uppercase_g = ascii::Char::CapitalG;
780    /// let a = ascii::Char::SmallA;
781    /// let g = ascii::Char::SmallG;
782    /// let zero = ascii::Char::Digit0;
783    /// let percent = ascii::Char::PercentSign;
784    /// let space = ascii::Char::Space;
785    /// let lf = ascii::Char::LineFeed;
786    /// let esc = ascii::Char::Escape;
787    ///
788    /// assert!(!uppercase_a.is_lowercase());
789    /// assert!(!uppercase_g.is_lowercase());
790    /// assert!(a.is_lowercase());
791    /// assert!(g.is_lowercase());
792    /// assert!(!zero.is_lowercase());
793    /// assert!(!percent.is_lowercase());
794    /// assert!(!space.is_lowercase());
795    /// assert!(!lf.is_lowercase());
796    /// assert!(!esc.is_lowercase());
797    /// ```
798    #[must_use]
799    #[unstable(feature = "ascii_char", issue = "110998")]
800    #[inline]
801    pub const fn is_lowercase(self) -> bool {
802        self.to_u8().is_ascii_lowercase()
803    }
804
805    /// Checks if the value is an alphanumeric character:
806    ///
807    /// - 0x41 'A' ..= 0x5A 'Z', or
808    /// - 0x61 'a' ..= 0x7A 'z', or
809    /// - 0x30 '0' ..= 0x39 '9'.
810    ///
811    /// # Examples
812    ///
813    /// ```
814    /// #![feature(ascii_char, ascii_char_variants)]
815    /// use std::ascii;
816    ///
817    /// let uppercase_a = ascii::Char::CapitalA;
818    /// let uppercase_g = ascii::Char::CapitalG;
819    /// let a = ascii::Char::SmallA;
820    /// let g = ascii::Char::SmallG;
821    /// let zero = ascii::Char::Digit0;
822    /// let percent = ascii::Char::PercentSign;
823    /// let space = ascii::Char::Space;
824    /// let lf = ascii::Char::LineFeed;
825    /// let esc = ascii::Char::Escape;
826    ///
827    /// assert!(uppercase_a.is_alphanumeric());
828    /// assert!(uppercase_g.is_alphanumeric());
829    /// assert!(a.is_alphanumeric());
830    /// assert!(g.is_alphanumeric());
831    /// assert!(zero.is_alphanumeric());
832    /// assert!(!percent.is_alphanumeric());
833    /// assert!(!space.is_alphanumeric());
834    /// assert!(!lf.is_alphanumeric());
835    /// assert!(!esc.is_alphanumeric());
836    /// ```
837    #[must_use]
838    #[unstable(feature = "ascii_char", issue = "110998")]
839    #[inline]
840    pub const fn is_alphanumeric(self) -> bool {
841        self.to_u8().is_ascii_alphanumeric()
842    }
843
844    /// Checks if the value is a decimal digit:
845    /// 0x30 '0' ..= 0x39 '9'.
846    ///
847    /// # Examples
848    ///
849    /// ```
850    /// #![feature(ascii_char, ascii_char_variants)]
851    /// use std::ascii;
852    ///
853    /// let uppercase_a = ascii::Char::CapitalA;
854    /// let uppercase_g = ascii::Char::CapitalG;
855    /// let a = ascii::Char::SmallA;
856    /// let g = ascii::Char::SmallG;
857    /// let zero = ascii::Char::Digit0;
858    /// let percent = ascii::Char::PercentSign;
859    /// let space = ascii::Char::Space;
860    /// let lf = ascii::Char::LineFeed;
861    /// let esc = ascii::Char::Escape;
862    ///
863    /// assert!(!uppercase_a.is_digit());
864    /// assert!(!uppercase_g.is_digit());
865    /// assert!(!a.is_digit());
866    /// assert!(!g.is_digit());
867    /// assert!(zero.is_digit());
868    /// assert!(!percent.is_digit());
869    /// assert!(!space.is_digit());
870    /// assert!(!lf.is_digit());
871    /// assert!(!esc.is_digit());
872    /// ```
873    #[must_use]
874    #[unstable(feature = "ascii_char", issue = "110998")]
875    #[inline]
876    pub const fn is_digit(self) -> bool {
877        self.to_u8().is_ascii_digit()
878    }
879
880    /// Checks if the value is an octal digit:
881    /// 0x30 '0' ..= 0x37 '7'.
882    ///
883    /// # Examples
884    ///
885    /// ```
886    /// #![feature(ascii_char, ascii_char_variants)]
887    ///
888    /// use std::ascii;
889    ///
890    /// let uppercase_a = ascii::Char::CapitalA;
891    /// let a = ascii::Char::SmallA;
892    /// let zero = ascii::Char::Digit0;
893    /// let seven = ascii::Char::Digit7;
894    /// let eight = ascii::Char::Digit8;
895    /// let percent = ascii::Char::PercentSign;
896    /// let lf = ascii::Char::LineFeed;
897    /// let esc = ascii::Char::Escape;
898    ///
899    /// assert!(!uppercase_a.is_octdigit());
900    /// assert!(!a.is_octdigit());
901    /// assert!(zero.is_octdigit());
902    /// assert!(seven.is_octdigit());
903    /// assert!(!eight.is_octdigit());
904    /// assert!(!percent.is_octdigit());
905    /// assert!(!lf.is_octdigit());
906    /// assert!(!esc.is_octdigit());
907    /// ```
908    #[must_use]
909    // This is blocked on two unstable features. Please ensure both are
910    // stabilized before marking this method as stable.
911    #[unstable(feature = "ascii_char", issue = "110998")]
912    // #[unstable(feature = "is_ascii_octdigit", issue = "101288")]
913    #[inline]
914    pub const fn is_octdigit(self) -> bool {
915        self.to_u8().is_ascii_octdigit()
916    }
917
918    /// Checks if the value is a hexadecimal digit:
919    ///
920    /// - 0x30 '0' ..= 0x39 '9', or
921    /// - 0x41 'A' ..= 0x46 'F', or
922    /// - 0x61 'a' ..= 0x66 'f'.
923    ///
924    /// # Examples
925    ///
926    /// ```
927    /// #![feature(ascii_char, ascii_char_variants)]
928    /// use std::ascii;
929    ///
930    /// let uppercase_a = ascii::Char::CapitalA;
931    /// let uppercase_g = ascii::Char::CapitalG;
932    /// let a = ascii::Char::SmallA;
933    /// let g = ascii::Char::SmallG;
934    /// let zero = ascii::Char::Digit0;
935    /// let percent = ascii::Char::PercentSign;
936    /// let space = ascii::Char::Space;
937    /// let lf = ascii::Char::LineFeed;
938    /// let esc = ascii::Char::Escape;
939    ///
940    /// assert!(uppercase_a.is_hexdigit());
941    /// assert!(!uppercase_g.is_hexdigit());
942    /// assert!(a.is_hexdigit());
943    /// assert!(!g.is_hexdigit());
944    /// assert!(zero.is_hexdigit());
945    /// assert!(!percent.is_hexdigit());
946    /// assert!(!space.is_hexdigit());
947    /// assert!(!lf.is_hexdigit());
948    /// assert!(!esc.is_hexdigit());
949    /// ```
950    #[must_use]
951    #[unstable(feature = "ascii_char", issue = "110998")]
952    #[inline]
953    pub const fn is_hexdigit(self) -> bool {
954        self.to_u8().is_ascii_hexdigit()
955    }
956
957    /// Checks if the value is a punctuation or symbol character
958    /// (i.e. not alphanumeric, whitespace, or control):
959    ///
960    /// - 0x21 ..= 0x2F `! " # $ % & ' ( ) * + , - . /`, or
961    /// - 0x3A ..= 0x40 `: ; < = > ? @`, or
962    /// - 0x5B ..= 0x60 `` [ \ ] ^ _ ` ``, or
963    /// - 0x7B ..= 0x7E `{ | } ~`
964    ///
965    /// # Examples
966    ///
967    /// ```
968    /// #![feature(ascii_char, ascii_char_variants)]
969    /// use std::ascii;
970    ///
971    /// let uppercase_a = ascii::Char::CapitalA;
972    /// let uppercase_g = ascii::Char::CapitalG;
973    /// let a = ascii::Char::SmallA;
974    /// let g = ascii::Char::SmallG;
975    /// let zero = ascii::Char::Digit0;
976    /// let percent = ascii::Char::PercentSign;
977    /// let space = ascii::Char::Space;
978    /// let lf = ascii::Char::LineFeed;
979    /// let esc = ascii::Char::Escape;
980    ///
981    /// assert!(!uppercase_a.is_punctuation());
982    /// assert!(!uppercase_g.is_punctuation());
983    /// assert!(!a.is_punctuation());
984    /// assert!(!g.is_punctuation());
985    /// assert!(!zero.is_punctuation());
986    /// assert!(percent.is_punctuation());
987    /// assert!(!space.is_punctuation());
988    /// assert!(!lf.is_punctuation());
989    /// assert!(!esc.is_punctuation());
990    /// ```
991    #[must_use]
992    #[unstable(feature = "ascii_char", issue = "110998")]
993    #[inline]
994    pub const fn is_punctuation(self) -> bool {
995        self.to_u8().is_ascii_punctuation()
996    }
997
998    /// Checks if the value is a graphic character
999    /// (i.e. not whitespace or control):
1000    /// 0x21 '!' ..= 0x7E '~'.
1001    ///
1002    /// # Examples
1003    ///
1004    /// ```
1005    /// #![feature(ascii_char, ascii_char_variants)]
1006    /// use std::ascii;
1007    ///
1008    /// let uppercase_a = ascii::Char::CapitalA;
1009    /// let uppercase_g = ascii::Char::CapitalG;
1010    /// let a = ascii::Char::SmallA;
1011    /// let g = ascii::Char::SmallG;
1012    /// let zero = ascii::Char::Digit0;
1013    /// let percent = ascii::Char::PercentSign;
1014    /// let space = ascii::Char::Space;
1015    /// let lf = ascii::Char::LineFeed;
1016    /// let esc = ascii::Char::Escape;
1017    ///
1018    /// assert!(uppercase_a.is_graphic());
1019    /// assert!(uppercase_g.is_graphic());
1020    /// assert!(a.is_graphic());
1021    /// assert!(g.is_graphic());
1022    /// assert!(zero.is_graphic());
1023    /// assert!(percent.is_graphic());
1024    /// assert!(!space.is_graphic());
1025    /// assert!(!lf.is_graphic());
1026    /// assert!(!esc.is_graphic());
1027    /// ```
1028    #[must_use]
1029    #[unstable(feature = "ascii_char", issue = "110998")]
1030    #[inline]
1031    pub const fn is_graphic(self) -> bool {
1032        self.to_u8().is_ascii_graphic()
1033    }
1034
1035    /// Checks if the value is a whitespace character:
1036    /// 0x20 SPACE, 0x09 HORIZONTAL TAB, 0x0A LINE FEED,
1037    /// 0x0C FORM FEED, or 0x0D CARRIAGE RETURN.
1038    ///
1039    /// Rust uses the WhatWG Infra Standard's [definition of ASCII
1040    /// whitespace][infra-aw]. There are several other definitions in
1041    /// wide use. For instance, [the POSIX locale][pct] includes
1042    /// 0x0B VERTICAL TAB as well as all the above characters,
1043    /// but—from the very same specification—[the default rule for
1044    /// "field splitting" in the Bourne shell][bfs] considers *only*
1045    /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
1046    ///
1047    /// If you are writing a program that will process an existing
1048    /// file format, check what that format's definition of whitespace is
1049    /// before using this function.
1050    ///
1051    /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
1052    /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
1053    /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
1054    ///
1055    /// # Examples
1056    ///
1057    /// ```
1058    /// #![feature(ascii_char, ascii_char_variants)]
1059    /// use std::ascii;
1060    ///
1061    /// let uppercase_a = ascii::Char::CapitalA;
1062    /// let uppercase_g = ascii::Char::CapitalG;
1063    /// let a = ascii::Char::SmallA;
1064    /// let g = ascii::Char::SmallG;
1065    /// let zero = ascii::Char::Digit0;
1066    /// let percent = ascii::Char::PercentSign;
1067    /// let space = ascii::Char::Space;
1068    /// let lf = ascii::Char::LineFeed;
1069    /// let esc = ascii::Char::Escape;
1070    ///
1071    /// assert!(!uppercase_a.is_whitespace());
1072    /// assert!(!uppercase_g.is_whitespace());
1073    /// assert!(!a.is_whitespace());
1074    /// assert!(!g.is_whitespace());
1075    /// assert!(!zero.is_whitespace());
1076    /// assert!(!percent.is_whitespace());
1077    /// assert!(space.is_whitespace());
1078    /// assert!(lf.is_whitespace());
1079    /// assert!(!esc.is_whitespace());
1080    /// ```
1081    #[must_use]
1082    #[unstable(feature = "ascii_char", issue = "110998")]
1083    #[inline]
1084    pub const fn is_whitespace(self) -> bool {
1085        self.to_u8().is_ascii_whitespace()
1086    }
1087
1088    /// Checks if the value is a control character:
1089    /// 0x00 NUL ..= 0x1F UNIT SEPARATOR, or 0x7F DELETE.
1090    /// Note that most whitespace characters are control
1091    /// characters, but SPACE is not.
1092    ///
1093    /// # Examples
1094    ///
1095    /// ```
1096    /// #![feature(ascii_char, ascii_char_variants)]
1097    /// use std::ascii;
1098    ///
1099    /// let uppercase_a = ascii::Char::CapitalA;
1100    /// let uppercase_g = ascii::Char::CapitalG;
1101    /// let a = ascii::Char::SmallA;
1102    /// let g = ascii::Char::SmallG;
1103    /// let zero = ascii::Char::Digit0;
1104    /// let percent = ascii::Char::PercentSign;
1105    /// let space = ascii::Char::Space;
1106    /// let lf = ascii::Char::LineFeed;
1107    /// let esc = ascii::Char::Escape;
1108    ///
1109    /// assert!(!uppercase_a.is_control());
1110    /// assert!(!uppercase_g.is_control());
1111    /// assert!(!a.is_control());
1112    /// assert!(!g.is_control());
1113    /// assert!(!zero.is_control());
1114    /// assert!(!percent.is_control());
1115    /// assert!(!space.is_control());
1116    /// assert!(lf.is_control());
1117    /// assert!(esc.is_control());
1118    /// ```
1119    #[must_use]
1120    #[unstable(feature = "ascii_char", issue = "110998")]
1121    #[inline]
1122    pub const fn is_control(self) -> bool {
1123        self.to_u8().is_ascii_control()
1124    }
1125
1126    /// Returns an iterator that produces an escaped version of a
1127    /// character.
1128    ///
1129    /// The behavior is identical to
1130    /// [`ascii::escape_default`](crate::ascii::escape_default).
1131    ///
1132    /// # Examples
1133    ///
1134    /// ```
1135    /// #![feature(ascii_char, ascii_char_variants)]
1136    /// use std::ascii;
1137    ///
1138    /// let zero = ascii::Char::Digit0;
1139    /// let tab = ascii::Char::CharacterTabulation;
1140    /// let cr = ascii::Char::CarriageReturn;
1141    /// let lf = ascii::Char::LineFeed;
1142    /// let apostrophe = ascii::Char::Apostrophe;
1143    /// let double_quote = ascii::Char::QuotationMark;
1144    /// let backslash = ascii::Char::ReverseSolidus;
1145    ///
1146    /// assert_eq!("0", zero.escape_ascii().to_string());
1147    /// assert_eq!("\\t", tab.escape_ascii().to_string());
1148    /// assert_eq!("\\r", cr.escape_ascii().to_string());
1149    /// assert_eq!("\\n", lf.escape_ascii().to_string());
1150    /// assert_eq!("\\'", apostrophe.escape_ascii().to_string());
1151    /// assert_eq!("\\\"", double_quote.escape_ascii().to_string());
1152    /// assert_eq!("\\\\", backslash.escape_ascii().to_string());
1153    /// ```
1154    #[must_use = "this returns the escaped character as an iterator, \
1155                  without modifying the original"]
1156    #[unstable(feature = "ascii_char", issue = "110998")]
1157    #[inline]
1158    pub fn escape_ascii(self) -> super::EscapeDefault {
1159        super::escape_default(self.to_u8())
1160    }
1161}
1162
1163macro_rules! into_int_impl {
1164    ($($ty:ty)*) => {
1165        $(
1166            #[unstable(feature = "ascii_char", issue = "110998")]
1167            #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
1168            impl const From<AsciiChar> for $ty {
1169                #[inline]
1170                fn from(chr: AsciiChar) -> $ty {
1171                    chr as u8 as $ty
1172                }
1173            }
1174        )*
1175    }
1176}
1177
1178into_int_impl!(u8 u16 u32 u64 u128 char);
1179
1180impl [AsciiChar] {
1181    /// Views this slice of ASCII characters as a UTF-8 `str`.
1182    #[unstable(feature = "ascii_char", issue = "110998")]
1183    #[inline]
1184    pub const fn as_str(&self) -> &str {
1185        let ascii_ptr: *const Self = self;
1186        let str_ptr = ascii_ptr as *const str;
1187        // SAFETY: Each ASCII codepoint in UTF-8 is encoded as one single-byte
1188        // code unit having the same value as the ASCII byte.
1189        unsafe { &*str_ptr }
1190    }
1191
1192    /// Views this slice of ASCII characters as a slice of `u8` bytes.
1193    #[unstable(feature = "ascii_char", issue = "110998")]
1194    #[inline]
1195    pub const fn as_bytes(&self) -> &[u8] {
1196        self.as_str().as_bytes()
1197    }
1198}
1199
1200#[unstable(feature = "ascii_char", issue = "110998")]
1201impl fmt::Display for AsciiChar {
1202    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1203        <str as fmt::Display>::fmt(self.as_str(), f)
1204    }
1205}
1206
1207#[unstable(feature = "ascii_char", issue = "110998")]
1208impl fmt::Debug for AsciiChar {
1209    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1210        use AsciiChar::{Apostrophe, Null, ReverseSolidus as Backslash};
1211
1212        fn backslash(a: AsciiChar) -> ([AsciiChar; 6], usize) {
1213            ([Apostrophe, Backslash, a, Apostrophe, Null, Null], 4)
1214        }
1215
1216        let (buf, len) = match self {
1217            AsciiChar::Null => backslash(AsciiChar::Digit0),
1218            AsciiChar::CharacterTabulation => backslash(AsciiChar::SmallT),
1219            AsciiChar::CarriageReturn => backslash(AsciiChar::SmallR),
1220            AsciiChar::LineFeed => backslash(AsciiChar::SmallN),
1221            AsciiChar::ReverseSolidus => backslash(AsciiChar::ReverseSolidus),
1222            AsciiChar::Apostrophe => backslash(AsciiChar::Apostrophe),
1223            _ if self.to_u8().is_ascii_control() => {
1224                const HEX_DIGITS: [AsciiChar; 16] = *b"0123456789abcdef".as_ascii().unwrap();
1225
1226                let byte = self.to_u8();
1227                let hi = HEX_DIGITS[usize::from(byte >> 4)];
1228                let lo = HEX_DIGITS[usize::from(byte & 0xf)];
1229                ([Apostrophe, Backslash, AsciiChar::SmallX, hi, lo, Apostrophe], 6)
1230            }
1231            _ => ([Apostrophe, *self, Apostrophe, Null, Null, Null], 3),
1232        };
1233
1234        f.write_str(buf[..len].as_str())
1235    }
1236}