Skip to content

Commit

Permalink
Reduce public dependencies
Browse files Browse the repository at this point in the history
Hiding error variants from a library's public error type to prevent
dependency updates from becoming breaking changes.
We can add `UrdfErrorKind` enum or `is_*` methods that indicate the kind of
error if needed, but don't expose dependencies' types directly in the
public API.
  • Loading branch information
taiki-e committed Jan 28, 2021
1 parent 5910729 commit 5b6eaad
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 48 deletions.
8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ categories = ["data-structures", "parsing"]
repository = "https://github.com/openrr/urdf-rs"
documentation = "http://docs.rs/urdf-rs"

# Note: serde is public dependency.
[dependencies]
serde-xml-rs = "0.4.0"
serde = { version = "1.0.118", features = ["derive"] }
RustyXML = "0.3.0"
regex = "1.4.2"
RustyXML = "0.3.0"
serde = { version = "1.0.118", features = ["derive"] }
serde-xml-rs = "0.4.0"
thiserror = "1.0.7"
78 changes: 37 additions & 41 deletions src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,58 +1,54 @@
use std::error::Error;
use std::fmt;
use std::string;

#[derive(Debug)]
pub enum UrdfError {
File(::std::io::Error),
Xml(::serde_xml_rs::Error),
RustyXml(::xml::BuilderError),
Parse(String),
use thiserror::Error;

/// Alias for a `Result` with the error type `UrdfError`.
pub type Result<T> = std::result::Result<T, UrdfError>;

#[derive(Debug, Error)]
#[error(transparent)]
pub struct UrdfError(#[from] ErrorKind);

// Hiding error variants from a library's public error type to prevent
// dependency updates from becoming breaking changes.
// We can add `UrdfErrorKind` enum or `is_*` methods that indicate the kind of
// error if needed, but don't expose dependencies' types directly in the
// public API.
#[derive(Debug, Error)]
pub(crate) enum ErrorKind {
#[error(transparent)]
File(#[from] std::io::Error),
#[error(transparent)]
Xml(#[from] serde_xml_rs::Error),
#[error(transparent)]
RustyXml(#[from] xml::BuilderError),
#[error("command error {}", .0)]
Command(String),
}

pub type Result<T> = ::std::result::Result<T, UrdfError>;

impl fmt::Display for UrdfError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
UrdfError::File(ref err) => err.fmt(f),
UrdfError::Xml(ref err) => err.fmt(f),
UrdfError::RustyXml(ref err) => err.fmt(f),
UrdfError::Parse(ref msg) => write!(f, "parse error {}", msg),
UrdfError::Command(ref msg) => write!(f, "command error {}", msg),
}
impl UrdfError {
pub(crate) fn new(err: impl Into<ErrorKind>) -> Self {
Self(err.into())
}
}

impl Error for UrdfError {}

impl From<std::io::Error> for UrdfError {
fn from(err: std::io::Error) -> UrdfError {
UrdfError::File(err)
}
}

impl From<serde_xml_rs::Error> for UrdfError {
fn from(err: serde_xml_rs::Error) -> UrdfError {
UrdfError::Xml(err)
ErrorKind::File(err).into()
}
}

impl From<xml::BuilderError> for UrdfError {
fn from(err: xml::BuilderError) -> UrdfError {
UrdfError::RustyXml(err)
impl From<&str> for UrdfError {
fn from(err: &str) -> UrdfError {
ErrorKind::Command(err.to_owned()).into()
}
}

impl<'a> From<&'a str> for UrdfError {
fn from(err: &'a str) -> UrdfError {
UrdfError::Command(err.to_owned())
impl From<std::string::FromUtf8Error> for UrdfError {
fn from(err: std::string::FromUtf8Error) -> UrdfError {
ErrorKind::Command(err.to_string()).into()
}
}

impl From<string::FromUtf8Error> for UrdfError {
fn from(err: string::FromUtf8Error) -> UrdfError {
UrdfError::Command(err.to_string())
}
}
// Note: These implementations are intentionally not-exist to prevent dependency
// updates from becoming breaking changes.
// impl From<serde_xml_rs::Error> for UrdfError
// impl From<xml::BuilderError> for UrdfError
4 changes: 2 additions & 2 deletions src/funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::path::Path;

/// sort <link> and <joint> to avoid the [issue](https://github.com/RReverser/serde-xml-rs/issues/5)
fn sort_link_joint(string: &str) -> Result<String> {
let e: xml::Element = string.parse()?;
let e: xml::Element = string.parse().map_err(UrdfError::new)?;
let mut links = Vec::new();
let mut joints = Vec::new();
let mut materials = Vec::new();
Expand Down Expand Up @@ -94,7 +94,7 @@ pub fn read_file<P: AsRef<Path>>(path: P) -> Result<Robot> {
pub fn read_from_string(string: &str) -> Result<Robot> {
let sorted_string = sort_link_joint(string)?;
serde_xml_rs::from_str(&sorted_string).map_err(From::from)
serde_xml_rs::from_str(&sorted_string).map_err(UrdfError::new)
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ where
if output.status.success() {
Ok(String::from_utf8(output.stdout)?)
} else {
Err(UrdfError::Command("faild to xacro".to_owned()))
Err(ErrorKind::Command("faild to xacro".to_owned()).into())
}
}

Expand Down Expand Up @@ -73,7 +73,7 @@ where
read_file(&input_path)
}
} else {
return Err(UrdfError::Command("failed to get extension".to_owned()));
Err(ErrorKind::Command("failed to get extension".to_owned()).into())
}
}

Expand Down

0 comments on commit 5b6eaad

Please # to comment.