1use crate::mem::transmute;
7use crate::{assert_unsafe_precondition, fmt};
8
9#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
58#[unstable(feature = "ascii_char", issue = "110998")]
59#[repr(u8)]
60pub enum AsciiChar {
61    #[unstable(feature = "ascii_char_variants", issue = "110998")]
63    Null = 0,
64    #[unstable(feature = "ascii_char_variants", issue = "110998")]
66    StartOfHeading = 1,
67    #[unstable(feature = "ascii_char_variants", issue = "110998")]
69    StartOfText = 2,
70    #[unstable(feature = "ascii_char_variants", issue = "110998")]
72    EndOfText = 3,
73    #[unstable(feature = "ascii_char_variants", issue = "110998")]
75    EndOfTransmission = 4,
76    #[unstable(feature = "ascii_char_variants", issue = "110998")]
78    Enquiry = 5,
79    #[unstable(feature = "ascii_char_variants", issue = "110998")]
81    Acknowledge = 6,
82    #[unstable(feature = "ascii_char_variants", issue = "110998")]
84    Bell = 7,
85    #[unstable(feature = "ascii_char_variants", issue = "110998")]
87    Backspace = 8,
88    #[unstable(feature = "ascii_char_variants", issue = "110998")]
90    CharacterTabulation = 9,
91    #[unstable(feature = "ascii_char_variants", issue = "110998")]
93    LineFeed = 10,
94    #[unstable(feature = "ascii_char_variants", issue = "110998")]
96    LineTabulation = 11,
97    #[unstable(feature = "ascii_char_variants", issue = "110998")]
99    FormFeed = 12,
100    #[unstable(feature = "ascii_char_variants", issue = "110998")]
102    CarriageReturn = 13,
103    #[unstable(feature = "ascii_char_variants", issue = "110998")]
105    ShiftOut = 14,
106    #[unstable(feature = "ascii_char_variants", issue = "110998")]
108    ShiftIn = 15,
109    #[unstable(feature = "ascii_char_variants", issue = "110998")]
111    DataLinkEscape = 16,
112    #[unstable(feature = "ascii_char_variants", issue = "110998")]
114    DeviceControlOne = 17,
115    #[unstable(feature = "ascii_char_variants", issue = "110998")]
117    DeviceControlTwo = 18,
118    #[unstable(feature = "ascii_char_variants", issue = "110998")]
120    DeviceControlThree = 19,
121    #[unstable(feature = "ascii_char_variants", issue = "110998")]
123    DeviceControlFour = 20,
124    #[unstable(feature = "ascii_char_variants", issue = "110998")]
126    NegativeAcknowledge = 21,
127    #[unstable(feature = "ascii_char_variants", issue = "110998")]
129    SynchronousIdle = 22,
130    #[unstable(feature = "ascii_char_variants", issue = "110998")]
132    EndOfTransmissionBlock = 23,
133    #[unstable(feature = "ascii_char_variants", issue = "110998")]
135    Cancel = 24,
136    #[unstable(feature = "ascii_char_variants", issue = "110998")]
138    EndOfMedium = 25,
139    #[unstable(feature = "ascii_char_variants", issue = "110998")]
141    Substitute = 26,
142    #[unstable(feature = "ascii_char_variants", issue = "110998")]
144    Escape = 27,
145    #[unstable(feature = "ascii_char_variants", issue = "110998")]
147    InformationSeparatorFour = 28,
148    #[unstable(feature = "ascii_char_variants", issue = "110998")]
150    InformationSeparatorThree = 29,
151    #[unstable(feature = "ascii_char_variants", issue = "110998")]
153    InformationSeparatorTwo = 30,
154    #[unstable(feature = "ascii_char_variants", issue = "110998")]
156    InformationSeparatorOne = 31,
157    #[unstable(feature = "ascii_char_variants", issue = "110998")]
159    Space = 32,
160    #[unstable(feature = "ascii_char_variants", issue = "110998")]
162    ExclamationMark = 33,
163    #[unstable(feature = "ascii_char_variants", issue = "110998")]
165    QuotationMark = 34,
166    #[unstable(feature = "ascii_char_variants", issue = "110998")]
168    NumberSign = 35,
169    #[unstable(feature = "ascii_char_variants", issue = "110998")]
171    DollarSign = 36,
172    #[unstable(feature = "ascii_char_variants", issue = "110998")]
174    PercentSign = 37,
175    #[unstable(feature = "ascii_char_variants", issue = "110998")]
177    Ampersand = 38,
178    #[unstable(feature = "ascii_char_variants", issue = "110998")]
180    Apostrophe = 39,
181    #[unstable(feature = "ascii_char_variants", issue = "110998")]
183    LeftParenthesis = 40,
184    #[unstable(feature = "ascii_char_variants", issue = "110998")]
186    RightParenthesis = 41,
187    #[unstable(feature = "ascii_char_variants", issue = "110998")]
189    Asterisk = 42,
190    #[unstable(feature = "ascii_char_variants", issue = "110998")]
192    PlusSign = 43,
193    #[unstable(feature = "ascii_char_variants", issue = "110998")]
195    Comma = 44,
196    #[unstable(feature = "ascii_char_variants", issue = "110998")]
198    HyphenMinus = 45,
199    #[unstable(feature = "ascii_char_variants", issue = "110998")]
201    FullStop = 46,
202    #[unstable(feature = "ascii_char_variants", issue = "110998")]
204    Solidus = 47,
205    #[unstable(feature = "ascii_char_variants", issue = "110998")]
207    Digit0 = 48,
208    #[unstable(feature = "ascii_char_variants", issue = "110998")]
210    Digit1 = 49,
211    #[unstable(feature = "ascii_char_variants", issue = "110998")]
213    Digit2 = 50,
214    #[unstable(feature = "ascii_char_variants", issue = "110998")]
216    Digit3 = 51,
217    #[unstable(feature = "ascii_char_variants", issue = "110998")]
219    Digit4 = 52,
220    #[unstable(feature = "ascii_char_variants", issue = "110998")]
222    Digit5 = 53,
223    #[unstable(feature = "ascii_char_variants", issue = "110998")]
225    Digit6 = 54,
226    #[unstable(feature = "ascii_char_variants", issue = "110998")]
228    Digit7 = 55,
229    #[unstable(feature = "ascii_char_variants", issue = "110998")]
231    Digit8 = 56,
232    #[unstable(feature = "ascii_char_variants", issue = "110998")]
234    Digit9 = 57,
235    #[unstable(feature = "ascii_char_variants", issue = "110998")]
237    Colon = 58,
238    #[unstable(feature = "ascii_char_variants", issue = "110998")]
240    Semicolon = 59,
241    #[unstable(feature = "ascii_char_variants", issue = "110998")]
243    LessThanSign = 60,
244    #[unstable(feature = "ascii_char_variants", issue = "110998")]
246    EqualsSign = 61,
247    #[unstable(feature = "ascii_char_variants", issue = "110998")]
249    GreaterThanSign = 62,
250    #[unstable(feature = "ascii_char_variants", issue = "110998")]
252    QuestionMark = 63,
253    #[unstable(feature = "ascii_char_variants", issue = "110998")]
255    CommercialAt = 64,
256    #[unstable(feature = "ascii_char_variants", issue = "110998")]
258    CapitalA = 65,
259    #[unstable(feature = "ascii_char_variants", issue = "110998")]
261    CapitalB = 66,
262    #[unstable(feature = "ascii_char_variants", issue = "110998")]
264    CapitalC = 67,
265    #[unstable(feature = "ascii_char_variants", issue = "110998")]
267    CapitalD = 68,
268    #[unstable(feature = "ascii_char_variants", issue = "110998")]
270    CapitalE = 69,
271    #[unstable(feature = "ascii_char_variants", issue = "110998")]
273    CapitalF = 70,
274    #[unstable(feature = "ascii_char_variants", issue = "110998")]
276    CapitalG = 71,
277    #[unstable(feature = "ascii_char_variants", issue = "110998")]
279    CapitalH = 72,
280    #[unstable(feature = "ascii_char_variants", issue = "110998")]
282    CapitalI = 73,
283    #[unstable(feature = "ascii_char_variants", issue = "110998")]
285    CapitalJ = 74,
286    #[unstable(feature = "ascii_char_variants", issue = "110998")]
288    CapitalK = 75,
289    #[unstable(feature = "ascii_char_variants", issue = "110998")]
291    CapitalL = 76,
292    #[unstable(feature = "ascii_char_variants", issue = "110998")]
294    CapitalM = 77,
295    #[unstable(feature = "ascii_char_variants", issue = "110998")]
297    CapitalN = 78,
298    #[unstable(feature = "ascii_char_variants", issue = "110998")]
300    CapitalO = 79,
301    #[unstable(feature = "ascii_char_variants", issue = "110998")]
303    CapitalP = 80,
304    #[unstable(feature = "ascii_char_variants", issue = "110998")]
306    CapitalQ = 81,
307    #[unstable(feature = "ascii_char_variants", issue = "110998")]
309    CapitalR = 82,
310    #[unstable(feature = "ascii_char_variants", issue = "110998")]
312    CapitalS = 83,
313    #[unstable(feature = "ascii_char_variants", issue = "110998")]
315    CapitalT = 84,
316    #[unstable(feature = "ascii_char_variants", issue = "110998")]
318    CapitalU = 85,
319    #[unstable(feature = "ascii_char_variants", issue = "110998")]
321    CapitalV = 86,
322    #[unstable(feature = "ascii_char_variants", issue = "110998")]
324    CapitalW = 87,
325    #[unstable(feature = "ascii_char_variants", issue = "110998")]
327    CapitalX = 88,
328    #[unstable(feature = "ascii_char_variants", issue = "110998")]
330    CapitalY = 89,
331    #[unstable(feature = "ascii_char_variants", issue = "110998")]
333    CapitalZ = 90,
334    #[unstable(feature = "ascii_char_variants", issue = "110998")]
336    LeftSquareBracket = 91,
337    #[unstable(feature = "ascii_char_variants", issue = "110998")]
339    ReverseSolidus = 92,
340    #[unstable(feature = "ascii_char_variants", issue = "110998")]
342    RightSquareBracket = 93,
343    #[unstable(feature = "ascii_char_variants", issue = "110998")]
345    CircumflexAccent = 94,
346    #[unstable(feature = "ascii_char_variants", issue = "110998")]
348    LowLine = 95,
349    #[unstable(feature = "ascii_char_variants", issue = "110998")]
351    GraveAccent = 96,
352    #[unstable(feature = "ascii_char_variants", issue = "110998")]
354    SmallA = 97,
355    #[unstable(feature = "ascii_char_variants", issue = "110998")]
357    SmallB = 98,
358    #[unstable(feature = "ascii_char_variants", issue = "110998")]
360    SmallC = 99,
361    #[unstable(feature = "ascii_char_variants", issue = "110998")]
363    SmallD = 100,
364    #[unstable(feature = "ascii_char_variants", issue = "110998")]
366    SmallE = 101,
367    #[unstable(feature = "ascii_char_variants", issue = "110998")]
369    SmallF = 102,
370    #[unstable(feature = "ascii_char_variants", issue = "110998")]
372    SmallG = 103,
373    #[unstable(feature = "ascii_char_variants", issue = "110998")]
375    SmallH = 104,
376    #[unstable(feature = "ascii_char_variants", issue = "110998")]
378    SmallI = 105,
379    #[unstable(feature = "ascii_char_variants", issue = "110998")]
381    SmallJ = 106,
382    #[unstable(feature = "ascii_char_variants", issue = "110998")]
384    SmallK = 107,
385    #[unstable(feature = "ascii_char_variants", issue = "110998")]
387    SmallL = 108,
388    #[unstable(feature = "ascii_char_variants", issue = "110998")]
390    SmallM = 109,
391    #[unstable(feature = "ascii_char_variants", issue = "110998")]
393    SmallN = 110,
394    #[unstable(feature = "ascii_char_variants", issue = "110998")]
396    SmallO = 111,
397    #[unstable(feature = "ascii_char_variants", issue = "110998")]
399    SmallP = 112,
400    #[unstable(feature = "ascii_char_variants", issue = "110998")]
402    SmallQ = 113,
403    #[unstable(feature = "ascii_char_variants", issue = "110998")]
405    SmallR = 114,
406    #[unstable(feature = "ascii_char_variants", issue = "110998")]
408    SmallS = 115,
409    #[unstable(feature = "ascii_char_variants", issue = "110998")]
411    SmallT = 116,
412    #[unstable(feature = "ascii_char_variants", issue = "110998")]
414    SmallU = 117,
415    #[unstable(feature = "ascii_char_variants", issue = "110998")]
417    SmallV = 118,
418    #[unstable(feature = "ascii_char_variants", issue = "110998")]
420    SmallW = 119,
421    #[unstable(feature = "ascii_char_variants", issue = "110998")]
423    SmallX = 120,
424    #[unstable(feature = "ascii_char_variants", issue = "110998")]
426    SmallY = 121,
427    #[unstable(feature = "ascii_char_variants", issue = "110998")]
429    SmallZ = 122,
430    #[unstable(feature = "ascii_char_variants", issue = "110998")]
432    LeftCurlyBracket = 123,
433    #[unstable(feature = "ascii_char_variants", issue = "110998")]
435    VerticalLine = 124,
436    #[unstable(feature = "ascii_char_variants", issue = "110998")]
438    RightCurlyBracket = 125,
439    #[unstable(feature = "ascii_char_variants", issue = "110998")]
441    Tilde = 126,
442    #[unstable(feature = "ascii_char_variants", issue = "110998")]
444    Delete = 127,
445}
446
447impl AsciiChar {
448    #[unstable(feature = "ascii_char", issue = "110998")]
451    #[inline]
452    pub const fn from_u8(b: u8) -> Option<Self> {
453        if b <= 127 {
454            Some(unsafe { Self::from_u8_unchecked(b) })
456        } else {
457            None
458        }
459    }
460
461    #[unstable(feature = "ascii_char", issue = "110998")]
468    #[inline]
469    pub const unsafe fn from_u8_unchecked(b: u8) -> Self {
470        unsafe { transmute(b) }
472    }
473
474    #[unstable(feature = "ascii_char", issue = "110998")]
479    #[inline]
480    pub const fn digit(d: u8) -> Option<Self> {
481        if d < 10 {
482            Some(unsafe { Self::digit_unchecked(d) })
484        } else {
485            None
486        }
487    }
488
489    #[unstable(feature = "ascii_char", issue = "110998")]
505    #[inline]
506    pub const unsafe fn digit_unchecked(d: u8) -> Self {
507        assert_unsafe_precondition!(
508            check_language_ub,
509            "`ascii::Char::digit_unchecked` input cannot exceed 9.",
510            (d: u8 = d) => d < 10
511        );
512
513        unsafe {
517            let byte = b'0'.unchecked_add(d);
518            Self::from_u8_unchecked(byte)
519        }
520    }
521
522    #[unstable(feature = "ascii_char", issue = "110998")]
524    #[inline]
525    pub const fn to_u8(self) -> u8 {
526        self as u8
527    }
528
529    #[unstable(feature = "ascii_char", issue = "110998")]
531    #[inline]
532    pub const fn to_char(self) -> char {
533        self as u8 as char
534    }
535
536    #[unstable(feature = "ascii_char", issue = "110998")]
538    #[inline]
539    pub const fn as_str(&self) -> &str {
540        crate::slice::from_ref(self).as_str()
541    }
542}
543
544macro_rules! into_int_impl {
545    ($($ty:ty)*) => {
546        $(
547            #[unstable(feature = "ascii_char", issue = "110998")]
548            impl From<AsciiChar> for $ty {
549                #[inline]
550                fn from(chr: AsciiChar) -> $ty {
551                    chr as u8 as $ty
552                }
553            }
554        )*
555    }
556}
557
558into_int_impl!(u8 u16 u32 u64 u128 char);
559
560impl [AsciiChar] {
561    #[unstable(feature = "ascii_char", issue = "110998")]
563    #[inline]
564    pub const fn as_str(&self) -> &str {
565        let ascii_ptr: *const Self = self;
566        let str_ptr = ascii_ptr as *const str;
567        unsafe { &*str_ptr }
570    }
571
572    #[unstable(feature = "ascii_char", issue = "110998")]
574    #[inline]
575    pub const fn as_bytes(&self) -> &[u8] {
576        self.as_str().as_bytes()
577    }
578}
579
580#[unstable(feature = "ascii_char", issue = "110998")]
581impl fmt::Display for AsciiChar {
582    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
583        <str as fmt::Display>::fmt(self.as_str(), f)
584    }
585}
586
587#[unstable(feature = "ascii_char", issue = "110998")]
588impl fmt::Debug for AsciiChar {
589    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
590        use AsciiChar::{Apostrophe, Null, ReverseSolidus as Backslash};
591
592        fn backslash(a: AsciiChar) -> ([AsciiChar; 6], usize) {
593            ([Apostrophe, Backslash, a, Apostrophe, Null, Null], 4)
594        }
595
596        let (buf, len) = match self {
597            AsciiChar::Null => backslash(AsciiChar::Digit0),
598            AsciiChar::CharacterTabulation => backslash(AsciiChar::SmallT),
599            AsciiChar::CarriageReturn => backslash(AsciiChar::SmallR),
600            AsciiChar::LineFeed => backslash(AsciiChar::SmallN),
601            AsciiChar::ReverseSolidus => backslash(AsciiChar::ReverseSolidus),
602            AsciiChar::Apostrophe => backslash(AsciiChar::Apostrophe),
603            _ if self.to_u8().is_ascii_control() => {
604                const HEX_DIGITS: [AsciiChar; 16] = *b"0123456789abcdef".as_ascii().unwrap();
605
606                let byte = self.to_u8();
607                let hi = HEX_DIGITS[usize::from(byte >> 4)];
608                let lo = HEX_DIGITS[usize::from(byte & 0xf)];
609                ([Apostrophe, Backslash, AsciiChar::SmallX, hi, lo, Apostrophe], 6)
610            }
611            _ => ([Apostrophe, *self, Apostrophe, Null, Null, Null], 3),
612        };
613
614        f.write_str(buf[..len].as_str())
615    }
616}