@@ -101,7 +101,7 @@ fn parse_union_child(matcher_rule: pest::iterators::Pair<Rule>) -> Vec<Box<dyn m
101
101
}
102
102
103
103
Rule :: singleInner => {
104
- ms. push ( Box :: new ( matchers:: Child :: new ( unescape ( r. as_str ( ) ) ) ) ) ;
104
+ ms. push ( Box :: new ( matchers:: Child :: new ( unescape_single ( r. as_str ( ) ) ) ) ) ;
105
105
}
106
106
107
107
_ => ( ) ,
@@ -119,38 +119,55 @@ fn parse_union_array_index(
119
119
ms
120
120
}
121
121
122
- const ESCAPED : & str = "\" '\\ /bfnrt" ;
123
- const UNESCAPED : & str = "\" '\\ /\u{0008} \u{000C} \u{000A} \u{000D} \u{0009} " ;
124
-
125
122
fn unescape ( contents : & str ) -> String {
123
+ let s = format ! ( r#""{}""# , contents) ;
124
+ serde_json:: from_str ( & s) . unwrap ( )
125
+ }
126
+
127
+ fn unescape_single ( contents : & str ) -> String {
128
+ let d = to_double_quoted ( contents) ;
129
+ unescape ( & d)
130
+ }
131
+
132
+ // converts a single quoted string body into a string that can be unescaped
133
+ // by a function that knows how to unescape double quoted string,
134
+ // It works by unescaping single quotes and escaping double quotes while leaving
135
+ // everything else untouched.
136
+ fn to_double_quoted ( contents : & str ) -> String {
126
137
let mut output = String :: new ( ) ;
127
- let xs: Vec < char > = contents. chars ( ) . collect ( ) ;
128
- let mut i = 0 ;
129
- while i < xs. len ( ) {
130
- if xs[ i] == '\\' {
131
- i += 1 ;
132
- if xs[ i] == 'u' {
133
- i += 1 ;
134
-
135
- // convert xs[i..i+4] to Unicode character and add it to the output
136
- let x = xs[ i..i + 4 ] . iter ( ) . collect :: < String > ( ) ;
137
- let n = u32:: from_str_radix ( & x, 16 ) ;
138
- let u = std:: char:: from_u32 ( n. unwrap ( ) ) ;
139
- output. push ( u. unwrap ( ) ) ;
140
-
141
- i += 4 ;
138
+ let mut escaping = false ;
139
+ for ch in contents. chars ( ) {
140
+ if !escaping {
141
+ if ch == '\\' {
142
+ escaping = true ;
142
143
} else {
143
- for ( j, c) in ESCAPED . chars ( ) . enumerate ( ) {
144
- if xs[ i] == c {
145
- output. push ( UNESCAPED . chars ( ) . nth ( j) . unwrap ( ) )
146
- }
144
+ if ch == '"' {
145
+ output. push ( '\\' ) ;
147
146
}
148
- i += 1 ;
147
+ output . push ( ch ) ;
149
148
}
150
149
} else {
151
- output. push ( xs[ i] ) ;
152
- i += 1 ;
150
+ escaping = false ;
151
+ if ch != '\'' {
152
+ output. push ( '\\' ) ;
153
+ } ;
154
+ output. push ( ch) ;
153
155
}
154
156
}
155
157
output
156
158
}
159
+
160
+ #[ cfg( test) ]
161
+ mod test {
162
+ use super :: * ;
163
+
164
+ #[ test]
165
+ fn test_to_double ( ) {
166
+ assert_eq ! ( to_double_quoted( r#"ab"# ) , r#"ab"# ) ;
167
+ assert_eq ! ( to_double_quoted( r#"a"b"# ) , r#"a\"b"# ) ;
168
+ assert_eq ! ( to_double_quoted( r#"a\'b"# ) , r#"a'b"# ) ;
169
+ assert_eq ! ( to_double_quoted( r#"a\nb"# ) , r#"a\nb"# ) ;
170
+ assert_eq ! ( to_double_quoted( r#"a\bb"# ) , r#"a\bb"# ) ;
171
+ assert_eq ! ( to_double_quoted( r#"a\\b"# ) , r#"a\\b"# ) ;
172
+ }
173
+ }
0 commit comments