diff --git a/Cargo.lock b/Cargo.lock index 023ccb8..6e0b90a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -121,6 +121,7 @@ dependencies = [ "regex", "serde", "strong-xml", + "thiserror", ] [[package]] @@ -162,9 +163,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.19" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" dependencies = [ "unicode-xid", ] @@ -235,9 +236,9 @@ dependencies = [ [[package]] name = "strong-xml" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee06e7e5baf4508dea83506a83fcc5b80a404d4c0e9c473c9a4b38b802af3a07" +checksum = "da0e355b33893aa1b6d2f29110e729609c87a4241817a3e53ffba4c31421b1b1" dependencies = [ "jetscii", "lazy_static", @@ -248,9 +249,9 @@ dependencies = [ [[package]] name = "strong-xml-derive" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2e4e25fb64e61f55d495134d9e5ac68b1fa4bb2855b5a5b53857b9460e2bfde" +checksum = "e9053670189294a3fa7d7379a58b07ab0d0608debe80f5a16d31e2faa6e13b69" dependencies = [ "proc-macro2", "quote", @@ -265,9 +266,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "syn" -version = "1.0.39" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" +checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f" dependencies = [ "proc-macro2", "quote", @@ -283,6 +284,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.0.1" diff --git a/opml_api/Cargo.toml b/opml_api/Cargo.toml index ff9305c..99bfe0c 100644 --- a/opml_api/Cargo.toml +++ b/opml_api/Cargo.toml @@ -17,4 +17,5 @@ path = "source/lib.rs" [dependencies] regex = "1.3" serde = { version = "1.0", features = ["derive"] } -strong-xml = "0.6" +strong-xml = "0.6.1" +thiserror = "1.0.24" diff --git a/opml_api/source/lib.rs b/opml_api/source/lib.rs index 327d448..8b188c6 100644 --- a/opml_api/source/lib.rs +++ b/opml_api/source/lib.rs @@ -61,10 +61,23 @@ use regex::Regex; use serde::{Deserialize, Serialize}; -use strong_xml::{XmlError, XmlRead, XmlWrite}; +use strong_xml::{XmlRead, XmlWrite}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum Error { + #[error("OPML body has no elements")] + BodyHasNoOutlines, + #[error("Unsupported OPML version: {0:?}")] + UnsupportedVersion(String), + #[error("Failed to process XML file")] + XmlError(#[from] strong_xml::XmlError), +} /// The top-level [OPML](struct.OPML.html) element. -#[derive(XmlWrite, XmlRead, PartialEq, Debug, Clone, Serialize, Deserialize)] +#[derive( + XmlWrite, XmlRead, PartialEq, Debug, Clone, Serialize, Deserialize, +)] #[xml(tag = "opml")] pub struct OPML { /// The version attribute from the element, valid values are `1.0`, `1.1` and `2.0`. @@ -99,13 +112,8 @@ impl OPML { /// /// assert_eq!(parsed, expected); /// ``` - pub fn new(xml: &str) -> Result { - let opml: Result = OPML::from_str(xml); - - let opml = match opml { - Ok(value) => value, - Err(err) => return Err(format!("XML parsing error: {:#?}", err)), - }; + pub fn new(xml: &str) -> Result { + let opml = OPML::from_str(xml)?; let version = &opml.version; @@ -116,15 +124,12 @@ impl OPML { if !valid_version_regex.is_match(version) || !valid_versions.contains(&version.as_str()) { - return Err(format!( - "Unsupported OPML version detected: {}", - opml.version - )); + return Err(Error::UnsupportedVersion(opml.version)); } // SPEC: A `` contains one or more `` elements. if opml.body.outlines.is_empty() { - return Err("OPML body has no outlines.".to_string()); + return Err(Error::BodyHasNoOutlines); } Ok(opml) @@ -172,13 +177,8 @@ impl OPML { /// let expected = r#""#; /// assert_eq!(xml, expected); /// ``` - pub fn to_xml(&self) -> Result { - let result: Result = self.to_string(); - - match result { - Ok(value) => Ok(value), - Err(err) => Err(format!("XML writing error: {:#?}", err)), - } + pub fn to_xml(&self) -> Result { + Ok(self.to_string()?) } } diff --git a/opml_api/tests/errors.rs b/opml_api/tests/errors.rs index e3265c5..b2fa0c8 100644 --- a/opml_api/tests/errors.rs +++ b/opml_api/tests/errors.rs @@ -1,6 +1,5 @@ -use std::fs::read_to_string as read; - use opml::*; +use std::fs::read_to_string as read; #[test] #[should_panic] @@ -10,15 +9,15 @@ fn test_invalid_xml() { } #[test] -#[should_panic(expected = "Unsupported OPML version detected: invalid")] fn test_invalid_opml_version() { let sample = read("tests/samples/invalid_opml_version.opml").unwrap(); - OPML::new(sample.as_str()).unwrap(); + let res = OPML::new(sample.as_str()); + assert!(matches!(res, Err(Error::UnsupportedVersion(e)) if e == "invalid")); } #[test] -#[should_panic(expected = "OPML body has no outlines.")] fn test_invalid_opml_no_outlines() { let sample = read("tests/samples/invalid_opml_no_outlines.opml").unwrap(); - OPML::new(sample.as_str()).unwrap(); + let res = OPML::new(sample.as_str()); + assert!(matches!(res, Err(Error::BodyHasNoOutlines))); }