Skip to main content

ff_probe/
error.rs

1//! Error types for media probing.
2
3use std::path::PathBuf;
4use thiserror::Error;
5
6/// Error type for media probing operations.
7#[derive(Error, Debug)]
8pub enum ProbeError {
9    /// The specified file was not found.
10    #[error("File not found: {path}")]
11    FileNotFound {
12        /// Path to the file that was not found.
13        path: PathBuf,
14    },
15
16    /// The file could not be opened.
17    #[error("Cannot open file: {path} - {reason}")]
18    CannotOpen {
19        /// Path to the file that could not be opened.
20        path: PathBuf,
21        /// Reason why the file could not be opened.
22        reason: String,
23    },
24
25    /// The file is not a valid media file.
26    #[error("Invalid media file: {path} - {reason}")]
27    InvalidMedia {
28        /// Path to the invalid media file.
29        path: PathBuf,
30        /// Reason why the file is invalid.
31        reason: String,
32    },
33
34    /// No streams were found in the file.
35    #[error("No streams found in file: {path}")]
36    NoStreams {
37        /// Path to the file with no streams.
38        path: PathBuf,
39    },
40
41    /// An I/O error occurred.
42    #[error("IO error: {0}")]
43    Io(#[from] std::io::Error),
44
45    /// An `FFmpeg` error occurred.
46    #[error("ffmpeg error: {message} (code={code})")]
47    Ffmpeg {
48        /// Raw `FFmpeg` error code (negative integer). `0` when no numeric code is available.
49        code: i32,
50        /// Human-readable error message from `av_strerror` or an internal description.
51        message: String,
52    },
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn test_file_not_found_error() {
61        let err = ProbeError::FileNotFound {
62            path: PathBuf::from("/path/to/missing.mp4"),
63        };
64        let msg = err.to_string();
65        assert!(msg.contains("File not found"));
66        assert!(msg.contains("missing.mp4"));
67    }
68
69    #[test]
70    fn test_cannot_open_error() {
71        let err = ProbeError::CannotOpen {
72            path: PathBuf::from("/path/to/file.mp4"),
73            reason: "permission denied".to_string(),
74        };
75        let msg = err.to_string();
76        assert!(msg.contains("Cannot open file"));
77        assert!(msg.contains("permission denied"));
78    }
79
80    #[test]
81    fn test_invalid_media_error() {
82        let err = ProbeError::InvalidMedia {
83            path: PathBuf::from("/path/to/bad.mp4"),
84            reason: "corrupted header".to_string(),
85        };
86        let msg = err.to_string();
87        assert!(msg.contains("Invalid media file"));
88        assert!(msg.contains("corrupted header"));
89    }
90
91    #[test]
92    fn test_no_streams_error() {
93        let err = ProbeError::NoStreams {
94            path: PathBuf::from("/path/to/empty.mp4"),
95        };
96        let msg = err.to_string();
97        assert!(msg.contains("No streams found"));
98    }
99
100    #[test]
101    fn ffmpeg_should_display_code_and_message() {
102        let err = ProbeError::Ffmpeg {
103            code: -2,
104            message: "codec not found".to_string(),
105        };
106        let msg = err.to_string();
107        assert!(msg.contains("ffmpeg error"));
108        assert!(msg.contains("codec not found"));
109        assert!(msg.contains("code=-2"));
110    }
111
112    #[test]
113    fn test_io_error_conversion() {
114        let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
115        let err: ProbeError = io_err.into();
116        assert!(matches!(err, ProbeError::Io(_)));
117    }
118}