use std::fmt;
use std::io;
#[derive(Debug)]
#[non_exhaustive]
pub enum ParseError {
Io(io::Error),
Syntax {
line: usize,
kind: SyntaxError,
},
}
impl ParseError {
pub fn line(&self) -> Option<usize> {
match self {
ParseError::Syntax { line, .. } => Some(*line),
ParseError::Io(_) => None,
}
}
pub fn syntax(&self) -> Option<&SyntaxError> {
match self {
ParseError::Syntax { kind, .. } => Some(kind),
ParseError::Io(_) => None,
}
}
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ParseError::Io(error) => write!(f, "failed to read playlist: {error}"),
ParseError::Syntax { line, kind } => write!(f, "line {line}: {kind}"),
}
}
}
impl std::error::Error for ParseError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
ParseError::Io(error) => Some(error),
ParseError::Syntax { kind, .. } => Some(kind),
}
}
}
impl From<io::Error> for ParseError {
fn from(error: io::Error) -> Self {
ParseError::Io(error)
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum SubstitutionError {
UndefinedVariable(String),
MissingImport(String),
MissingQueryParameter(String),
DuplicateVariable(String),
InvalidDefine(String),
InvalidValue(String),
Parse(ParseError),
}
impl fmt::Display for SubstitutionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SubstitutionError::UndefinedVariable(name) => write!(f, "undefined variable: {name}"),
SubstitutionError::MissingImport(name) => {
write!(f, "missing imported variable: {name}")
}
SubstitutionError::MissingQueryParameter(name) => {
write!(f, "missing query parameter: {name}")
}
SubstitutionError::DuplicateVariable(name) => {
write!(f, "variable defined more than once: {name}")
}
SubstitutionError::InvalidDefine(value) => write!(f, "invalid EXT-X-DEFINE: {value}"),
SubstitutionError::InvalidValue(name) => {
write!(
f,
"variable value contains a control character or quote: {name}"
)
}
SubstitutionError::Parse(error) => write!(f, "{error}"),
}
}
}
impl std::error::Error for SubstitutionError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
SubstitutionError::Parse(error) => Some(error),
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum SyntaxError {
MissingUriAfterExtInf,
InvalidExtInf(String),
MalformedAttributeList { reason: &'static str, input: String },
MissingAttribute {
tag: &'static str,
attribute: &'static str,
},
InvalidAttributeValue {
tag: &'static str,
attribute: &'static str,
value: String,
},
MissingTagValue { tag: &'static str },
InvalidTagValue { tag: &'static str, value: String },
ConflictingAttributes {
tag: &'static str,
reason: &'static str,
},
}
impl fmt::Display for SyntaxError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SyntaxError::MissingUriAfterExtInf => write!(f, "missing URI after EXTINF"),
SyntaxError::InvalidExtInf(value) => write!(f, "invalid EXTINF: {value}"),
SyntaxError::MalformedAttributeList { reason, input } => {
write!(f, "malformed attribute list ({reason}): {input}")
}
SyntaxError::MissingAttribute { tag, attribute } => {
write!(f, "{tag} requires {attribute}")
}
SyntaxError::InvalidAttributeValue {
tag,
attribute,
value,
} => write!(f, "invalid {tag} {attribute}: {value}"),
SyntaxError::MissingTagValue { tag } => write!(f, "{tag} requires a value"),
SyntaxError::InvalidTagValue { tag, value } => write!(f, "invalid {tag}: {value}"),
SyntaxError::ConflictingAttributes { tag, reason } => write!(f, "{tag}: {reason}"),
}
}
}
impl std::error::Error for SyntaxError {}