@@ -17,24 +17,36 @@ pub enum EscapedChar {
1717 End ,
1818}
1919
20- #[ repr( u8 ) ]
20+ #[ derive( Clone , Copy ) ]
21+ pub enum OctalParsing {
22+ TwoDigits = 2 ,
23+ ThreeDigits = 3 ,
24+ }
25+
2126#[ derive( Clone , Copy ) ]
2227enum Base {
23- Oct = 8 ,
24- Hex = 16 ,
28+ Oct ( OctalParsing ) ,
29+ Hex ,
2530}
2631
2732impl Base {
33+ fn as_base ( & self ) -> u8 {
34+ match self {
35+ Base :: Oct ( _) => 8 ,
36+ Base :: Hex => 16 ,
37+ }
38+ }
39+
2840 fn max_digits ( & self ) -> u8 {
2941 match self {
30- Self :: Oct => 3 ,
42+ Self :: Oct ( parsing ) => * parsing as u8 ,
3143 Self :: Hex => 2 ,
3244 }
3345 }
3446
3547 fn convert_digit ( & self , c : u8 ) -> Option < u8 > {
3648 match self {
37- Self :: Oct => {
49+ Self :: Oct ( _ ) => {
3850 if matches ! ( c, b'0' ..=b'7' ) {
3951 Some ( c - b'0' )
4052 } else {
@@ -68,7 +80,7 @@ fn parse_code(input: &mut &[u8], base: Base) -> Option<u8> {
6880 let Some ( n) = base. convert_digit ( * c) else {
6981 break ;
7082 } ;
71- ret = ret. wrapping_mul ( base as u8 ) . wrapping_add ( n) ;
83+ ret = ret. wrapping_mul ( base. as_base ( ) ) . wrapping_add ( n) ;
7284 * input = rest;
7385 }
7486
@@ -87,7 +99,9 @@ fn parse_unicode(input: &mut &[u8], digits: u8) -> Option<char> {
8799 for _ in 1 ..digits {
88100 let ( c, rest) = input. split_first ( ) ?;
89101 let n = Base :: Hex . convert_digit ( * c) ?;
90- ret = ret. wrapping_mul ( Base :: Hex as u32 ) . wrapping_add ( n as u32 ) ;
102+ ret = ret
103+ . wrapping_mul ( Base :: Hex . as_base ( ) as u32 )
104+ . wrapping_add ( n as u32 ) ;
91105 * input = rest;
92106 }
93107
@@ -99,13 +113,16 @@ fn parse_unicode(input: &mut &[u8], digits: u8) -> Option<char> {
99113pub struct EscapeError { }
100114
101115/// Parse an escape sequence, like `\n` or `\xff`, etc.
102- pub fn parse_escape_code ( rest : & mut & [ u8 ] ) -> Result < EscapedChar , EscapeError > {
116+ pub fn parse_escape_code (
117+ rest : & mut & [ u8 ] ,
118+ zero_octal_parsing : Option < OctalParsing > ,
119+ ) -> Result < EscapedChar , EscapeError > {
103120 if let [ c, new_rest @ ..] = rest {
104121 // This is for the \NNN syntax for octal sequences.
105122 // Note that '0' is intentionally omitted because that
106123 // would be the \0NNN syntax.
107124 if let b'1' ..=b'7' = c {
108- if let Some ( parsed) = parse_code ( rest, Base :: Oct ) {
125+ if let Some ( parsed) = parse_code ( rest, Base :: Oct ( OctalParsing :: ThreeDigits ) ) {
109126 return Ok ( EscapedChar :: Byte ( parsed) ) ;
110127 }
111128 }
@@ -131,7 +148,11 @@ pub fn parse_escape_code(rest: &mut &[u8]) -> Result<EscapedChar, EscapeError> {
131148 }
132149 }
133150 b'0' => Ok ( EscapedChar :: Byte (
134- parse_code ( rest, Base :: Oct ) . unwrap_or ( b'\0' ) ,
151+ parse_code (
152+ rest,
153+ Base :: Oct ( zero_octal_parsing. unwrap_or ( OctalParsing :: TwoDigits ) ) ,
154+ )
155+ . unwrap_or ( b'\0' ) ,
135156 ) ) ,
136157 b'u' => Ok ( EscapedChar :: Char ( parse_unicode ( rest, 4 ) . unwrap_or ( '\0' ) ) ) ,
137158 b'U' => Ok ( EscapedChar :: Char ( parse_unicode ( rest, 8 ) . unwrap_or ( '\0' ) ) ) ,
0 commit comments