Rollup merge of #115434 - soqb:ascii-char-manual-debug, r=dtolnay

make `Debug` impl for `ascii::Char` match that of `char`

# Objective
use a more recognisable format for the `Debug` impl on `ascii::Char` than the derived one based off the enum variants. The alogorithm used is the following:
 - escape `ascii::Char::{Null, CharacterTabulation, CarraigeReturn, LineFeed, ReverseSolidus, Apostrophe}` to `'\0'`, `'\t'`, `'\r'`, `'\n'`, `'\\'` and `'\''` respectively. these are the same escape codes as `<char as Debug>::fmt` uses.
 - if `u8::is_ascii_control` is false, print the character wrapped in single quotes.
 - otherwise, print in the format `'\xAB'` where `A` and `B` are the hex nibbles of the byte. (`char` uses unicode escapes and this seems like the corresponding ascii format).

Tracking issue: https://github.com/rust-lang/rust/issues/110998
This commit is contained in:
Dylan DPC 2023-09-17 11:23:24 +00:00 committed by GitHub
commit 584eb696df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3,7 +3,7 @@
//! suggestions from rustc if you get anything slightly wrong in here, and overall
//! helps with clarity as we're also referring to `char` intentionally in here.
use crate::fmt;
use crate::fmt::{self, Write};
use crate::mem::transmute;
/// One of the 128 Unicode characters from U+0000 through U+007F,
@ -54,7 +54,7 @@
/// [chart]: https://www.unicode.org/charts/PDF/U0000.pdf
/// [NIST FIPS 1-2]: https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub1-2-1977.pdf
/// [NamesList]: https://www.unicode.org/Public/15.0.0/ucd/NamesList.txt
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[unstable(feature = "ascii_char", issue = "110998")]
#[repr(u8)]
pub enum AsciiChar {
@ -563,3 +563,40 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<str as fmt::Display>::fmt(self.as_str(), f)
}
}
#[unstable(feature = "ascii_char", issue = "110998")]
impl fmt::Debug for AsciiChar {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[inline]
fn backslash(a: AsciiChar) -> ([AsciiChar; 4], u8) {
([AsciiChar::ReverseSolidus, a, AsciiChar::Null, AsciiChar::Null], 2)
}
let (buf, len) = match self {
AsciiChar::Null => backslash(AsciiChar::Digit0),
AsciiChar::CharacterTabulation => backslash(AsciiChar::SmallT),
AsciiChar::CarriageReturn => backslash(AsciiChar::SmallR),
AsciiChar::LineFeed => backslash(AsciiChar::SmallN),
AsciiChar::ReverseSolidus => backslash(AsciiChar::ReverseSolidus),
AsciiChar::Apostrophe => backslash(AsciiChar::Apostrophe),
_ => {
let byte = self.to_u8();
if !byte.is_ascii_control() {
([*self, AsciiChar::Null, AsciiChar::Null, AsciiChar::Null], 1)
} else {
const HEX_DIGITS: [AsciiChar; 16] = *b"0123456789abcdef".as_ascii().unwrap();
let hi = HEX_DIGITS[usize::from(byte >> 4)];
let lo = HEX_DIGITS[usize::from(byte & 0xf)];
([AsciiChar::ReverseSolidus, AsciiChar::SmallX, hi, lo], 4)
}
}
};
f.write_char('\'')?;
for byte in &buf[..len as usize] {
f.write_str(byte.as_str())?;
}
f.write_char('\'')
}
}