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, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
58#[unstable(feature = "ascii_char", issue = "110998")]
59#[repr(u8)]
60pub enum AsciiChar {
61    /// U+0000 (The default variant)
62    #[unstable(feature = "ascii_char_variants", issue = "110998")]
63    Null = 0,
64    /// U+0001
65    #[unstable(feature = "ascii_char_variants", issue = "110998")]
66    StartOfHeading = 1,
67    /// U+0002
68    #[unstable(feature = "ascii_char_variants", issue = "110998")]
69    StartOfText = 2,
70    /// U+0003
71    #[unstable(feature = "ascii_char_variants", issue = "110998")]
72    EndOfText = 3,
73    /// U+0004
74    #[unstable(feature = "ascii_char_variants", issue = "110998")]
75    EndOfTransmission = 4,
76    /// U+0005
77    #[unstable(feature = "ascii_char_variants", issue = "110998")]
78    Enquiry = 5,
79    /// U+0006
80    #[unstable(feature = "ascii_char_variants", issue = "110998")]
81    Acknowledge = 6,
82    /// U+0007
83    #[unstable(feature = "ascii_char_variants", issue = "110998")]
84    Bell = 7,
85    /// U+0008
86    #[unstable(feature = "ascii_char_variants", issue = "110998")]
87    Backspace = 8,
88    /// U+0009
89    #[unstable(feature = "ascii_char_variants", issue = "110998")]
90    CharacterTabulation = 9,
91    /// U+000A
92    #[unstable(feature = "ascii_char_variants", issue = "110998")]
93    LineFeed = 10,
94    /// U+000B
95    #[unstable(feature = "ascii_char_variants", issue = "110998")]
96    LineTabulation = 11,
97    /// U+000C
98    #[unstable(feature = "ascii_char_variants", issue = "110998")]
99    FormFeed = 12,
100    /// U+000D
101    #[unstable(feature = "ascii_char_variants", issue = "110998")]
102    CarriageReturn = 13,
103    /// U+000E
104    #[unstable(feature = "ascii_char_variants", issue = "110998")]
105    ShiftOut = 14,
106    /// U+000F
107    #[unstable(feature = "ascii_char_variants", issue = "110998")]
108    ShiftIn = 15,
109    /// U+0010
110    #[unstable(feature = "ascii_char_variants", issue = "110998")]
111    DataLinkEscape = 16,
112    /// U+0011
113    #[unstable(feature = "ascii_char_variants", issue = "110998")]
114    DeviceControlOne = 17,
115    /// U+0012
116    #[unstable(feature = "ascii_char_variants", issue = "110998")]
117    DeviceControlTwo = 18,
118    /// U+0013
119    #[unstable(feature = "ascii_char_variants", issue = "110998")]
120    DeviceControlThree = 19,
121    /// U+0014
122    #[unstable(feature = "ascii_char_variants", issue = "110998")]
123    DeviceControlFour = 20,
124    /// U+0015
125    #[unstable(feature = "ascii_char_variants", issue = "110998")]
126    NegativeAcknowledge = 21,
127    /// U+0016
128    #[unstable(feature = "ascii_char_variants", issue = "110998")]
129    SynchronousIdle = 22,
130    /// U+0017
131    #[unstable(feature = "ascii_char_variants", issue = "110998")]
132    EndOfTransmissionBlock = 23,
133    /// U+0018
134    #[unstable(feature = "ascii_char_variants", issue = "110998")]
135    Cancel = 24,
136    /// U+0019
137    #[unstable(feature = "ascii_char_variants", issue = "110998")]
138    EndOfMedium = 25,
139    /// U+001A
140    #[unstable(feature = "ascii_char_variants", issue = "110998")]
141    Substitute = 26,
142    /// U+001B
143    #[unstable(feature = "ascii_char_variants", issue = "110998")]
144    Escape = 27,
145    /// U+001C
146    #[unstable(feature = "ascii_char_variants", issue = "110998")]
147    InformationSeparatorFour = 28,
148    /// U+001D
149    #[unstable(feature = "ascii_char_variants", issue = "110998")]
150    InformationSeparatorThree = 29,
151    /// U+001E
152    #[unstable(feature = "ascii_char_variants", issue = "110998")]
153    InformationSeparatorTwo = 30,
154    /// U+001F
155    #[unstable(feature = "ascii_char_variants", issue = "110998")]
156    InformationSeparatorOne = 31,
157    /// U+0020
158    #[unstable(feature = "ascii_char_variants", issue = "110998")]
159    Space = 32,
160    /// U+0021
161    #[unstable(feature = "ascii_char_variants", issue = "110998")]
162    ExclamationMark = 33,
163    /// U+0022
164    #[unstable(feature = "ascii_char_variants", issue = "110998")]
165    QuotationMark = 34,
166    /// U+0023
167    #[unstable(feature = "ascii_char_variants", issue = "110998")]
168    NumberSign = 35,
169    /// U+0024
170    #[unstable(feature = "ascii_char_variants", issue = "110998")]
171    DollarSign = 36,
172    /// U+0025
173    #[unstable(feature = "ascii_char_variants", issue = "110998")]
174    PercentSign = 37,
175    /// U+0026
176    #[unstable(feature = "ascii_char_variants", issue = "110998")]
177    Ampersand = 38,
178    /// U+0027
179    #[unstable(feature = "ascii_char_variants", issue = "110998")]
180    Apostrophe = 39,
181    /// U+0028
182    #[unstable(feature = "ascii_char_variants", issue = "110998")]
183    LeftParenthesis = 40,
184    /// U+0029
185    #[unstable(feature = "ascii_char_variants", issue = "110998")]
186    RightParenthesis = 41,
187    /// U+002A
188    #[unstable(feature = "ascii_char_variants", issue = "110998")]
189    Asterisk = 42,
190    /// U+002B
191    #[unstable(feature = "ascii_char_variants", issue = "110998")]
192    PlusSign = 43,
193    /// U+002C
194    #[unstable(feature = "ascii_char_variants", issue = "110998")]
195    Comma = 44,
196    /// U+002D
197    #[unstable(feature = "ascii_char_variants", issue = "110998")]
198    HyphenMinus = 45,
199    /// U+002E
200    #[unstable(feature = "ascii_char_variants", issue = "110998")]
201    FullStop = 46,
202    /// U+002F
203    #[unstable(feature = "ascii_char_variants", issue = "110998")]
204    Solidus = 47,
205    /// U+0030
206    #[unstable(feature = "ascii_char_variants", issue = "110998")]
207    Digit0 = 48,
208    /// U+0031
209    #[unstable(feature = "ascii_char_variants", issue = "110998")]
210    Digit1 = 49,
211    /// U+0032
212    #[unstable(feature = "ascii_char_variants", issue = "110998")]
213    Digit2 = 50,
214    /// U+0033
215    #[unstable(feature = "ascii_char_variants", issue = "110998")]
216    Digit3 = 51,
217    /// U+0034
218    #[unstable(feature = "ascii_char_variants", issue = "110998")]
219    Digit4 = 52,
220    /// U+0035
221    #[unstable(feature = "ascii_char_variants", issue = "110998")]
222    Digit5 = 53,
223    /// U+0036
224    #[unstable(feature = "ascii_char_variants", issue = "110998")]
225    Digit6 = 54,
226    /// U+0037
227    #[unstable(feature = "ascii_char_variants", issue = "110998")]
228    Digit7 = 55,
229    /// U+0038
230    #[unstable(feature = "ascii_char_variants", issue = "110998")]
231    Digit8 = 56,
232    /// U+0039
233    #[unstable(feature = "ascii_char_variants", issue = "110998")]
234    Digit9 = 57,
235    /// U+003A
236    #[unstable(feature = "ascii_char_variants", issue = "110998")]
237    Colon = 58,
238    /// U+003B
239    #[unstable(feature = "ascii_char_variants", issue = "110998")]
240    Semicolon = 59,
241    /// U+003C
242    #[unstable(feature = "ascii_char_variants", issue = "110998")]
243    LessThanSign = 60,
244    /// U+003D
245    #[unstable(feature = "ascii_char_variants", issue = "110998")]
246    EqualsSign = 61,
247    /// U+003E
248    #[unstable(feature = "ascii_char_variants", issue = "110998")]
249    GreaterThanSign = 62,
250    /// U+003F
251    #[unstable(feature = "ascii_char_variants", issue = "110998")]
252    QuestionMark = 63,
253    /// U+0040
254    #[unstable(feature = "ascii_char_variants", issue = "110998")]
255    CommercialAt = 64,
256    /// U+0041
257    #[unstable(feature = "ascii_char_variants", issue = "110998")]
258    CapitalA = 65,
259    /// U+0042
260    #[unstable(feature = "ascii_char_variants", issue = "110998")]
261    CapitalB = 66,
262    /// U+0043
263    #[unstable(feature = "ascii_char_variants", issue = "110998")]
264    CapitalC = 67,
265    /// U+0044
266    #[unstable(feature = "ascii_char_variants", issue = "110998")]
267    CapitalD = 68,
268    /// U+0045
269    #[unstable(feature = "ascii_char_variants", issue = "110998")]
270    CapitalE = 69,
271    /// U+0046
272    #[unstable(feature = "ascii_char_variants", issue = "110998")]
273    CapitalF = 70,
274    /// U+0047
275    #[unstable(feature = "ascii_char_variants", issue = "110998")]
276    CapitalG = 71,
277    /// U+0048
278    #[unstable(feature = "ascii_char_variants", issue = "110998")]
279    CapitalH = 72,
280    /// U+0049
281    #[unstable(feature = "ascii_char_variants", issue = "110998")]
282    CapitalI = 73,
283    /// U+004A
284    #[unstable(feature = "ascii_char_variants", issue = "110998")]
285    CapitalJ = 74,
286    /// U+004B
287    #[unstable(feature = "ascii_char_variants", issue = "110998")]
288    CapitalK = 75,
289    /// U+004C
290    #[unstable(feature = "ascii_char_variants", issue = "110998")]
291    CapitalL = 76,
292    /// U+004D
293    #[unstable(feature = "ascii_char_variants", issue = "110998")]
294    CapitalM = 77,
295    /// U+004E
296    #[unstable(feature = "ascii_char_variants", issue = "110998")]
297    CapitalN = 78,
298    /// U+004F
299    #[unstable(feature = "ascii_char_variants", issue = "110998")]
300    CapitalO = 79,
301    /// U+0050
302    #[unstable(feature = "ascii_char_variants", issue = "110998")]
303    CapitalP = 80,
304    /// U+0051
305    #[unstable(feature = "ascii_char_variants", issue = "110998")]
306    CapitalQ = 81,
307    /// U+0052
308    #[unstable(feature = "ascii_char_variants", issue = "110998")]
309    CapitalR = 82,
310    /// U+0053
311    #[unstable(feature = "ascii_char_variants", issue = "110998")]
312    CapitalS = 83,
313    /// U+0054
314    #[unstable(feature = "ascii_char_variants", issue = "110998")]
315    CapitalT = 84,
316    /// U+0055
317    #[unstable(feature = "ascii_char_variants", issue = "110998")]
318    CapitalU = 85,
319    /// U+0056
320    #[unstable(feature = "ascii_char_variants", issue = "110998")]
321    CapitalV = 86,
322    /// U+0057
323    #[unstable(feature = "ascii_char_variants", issue = "110998")]
324    CapitalW = 87,
325    /// U+0058
326    #[unstable(feature = "ascii_char_variants", issue = "110998")]
327    CapitalX = 88,
328    /// U+0059
329    #[unstable(feature = "ascii_char_variants", issue = "110998")]
330    CapitalY = 89,
331    /// U+005A
332    #[unstable(feature = "ascii_char_variants", issue = "110998")]
333    CapitalZ = 90,
334    /// U+005B
335    #[unstable(feature = "ascii_char_variants", issue = "110998")]
336    LeftSquareBracket = 91,
337    /// U+005C
338    #[unstable(feature = "ascii_char_variants", issue = "110998")]
339    ReverseSolidus = 92,
340    /// U+005D
341    #[unstable(feature = "ascii_char_variants", issue = "110998")]
342    RightSquareBracket = 93,
343    /// U+005E
344    #[unstable(feature = "ascii_char_variants", issue = "110998")]
345    CircumflexAccent = 94,
346    /// U+005F
347    #[unstable(feature = "ascii_char_variants", issue = "110998")]
348    LowLine = 95,
349    /// U+0060
350    #[unstable(feature = "ascii_char_variants", issue = "110998")]
351    GraveAccent = 96,
352    /// U+0061
353    #[unstable(feature = "ascii_char_variants", issue = "110998")]
354    SmallA = 97,
355    /// U+0062
356    #[unstable(feature = "ascii_char_variants", issue = "110998")]
357    SmallB = 98,
358    /// U+0063
359    #[unstable(feature = "ascii_char_variants", issue = "110998")]
360    SmallC = 99,
361    /// U+0064
362    #[unstable(feature = "ascii_char_variants", issue = "110998")]
363    SmallD = 100,
364    /// U+0065
365    #[unstable(feature = "ascii_char_variants", issue = "110998")]
366    SmallE = 101,
367    /// U+0066
368    #[unstable(feature = "ascii_char_variants", issue = "110998")]
369    SmallF = 102,
370    /// U+0067
371    #[unstable(feature = "ascii_char_variants", issue = "110998")]
372    SmallG = 103,
373    /// U+0068
374    #[unstable(feature = "ascii_char_variants", issue = "110998")]
375    SmallH = 104,
376    /// U+0069
377    #[unstable(feature = "ascii_char_variants", issue = "110998")]
378    SmallI = 105,
379    /// U+006A
380    #[unstable(feature = "ascii_char_variants", issue = "110998")]
381    SmallJ = 106,
382    /// U+006B
383    #[unstable(feature = "ascii_char_variants", issue = "110998")]
384    SmallK = 107,
385    /// U+006C
386    #[unstable(feature = "ascii_char_variants", issue = "110998")]
387    SmallL = 108,
388    /// U+006D
389    #[unstable(feature = "ascii_char_variants", issue = "110998")]
390    SmallM = 109,
391    /// U+006E
392    #[unstable(feature = "ascii_char_variants", issue = "110998")]
393    SmallN = 110,
394    /// U+006F
395    #[unstable(feature = "ascii_char_variants", issue = "110998")]
396    SmallO = 111,
397    /// U+0070
398    #[unstable(feature = "ascii_char_variants", issue = "110998")]
399    SmallP = 112,
400    /// U+0071
401    #[unstable(feature = "ascii_char_variants", issue = "110998")]
402    SmallQ = 113,
403    /// U+0072
404    #[unstable(feature = "ascii_char_variants", issue = "110998")]
405    SmallR = 114,
406    /// U+0073
407    #[unstable(feature = "ascii_char_variants", issue = "110998")]
408    SmallS = 115,
409    /// U+0074
410    #[unstable(feature = "ascii_char_variants", issue = "110998")]
411    SmallT = 116,
412    /// U+0075
413    #[unstable(feature = "ascii_char_variants", issue = "110998")]
414    SmallU = 117,
415    /// U+0076
416    #[unstable(feature = "ascii_char_variants", issue = "110998")]
417    SmallV = 118,
418    /// U+0077
419    #[unstable(feature = "ascii_char_variants", issue = "110998")]
420    SmallW = 119,
421    /// U+0078
422    #[unstable(feature = "ascii_char_variants", issue = "110998")]
423    SmallX = 120,
424    /// U+0079
425    #[unstable(feature = "ascii_char_variants", issue = "110998")]
426    SmallY = 121,
427    /// U+007A
428    #[unstable(feature = "ascii_char_variants", issue = "110998")]
429    SmallZ = 122,
430    /// U+007B
431    #[unstable(feature = "ascii_char_variants", issue = "110998")]
432    LeftCurlyBracket = 123,
433    /// U+007C
434    #[unstable(feature = "ascii_char_variants", issue = "110998")]
435    VerticalLine = 124,
436    /// U+007D
437    #[unstable(feature = "ascii_char_variants", issue = "110998")]
438    RightCurlyBracket = 125,
439    /// U+007E
440    #[unstable(feature = "ascii_char_variants", issue = "110998")]
441    Tilde = 126,
442    /// U+007F
443    #[unstable(feature = "ascii_char_variants", issue = "110998")]
444    Delete = 127,
445}
446
447impl AsciiChar {
448    /// Creates an ascii character from the byte `b`,
449    /// or returns `None` if it's too large.
450    #[unstable(feature = "ascii_char", issue = "110998")]
451    #[inline]
452    pub const fn from_u8(b: u8) -> Option<Self> {
453        if b <= 127 {
454            // SAFETY: Just checked that `b` is in-range
455            Some(unsafe { Self::from_u8_unchecked(b) })
456        } else {
457            None
458        }
459    }
460
461    /// Creates an ASCII character from the byte `b`,
462    /// without checking whether it's valid.
463    ///
464    /// # Safety
465    ///
466    /// `b` must be in `0..=127`, or else this is UB.
467    #[unstable(feature = "ascii_char", issue = "110998")]
468    #[inline]
469    pub const unsafe fn from_u8_unchecked(b: u8) -> Self {
470        // SAFETY: Our safety precondition is that `b` is in-range.
471        unsafe { transmute(b) }
472    }
473
474    /// When passed the *number* `0`, `1`, …, `9`, returns the *character*
475    /// `'0'`, `'1'`, …, `'9'` respectively.
476    ///
477    /// If `d >= 10`, returns `None`.
478    #[unstable(feature = "ascii_char", issue = "110998")]
479    #[inline]
480    pub const fn digit(d: u8) -> Option<Self> {
481        if d < 10 {
482            // SAFETY: Just checked it's in-range.
483            Some(unsafe { Self::digit_unchecked(d) })
484        } else {
485            None
486        }
487    }
488
489    /// When passed the *number* `0`, `1`, …, `9`, returns the *character*
490    /// `'0'`, `'1'`, …, `'9'` respectively, without checking that it's in-range.
491    ///
492    /// # Safety
493    ///
494    /// This is immediate UB if called with `d > 64`.
495    ///
496    /// If `d >= 10` and `d <= 64`, this is allowed to return any value or panic.
497    /// Notably, it should not be expected to return hex digits, or any other
498    /// reasonable extension of the decimal digits.
499    ///
500    /// (This loose safety condition is intended to simplify soundness proofs
501    /// when writing code using this method, since the implementation doesn't
502    /// need something really specific, not to make those other arguments do
503    /// something useful. It might be tightened before stabilization.)
504    #[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        // SAFETY: `'0'` through `'9'` are U+00030 through U+0039,
514        // so because `d` must be 64 or less the addition can return at most
515        // 112 (0x70), which doesn't overflow and is within the ASCII range.
516        unsafe {
517            let byte = b'0'.unchecked_add(d);
518            Self::from_u8_unchecked(byte)
519        }
520    }
521
522    /// Gets this ASCII character as a byte.
523    #[unstable(feature = "ascii_char", issue = "110998")]
524    #[inline]
525    pub const fn to_u8(self) -> u8 {
526        self as u8
527    }
528
529    /// Gets this ASCII character as a `char` Unicode Scalar Value.
530    #[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    /// Views this ASCII character as a one-code-unit UTF-8 `str`.
537    #[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    /// Views this slice of ASCII characters as a UTF-8 `str`.
562    #[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        // SAFETY: Each ASCII codepoint in UTF-8 is encoded as one single-byte
568        // code unit having the same value as the ASCII byte.
569        unsafe { &*str_ptr }
570    }
571
572    /// Views this slice of ASCII characters as a slice of `u8` bytes.
573    #[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}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy