@@ -148,19 +148,37 @@ fn unquote_string(s: &str) -> Result<String, Error<Token, Token>> {
148
148
let mut res = String :: with_capacity ( s. len ( ) ) ;
149
149
debug_assert ! ( s. starts_with( '"' ) && s. ends_with( '"' ) ) ;
150
150
let mut chars = s[ 1 ..s. len ( ) -1 ] . chars ( ) ;
151
+ let mut temp_code_point = String :: with_capacity ( 4 ) ;
151
152
while let Some ( c) = chars. next ( ) {
152
153
match c {
153
154
'\\' => {
154
- match chars. next ( ) . expect ( "slash cant be and the end" ) {
155
+ match chars. next ( ) . expect ( "slash cant be at the end" ) {
155
156
c@'"' | c@'\\' | c@'/' => res. push ( c) ,
156
157
'b' => res. push ( '\u{0010}' ) ,
157
158
'f' => res. push ( '\u{000C}' ) ,
158
159
'n' => res. push ( '\n' ) ,
159
160
'r' => res. push ( '\r' ) ,
160
161
't' => res. push ( '\t' ) ,
161
162
'u' => {
162
- unimplemented ! ( ) ;
163
- }
163
+ temp_code_point. clear ( ) ;
164
+ for _ in 0 ..4 {
165
+ match chars. next ( ) {
166
+ Some ( inner_c) => temp_code_point. push ( inner_c) ,
167
+ None => return Err ( Error :: unexpected_message (
168
+ format_args ! ( "\\ u must have 4 characters after it, only found '{}'" , temp_code_point)
169
+ ) ) ,
170
+ }
171
+ }
172
+
173
+ // convert our hex string into a u32, then convert that into a char
174
+ match u32:: from_str_radix ( & temp_code_point, 16 ) . map ( std:: char:: from_u32) {
175
+ Ok ( Some ( unicode_char) ) => res. push ( unicode_char) ,
176
+ _ => {
177
+ return Err ( Error :: unexpected_message (
178
+ format_args ! ( "{} is not a valid unicode code point" , temp_code_point) ) )
179
+ }
180
+ }
181
+ } ,
164
182
c => {
165
183
return Err ( Error :: unexpected_message (
166
184
format_args ! ( "bad escaped char {:?}" , c) ) ) ;
@@ -263,6 +281,7 @@ pub fn parse_type<'a>(input: &mut TokenStream<'a>)
263
281
#[ cfg( test) ]
264
282
mod tests {
265
283
use super :: Number ;
284
+ use super :: unquote_string;
266
285
267
286
#[ test]
268
287
fn number_from_i32_and_to_i64_conversion ( ) {
@@ -271,4 +290,17 @@ mod tests {
271
290
assert_eq ! ( Number :: from( i32 :: min_value( ) ) . as_i64( ) , Some ( i32 :: min_value( ) as i64 ) ) ;
272
291
assert_eq ! ( Number :: from( i32 :: max_value( ) ) . as_i64( ) , Some ( i32 :: max_value( ) as i64 ) ) ;
273
292
}
293
+
294
+ #[ test]
295
+ fn unquote_unicode_string ( ) {
296
+ // basic tests
297
+ assert_eq ! ( unquote_string( r#""\u0009""# ) . expect( "" ) , "\u{0009} " ) ;
298
+ assert_eq ! ( unquote_string( r#""\u000A""# ) . expect( "" ) , "\u{000A} " ) ;
299
+ assert_eq ! ( unquote_string( r#""\u000D""# ) . expect( "" ) , "\u{000D} " ) ;
300
+ assert_eq ! ( unquote_string( r#""\u0020""# ) . expect( "" ) , "\u{0020} " ) ;
301
+ assert_eq ! ( unquote_string( r#""\uFFFF""# ) . expect( "" ) , "\u{FFFF} " ) ;
302
+
303
+ // a more complex string
304
+ assert_eq ! ( unquote_string( r#""\u0009 hello \u000A there""# ) . expect( "" ) , "\u{0009} hello \u{000A} there" ) ;
305
+ }
274
306
}
0 commit comments