Skip to main content

bed_utils/bed/
strand.rs

1//! BED record feature strand.
2
3use std::{error, fmt, str::FromStr};
4
5use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9/// A BED record feature strand.
10#[derive(
11    Archive, RkyvSerialize, RkyvDeserialize, Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord,
12)]
13#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
14pub enum Strand {
15    /// Forward (sense or coding) strand (`+`).
16    Forward,
17    /// Reverse (antisense or complementary) strand (`-`).
18    Reverse,
19}
20
21impl AsRef<str> for Strand {
22    fn as_ref(&self) -> &str {
23        match self {
24            Self::Forward => "+",
25            Self::Reverse => "-",
26        }
27    }
28}
29
30impl fmt::Display for Strand {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        f.write_str(self.as_ref())
33    }
34}
35
36/// An error returned when a raw BED record strand fails to parse.
37#[derive(Clone, Debug, Eq, PartialEq)]
38pub enum ParseError {
39    /// The input is empty.
40    Empty,
41    /// The input is invalid.
42    Invalid,
43}
44
45impl error::Error for ParseError {}
46
47impl fmt::Display for ParseError {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        match self {
50            Self::Empty => f.write_str("empty input"),
51            Self::Invalid => f.write_str("invalid input"),
52        }
53    }
54}
55
56impl FromStr for Strand {
57    type Err = ParseError;
58
59    fn from_str(s: &str) -> Result<Self, Self::Err> {
60        match s {
61            "" => Err(ParseError::Empty),
62            "+" => Ok(Self::Forward),
63            "-" => Ok(Self::Reverse),
64            _ => Err(ParseError::Invalid),
65        }
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn test_fmt() {
75        assert_eq!(Strand::Forward.to_string(), "+");
76        assert_eq!(Strand::Reverse.to_string(), "-");
77    }
78
79    #[test]
80    fn test_from_str() {
81        assert_eq!("+".parse(), Ok(Strand::Forward));
82        assert_eq!("-".parse(), Ok(Strand::Reverse));
83
84        assert_eq!("".parse::<Strand>(), Err(ParseError::Empty));
85        assert_eq!("ndls".parse::<Strand>(), Err(ParseError::Invalid));
86    }
87}