read_structure/
segment_type.rs1use std::{convert::TryFrom, mem, str::FromStr};
7
8use strum::IntoEnumIterator;
9use strum_macros::EnumIter;
10
11use crate::ReadStructureError;
12
13#[non_exhaustive]
15#[derive(Debug, Copy, Clone, EnumIter, PartialEq, Eq, Hash, PartialOrd, Ord)]
16#[repr(u8)]
17pub enum SegmentType {
18 Template = b'T',
20 SampleBarcode = b'B',
22 MolecularBarcode = b'M',
24 Skip = b'S',
26 CellularBarcode = b'C',
28}
29
30impl SegmentType {
31 pub fn value(&self) -> char {
33 let value = *self as u8;
34 value as char
35 }
36}
37
38impl TryFrom<char> for SegmentType {
39 type Error = ReadStructureError;
40
41 fn try_from(value: char) -> Result<Self, Self::Error> {
47 match value {
48 'T' => Ok(SegmentType::Template),
49 'B' => Ok(SegmentType::SampleBarcode),
50 'M' => Ok(SegmentType::MolecularBarcode),
51 'S' => Ok(SegmentType::Skip),
52 'C' => Ok(SegmentType::CellularBarcode),
53 _ => Err(ReadStructureError::ReadSegmentTypeInvalid(value)),
54 }
55 }
56}
57
58impl TryFrom<u8> for SegmentType {
59 type Error = ReadStructureError;
60
61 fn try_from(value: u8) -> Result<Self, Self::Error> {
67 Self::try_from(value as char)
68 }
69}
70
71impl FromStr for SegmentType {
72 type Err = ReadStructureError;
73
74 fn from_str(value: &str) -> Result<Self, Self::Err> {
80 if value.len() == 1 {
81 Self::try_from(value.chars().next().unwrap())
82 } else {
83 Err(ReadStructureError::ReadSegmentTypeStringInvalid(value.to_owned()))
84 }
85 }
86}
87
88#[cfg(test)]
89mod test {
90 use std::convert::TryFrom;
91 use std::str::FromStr;
92
93 use crate::{ReadStructureError, segment_type::SegmentType};
94 use strum::IntoEnumIterator;
95
96 #[test]
97 fn test_segment_type_round_trip() -> Result<(), ReadStructureError> {
98 assert_eq!(SegmentType::iter().len(), 5);
99 for tpe in SegmentType::iter() {
100 assert_eq!(SegmentType::try_from(tpe.value())?, tpe);
101 }
102 Ok(())
103 }
104
105 #[test]
106 fn test_invalid_segment_type() {
107 assert!(SegmentType::try_from(b'G').is_err());
108 }
109
110 #[test]
111 fn test_segment_type_from_str() -> Result<(), ReadStructureError> {
112 let segment_types_char: [char; 5] = ['T', 'B', 'M', 'S', 'C'];
113 let segment_types_str: [&str; 5] = ["T", "B", "M", "S", "C"];
114 let mut iter = segment_types_str.iter().zip(segment_types_char.iter());
115 for (s, c) in iter {
116 assert_eq!(SegmentType::from_str(s)?, SegmentType::try_from(*c)?);
117 }
118 Ok(())
119 }
120
121 #[test]
122 fn test_invalid_segment_type_string() {
123 assert!(SegmentType::from_str("").is_err());
124 assert!(SegmentType::from_str("GG").is_err());
125 assert!(SegmentType::from_str("TG").is_err());
126 assert!(!SegmentType::from_str("T").is_err());
127 }
128}