#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[error("no extractor supports this URL: {0}")]
UnsupportedUrl(String),
#[error("network error during {stage}: {source}")]
Network {
stage: &'static str,
#[source]
source: reqwest::Error,
},
#[error("extraction failed at {stage}: {message}")]
Extraction {
stage: &'static str,
message: String,
},
#[error("media unavailable: {reason}")]
Unavailable {
reason: UnavailableReason,
message: String,
},
#[error("cipher error: {0}")]
Cipher(String),
#[error("no matching format: {0}")]
FormatNotFound(String),
#[error("io error: {0}")]
Io(#[from] std::io::Error),
#[error("postprocess error: {0}")]
Postprocess(String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum UnavailableReason {
Gone,
AgeRestricted,
GeoBlocked,
Live,
Other,
}
impl std::fmt::Display for UnavailableReason {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
UnavailableReason::Gone => "gone",
UnavailableReason::AgeRestricted => "age-restricted",
UnavailableReason::GeoBlocked => "geo-blocked",
UnavailableReason::Live => "live",
UnavailableReason::Other => "other",
};
f.write_str(s)
}
}
pub type Result<T> = std::result::Result<T, Error>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn error_display_is_useful() {
let e = Error::UnsupportedUrl("https://example.com/x".into());
assert!(e.to_string().contains("example.com"));
}
}