From 83be829f0b04ddfe9c48af28c7b98674b201a935 Mon Sep 17 00:00:00 2001 From: Garrett Berg Date: Thu, 27 Jul 2017 16:37:30 -0600 Subject: [PATCH] fix bugs with pretty --- src/ser.rs | 52 +++++++++++++++++++++------------------------- tests/pretty.rs | 19 +++++++++++++++++ tests/valid.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 92 insertions(+), 34 deletions(-) diff --git a/src/ser.rs b/src/ser.rs index 3c9b354..febe429 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -450,14 +450,18 @@ impl<'a> Serializer<'a> { if ok { drop(write!(self.dst, "{}", key)); } else { - self.emit_str(key)?; + self.emit_str(key, true)?; } Ok(()) } - fn emit_str(&mut self, value: &str) -> Result<(), Error> { - let do_pretty = if self.settings.pretty_string { - value.contains('\n') + fn emit_str(&mut self, value: &str, is_key: bool) -> Result<(), Error> { + let do_pretty = if !is_key && self.settings.pretty_string { + // do pretty only if the block contains at least one newline + value.contains('\n') + // but not if it contains any of these, as they are not + // representable + && !value.contains("'''") } else { false }; @@ -466,31 +470,21 @@ impl<'a> Serializer<'a> { } else { drop(write!(self.dst, "\"")); } - for ch in value.chars() { - match ch { - '\u{8}' => drop(write!(self.dst, "\\b")), - '\u{9}' => drop(write!(self.dst, "\\t")), - '\u{a}' => { - if do_pretty { - drop(write!(self.dst, "\n")); - } else { - drop(write!(self.dst, "\\n")); - } - }, - '\u{c}' => drop(write!(self.dst, "\\f")), - '\u{d}' => drop(write!(self.dst, "\\r")), - '\u{22}' => { - if do_pretty { - drop(write!(self.dst, "\"")) - } else { - drop(write!(self.dst, "\\\"")) - } - }, - '\u{5c}' => drop(write!(self.dst, "\\\\")), - c if c < '\u{1f}' => { - drop(write!(self.dst, "\\u{:04X}", ch as u32)) + if do_pretty { + drop(write!(self.dst, "{}", value)); + } else { + for ch in value.chars() { + match ch { + '\u{8}' => drop(write!(self.dst, "\\b")), + '\u{9}' => drop(write!(self.dst, "\\t")), + '\u{a}' => drop(write!(self.dst, "\\n")), + '\u{c}' => drop(write!(self.dst, "\\f")), + '\u{d}' => drop(write!(self.dst, "\\r")), + '\u{22}' => drop(write!(self.dst, "\\\"")), + '\u{5c}' => drop(write!(self.dst, "\\\\")), + c if c < '\u{1f}' => drop(write!(self.dst, "\\u{:04X}", ch as u32)), + ch => drop(write!(self.dst, "{}", ch)), } - ch => drop(write!(self.dst, "{}", ch)), } } if do_pretty { @@ -651,7 +645,7 @@ impl<'a, 'b> ser::Serializer for &'b mut Serializer<'a> { fn serialize_str(mut self, value: &str) -> Result<(), Self::Error> { self.emit_key("string")?; - self.emit_str(value)?; + self.emit_str(value, false)?; if let State::Table { .. } = self.state { self.dst.push_str("\n"); } diff --git a/tests/pretty.rs b/tests/pretty.rs index ae9a839..f7d1612 100644 --- a/tests/pretty.rs +++ b/tests/pretty.rs @@ -166,3 +166,22 @@ fn pretty_no_string() { } assert_eq!(toml, &result); } + +const PRETTY_TRICKY: &'static str = r"[example] +text = ''' +this is the first line +This has a ''\' in it for no reason +this is the third line +''' +"; + +#[test] +fn pretty_tricky() { + let toml = PRETTY_TRICKY; + let value: toml::Value = toml::from_str(toml).unwrap(); + let mut result = String::with_capacity(128); + value.serialize(&mut toml::Serializer::pretty(&mut result)).unwrap(); + println!("EXPECTED:\n{}", toml); + println!("\nRESULT:\n{}", result); + assert_eq!(toml, &result); +} diff --git a/tests/valid.rs b/tests/valid.rs index 6a04866..b186800 100644 --- a/tests/valid.rs +++ b/tests/valid.rs @@ -1,7 +1,9 @@ extern crate toml; +extern crate serde; extern crate serde_json; -use toml::Value as Toml; +use toml::{Value as Toml, to_string_pretty}; +use serde::ser::Serialize; use serde_json::Value as Json; fn to_json(toml: toml::Value) -> Json { @@ -40,10 +42,52 @@ fn to_json(toml: toml::Value) -> Json { } } -fn run(toml: &str, json: &str) { - println!("parsing:\n{}", toml); - let toml: Toml = toml.parse().unwrap(); - let json: Json = json.parse().unwrap(); +fn run_pretty(toml: Toml) { + // Assert toml == json + println!("### pretty round trip parse."); + + // standard pretty + let toml_raw = to_string_pretty(&toml).expect("to string"); + let toml2 = toml_raw.parse().expect("from string"); + assert_eq!(toml, toml2); + + // pretty with indent 2 + let mut result = String::with_capacity(128); + { + let mut serializer = toml::Serializer::pretty(&mut result); + serializer.pretty_array_indent(2); + toml.serialize(&mut serializer).expect("to string"); + } + assert_eq!(toml, result.parse().expect("from str")); + result.clear(); + { + let mut serializer = toml::Serializer::new(&mut result); + serializer.pretty_array_trailing_comma(false); + toml.serialize(&mut serializer).expect("to string"); + } + assert_eq!(toml, result.parse().expect("from str")); + result.clear(); + { + let mut serializer = toml::Serializer::pretty(&mut result); + serializer.pretty_string(false); + toml.serialize(&mut serializer).expect("to string"); + assert_eq!(toml, toml2); + } + assert_eq!(toml, result.parse().expect("from str")); + result.clear(); + { + let mut serializer = toml::Serializer::pretty(&mut result); + serializer.pretty_array(false); + toml.serialize(&mut serializer).expect("to string"); + assert_eq!(toml, toml2); + } + assert_eq!(toml, result.parse().expect("from str")); +} + +fn run(toml_raw: &str, json_raw: &str) { + println!("parsing:\n{}", toml_raw); + let toml: Toml = toml_raw.parse().unwrap(); + let json: Json = json_raw.parse().unwrap(); // Assert toml == json let toml_json = to_json(toml.clone()); @@ -56,6 +100,7 @@ fn run(toml: &str, json: &str) { println!("round trip parse: {}", toml); let toml2 = toml.to_string().parse().unwrap(); assert_eq!(toml, toml2); + run_pretty(toml); } macro_rules! test( ($name:ident, $toml:expr, $json:expr) => (