use crate::{Error, Result};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SegmentInfo {
pub record_name: String,
pub num_samples: u64,
}
impl SegmentInfo {
pub fn from_segment_line(line: &str) -> Result<Self> {
let line = line.trim();
let mut parts = line.split_whitespace();
let record_name = parts
.next()
.ok_or_else(|| Error::InvalidHeader("Missing record name".to_string()))?
.to_string();
if !Self::is_valid_record_name(&record_name) {
return Err(Error::InvalidHeader(format!(
"Invalid record name '{record_name}': must contain only letters, digits, underscores, or '~'"
)));
}
let num_samples_str = parts
.next()
.ok_or_else(|| Error::InvalidHeader("Missing number of samples".to_string()))?;
let num_samples = num_samples_str
.parse()
.map_err(|e| Error::InvalidHeader(format!("Invalid number of samples: {e}")))?;
if parts.next().is_some() {
return Err(Error::InvalidHeader(
"Extra fields found in segment specification line".to_string(),
));
}
Ok(Self {
record_name,
num_samples,
})
}
fn is_valid_record_name(name: &str) -> bool {
if name == "~" {
return true;
}
name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
}
#[must_use]
pub fn record_name(&self) -> &str {
&self.record_name
}
#[must_use]
pub const fn num_samples(&self) -> u64 {
self.num_samples
}
#[must_use]
pub fn is_null_segment(&self) -> bool {
self.record_name == "~"
}
}