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