Auto merge of #125144 - fmease:rollup-4uft293, r=fmease · rust-lang/rust@ade234d (original) (raw)

`@@ -6,56 +6,79 @@ use crate::ops::Range;

`

6

6

``

7

7

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

`

8

8

``

9

``

`-

/// Escapes a byte into provided buffer; returns length of escaped

`

10

``

`-

/// representation.

`

11

``

`-

pub(crate) fn escape_ascii_into(output: &mut [ascii::Char; 4], byte: u8) -> Range {

`

12

``

`-

#[inline]

`

13

``

`-

fn backslash(a: ascii::Char) -> ([ascii::Char; 4], u8) {

`

14

``

`-

([ascii::Char::ReverseSolidus, a, ascii::Char::Null, ascii::Char::Null], 2)

`

15

``

`-

}

`

``

9

`+

#[inline]

`

``

10

`+

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

`

``

11

`+

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

`

``

12

+

``

13

`+

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

`

``

14

+

``

15

`+

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

`

``

16

`+

output[1] = a;

`

``

17

+

``

18

`+

(output, 0..2)

`

``

19

`+

}

`

16

20

``

17

``

`-

let (data, len) = match byte {

`

``

21

`+

/// Escapes an ASCII character.

`

``

22

`+

///

`

``

23

`+

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

`

``

24

`+

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

`

``

25

`+

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

`

``

26

+

``

27

`+

match byte {

`

18

28

`b'\t' => backslash(ascii::Char::SmallT),

`

19

29

`b'\r' => backslash(ascii::Char::SmallR),

`

20

30

`b'\n' => backslash(ascii::Char::SmallN),

`

21

31

`b'\' => backslash(ascii::Char::ReverseSolidus),

`

22

32

`b''' => backslash(ascii::Char::Apostrophe),

`

23

33

`b'"' => backslash(ascii::Char::QuotationMark),

`

24

``

`-

_ => {

`

25

``

`-

if let Some(a) = byte.as_ascii()

`

``

34

`+

byte => {

`

``

35

`+

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

`

``

36

+

``

37

`+

if let Some(c) = byte.as_ascii()

`

26

38

` && !byte.is_ascii_control()

`

27

39

`{

`

28

``

`-

([a, ascii::Char::Null, ascii::Char::Null, ascii::Char::Null], 1)

`

``

40

`+

output[0] = c;

`

``

41

`+

(output, 0..1)

`

29

42

`} else {

`

30

``

`-

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

`

31

``

`-

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

`

32

``

`-

([ascii::Char::ReverseSolidus, ascii::Char::SmallX, hi, lo], 4)

`

``

43

`+

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

`

``

44

`+

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

`

``

45

+

``

46

`+

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

`

``

47

`+

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

`

``

48

`+

output[2] = hi;

`

``

49

`+

output[3] = lo;

`

``

50

+

``

51

`+

(output, 0..4)

`

33

52

`}

`

34

53

`}

`

35

``

`-

};

`

36

``

`-

*output = data;

`

37

``

`-

0..len

`

``

54

`+

}

`

38

55

`}

`

39

56

``

40

``

`` -

/// Escapes a character into provided buffer using \u{NNNN} representation.

``

41

``

`-

pub(crate) fn escape_unicode_into(output: &mut [ascii::Char; 10], ch: char) -> Range {

`

``

57

`` +

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

``

``

58

`+

///

`

``

59

`+

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

`

``

60

`+

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

`

``

61

`+

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

`

``

62

+

``

63

`+

let c = u32::from(c);

`

``

64

+

``

65

`` +

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

``

``

66

`+

// one digit should be printed.

`

``

67

`+

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

`

``

68

+

``

69

`+

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

`

``

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];

`

42

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;

`

43

80

``

44

``

`-

let ch = ch as u32;

`

45

``

`-

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

`

46

``

`-

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

`

47

``

`-

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

`

48

``

`-

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

`

49

``

`-

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

`

50

``

`-

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

`

51

``

-

52

``

`-

// or-ing 1 ensures that for ch==0 the code computes that one digit should

`

53

``

`-

// be printed.

`

54

``

`-

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

`

55

``

`-

const UNICODE_ESCAPE_PREFIX: &[ascii::Char; 3] = b"\u{".as_ascii().unwrap();

`

56

``

`-

output[start..][..3].copy_from_slice(UNICODE_ESCAPE_PREFIX);

`

57

``

-

58

``

`-

(start as u8)..10

`

``

81

`+

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

`

59

82

`}

`

60

83

``

61

84

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

`

`@@ -65,45 +88,63 @@ pub(crate) fn escape_unicode_into(output: &mut [ascii::Char; 10], ch: char) -> R

`

65

88

`#[derive(Clone, Debug)]

`

66

89

`pub(crate) struct EscapeIterInner {

`

67

90

`// The element type ensures this is always ASCII, and thus also valid UTF-8.

`

68

``

`-

pub(crate) data: [ascii::Char; N],

`

``

91

`+

data: [ascii::Char; N],

`

69

92

``

70

``

`-

// Invariant: alive.start <= alive.end <= N.

`

71

``

`-

pub(crate) alive: Range,

`

``

93

`` +

// Invariant: alive.start <= alive.end <= N

``

``

94

`+

alive: Range,

`

72

95

`}

`

73

96

``

74

97

`impl EscapeIterInner {

`

75

``

`-

pub fn new(data: [ascii::Char; N], alive: Range) -> Self {

`

76

``

`-

const { assert!(N < 256) };

`

77

``

`-

debug_assert!(alive.start <= alive.end && usize::from(alive.end) <= N, "{alive:?}");

`

78

``

`-

Self { data, alive }

`

``

98

`+

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

`

``

99

`+

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

`

``

100

`+

Self { data, alive: range }

`

``

101

`+

}

`

``

102

+

``

103

`+

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

`

``

104

`+

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

`

``

105

`+

Self { data, alive: range }

`

79

106

`}

`

80

107

``

81

``

`-

pub fn from_array(array: [ascii::Char; M]) -> Self {

`

82

``

`-

const { assert!(M <= N) };

`

``

108

`+

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

`

``

109

`+

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

`

``

110

`+

Self { data, alive: range }

`

``

111

`+

}

`

83

112

``

84

``

`-

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

`

85

``

`-

data[..M].copy_from_slice(&array);

`

86

``

`-

Self::new(data, 0..M as u8)

`

``

113

`+

#[inline]

`

``

114

`+

pub const fn empty() -> Self {

`

``

115

`+

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

`

87

116

`}

`

88

117

``

``

118

`+

#[inline]

`

89

119

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

`

90

``

`-

&self.data[usize::from(self.alive.start)..usize::from(self.alive.end)]

`

``

120

`` +

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

``

``

121

`+

unsafe {

`

``

122

`+

self.data.get_unchecked(usize::from(self.alive.start)..usize::from(self.alive.end))

`

``

123

`+

}

`

91

124

`}

`

92

125

``

``

126

`+

#[inline]

`

93

127

`pub fn as_str(&self) -> &str {

`

94

128

`self.as_ascii().as_str()

`

95

129

`}

`

96

130

``

``

131

`+

#[inline]

`

97

132

`pub fn len(&self) -> usize {

`

98

133

` usize::from(self.alive.end - self.alive.start)

`

99

134

`}

`

100

135

``

101

136

`pub fn next(&mut self) -> Option {

`

102

``

`-

self.alive.next().map(|i| self.data[usize::from(i)].to_u8())

`

``

137

`+

let i = self.alive.next()?;

`

``

138

+

``

139

`` +

// SAFETY: i is guaranteed to be a valid index for self.data.

``

``

140

`+

unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) }

`

103

141

`}

`

104

142

``

105

143

`pub fn next_back(&mut self) -> Option {

`

106

``

`-

self.alive.next_back().map(|i| self.data[usize::from(i)].to_u8())

`

``

144

`+

let i = self.alive.next_back()?;

`

``

145

+

``

146

`` +

// SAFETY: i is guaranteed to be a valid index for self.data.

``

``

147

`+

unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) }

`

107

148

`}

`

108

149

``

109

150

`pub fn advance_by(&mut self, n: usize) -> Result<(), NonZero> {

`