m3u8_parser/m3u8/
error.rs1use std::fmt;
4use std::io;
5
6#[derive(Debug)]
8#[non_exhaustive]
9pub enum ParseError {
10 Io(io::Error),
12 Syntax {
14 line: usize,
16 kind: SyntaxError,
17 },
18}
19
20impl ParseError {
21 pub fn line(&self) -> Option<usize> {
23 match self {
24 ParseError::Syntax { line, .. } => Some(*line),
25 ParseError::Io(_) => None,
26 }
27 }
28
29 pub fn syntax(&self) -> Option<&SyntaxError> {
31 match self {
32 ParseError::Syntax { kind, .. } => Some(kind),
33 ParseError::Io(_) => None,
34 }
35 }
36}
37
38impl fmt::Display for ParseError {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 match self {
41 ParseError::Io(error) => write!(f, "failed to read playlist: {error}"),
42 ParseError::Syntax { line, kind } => write!(f, "line {line}: {kind}"),
43 }
44 }
45}
46
47impl std::error::Error for ParseError {
48 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
49 match self {
50 ParseError::Io(error) => Some(error),
51 ParseError::Syntax { kind, .. } => Some(kind),
52 }
53 }
54}
55
56impl From<io::Error> for ParseError {
57 fn from(error: io::Error) -> Self {
58 ParseError::Io(error)
59 }
60}
61
62#[derive(Debug)]
64#[non_exhaustive]
65pub enum SubstitutionError {
66 UndefinedVariable(String),
68 MissingImport(String),
70 MissingQueryParameter(String),
72 DuplicateVariable(String),
74 InvalidDefine(String),
77 InvalidValue(String),
80 Parse(ParseError),
82}
83
84impl fmt::Display for SubstitutionError {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 match self {
87 SubstitutionError::UndefinedVariable(name) => write!(f, "undefined variable: {name}"),
88 SubstitutionError::MissingImport(name) => {
89 write!(f, "missing imported variable: {name}")
90 }
91 SubstitutionError::MissingQueryParameter(name) => {
92 write!(f, "missing query parameter: {name}")
93 }
94 SubstitutionError::DuplicateVariable(name) => {
95 write!(f, "variable defined more than once: {name}")
96 }
97 SubstitutionError::InvalidDefine(value) => write!(f, "invalid EXT-X-DEFINE: {value}"),
98 SubstitutionError::InvalidValue(name) => {
99 write!(
100 f,
101 "variable value contains a control character or quote: {name}"
102 )
103 }
104 SubstitutionError::Parse(error) => write!(f, "{error}"),
105 }
106 }
107}
108
109impl std::error::Error for SubstitutionError {
110 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
111 match self {
112 SubstitutionError::Parse(error) => Some(error),
113 _ => None,
114 }
115 }
116}
117
118#[derive(Debug, Clone, PartialEq)]
120#[non_exhaustive]
121pub enum SyntaxError {
122 MissingUriAfterExtInf,
124 InvalidExtInf(String),
126 MalformedAttributeList { reason: &'static str, input: String },
128 MissingAttribute {
130 tag: &'static str,
131 attribute: &'static str,
132 },
133 InvalidAttributeValue {
135 tag: &'static str,
136 attribute: &'static str,
137 value: String,
138 },
139 MissingTagValue { tag: &'static str },
141 InvalidTagValue { tag: &'static str, value: String },
143 ConflictingAttributes {
145 tag: &'static str,
146 reason: &'static str,
147 },
148}
149
150impl fmt::Display for SyntaxError {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 match self {
153 SyntaxError::MissingUriAfterExtInf => write!(f, "missing URI after EXTINF"),
154 SyntaxError::InvalidExtInf(value) => write!(f, "invalid EXTINF: {value}"),
155 SyntaxError::MalformedAttributeList { reason, input } => {
156 write!(f, "malformed attribute list ({reason}): {input}")
157 }
158 SyntaxError::MissingAttribute { tag, attribute } => {
159 write!(f, "{tag} requires {attribute}")
160 }
161 SyntaxError::InvalidAttributeValue {
162 tag,
163 attribute,
164 value,
165 } => write!(f, "invalid {tag} {attribute}: {value}"),
166 SyntaxError::MissingTagValue { tag } => write!(f, "{tag} requires a value"),
167 SyntaxError::InvalidTagValue { tag, value } => write!(f, "invalid {tag}: {value}"),
168 SyntaxError::ConflictingAttributes { tag, reason } => write!(f, "{tag}: {reason}"),
169 }
170 }
171}
172
173impl std::error::Error for SyntaxError {}