ffmpeg_light/
error.rs

1use std::io;
2
3use thiserror::Error;
4
5/// Result alias used throughout the crate.
6pub type Result<T> = std::result::Result<T, Error>;
7
8/// Errors that can occur when invoking FFmpeg or parsing its output.
9#[derive(Debug, Error)]
10pub enum Error {
11    /// The required binary could not be located on the current PATH.
12    #[error("binary '{binary}' not found on PATH")]
13    BinaryNotFound {
14        /// Name or path of the binary that could not be located.
15        binary: String,
16    },
17
18    /// A spawned command exited with a non-zero status code.
19    #[error("{binary} failed (code: {exit_code:?}): {message}")]
20    CommandFailed {
21        /// Binary that was executed (ffmpeg/ffprobe).
22        binary: String,
23        /// Exit code if provided by the OS.
24        exit_code: Option<i32>,
25        /// Captured stderr output (truncated when large).
26        message: String,
27    },
28
29    /// Errors produced by std::process or other IO operations.
30    #[error(transparent)]
31    Io(#[from] io::Error),
32
33    /// Errors produced while parsing ffprobe JSON.
34    #[error(transparent)]
35    Json(#[from] serde_json::Error),
36
37    /// Returned when user input does not satisfy the builder requirements.
38    #[error("invalid input: {0}")]
39    InvalidInput(String),
40
41    /// Returned when textual parsing fails (for example, invalid duration strings).
42    #[error("parse error: {0}")]
43    Parse(String),
44
45    /// Placeholder for functionality that has not yet been implemented.
46    #[error("unsupported operation: {0}")]
47    Unsupported(String),
48}
49
50impl Error {
51    /// Utility to build a `CommandFailed` from a binary label and captured output.
52    pub(crate) fn command_failed(binary: &str, exit_code: Option<i32>, stderr: &[u8]) -> Self {
53        let message = truncate(stderr);
54        Error::CommandFailed {
55            binary: binary.to_string(),
56            exit_code,
57            message,
58        }
59    }
60}
61
62fn truncate(message: &[u8]) -> String {
63    const MAX: usize = 4096;
64    let mut text = String::from_utf8_lossy(message).into_owned();
65    if text.len() > MAX {
66        text.truncate(MAX);
67        text.push_str("…");
68    }
69    text
70}