bio_seq/
error.rs

1use core::fmt;
2use core::result;
3
4#[derive(Debug, PartialEq)]
5pub enum ParseBioError {
6    UnrecognisedBase(u8),
7    MismatchedLength(usize, usize),
8    SequenceTooLong(usize, usize),
9}
10
11pub type Result<T> = result::Result<T, ParseBioError>;
12
13impl fmt::Display for ParseBioError {
14    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15        match self {
16            ParseBioError::UnrecognisedBase(byte) => {
17                if byte.is_ascii_alphanumeric() {
18                    write!(
19                        f,
20                        "Unrecognised character: '{}' ({byte:#04X?})",
21                        *byte as char,
22                    )
23                } else {
24                    write!(f, "Unrecognised character: {byte:#04X?}")
25                }
26            }
27
28            ParseBioError::MismatchedLength(got, expected) => {
29                write!(f, "Expected length {expected}, got {got}")
30            }
31
32            ParseBioError::SequenceTooLong(got, expected) => {
33                write!(f, "Expected length <= {expected}, got {got}")
34            }
35        }
36    }
37}
38
39impl From<ParseBioError> for std::io::Error {
40    fn from(err: ParseBioError) -> Self {
41        std::io::Error::other(err)
42    }
43}
44
45// #![feature(error_in_core)
46impl std::error::Error for ParseBioError {}
47
48#[cfg(test)]
49mod tests {
50    use crate::prelude::*;
51
52    #[test]
53    fn test_parse_error() {
54        let seq = Seq::<Dna>::from_str("ACGTx").unwrap_err();
55        assert_eq!(
56            format!("{seq}"),
57            "Unrecognised character: 'x' (0x78)".to_string()
58        );
59
60        let seq = Seq::<Dna>::from_str("ACGT\n").unwrap_err();
61        assert_eq!(format!("{seq}"), "Unrecognised character: 0x0A".to_string());
62
63        let err: std::io::Error = seq.into();
64        assert_eq!(err.kind(), std::io::ErrorKind::Other);
65
66        let seq = Seq::<Dna>::from_str("ACGTT");
67        assert!(seq.is_ok());
68    }
69
70    #[test]
71    fn test_mismatched_length() {
72        let seq: &SeqSlice<Dna> = dna!("ACGTGAT");
73        let kmer = Kmer::<Dna, 14>::try_from(seq).unwrap_err();
74        assert_eq!(format!("{kmer}"), "Expected length 7, got 14".to_string());
75
76        let kmer = Kmer::<Dna, 6>::try_from(seq).unwrap_err();
77        assert_eq!(format!("{kmer}"), "Expected length 7, got 6".to_string());
78
79        let kmer = Kmer::<Dna, 7>::try_from(seq);
80        assert!(kmer.is_ok());
81    }
82
83    #[test]
84    fn test_size_error() {
85        let seq = dna!("ACGTACGTACGTACGTACGTACGTACGTACGTA");
86        let int = TryInto::<usize>::try_into(seq).unwrap_err();
87
88        let expected_size = usize::BITS / Dna::BITS as u32;
89
90        assert_eq!(
91            format!("{int}"),
92            format!("Expected length <= {expected_size}, got 33")
93        );
94
95        let good = TryInto::<usize>::try_into(&seq[..expected_size as usize]);
96        assert!(good.is_ok());
97    }
98}