fix bugs with pretty

This commit is contained in:
Garrett Berg 2017-07-27 16:37:30 -06:00
parent f81a488362
commit 83be829f0b
3 changed files with 92 additions and 34 deletions

View file

@ -450,14 +450,18 @@ impl<'a> Serializer<'a> {
if ok { if ok {
drop(write!(self.dst, "{}", key)); drop(write!(self.dst, "{}", key));
} else { } else {
self.emit_str(key)?; self.emit_str(key, true)?;
} }
Ok(()) Ok(())
} }
fn emit_str(&mut self, value: &str) -> Result<(), Error> { fn emit_str(&mut self, value: &str, is_key: bool) -> Result<(), Error> {
let do_pretty = if self.settings.pretty_string { let do_pretty = if !is_key && self.settings.pretty_string {
// do pretty only if the block contains at least one newline
value.contains('\n') value.contains('\n')
// but not if it contains any of these, as they are not
// representable
&& !value.contains("'''")
} else { } else {
false false
}; };
@ -466,31 +470,21 @@ impl<'a> Serializer<'a> {
} else { } else {
drop(write!(self.dst, "\"")); drop(write!(self.dst, "\""));
} }
for ch in value.chars() { if do_pretty {
match ch { drop(write!(self.dst, "{}", value));
'\u{8}' => drop(write!(self.dst, "\\b")), } else {
'\u{9}' => drop(write!(self.dst, "\\t")), for ch in value.chars() {
'\u{a}' => { match ch {
if do_pretty { '\u{8}' => drop(write!(self.dst, "\\b")),
drop(write!(self.dst, "\n")); '\u{9}' => drop(write!(self.dst, "\\t")),
} else { '\u{a}' => drop(write!(self.dst, "\\n")),
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{c}' => drop(write!(self.dst, "\\f")), '\u{5c}' => drop(write!(self.dst, "\\\\")),
'\u{d}' => drop(write!(self.dst, "\\r")), c if c < '\u{1f}' => drop(write!(self.dst, "\\u{:04X}", ch as u32)),
'\u{22}' => { ch => drop(write!(self.dst, "{}", ch)),
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))
} }
ch => drop(write!(self.dst, "{}", ch)),
} }
} }
if do_pretty { 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> { fn serialize_str(mut self, value: &str) -> Result<(), Self::Error> {
self.emit_key("string")?; self.emit_key("string")?;
self.emit_str(value)?; self.emit_str(value, false)?;
if let State::Table { .. } = self.state { if let State::Table { .. } = self.state {
self.dst.push_str("\n"); self.dst.push_str("\n");
} }

View file

@ -166,3 +166,22 @@ fn pretty_no_string() {
} }
assert_eq!(toml, &result); 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);
}

View file

@ -1,7 +1,9 @@
extern crate toml; extern crate toml;
extern crate serde;
extern crate serde_json; 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; use serde_json::Value as Json;
fn to_json(toml: toml::Value) -> 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) { fn run_pretty(toml: Toml) {
println!("parsing:\n{}", toml); // Assert toml == json
let toml: Toml = toml.parse().unwrap(); println!("### pretty round trip parse.");
let json: Json = json.parse().unwrap();
// 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 // Assert toml == json
let toml_json = to_json(toml.clone()); let toml_json = to_json(toml.clone());
@ -56,6 +100,7 @@ fn run(toml: &str, json: &str) {
println!("round trip parse: {}", toml); println!("round trip parse: {}", toml);
let toml2 = toml.to_string().parse().unwrap(); let toml2 = toml.to_string().parse().unwrap();
assert_eq!(toml, toml2); assert_eq!(toml, toml2);
run_pretty(toml);
} }
macro_rules! test( ($name:ident, $toml:expr, $json:expr) => ( macro_rules! test( ($name:ident, $toml:expr, $json:expr) => (