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
45impl 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}