Repository: toml-rs/toml (language: rust)

Issue:
`toml_edit` doesn't properly handle quotes in strings
Run `cargo test decoder_compliance -- --noignore` and you'll see a test failure for `'''' test ''''` which should produce `' test '`but instead errors.


Discussion / hints:
I tried reaching out on gitter but got no response: https://gitter.im/Marwes/combine?at=612547ac5739ab2df8b6c2ec
Github's regex is way too loose when it closes things as fixed because you explained it **wasn't** fixed.

Thanks for noticing!

Fix patch:
diff --git a/src/parser/strings.rs b/src/parser/strings.rs
index a1b1e17b..ee76afa7 100644
--- a/src/parser/strings.rs
+++ b/src/parser/strings.rs
@@ -116,14 +116,29 @@ parse!(hexescape(n: usize) -> char, {
 // ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body
 //                   ml-basic-string-delim
 parse!(ml_basic_string() -> String, {
-    between(
-        range(ML_BASIC_STRING_DELIM),
+    (
         range(ML_BASIC_STRING_DELIM),
         (
             optional(newline()),
             ml_basic_body(),
         ).map(|t| t.1),
-    ).message("While parsing a Multiline Basic String")
+        // Deviate from grammar by pulling mll_quotes into here so we can handle the confusion with
+        // it and the closing delim
+        choice((
+            attempt((
+                bytes(b"\"\""), range(ML_BASIC_STRING_DELIM)
+            )).map(|_| Some("\"\"")),
+            attempt((
+                bytes(b"\""), range(ML_BASIC_STRING_DELIM)
+            )).map(|_| Some("\"")),
+            range(ML_BASIC_STRING_DELIM).map(|_| None),
+        )),
+    ).map(|(_, mut b, q)| {
+        if let Some(q) = q {
+            b.push_str(q);
+        }
+        b
+    }).message("While parsing a Multiline Basic String")
 });
 
 // ml-basic-string-delim = 3quotation-mark
@@ -141,7 +156,7 @@ parse!(ml_basic_body() -> String, {
             total.push_str(&c);
             total
         }))),
-        // BUG: See #128
+        // Deviate: see `ml_basic_string`
         //optional(mll_quotes()),
     ).map(|(mut c, qc): (String, String)| {
         c.push_str(&qc);
@@ -216,14 +231,29 @@ fn is_literal_char(c: u8) -> bool {
 // ml-literal-string = ml-literal-string-delim [ newline ] ml-literal-body
 //                     ml-literal-string-delim
 parse!(ml_literal_string() -> String, {
-    between(
-        range(ML_LITERAL_STRING_DELIM),
+    (
         range(ML_LITERAL_STRING_DELIM),
         (
             optional(newline()),
             ml_literal_body(),
         ).map(|t| t.1.replace("\r\n", "\n")),
-    ).message("While parsing a Multiline Literal String")
+        // Deviate from grammar by pulling mll_quotes into here so we can handle the confusion with
+        // it and the closing delim
+        choice((
+            attempt((
+                bytes(b"''"), range(ML_LITERAL_STRING_DELIM)
+            )).map(|_| Some("''")),
+            attempt((
+                bytes(b"'"), range(ML_LITERAL_STRING_DELIM)
+            )).map(|_| Some("'")),
+            range(ML_LITERAL_STRING_DELIM).map(|_| None),
+        ))
+    ).map(|(_, mut b, q)| {
+        if let Some(q) = q {
+            b.push_str(q);
+        }
+        b
+    }).message("While parsing a Multiline Literal String")
 });
 
 // ml-literal-string-delim = 3apostrophe
@@ -234,7 +264,7 @@ parse!(ml_literal_body() -> &'a str, {
     recognize((
         skip_many(mll_content()),
         skip_many(attempt((mll_quotes(), skip_many1(mll_content())))),
-        // BUG: See #128
+        // Deviate: see ml_literal_string
         //optional(mll_quotes()),
     )).and_then(std::str::from_utf8)
 });


Test patch:
diff --git a/tests/decoder_compliance.rs b/tests/decoder_compliance.rs
index b5102775..0af48f0c 100644
--- a/tests/decoder_compliance.rs
+++ b/tests/decoder_compliance.rs
@@ -2,9 +2,6 @@ mod decoder;
 
 fn main() {
     let decoder = decoder::Decoder;
-    let mut harness = toml_test_harness::DecoderHarness::new(decoder);
-    harness
-        .ignore(["valid/string/multiline-quotes.toml"])
-        .unwrap();
+    let harness = toml_test_harness::DecoderHarness::new(decoder);
     harness.test();
 }
diff --git a/tests/easy_decoder_compliance.rs b/tests/easy_decoder_compliance.rs
index 9c1e4246..645e5e41 100644
--- a/tests/easy_decoder_compliance.rs
+++ b/tests/easy_decoder_compliance.rs
@@ -4,10 +4,7 @@ mod easy_decoder;
 #[cfg(feature = "easy")]
 fn main() {
     let decoder = easy_decoder::Decoder;
-    let mut harness = toml_test_harness::DecoderHarness::new(decoder);
-    harness
-        .ignore(["valid/string/multiline-quotes.toml"])
-        .unwrap();
+    let harness = toml_test_harness::DecoderHarness::new(decoder);
     harness.test();
 }
 
diff --git a/tests/easy_encoder_compliance.rs b/tests/easy_encoder_compliance.rs
index 6f934f99..372721dd 100644
--- a/tests/easy_encoder_compliance.rs
+++ b/tests/easy_encoder_compliance.rs
@@ -7,13 +7,7 @@ mod easy_encoder;
 fn main() {
     let encoder = easy_encoder::Encoder;
     let decoder = easy_decoder::Decoder;
-    let mut harness = toml_test_harness::EncoderHarness::new(encoder, decoder);
-    harness
-        .ignore([
-            // Can't verify until decoder is fixed
-            "valid/string/multiline-quotes.toml",
-        ])
-        .unwrap();
+    let harness = toml_test_harness::EncoderHarness::new(encoder, decoder);
     harness.test();
 }
 
diff --git a/tests/encoder_compliance.rs b/tests/encoder_compliance.rs
index 31aa95c1..09c3d0bf 100644
--- a/tests/encoder_compliance.rs
+++ b/tests/encoder_compliance.rs
@@ -4,12 +4,6 @@ mod encoder;
 fn main() {
     let encoder = encoder::Encoder;
     let decoder = decoder::Decoder;
-    let mut harness = toml_test_harness::EncoderHarness::new(encoder, decoder);
-    harness
-        .ignore([
-            // Can't verify until decoder is fixed
-            "valid/string/multiline-quotes.toml",
-        ])
-        .unwrap();
+    let harness = toml_test_harness::EncoderHarness::new(encoder, decoder);
     harness.test();
 }