use crate::model::Format;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("unsupported format: {detail}")]
UnsupportedFormat {
detail: String,
},
#[error("malformed {format:?} input: {context}")]
Malformed {
format: Format,
context: String,
},
#[error("{0:?} file is DRM-protected; boko does not decrypt")]
DrmProtected(Format),
#[error("not found: {what}")]
NotFound {
what: String,
},
}
pub type Result<T> = std::result::Result<T, Error>;
impl From<Error> for std::io::Error {
fn from(e: Error) -> Self {
match e {
Error::Io(io) => io,
Error::NotFound { .. } => std::io::Error::new(std::io::ErrorKind::NotFound, e),
Error::UnsupportedFormat { .. } => {
std::io::Error::new(std::io::ErrorKind::Unsupported, e)
}
Error::DrmProtected(_) => std::io::Error::new(std::io::ErrorKind::PermissionDenied, e),
Error::Malformed { .. } => std::io::Error::new(std::io::ErrorKind::InvalidData, e),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn io_error_roundtrip() {
let io = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "nope");
let err = Error::from(io);
let back: std::io::Error = err.into();
assert_eq!(back.kind(), std::io::ErrorKind::PermissionDenied);
}
#[test]
fn kind_mapping() {
let err: std::io::Error = Error::NotFound {
what: "chapter 3".into(),
}
.into();
assert_eq!(err.kind(), std::io::ErrorKind::NotFound);
let err: std::io::Error = Error::UnsupportedFormat {
detail: "mobi write".into(),
}
.into();
assert_eq!(err.kind(), std::io::ErrorKind::Unsupported);
let err: std::io::Error = Error::DrmProtected(Format::Azw3).into();
assert_eq!(err.kind(), std::io::ErrorKind::PermissionDenied);
let err: std::io::Error = Error::Malformed {
format: Format::Kfx,
context: "bad".into(),
}
.into();
assert_eq!(err.kind(), std::io::ErrorKind::InvalidData);
}
#[test]
fn display_output() {
let err = Error::Malformed {
format: Format::Kfx,
context: "truncated entity table".into(),
};
assert_eq!(
err.to_string(),
"malformed Kfx input: truncated entity table"
);
let err = Error::NotFound {
what: "images/cover.jpg".into(),
};
assert_eq!(err.to_string(), "not found: images/cover.jpg");
}
}