Skip to main content

mediagit_compression/
error.rs

1// MediaGit - Git for Media Files
2// Copyright (C) 2025 MediaGit Contributors
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU Affero General Public License as published
6// by the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Affero General Public License for more details.
13
14//! Compression error types
15
16use thiserror::Error;
17
18/// Result type alias for compression operations
19pub type CompressionResult<T> = Result<T, CompressionError>;
20
21/// Errors that can occur during compression operations
22#[derive(Error, Debug)]
23pub enum CompressionError {
24    /// Compression operation failed
25    #[error("compression failed: {0}")]
26    CompressionFailed(String),
27
28    /// Decompression operation failed
29    #[error("decompression failed: {0}")]
30    DecompressionFailed(String),
31
32    /// Invalid input data
33    #[error("invalid input: {0}")]
34    InvalidInput(String),
35
36    /// Unsupported compression algorithm
37    #[error("unsupported algorithm: {0}")]
38    UnsupportedAlgorithm(String),
39
40    /// I/O error occurred
41    #[error("I/O error: {0}")]
42    Io(#[from] std::io::Error),
43
44    /// Zstd-specific error
45    #[error("zstd error: {0}")]
46    ZstdError(String),
47
48    /// Brotli-specific error
49    #[error("brotli error: {0}")]
50    BrotliError(String),
51
52    /// Generic error for opaque error types
53    #[error(transparent)]
54    Other(#[from] anyhow::Error),
55}
56
57impl CompressionError {
58    /// Create a compression failed error
59    pub fn compression_failed<S: Into<String>>(msg: S) -> Self {
60        CompressionError::CompressionFailed(msg.into())
61    }
62
63    /// Create a decompression failed error
64    pub fn decompression_failed<S: Into<String>>(msg: S) -> Self {
65        CompressionError::DecompressionFailed(msg.into())
66    }
67
68    /// Create an invalid input error
69    pub fn invalid_input<S: Into<String>>(msg: S) -> Self {
70        CompressionError::InvalidInput(msg.into())
71    }
72
73    /// Create an unsupported algorithm error
74    pub fn unsupported_algorithm<S: Into<String>>(algorithm: S) -> Self {
75        CompressionError::UnsupportedAlgorithm(algorithm.into())
76    }
77
78    /// Create a zstd-specific error
79    pub fn zstd_error<S: Into<String>>(msg: S) -> Self {
80        CompressionError::ZstdError(msg.into())
81    }
82
83    /// Create a brotli-specific error
84    pub fn brotli_error<S: Into<String>>(msg: S) -> Self {
85        CompressionError::BrotliError(msg.into())
86    }
87
88    /// Check if this is a compression failed error
89    pub fn is_compression_failed(&self) -> bool {
90        matches!(self, CompressionError::CompressionFailed(_))
91    }
92
93    /// Check if this is a decompression failed error
94    pub fn is_decompression_failed(&self) -> bool {
95        matches!(self, CompressionError::DecompressionFailed(_))
96    }
97
98    /// Check if this is an I/O error
99    pub fn is_io(&self) -> bool {
100        matches!(self, CompressionError::Io(_))
101    }
102}
103
104#[cfg(test)]
105mod tests {
106    use super::*;
107
108    #[test]
109    fn test_compression_error_creation() {
110        let err = CompressionError::compression_failed("test compression");
111        assert!(err.is_compression_failed());
112        assert_eq!(err.to_string(), "compression failed: test compression");
113    }
114
115    #[test]
116    fn test_decompression_error_creation() {
117        let err = CompressionError::decompression_failed("test decompression");
118        assert!(err.is_decompression_failed());
119        assert_eq!(err.to_string(), "decompression failed: test decompression");
120    }
121
122    #[test]
123    fn test_invalid_input_error() {
124        let err = CompressionError::invalid_input("empty data");
125        assert_eq!(err.to_string(), "invalid input: empty data");
126    }
127
128    #[test]
129    fn test_unsupported_algorithm_error() {
130        let err = CompressionError::unsupported_algorithm("gzip");
131        assert_eq!(err.to_string(), "unsupported algorithm: gzip");
132    }
133
134    #[test]
135    fn test_io_error_conversion() {
136        let io_err = std::io::Error::other("read failed");
137        let comp_err = CompressionError::from(io_err);
138        assert!(comp_err.is_io());
139    }
140}