@@ -53,6 +53,8 @@ pub (crate) fn escape_double_quoted(input: &str) -> String {
5353 '/'  => {  escaped. push ( '\\' ) ;  escaped. push ( '/' ) ;  } 
5454 '\u{0008}'  => {  escaped. push ( '\\' ) ;  escaped. push ( 'b' ) ;  } 
5555 '\u{000c}'  => {  escaped. push ( '\\' ) ;  escaped. push ( 'f' ) ;  } 
56+  '\u{2028}'  => {  escaped. push_str ( "\\ u2028" ) ;  } 
57+  '\u{2029}'  => {  escaped. push_str ( "\\ u2029" ) ;  } 
5658 _ => escaped. push ( c) , 
5759 } 
5860 } 
@@ -65,14 +67,16 @@ pub (crate) fn escape_single_quoted(input: &str) -> String {
6567 let  mut  escaped = String :: with_capacity ( input. len ( )  *  2 ) ; 
6668 for  c in  input. chars ( )  { 
6769 match  c { 
68-  '\''  => {  escaped. push ( '\\' ) ;  escaped. push ( '" ' ) ;  } 
70+  '\''  => {  escaped. push ( '\\' ) ;  escaped. push ( '\' ' ) ;  } 
6971 '\\'  => {  escaped. push ( '\\' ) ;  escaped. push ( '\\' ) ;  } 
7072 '\n'  => {  escaped. push ( '\\' ) ;  escaped. push ( 'n' ) ;  } 
7173 '\r'  => {  escaped. push ( '\\' ) ;  escaped. push ( 'r' ) ;  } 
7274 '\t'  => {  escaped. push ( '\\' ) ;  escaped. push ( 't' ) ;  } 
7375 '/'  => {  escaped. push ( '\\' ) ;  escaped. push ( '/' ) ;  } 
7476 '\u{0008}'  => {  escaped. push ( '\\' ) ;  escaped. push ( 'b' ) ;  } 
7577 '\u{000c}'  => {  escaped. push ( '\\' ) ;  escaped. push ( 'f' ) ;  } 
78+  '\u{2028}'  => {  escaped. push_str ( "\\ u2028" ) ;  } 
79+  '\u{2029}'  => {  escaped. push_str ( "\\ u2029" ) ;  } 
7680 _ => escaped. push ( c) , 
7781 } 
7882 } 
@@ -176,3 +180,151 @@ pub (crate) const MAX_DEPTH: usize = 2000;
176180
177181#[ cfg( feature = "unlimited_depth" ) ]  
178182pub  ( crate )  const  MAX_DEPTH :  usize  = usize:: MAX ; 
183+ 
184+ #[ cfg( test) ]  
185+ mod  tests { 
186+  use  super :: * ; 
187+ 
188+  #[ test]  
189+  fn  test_escape_single_quote_bug ( )  { 
190+  let  input = "Hello'World" ; 
191+  let  result = escape_single_quoted ( input) ; 
192+  let  expected = "Hello\\ 'World" ; 
193+  assert_eq ! ( result,  expected,  "Single quote should be escaped as \\ ' not \\ \" " ) ; 
194+  } 
195+ 
196+  #[ test]  
197+  fn  test_escape_double_quoted_comprehensive ( )  { 
198+  let  input = "Hello\" World\n \t \r \\ " ; 
199+  let  result = escape_double_quoted ( input) ; 
200+  let  expected = "Hello\\ \" World\\ n\\ t\\ r\\ \\ " ; 
201+  assert_eq ! ( result,  expected) ; 
202+  } 
203+ 
204+  #[ test]  
205+  fn  test_escape_single_quoted_comprehensive ( )  { 
206+  let  input = "Hello'World\n \t \r \\ " ; 
207+  let  result = escape_single_quoted ( input) ; 
208+  let  expected = "Hello\\ 'World\\ n\\ t\\ r\\ \\ " ; 
209+  assert_eq ! ( result,  expected) ; 
210+  } 
211+ 
212+  #[ test]   
213+  fn  test_unescape_basic_escapes ( )  { 
214+  let  input = "Hello\\ nWorld\\ t\\ r\\ \\ " ; 
215+  let  result = unescape ( input) . unwrap ( ) ; 
216+  let  expected = "Hello\n World\t \r \\ " ; 
217+  assert_eq ! ( result,  expected) ; 
218+  } 
219+ 
220+  #[ test]  
221+  fn  test_unescape_quotes ( )  { 
222+  let  input = "He said \\ \" Hello\\ \"  and she said \\ 'Hi\\ '" ; 
223+  let  result = unescape ( input) . unwrap ( ) ; 
224+  let  expected = "He said \" Hello\"  and she said 'Hi'" ; 
225+  assert_eq ! ( result,  expected) ; 
226+  } 
227+ 
228+  #[ test]  
229+  fn  test_unescape_unicode_valid ( )  { 
230+  let  input = "Unicode: \\ u0041\\ u0042\\ u2764" ; 
231+  let  result = unescape ( input) . unwrap ( ) ; 
232+  let  expected = "Unicode: AB❤" ; 
233+  assert_eq ! ( result,  expected) ; 
234+  } 
235+ 
236+  #[ test]  
237+  fn  test_unescape_hex_valid ( )  { 
238+  let  input = "Hex: \\ x41\\ x42\\ x21" ; 
239+  let  result = unescape ( input) . unwrap ( ) ; 
240+  let  expected = "Hex: AB!" ; 
241+  assert_eq ! ( result,  expected) ; 
242+  } 
243+ 
244+  #[ test]  
245+  fn  test_unescape_invalid_unicode_short ( )  { 
246+  let  input = "Invalid: \\ u12G" ;  // Invalid hex digit 
247+  let  result = unescape ( input) ; 
248+  assert ! ( result. is_err( ) ,  "Should fail on invalid unicode escape" ) ; 
249+  } 
250+ 
251+  #[ test]  
252+  fn  test_unescape_invalid_unicode_incomplete ( )  { 
253+  let  input = "Incomplete: \\ u123" ;  // Too few digits 
254+  let  result = unescape ( input) ; 
255+  assert ! ( result. is_err( ) ,  "Should fail on incomplete unicode escape" ) ; 
256+  } 
257+ 
258+  #[ test]  
259+  fn  test_unescape_invalid_hex_char ( )  { 
260+  let  input = "Invalid hex: \\ xZZ" ; 
261+  let  result = unescape ( input) ; 
262+  assert ! ( result. is_err( ) ,  "Should fail on invalid hex escape" ) ; 
263+  } 
264+ 
265+  #[ test]  
266+  fn  test_unescape_invalid_hex_incomplete ( )  { 
267+  let  input = "Incomplete hex: \\ x1" ; 
268+  let  result = unescape ( input) ; 
269+  assert ! ( result. is_err( ) ,  "Should fail on incomplete hex escape" ) ; 
270+  } 
271+ 
272+  #[ test]  
273+  fn  test_unescape_unknown_escape ( )  { 
274+  let  input = "Unknown: \\ z" ; 
275+  let  result = unescape ( input) ; 
276+  assert ! ( result. is_err( ) ,  "Should fail on unknown escape sequence" ) ; 
277+  } 
278+ 
279+  #[ test]  
280+  fn  test_unescape_incomplete_escape_at_end ( )  { 
281+  let  input = "Incomplete: \\ " ; 
282+  let  result = unescape ( input) ; 
283+  assert ! ( result. is_err( ) ,  "Should fail on incomplete escape at end" ) ; 
284+  } 
285+ 
286+  #[ test]  
287+  fn  test_unescape_line_continuation ( )  { 
288+  let  input = "Line\\ ncontinuation" ; 
289+  let  result = unescape ( input) . unwrap ( ) ; 
290+  let  expected = "Line\n continuation" ; 
291+  assert_eq ! ( result,  expected) ; 
292+  } 
293+ 
294+  #[ test]   
295+  fn  test_unescape_all_special_chars ( )  { 
296+  let  input = "\\ a\\ b\\ f\\ n\\ r\\ t\\ v\\ 0\\ \\ \\ '\\ \" " ; 
297+  let  result = unescape ( input) . unwrap ( ) ; 
298+  let  expected = "\x07 \x08 \x0C \n \r \t \x0B \0 \\ '\" " ; 
299+  assert_eq ! ( result,  expected) ; 
300+  } 
301+ 
302+  #[ test]  
303+  fn  test_unescape_unicode_line_separators ( )  { 
304+  let  input = "\\ u2028\\ u2029" ;  // Line separator, Paragraph separator 
305+  let  result = unescape ( input) . unwrap ( ) ; 
306+  let  expected = "\u{2028} \u{2029} " ; 
307+  assert_eq ! ( result,  expected) ; 
308+  } 
309+ 
310+  #[ test]  
311+  fn  test_read_hex_digits_valid ( )  { 
312+  let  mut  chars = "ABCD" . chars ( ) . peekable ( ) ; 
313+  let  result = read_hex_digits ( & mut  chars,  4 ,  "\\ u" ) . unwrap ( ) ; 
314+  assert_eq ! ( result,  0xABCD ) ; 
315+  } 
316+ 
317+  #[ test]  
318+  fn  test_read_hex_digits_invalid_char ( )  { 
319+  let  mut  chars = "12G4" . chars ( ) . peekable ( ) ; 
320+  let  result = read_hex_digits ( & mut  chars,  4 ,  "\\ u" ) ; 
321+  assert ! ( result. is_err( ) ,  "Should fail on invalid hex character" ) ; 
322+  } 
323+ 
324+  #[ test]  
325+  fn  test_read_hex_digits_incomplete ( )  { 
326+  let  mut  chars = "12" . chars ( ) . peekable ( ) ; 
327+  let  result = read_hex_digits ( & mut  chars,  4 ,  "\\ u" ) ; 
328+  assert ! ( result. is_err( ) ,  "Should fail on incomplete hex sequence" ) ; 
329+  } 
330+ } 
0 commit comments