1pub type EdlResult<T> = Result<T, EdlError>;
5
6#[derive(Debug, thiserror::Error)]
8pub enum EdlError {
9 #[error("I/O error: {0}")]
11 Io(#[from] std::io::Error),
12
13 #[error("Parse error at line {line}: {message}")]
15 Parse {
16 line: usize,
18 message: String,
20 },
21
22 #[error("Invalid timecode at line {line}: {message}")]
24 InvalidTimecode {
25 line: usize,
27 message: String,
29 },
30
31 #[error("Invalid event number: {0}")]
33 InvalidEventNumber(u32),
34
35 #[error("Invalid edit type: {0}")]
37 InvalidEditType(String),
38
39 #[error("Invalid track type: {0}")]
41 InvalidTrackType(String),
42
43 #[error("Invalid transition duration: {0}")]
45 InvalidTransitionDuration(String),
46
47 #[error("Invalid reel name: {0}")]
49 InvalidReelName(String),
50
51 #[error("Invalid motion effect: {0}")]
53 InvalidMotionEffect(String),
54
55 #[error("Invalid audio channel: {0}")]
57 InvalidAudioChannel(String),
58
59 #[error("Unsupported EDL format: {0}")]
61 UnsupportedFormat(String),
62
63 #[error("Validation error: {0}")]
65 ValidationError(String),
66
67 #[error("Event {0} not found")]
69 EventNotFound(u32),
70
71 #[error("Timecode out of range: {0}")]
73 TimecodeOutOfRange(String),
74
75 #[error("Invalid frame rate: {0}")]
77 InvalidFrameRate(String),
78
79 #[error("Invalid drop frame mode: {0}")]
81 InvalidDropFrameMode(String),
82
83 #[error("Comment parsing error at line {line}: {message}")]
85 CommentError {
86 line: usize,
88 message: String,
90 },
91
92 #[error("Event overlap detected: event {event1} overlaps with event {event2}")]
94 EventOverlap {
95 event1: u32,
97 event2: u32,
99 },
100
101 #[error("Gap in timeline detected between event {event1} and event {event2}")]
103 TimelineGap {
104 event1: u32,
106 event2: u32,
108 },
109
110 #[error("Invalid wipe pattern: {0}")]
112 InvalidWipePattern(String),
113
114 #[error("Invalid key type: {0}")]
116 InvalidKeyType(String),
117
118 #[error("Conversion error: {0}")]
120 ConversionError(String),
121
122 #[error("Missing required field: {0}")]
124 MissingField(String),
125
126 #[error("Invalid source timecode range: source out must be greater than source in")]
128 InvalidSourceRange,
129
130 #[error("Invalid record timecode range: record out must be greater than record in")]
132 InvalidRecordRange,
133}
134
135impl EdlError {
136 #[must_use]
138 pub fn parse(line: usize, message: impl Into<String>) -> Self {
139 Self::Parse {
140 line,
141 message: message.into(),
142 }
143 }
144
145 #[must_use]
147 pub fn invalid_timecode(line: usize, message: impl Into<String>) -> Self {
148 Self::InvalidTimecode {
149 line,
150 message: message.into(),
151 }
152 }
153
154 #[must_use]
156 pub fn comment_error(line: usize, message: impl Into<String>) -> Self {
157 Self::CommentError {
158 line,
159 message: message.into(),
160 }
161 }
162
163 #[must_use]
165 pub fn validation(message: impl Into<String>) -> Self {
166 Self::ValidationError(message.into())
167 }
168
169 #[must_use]
171 pub const fn event_overlap(event1: u32, event2: u32) -> Self {
172 Self::EventOverlap { event1, event2 }
173 }
174
175 #[must_use]
177 pub const fn timeline_gap(event1: u32, event2: u32) -> Self {
178 Self::TimelineGap { event1, event2 }
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185
186 #[test]
187 fn test_parse_error() {
188 let err = EdlError::parse(42, "Invalid syntax");
189 assert!(matches!(err, EdlError::Parse { line: 42, .. }));
190 let msg = format!("{err}");
191 assert!(msg.contains("42"));
192 assert!(msg.contains("Invalid syntax"));
193 }
194
195 #[test]
196 fn test_invalid_timecode() {
197 let err = EdlError::invalid_timecode(10, "Out of range");
198 assert!(matches!(err, EdlError::InvalidTimecode { line: 10, .. }));
199 }
200
201 #[test]
202 fn test_validation_error() {
203 let err = EdlError::validation("Timeline gap detected");
204 assert!(matches!(err, EdlError::ValidationError(_)));
205 }
206
207 #[test]
208 fn test_event_overlap() {
209 let err = EdlError::event_overlap(1, 2);
210 assert!(matches!(
211 err,
212 EdlError::EventOverlap {
213 event1: 1,
214 event2: 2
215 }
216 ));
217 }
218}