Skip to content

Commit

Permalink
Apply feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
RickyDaMa committed Aug 1, 2023
1 parent d440af5 commit 465d86a
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 163 deletions.
8 changes: 4 additions & 4 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,23 @@ use crate::Name;
#[non_exhaustive]
pub enum DesignSpaceLoadError {
/// An [`std::io::Error`].
#[error("failed to read file")]
#[error("failed to read designspace file: {0}")]
Io(#[from] IoError),

/// A parse error.
#[error("failed to deserialize")]
#[error("failed to deserialize designspace: {0}")]
DeError(#[from] DeError),
}

/// An error that occurs while attempting to write a designspace file to disk.
#[derive(Debug, Error)]
pub enum DesignSpaceSaveError {
/// An [`std::io::Error`].
#[error("failed to open/write file")]
#[error("failed to open/write designspace file: {0}")]
Io(#[from] IoError),

/// A serialization error.
#[error("failed to deserialize")]
#[error("failed to serialize designspace: {0}")]
SeError(#[from] DeError),
}

Expand Down
308 changes: 149 additions & 159 deletions src/serde_xml_plist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ mod ser {
"ValueInnerHelper should never serialize a boolean as it has no inner"
)
}
// TODO: once plist v1.6 is released, replace this with Data::to_xml_format
Value::Data(d) => serializer.serialize_str(&base64_standard.encode(d)),
Value::Date(d) => serializer.serialize_str(&d.to_xml_format()),
Value::Real(r) => serializer.serialize_f64(*r),
Expand Down Expand Up @@ -484,174 +485,163 @@ mod tests {
lib: Dictionary,
}

mod de {
use super::*;

#[test]
fn deserialize_everything() {
let xml = r#"
<?xml version='1.0' encoding='UTF-8'?>
<object>
<lib>
<dict>
<key>hasLoadedLib</key>
<string>Absolutely!</string>
<key>anArray</key>
<array>
<dict>
<key>class</key>
<string>aristocracy</string>
<key>heft</key>
<real>42.42</real>
</dict>
<integer>6</integer>
</array>
<key>isWorking</key>
<true/>
<key>isBroken</key>
<false/>
<key>bestBefore</key>
<date>2345-01-24T23:22:21Z</date>
<key>payload</key>
<data>
dSBnb3QgMHduZWQ=
</data>
</dict>
</lib>
</object>
"#;

let readme: TestMe = quick_xml::de::from_str(xml).unwrap();
assert_eq!(readme.lib.get("hasLoadedLib").unwrap().as_string(), Some("Absolutely!"));
let array = readme.lib.get("anArray").unwrap().as_array().unwrap();
assert_eq!(
array[0].as_dictionary().and_then(|d| d.get("class")),
Some(&Value::String("aristocracy".into()))
);
assert_eq!(
array[0].as_dictionary().and_then(|d| d.get("heft")),
Some(&Value::Real(42.42))
);
assert_eq!(array[1].as_signed_integer(), Some(6));
assert_eq!(readme.lib.get("isWorking"), Some(&Value::Boolean(true)));
assert_eq!(readme.lib.get("isBroken"), Some(&Value::Boolean(false)));
assert_eq!(
readme.lib.get("bestBefore").and_then(Value::as_date).map(|d| d.to_xml_format()),
Some("2345-01-24T23:22:21Z".into())
);
assert_eq!(
readme.lib.get("payload").and_then(Value::as_data),
Some("u got 0wned".as_bytes())
);
}

#[test]
fn empty_array_is_a_okay() {
let xml = r#"
<?xml version='1.0' encoding='UTF-8'?>
<object>
<lib>
<dict>
<key>emptyDict</key>
<dict></dict>
<key>emptyArray</key>
<array></array>
<key>emptyString</key>
<string></string>
</dict>
</lib>
</object>
"#;

let readme: TestMe = quick_xml::de::from_str(xml).unwrap();
assert_eq!(
readme.lib.get("emptyDict").and_then(Value::as_dictionary),
Some(&Dictionary::new())
);
assert_eq!(readme.lib.get("emptyArray").and_then(Value::as_array), Some(&Vec::new()));
assert_eq!(readme.lib.get("emptyString").and_then(Value::as_string), Some(""));
}

#[test]
#[should_panic(expected = "Invalid XML data")]
fn invalid_data() {
let xml = r#"
<?xml version='1.0' encoding='UTF-8'?>
<object>
<lib>
<dict>
<key>badData</key>
<data>💣</data>
</dict>
</lib>
</object>
"#;

let _readme: TestMe = quick_xml::de::from_str(xml).unwrap();
}

#[test]
#[should_panic(expected = "date")]
fn invalid_date() {
let xml = r#"
<?xml version='1.0' encoding='UTF-8'?>
<object>
<lib>
#[test]
fn deserialize_everything() {
let xml = r#"
<?xml version='1.0' encoding='UTF-8'?>
<object>
<lib>
<dict>
<key>hasLoadedLib</key>
<string>Absolutely!</string>
<key>anArray</key>
<array>
<dict>
<key>badDate</key>
<date>yesterday</date>
<key>class</key>
<string>aristocracy</string>
<key>heft</key>
<real>42.42</real>
</dict>
</lib>
</object>
"#;
<integer>6</integer>
</array>
<key>isWorking</key>
<true/>
<key>isBroken</key>
<false/>
<key>bestBefore</key>
<date>2345-01-24T23:22:21Z</date>
<key>payload</key>
<data>
dSBnb3QgMHduZWQ=
</data>
</dict>
</lib>
</object>
"#;

let readme: TestMe = quick_xml::de::from_str(xml).unwrap();
assert_eq!(readme.lib.get("hasLoadedLib").unwrap().as_string(), Some("Absolutely!"));
let array = readme.lib.get("anArray").unwrap().as_array().unwrap();
assert_eq!(
array[0].as_dictionary().and_then(|d| d.get("class")),
Some(&Value::String("aristocracy".into()))
);
assert_eq!(array[0].as_dictionary().and_then(|d| d.get("heft")), Some(&Value::Real(42.42)));
assert_eq!(array[1].as_signed_integer(), Some(6));
assert_eq!(readme.lib.get("isWorking"), Some(&Value::Boolean(true)));
assert_eq!(readme.lib.get("isBroken"), Some(&Value::Boolean(false)));
assert_eq!(
readme.lib.get("bestBefore").and_then(Value::as_date).map(|d| d.to_xml_format()),
Some("2345-01-24T23:22:21Z".into())
);
assert_eq!(
readme.lib.get("payload").and_then(Value::as_data),
Some("u got 0wned".as_bytes())
);
}

let _readme: TestMe = quick_xml::de::from_str(xml).unwrap();
}
#[test]
fn empty_array_is_a_okay() {
let xml = r#"
<?xml version='1.0' encoding='UTF-8'?>
<object>
<lib>
<dict>
<key>emptyDict</key>
<dict></dict>
<key>emptyArray</key>
<array></array>
<key>emptyString</key>
<string></string>
</dict>
</lib>
</object>
"#;

let readme: TestMe = quick_xml::de::from_str(xml).unwrap();
assert_eq!(
readme.lib.get("emptyDict").and_then(Value::as_dictionary),
Some(&Dictionary::new())
);
assert_eq!(readme.lib.get("emptyArray").and_then(Value::as_array), Some(&Vec::new()));
assert_eq!(readme.lib.get("emptyString").and_then(Value::as_string), Some(""));
}

mod ser {
use super::*;
#[test]
#[should_panic(expected = "Invalid XML data")]
fn invalid_data() {
let xml = r#"
<?xml version='1.0' encoding='UTF-8'?>
<object>
<lib>
<dict>
<key>badData</key>
<data>💣</data>
</dict>
</lib>
</object>
"#;

let _readme: TestMe = quick_xml::de::from_str(xml).unwrap();
}

use expect_test::{expect_file, ExpectFile};
use serde::Serialize;
use std::f64::consts::PI;
use std::time::SystemTime;
#[test]
#[should_panic(expected = "date")]
fn invalid_date() {
let xml = r#"
<?xml version='1.0' encoding='UTF-8'?>
<object>
<lib>
<dict>
<key>badDate</key>
<date>yesterday</date>
</dict>
</lib>
</object>
"#;

let _readme: TestMe = quick_xml::de::from_str(xml).unwrap();
}

fn to_xml_pretty(lib: Dictionary) -> String {
let mut buf = String::new();
let mut xml_writer = quick_xml::se::Serializer::new(&mut buf);
xml_writer.indent(' ', 2);
TestMe { lib }.serialize(xml_writer).unwrap();
buf
}
use expect_test::{expect_file, ExpectFile};
use serde::Serialize;
use std::f64::consts::PI;
use std::time::SystemTime;

fn to_xml_pretty(lib: Dictionary) -> String {
let mut buf = String::new();
let mut xml_writer = quick_xml::se::Serializer::new(&mut buf);
xml_writer.indent(' ', 2);
TestMe { lib }.serialize(xml_writer).unwrap();
buf
}

fn check(lib: Dictionary, expect: ExpectFile) {
let serialized = to_xml_pretty(lib);
expect.assert_eq(&serialized);
}
fn check(lib: Dictionary, expect: ExpectFile) {
let serialized = to_xml_pretty(lib);
expect.assert_eq(&serialized);
}

#[test]
fn empty() {
let lib = Dictionary::new();
check(lib, expect_file!("../testdata/empty.plist"));
}
#[test]
fn empty() {
let lib = Dictionary::new();
check(lib, expect_file!("../testdata/empty.plist"));
}

#[test]
fn a_bit_of_everything() {
let mut lib = Dictionary::new();
lib.insert(String::from("enabled"), Value::Boolean(true));
lib.insert(String::from("disabled"), Value::Boolean(false));
lib.insert(String::from("name"), Value::String("John Cena".into()));
lib.insert(String::from("age"), Value::Integer(46.into()));
lib.insert(String::from("today"), Value::Date(SystemTime::UNIX_EPOCH.into()));
lib.insert(String::from("pi"), Value::Real(PI));
lib.insert(String::from("wisdom"), Value::Data(vec![1, 2, 3]));
lib.insert(String::from("listicle"), Value::Array(lib.values().cloned().collect()));
lib.insert(String::from("recurse"), Value::Dictionary(lib.clone()));
lib.insert(String::from("empty_array"), Value::Array(Vec::new()));
lib.insert(String::from("empty_dict"), Value::Dictionary(Dictionary::new()));

check(lib, expect_file!("../testdata/a_bit_of_everything.plist"));
}
#[test]
fn a_bit_of_everything() {
let mut lib = Dictionary::new();
lib.insert(String::from("enabled"), Value::Boolean(true));
lib.insert(String::from("disabled"), Value::Boolean(false));
lib.insert(String::from("name"), Value::String("John Cena".into()));
lib.insert(String::from("age"), Value::Integer(46.into()));
lib.insert(String::from("today"), Value::Date(SystemTime::UNIX_EPOCH.into()));
lib.insert(String::from("pi"), Value::Real(PI));
lib.insert(String::from("wisdom"), Value::Data(vec![1, 2, 3]));
lib.insert(String::from("listicle"), Value::Array(lib.values().cloned().collect()));
lib.insert(String::from("recurse"), Value::Dictionary(lib.clone()));
lib.insert(String::from("empty_array"), Value::Array(Vec::new()));
lib.insert(String::from("empty_dict"), Value::Dictionary(Dictionary::new()));

check(lib, expect_file!("../testdata/a_bit_of_everything.plist"));
}
}

0 comments on commit 465d86a

Please sign in to comment.