Skip to main content

fgumi_lib/
errors.rs

1//! Custom error types for fgumi operations.
2
3use thiserror::Error;
4
5/// Result type alias for fgumi operations
6pub type Result<T> = std::result::Result<T, FgumiError>;
7
8/// Error type for fgumi operations
9#[derive(Error, Debug)]
10pub enum FgumiError {
11    /// Invalid parameter value provided
12    #[error("Invalid parameter '{parameter}': {reason}")]
13    InvalidParameter {
14        /// The parameter name
15        parameter: String,
16        /// Explanation of why it's invalid
17        reason: String,
18    },
19
20    /// Invalid frequency threshold
21    #[error("Invalid frequency threshold: {value} (must be between {min} and {max})")]
22    InvalidFrequency {
23        /// The invalid frequency value
24        value: f64,
25        /// Minimum valid value
26        min: f64,
27        /// Maximum valid value
28        max: f64,
29    },
30
31    /// Invalid quality threshold
32    #[error("Invalid quality threshold: {value} (must be between 0 and {max})")]
33    InvalidQuality {
34        /// The invalid quality value
35        value: u8,
36        /// Maximum valid value (usually 93 for SAM/BAM)
37        max: u8,
38    },
39
40    /// File format error
41    #[error("Invalid {file_type} file '{path}': {reason}")]
42    InvalidFileFormat {
43        /// Type of file (e.g., "BAM", "FASTQ")
44        file_type: String,
45        /// Path to the file
46        path: String,
47        /// Explanation of the problem
48        reason: String,
49    },
50
51    /// Required reference sequence not found
52    #[error("Reference sequence '{ref_name}' not found in header")]
53    ReferenceNotFound {
54        /// The reference sequence name
55        ref_name: String,
56    },
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn test_invalid_parameter() {
65        let error = FgumiError::InvalidParameter {
66            parameter: "min-reads".to_string(),
67            reason: "must be >= 1".to_string(),
68        };
69        let msg = format!("{error}");
70        assert!(msg.contains("Invalid parameter 'min-reads'"));
71        assert!(msg.contains("must be >= 1"));
72    }
73
74    #[test]
75    fn test_invalid_frequency() {
76        let error = FgumiError::InvalidFrequency { value: 1.5, min: 0.0, max: 1.0 };
77        let msg = format!("{error}");
78        assert!(msg.contains("1.5"));
79        assert!(msg.contains("between 0 and 1"));
80    }
81
82    #[test]
83    fn test_invalid_file_format() {
84        let error = FgumiError::InvalidFileFormat {
85            file_type: "BAM".to_string(),
86            path: "/path/to/file.bam".to_string(),
87            reason: "truncated file".to_string(),
88        };
89        let msg = format!("{error}");
90        assert!(msg.contains("Invalid BAM file"));
91        assert!(msg.contains("truncated file"));
92    }
93
94    #[test]
95    fn test_reference_not_found() {
96        let error = FgumiError::ReferenceNotFound { ref_name: "chr1".to_string() };
97        let msg = format!("{error}");
98        assert!(msg.contains("Reference sequence 'chr1' not found"));
99    }
100}