use crate::{ReadStructure, ReadStructureError, segment_type::SegmentType};
pub const ANY_LENGTH_BYTE: u8 = b'+';
pub const ANY_LENGTH_BYTE_SLICE: &[u8] = b"+";
pub const ANY_LENGTH_STR: &str = "+";
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ReadSegment {
pub length: Option<usize>,
pub kind: SegmentType,
}
impl ReadSegment {
pub fn length(&self) -> Option<usize> {
self.length
}
pub fn has_length(&self) -> bool {
self.length.is_some()
}
}
impl std::str::FromStr for ReadSegment {
type Err = ReadStructureError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let rs = ReadStructure::from_str(s)?;
if rs.number_of_segments() == 1 {
Ok(rs.first().copied().unwrap())
} else {
Err(ReadStructureError::ReadSegmentMultipleSegments(s.to_owned()))
}
}
}
impl std::fmt::Display for ReadSegment {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.length {
Some(l) => write!(f, "{}", l),
None => write!(f, "{}", ANY_LENGTH_STR),
}?;
write!(f, "{}", self.kind.value())
}
}
#[cfg(test)]
mod test {
use crate::read_segment::ANY_LENGTH_STR;
use crate::read_segment::ReadSegment;
use crate::segment_type::SegmentType;
use std::str::FromStr;
use strum::IntoEnumIterator;
#[test]
fn test_read_segment_length() {
let seg_fixed_length = ReadSegment { length: Some(10), kind: SegmentType::Template };
assert_eq!(seg_fixed_length.length().unwrap(), 10);
assert!(seg_fixed_length.has_length());
let seg_no_length = ReadSegment { length: None, kind: SegmentType::Template };
assert!(!seg_no_length.has_length());
}
#[test]
#[should_panic]
fn test_read_segment_fixed_length_panic() {
let seg_no_length = ReadSegment { length: None, kind: SegmentType::Template };
seg_no_length.length().unwrap();
}
#[test]
fn test_read_segment_to_string() {
for tpe in SegmentType::iter() {
let seg_fixed_length = ReadSegment { length: Some(10), kind: tpe };
assert_eq!(seg_fixed_length.to_string(), format!("10{}", tpe.value()));
let seg_no_length = ReadSegment { length: None, kind: tpe };
assert_eq!(seg_no_length.to_string(), format!("{}{}", ANY_LENGTH_STR, tpe.value()));
}
}
#[test]
fn test_read_segment_from_str() {
assert_eq!(
ReadSegment::from_str("+T").unwrap(),
ReadSegment { length: None, kind: SegmentType::Template }
);
assert_eq!(
ReadSegment::from_str("10S").unwrap(),
ReadSegment { length: Some(10), kind: SegmentType::Skip }
);
}
}