use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Error, Debug)]
pub enum Error {
#[error("Failed to fetch manifest: {0}")]
ManifestFetch(String),
#[error("Failed to parse manifest: {0}")]
ManifestParse(String),
#[error("Invalid manifest format: {0}")]
InvalidManifest(String),
#[error("No suitable rendition found")]
NoSuitableRendition,
#[error("Failed to fetch segment: {url}")]
SegmentFetch { url: String, source: reqwest::Error },
#[error("Segment timeout: {url}")]
SegmentTimeout { url: String },
#[error("Segment decryption failed")]
SegmentDecryption,
#[error("Buffer underrun")]
BufferUnderrun,
#[error("Buffer overflow")]
BufferOverflow,
#[error("Buffer seek failed: position {position}s not buffered")]
BufferSeekFailed { position: f64 },
#[error("DRM not supported: {system}")]
DrmNotSupported { system: String },
#[error("License acquisition failed: {0}")]
LicenseAcquisition(String),
#[error("License expired")]
LicenseExpired,
#[error("Content key not found")]
ContentKeyNotFound,
#[error("Playback stalled")]
PlaybackStalled,
#[error("Invalid playback state transition: {from} -> {to}")]
InvalidStateTransition { from: String, to: String },
#[error("Codec not supported: {codec}")]
CodecNotSupported { codec: String },
#[error("Network error: {0}")]
Network(#[from] reqwest::Error),
#[error("Connection timeout")]
ConnectionTimeout,
#[error("Invalid configuration: {0}")]
InvalidConfig(String),
#[error("Internal error: {0}")]
Internal(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
}
impl Error {
pub fn drm(msg: impl Into<String>) -> Self {
Error::LicenseAcquisition(msg.into())
}
pub fn is_recoverable(&self) -> bool {
matches!(
self,
Error::SegmentFetch { .. }
| Error::SegmentTimeout { .. }
| Error::BufferUnderrun
| Error::Network(_)
| Error::ConnectionTimeout
)
}
pub fn error_code(&self) -> &'static str {
match self {
Error::ManifestFetch(_) => "MANIFEST_FETCH",
Error::ManifestParse(_) => "MANIFEST_PARSE",
Error::InvalidManifest(_) => "INVALID_MANIFEST",
Error::NoSuitableRendition => "NO_RENDITION",
Error::SegmentFetch { .. } => "SEGMENT_FETCH",
Error::SegmentTimeout { .. } => "SEGMENT_TIMEOUT",
Error::SegmentDecryption => "SEGMENT_DECRYPT",
Error::BufferUnderrun => "BUFFER_UNDERRUN",
Error::BufferOverflow => "BUFFER_OVERFLOW",
Error::BufferSeekFailed { .. } => "BUFFER_SEEK",
Error::DrmNotSupported { .. } => "DRM_UNSUPPORTED",
Error::LicenseAcquisition(_) => "LICENSE_ACQUIRE",
Error::LicenseExpired => "LICENSE_EXPIRED",
Error::ContentKeyNotFound => "KEY_NOT_FOUND",
Error::PlaybackStalled => "PLAYBACK_STALLED",
Error::InvalidStateTransition { .. } => "INVALID_STATE",
Error::CodecNotSupported { .. } => "CODEC_UNSUPPORTED",
Error::Network(_) => "NETWORK",
Error::ConnectionTimeout => "TIMEOUT",
Error::InvalidConfig(_) => "INVALID_CONFIG",
Error::Internal(_) => "INTERNAL",
Error::Io(_) => "IO",
}
}
}