use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Error)]
pub enum Error {
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("unsupported: {0}")]
Unsupported(String),
#[error("invalid data: {0}")]
InvalidData(String),
#[error("end of stream")]
Eof,
#[error("need more data")]
NeedMore,
#[error("format not found: {0}")]
FormatNotFound(String),
#[error("codec not found: {0}")]
CodecNotFound(String),
#[error("resource exhausted: {0}")]
ResourceExhausted(String),
#[error("{0}")]
Other(String),
}
impl Error {
pub fn unsupported(msg: impl Into<String>) -> Self {
Self::Unsupported(msg.into())
}
pub fn invalid(msg: impl Into<String>) -> Self {
Self::InvalidData(msg.into())
}
pub fn other(msg: impl Into<String>) -> Self {
Self::Other(msg.into())
}
pub fn resource_exhausted(msg: impl Into<String>) -> Self {
Self::ResourceExhausted(msg.into())
}
pub fn format_not_found(msg: impl Into<String>) -> Self {
Self::FormatNotFound(msg.into())
}
pub fn codec_not_found(msg: impl Into<String>) -> Self {
Self::CodecNotFound(msg.into())
}
pub fn is_eof(&self) -> bool {
matches!(self, Self::Eof)
}
pub fn is_need_more(&self) -> bool {
matches!(self, Self::NeedMore)
}
pub fn is_resource_exhausted(&self) -> bool {
matches!(self, Self::ResourceExhausted(_))
}
pub fn is_starved(&self) -> bool {
matches!(self, Self::Eof | Self::NeedMore)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn constructors_produce_matching_variants() {
assert!(matches!(
Error::format_not_found("mkv"),
Error::FormatNotFound(s) if s == "mkv"
));
assert!(matches!(
Error::codec_not_found("vp8"),
Error::CodecNotFound(s) if s == "vp8"
));
assert!(matches!(
Error::resource_exhausted("pool"),
Error::ResourceExhausted(s) if s == "pool"
));
}
#[test]
fn predicates_partition_correctly() {
assert!(Error::Eof.is_eof());
assert!(!Error::Eof.is_need_more());
assert!(Error::NeedMore.is_need_more());
assert!(!Error::NeedMore.is_eof());
assert!(Error::Eof.is_starved());
assert!(Error::NeedMore.is_starved());
assert!(Error::resource_exhausted("x").is_resource_exhausted());
for e in [
Error::invalid("bad"),
Error::unsupported("feature"),
Error::other("misc"),
Error::format_not_found("f"),
Error::codec_not_found("c"),
] {
assert!(!e.is_eof());
assert!(!e.is_need_more());
assert!(!e.is_starved());
assert!(!e.is_resource_exhausted());
}
}
#[test]
fn display_messages_are_stable() {
assert_eq!(Error::Eof.to_string(), "end of stream");
assert_eq!(Error::NeedMore.to_string(), "need more data");
assert_eq!(Error::invalid("x").to_string(), "invalid data: x");
assert_eq!(Error::unsupported("y").to_string(), "unsupported: y");
assert_eq!(
Error::format_not_found("z").to_string(),
"format not found: z"
);
assert_eq!(
Error::codec_not_found("w").to_string(),
"codec not found: w"
);
assert_eq!(
Error::resource_exhausted("v").to_string(),
"resource exhausted: v"
);
assert_eq!(Error::other("u").to_string(), "u");
}
}