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}