|
4 | 4 | use std::str::Chars;
|
5 | 5 | use std::ops::Range;
|
6 | 6 |
|
| 7 | +#[cfg(test)] |
| 8 | +mod tests; |
| 9 | + |
7 | 10 | #[derive(Debug, PartialEq, Eq)]
|
8 | 11 | pub enum EscapeError {
|
9 | 12 | ZeroChars,
|
@@ -320,283 +323,3 @@ fn byte_from_char(c: char) -> u8 {
|
320 | 323 | fn is_ascii(x: u32) -> bool {
|
321 | 324 | x <= 0x7F
|
322 | 325 | }
|
323 |
| - |
324 |
| -#[cfg(test)] |
325 |
| -mod tests { |
326 |
| - use super::*; |
327 |
| - |
328 |
| - #[test] |
329 |
| - fn test_unescape_char_bad() { |
330 |
| - fn check(literal_text: &str, expected_error: EscapeError) { |
331 |
| - let actual_result = unescape_char(literal_text).map_err(|(_offset, err)| err); |
332 |
| - assert_eq!(actual_result, Err(expected_error)); |
333 |
| - } |
334 |
| - |
335 |
| - check("", EscapeError::ZeroChars); |
336 |
| - check(r"\", EscapeError::LoneSlash); |
337 |
| - |
338 |
| - check("\n", EscapeError::EscapeOnlyChar); |
339 |
| - check("\r\n", EscapeError::EscapeOnlyChar); |
340 |
| - check("\t", EscapeError::EscapeOnlyChar); |
341 |
| - check("'", EscapeError::EscapeOnlyChar); |
342 |
| - check("\r", EscapeError::BareCarriageReturn); |
343 |
| - |
344 |
| - check("spam", EscapeError::MoreThanOneChar); |
345 |
| - check(r"\x0ff", EscapeError::MoreThanOneChar); |
346 |
| - check(r#"\"a"#, EscapeError::MoreThanOneChar); |
347 |
| - check(r"\na", EscapeError::MoreThanOneChar); |
348 |
| - check(r"\ra", EscapeError::MoreThanOneChar); |
349 |
| - check(r"\ta", EscapeError::MoreThanOneChar); |
350 |
| - check(r"\\a", EscapeError::MoreThanOneChar); |
351 |
| - check(r"\'a", EscapeError::MoreThanOneChar); |
352 |
| - check(r"\0a", EscapeError::MoreThanOneChar); |
353 |
| - check(r"\u{0}x", EscapeError::MoreThanOneChar); |
354 |
| - check(r"\u{1F63b}}", EscapeError::MoreThanOneChar); |
355 |
| - |
356 |
| - check(r"\v", EscapeError::InvalidEscape); |
357 |
| - check(r"\💩", EscapeError::InvalidEscape); |
358 |
| - check(r"\●", EscapeError::InvalidEscape); |
359 |
| - |
360 |
| - check(r"\x", EscapeError::TooShortHexEscape); |
361 |
| - check(r"\x0", EscapeError::TooShortHexEscape); |
362 |
| - check(r"\xf", EscapeError::TooShortHexEscape); |
363 |
| - check(r"\xa", EscapeError::TooShortHexEscape); |
364 |
| - check(r"\xx", EscapeError::InvalidCharInHexEscape); |
365 |
| - check(r"\xы", EscapeError::InvalidCharInHexEscape); |
366 |
| - check(r"\x🦀", EscapeError::InvalidCharInHexEscape); |
367 |
| - check(r"\xtt", EscapeError::InvalidCharInHexEscape); |
368 |
| - check(r"\xff", EscapeError::OutOfRangeHexEscape); |
369 |
| - check(r"\xFF", EscapeError::OutOfRangeHexEscape); |
370 |
| - check(r"\x80", EscapeError::OutOfRangeHexEscape); |
371 |
| - |
372 |
| - check(r"\u", EscapeError::NoBraceInUnicodeEscape); |
373 |
| - check(r"\u[0123]", EscapeError::NoBraceInUnicodeEscape); |
374 |
| - check(r"\u{0x}", EscapeError::InvalidCharInUnicodeEscape); |
375 |
| - check(r"\u{", EscapeError::UnclosedUnicodeEscape); |
376 |
| - check(r"\u{0000", EscapeError::UnclosedUnicodeEscape); |
377 |
| - check(r"\u{}", EscapeError::EmptyUnicodeEscape); |
378 |
| - check(r"\u{_0000}", EscapeError::LeadingUnderscoreUnicodeEscape); |
379 |
| - check(r"\u{0000000}", EscapeError::OverlongUnicodeEscape); |
380 |
| - check(r"\u{FFFFFF}", EscapeError::OutOfRangeUnicodeEscape); |
381 |
| - check(r"\u{ffffff}", EscapeError::OutOfRangeUnicodeEscape); |
382 |
| - check(r"\u{ffffff}", EscapeError::OutOfRangeUnicodeEscape); |
383 |
| - |
384 |
| - check(r"\u{DC00}", EscapeError::LoneSurrogateUnicodeEscape); |
385 |
| - check(r"\u{DDDD}", EscapeError::LoneSurrogateUnicodeEscape); |
386 |
| - check(r"\u{DFFF}", EscapeError::LoneSurrogateUnicodeEscape); |
387 |
| - |
388 |
| - check(r"\u{D800}", EscapeError::LoneSurrogateUnicodeEscape); |
389 |
| - check(r"\u{DAAA}", EscapeError::LoneSurrogateUnicodeEscape); |
390 |
| - check(r"\u{DBFF}", EscapeError::LoneSurrogateUnicodeEscape); |
391 |
| - } |
392 |
| - |
393 |
| - #[test] |
394 |
| - fn test_unescape_char_good() { |
395 |
| - fn check(literal_text: &str, expected_char: char) { |
396 |
| - let actual_result = unescape_char(literal_text); |
397 |
| - assert_eq!(actual_result, Ok(expected_char)); |
398 |
| - } |
399 |
| - |
400 |
| - check("a", 'a'); |
401 |
| - check("ы", 'ы'); |
402 |
| - check("🦀", '🦀'); |
403 |
| - |
404 |
| - check(r#"\""#, '"'); |
405 |
| - check(r"\n", '\n'); |
406 |
| - check(r"\r", '\r'); |
407 |
| - check(r"\t", '\t'); |
408 |
| - check(r"\\", '\\'); |
409 |
| - check(r"\'", '\''); |
410 |
| - check(r"\0", '\0'); |
411 |
| - |
412 |
| - check(r"\x00", '\0'); |
413 |
| - check(r"\x5a", 'Z'); |
414 |
| - check(r"\x5A", 'Z'); |
415 |
| - check(r"\x7f", 127 as char); |
416 |
| - |
417 |
| - check(r"\u{0}", '\0'); |
418 |
| - check(r"\u{000000}", '\0'); |
419 |
| - check(r"\u{41}", 'A'); |
420 |
| - check(r"\u{0041}", 'A'); |
421 |
| - check(r"\u{00_41}", 'A'); |
422 |
| - check(r"\u{4__1__}", 'A'); |
423 |
| - check(r"\u{1F63b}", '😻'); |
424 |
| - } |
425 |
| - |
426 |
| - #[test] |
427 |
| - fn test_unescape_str_good() { |
428 |
| - fn check(literal_text: &str, expected: &str) { |
429 |
| - let mut buf = Ok(String::with_capacity(literal_text.len())); |
430 |
| - unescape_str(literal_text, &mut |range, c| { |
431 |
| - if let Ok(b) = &mut buf { |
432 |
| - match c { |
433 |
| - Ok(c) => b.push(c), |
434 |
| - Err(e) => buf = Err((range, e)), |
435 |
| - } |
436 |
| - } |
437 |
| - }); |
438 |
| - let buf = buf.as_ref().map(|it| it.as_ref()); |
439 |
| - assert_eq!(buf, Ok(expected)) |
440 |
| - } |
441 |
| - |
442 |
| - check("foo", "foo"); |
443 |
| - check("", ""); |
444 |
| - check(" \t\n\r\n", " \t\n\n"); |
445 |
| - |
446 |
| - check("hello \\\n world", "hello world"); |
447 |
| - check("hello \\\r\n world", "hello world"); |
448 |
| - check("thread's", "thread's") |
449 |
| - } |
450 |
| - |
451 |
| - #[test] |
452 |
| - fn test_unescape_byte_bad() { |
453 |
| - fn check(literal_text: &str, expected_error: EscapeError) { |
454 |
| - let actual_result = unescape_byte(literal_text).map_err(|(_offset, err)| err); |
455 |
| - assert_eq!(actual_result, Err(expected_error)); |
456 |
| - } |
457 |
| - |
458 |
| - check("", EscapeError::ZeroChars); |
459 |
| - check(r"\", EscapeError::LoneSlash); |
460 |
| - |
461 |
| - check("\n", EscapeError::EscapeOnlyChar); |
462 |
| - check("\r\n", EscapeError::EscapeOnlyChar); |
463 |
| - check("\t", EscapeError::EscapeOnlyChar); |
464 |
| - check("'", EscapeError::EscapeOnlyChar); |
465 |
| - check("\r", EscapeError::BareCarriageReturn); |
466 |
| - |
467 |
| - check("spam", EscapeError::MoreThanOneChar); |
468 |
| - check(r"\x0ff", EscapeError::MoreThanOneChar); |
469 |
| - check(r#"\"a"#, EscapeError::MoreThanOneChar); |
470 |
| - check(r"\na", EscapeError::MoreThanOneChar); |
471 |
| - check(r"\ra", EscapeError::MoreThanOneChar); |
472 |
| - check(r"\ta", EscapeError::MoreThanOneChar); |
473 |
| - check(r"\\a", EscapeError::MoreThanOneChar); |
474 |
| - check(r"\'a", EscapeError::MoreThanOneChar); |
475 |
| - check(r"\0a", EscapeError::MoreThanOneChar); |
476 |
| - |
477 |
| - check(r"\v", EscapeError::InvalidEscape); |
478 |
| - check(r"\💩", EscapeError::InvalidEscape); |
479 |
| - check(r"\●", EscapeError::InvalidEscape); |
480 |
| - |
481 |
| - check(r"\x", EscapeError::TooShortHexEscape); |
482 |
| - check(r"\x0", EscapeError::TooShortHexEscape); |
483 |
| - check(r"\xa", EscapeError::TooShortHexEscape); |
484 |
| - check(r"\xf", EscapeError::TooShortHexEscape); |
485 |
| - check(r"\xx", EscapeError::InvalidCharInHexEscape); |
486 |
| - check(r"\xы", EscapeError::InvalidCharInHexEscape); |
487 |
| - check(r"\x🦀", EscapeError::InvalidCharInHexEscape); |
488 |
| - check(r"\xtt", EscapeError::InvalidCharInHexEscape); |
489 |
| - |
490 |
| - check(r"\u", EscapeError::NoBraceInUnicodeEscape); |
491 |
| - check(r"\u[0123]", EscapeError::NoBraceInUnicodeEscape); |
492 |
| - check(r"\u{0x}", EscapeError::InvalidCharInUnicodeEscape); |
493 |
| - check(r"\u{", EscapeError::UnclosedUnicodeEscape); |
494 |
| - check(r"\u{0000", EscapeError::UnclosedUnicodeEscape); |
495 |
| - check(r"\u{}", EscapeError::EmptyUnicodeEscape); |
496 |
| - check(r"\u{_0000}", EscapeError::LeadingUnderscoreUnicodeEscape); |
497 |
| - check(r"\u{0000000}", EscapeError::OverlongUnicodeEscape); |
498 |
| - |
499 |
| - check("ы", EscapeError::NonAsciiCharInByte); |
500 |
| - check("🦀", EscapeError::NonAsciiCharInByte); |
501 |
| - |
502 |
| - check(r"\u{0}", EscapeError::UnicodeEscapeInByte); |
503 |
| - check(r"\u{000000}", EscapeError::UnicodeEscapeInByte); |
504 |
| - check(r"\u{41}", EscapeError::UnicodeEscapeInByte); |
505 |
| - check(r"\u{0041}", EscapeError::UnicodeEscapeInByte); |
506 |
| - check(r"\u{00_41}", EscapeError::UnicodeEscapeInByte); |
507 |
| - check(r"\u{4__1__}", EscapeError::UnicodeEscapeInByte); |
508 |
| - check(r"\u{1F63b}", EscapeError::UnicodeEscapeInByte); |
509 |
| - check(r"\u{0}x", EscapeError::UnicodeEscapeInByte); |
510 |
| - check(r"\u{1F63b}}", EscapeError::UnicodeEscapeInByte); |
511 |
| - check(r"\u{FFFFFF}", EscapeError::UnicodeEscapeInByte); |
512 |
| - check(r"\u{ffffff}", EscapeError::UnicodeEscapeInByte); |
513 |
| - check(r"\u{ffffff}", EscapeError::UnicodeEscapeInByte); |
514 |
| - check(r"\u{DC00}", EscapeError::UnicodeEscapeInByte); |
515 |
| - check(r"\u{DDDD}", EscapeError::UnicodeEscapeInByte); |
516 |
| - check(r"\u{DFFF}", EscapeError::UnicodeEscapeInByte); |
517 |
| - check(r"\u{D800}", EscapeError::UnicodeEscapeInByte); |
518 |
| - check(r"\u{DAAA}", EscapeError::UnicodeEscapeInByte); |
519 |
| - check(r"\u{DBFF}", EscapeError::UnicodeEscapeInByte); |
520 |
| - } |
521 |
| - |
522 |
| - #[test] |
523 |
| - fn test_unescape_byte_good() { |
524 |
| - fn check(literal_text: &str, expected_byte: u8) { |
525 |
| - let actual_result = unescape_byte(literal_text); |
526 |
| - assert_eq!(actual_result, Ok(expected_byte)); |
527 |
| - } |
528 |
| - |
529 |
| - check("a", b'a'); |
530 |
| - |
531 |
| - check(r#"\""#, b'"'); |
532 |
| - check(r"\n", b'\n'); |
533 |
| - check(r"\r", b'\r'); |
534 |
| - check(r"\t", b'\t'); |
535 |
| - check(r"\\", b'\\'); |
536 |
| - check(r"\'", b'\''); |
537 |
| - check(r"\0", b'\0'); |
538 |
| - |
539 |
| - check(r"\x00", b'\0'); |
540 |
| - check(r"\x5a", b'Z'); |
541 |
| - check(r"\x5A", b'Z'); |
542 |
| - check(r"\x7f", 127); |
543 |
| - check(r"\x80", 128); |
544 |
| - check(r"\xff", 255); |
545 |
| - check(r"\xFF", 255); |
546 |
| - } |
547 |
| - |
548 |
| - #[test] |
549 |
| - fn test_unescape_byte_str_good() { |
550 |
| - fn check(literal_text: &str, expected: &[u8]) { |
551 |
| - let mut buf = Ok(Vec::with_capacity(literal_text.len())); |
552 |
| - unescape_byte_str(literal_text, &mut |range, c| { |
553 |
| - if let Ok(b) = &mut buf { |
554 |
| - match c { |
555 |
| - Ok(c) => b.push(c), |
556 |
| - Err(e) => buf = Err((range, e)), |
557 |
| - } |
558 |
| - } |
559 |
| - }); |
560 |
| - let buf = buf.as_ref().map(|it| it.as_ref()); |
561 |
| - assert_eq!(buf, Ok(expected)) |
562 |
| - } |
563 |
| - |
564 |
| - check("foo", b"foo"); |
565 |
| - check("", b""); |
566 |
| - check(" \t\n\r\n", b" \t\n\n"); |
567 |
| - |
568 |
| - check("hello \\\n world", b"hello world"); |
569 |
| - check("hello \\\r\n world", b"hello world"); |
570 |
| - check("thread's", b"thread's") |
571 |
| - } |
572 |
| - |
573 |
| - #[test] |
574 |
| - fn test_unescape_raw_str() { |
575 |
| - fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) { |
576 |
| - let mut unescaped = Vec::with_capacity(literal.len()); |
577 |
| - unescape_raw_str(literal, &mut |range, res| unescaped.push((range, res))); |
578 |
| - assert_eq!(unescaped, expected); |
579 |
| - } |
580 |
| - |
581 |
| - check("\r\n", &[(0..2, Ok('\n'))]); |
582 |
| - check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]); |
583 |
| - check("\rx", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString)), (1..2, Ok('x'))]); |
584 |
| - } |
585 |
| - |
586 |
| - #[test] |
587 |
| - fn test_unescape_raw_byte_str() { |
588 |
| - fn check(literal: &str, expected: &[(Range<usize>, Result<u8, EscapeError>)]) { |
589 |
| - let mut unescaped = Vec::with_capacity(literal.len()); |
590 |
| - unescape_raw_byte_str(literal, &mut |range, res| unescaped.push((range, res))); |
591 |
| - assert_eq!(unescaped, expected); |
592 |
| - } |
593 |
| - |
594 |
| - check("\r\n", &[(0..2, Ok(byte_from_char('\n')))]); |
595 |
| - check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]); |
596 |
| - check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByteString))]); |
597 |
| - check( |
598 |
| - "🦀a", |
599 |
| - &[(0..4, Err(EscapeError::NonAsciiCharInByteString)), (4..5, Ok(byte_from_char('a')))], |
600 |
| - ); |
601 |
| - } |
602 |
| -} |
0 commit comments