Improve escape methods. · rust-lang/rust@4edf12d

@@ -7,21 +7,21 @@ use crate::ops::Range;

77

const HEX_DIGITS: [ascii::Char; 16] = *b"0123456789abcdef".as_ascii().unwrap();

8899

#[inline]

10-

const fn backslash<const N: usize>(a: ascii::Char) -> ([ascii::Char; N], u8) {

10+

const fn backslash<const N: usize>(a: ascii::Char) -> ([ascii::Char; N], Range<u8>) {

1111

const { assert!(N >= 2) };

12121313

let mut output = [ascii::Char::Null; N];

14141515

output[0] = ascii::Char::ReverseSolidus;

1616

output[1] = a;

171718-

(output, 2)

18+

(output, 0..2)

1919

}

20202121

/// Escapes an ASCII character.

2222

///

2323

/// Returns a buffer and the length of the escaped representation.

24-

const fn escape_ascii<const N: usize>(byte: u8) -> ([ascii::Char; N], u8) {

24+

const fn escape_ascii<const N: usize>(byte: u8) -> ([ascii::Char; N], Range<u8>) {

2525

const { assert!(N >= 4) };

26262727

match byte {

@@ -38,7 +38,7 @@ const fn escape_ascii<const N: usize>(byte: u8) -> ([ascii::Char; N], u8) {

3838

&& !byte.is_ascii_control()

3939

{

4040

output[0] = c;

41-

(output, 1)

41+

(output, 0..1)

4242

} else {

4343

let hi = HEX_DIGITS[(byte >> 4) as usize];

4444

let lo = HEX_DIGITS[(byte & 0xf) as usize];

@@ -48,7 +48,7 @@ const fn escape_ascii<const N: usize>(byte: u8) -> ([ascii::Char; N], u8) {

4848

output[2] = hi;

4949

output[3] = lo;

505051-

(output, 4)

51+

(output, 0..4)

5252

}

5353

}

5454

}

@@ -57,34 +57,28 @@ const fn escape_ascii<const N: usize>(byte: u8) -> ([ascii::Char; N], u8) {

5757

/// Escapes a character `\u{NNNN}` representation.

5858

///

5959

/// Returns a buffer and the length of the escaped representation.

60-

const fn escape_unicode<const N: usize>(c: char) -> ([ascii::Char; N], u8) {

61-

const { assert!(N >= 10) };

60+

const fn escape_unicode<const N: usize>(c: char) -> ([ascii::Char; N], Range<u8>) {

61+

const { assert!(N >= 10 && N < u8::MAX as usize) };

626263-

let c = c as u32;

63+

let c = u32::from(c);

64646565

// OR-ing `1` ensures that for `c == 0` the code computes that

6666

// one digit should be printed.

67-

let u_len = (8 - (c | 1).leading_zeros() / 4) as usize;

68-69-

let closing_paren_offset = 3 + u_len;

67+

let start = (c | 1).leading_zeros() as usize / 4 - 2;

70687169

let mut output = [ascii::Char::Null; N];

72-73-

output[0] = ascii::Char::ReverseSolidus;

74-

output[1] = ascii::Char::SmallU;

75-

output[2] = ascii::Char::LeftCurlyBracket;

76-77-

output[3 + u_len.saturating_sub(6)] = HEX_DIGITS[((c >> 20) & 0x0f) as usize];

78-

output[3 + u_len.saturating_sub(5)] = HEX_DIGITS[((c >> 16) & 0x0f) as usize];

79-

output[3 + u_len.saturating_sub(4)] = HEX_DIGITS[((c >> 12) & 0x0f) as usize];

80-

output[3 + u_len.saturating_sub(3)] = HEX_DIGITS[((c >> 8) & 0x0f) as usize];

81-

output[3 + u_len.saturating_sub(2)] = HEX_DIGITS[((c >> 4) & 0x0f) as usize];

82-

output[3 + u_len.saturating_sub(1)] = HEX_DIGITS[((c >> 0) & 0x0f) as usize];

83-84-

output[closing_paren_offset] = ascii::Char::RightCurlyBracket;

85-86-

let len = (closing_paren_offset + 1) as u8;

87-

(output, len)

70+

output[3] = HEX_DIGITS[((c >> 20) & 15) as usize];

71+

output[4] = HEX_DIGITS[((c >> 16) & 15) as usize];

72+

output[5] = HEX_DIGITS[((c >> 12) & 15) as usize];

73+

output[6] = HEX_DIGITS[((c >> 8) & 15) as usize];

74+

output[7] = HEX_DIGITS[((c >> 4) & 15) as usize];

75+

output[8] = HEX_DIGITS[((c >> 0) & 15) as usize];

76+

output[9] = ascii::Char::RightCurlyBracket;

77+

output[start + 0] = ascii::Char::ReverseSolidus;

78+

output[start + 1] = ascii::Char::SmallU;

79+

output[start + 2] = ascii::Char::LeftCurlyBracket;

80+81+

(output, (start as u8)..(N as u8))

8882

}

89839084

/// An iterator over an fixed-size array.

@@ -102,25 +96,26 @@ pub(crate) struct EscapeIterInner<const N: usize> {

1029610397

impl<const N: usize> EscapeIterInner<N> {

10498

pub const fn backslash(c: ascii::Char) -> Self {

105-

let (data, len) = backslash(c);

106-

Self { data, alive: 0..len }

99+

let (data, range) = backslash(c);

100+

Self { data, alive: range }

107101

}

108102109103

pub const fn ascii(c: u8) -> Self {

110-

let (data, len) = escape_ascii(c);

111-

Self { data, alive: 0..len }

104+

let (data, range) = escape_ascii(c);

105+

Self { data, alive: range }

112106

}

113107114108

pub const fn unicode(c: char) -> Self {

115-

let (data, len) = escape_unicode(c);

116-

Self { data, alive: 0..len }

109+

let (data, range) = escape_unicode(c);

110+

Self { data, alive: range }

117111

}

118112119113

#[inline]

120114

pub const fn empty() -> Self {

121115

Self { data: [ascii::Char::Null; N], alive: 0..0 }

122116

}

123117118+

#[inline]

124119

pub fn as_ascii(&self) -> &[ascii::Char] {

125120

// SAFETY: `self.alive` is guaranteed to be a valid range for indexing `self.data`.

126121

unsafe {