use nonempty::NonEmpty;
use thiserror::Error;
use crate::alignment::Section;
use crate::alignment::section::data;
use crate::alignment::section::header;
#[derive(Debug, Error)]
pub enum MissingError {
#[error("data")]
Data,
#[error("header")]
Header,
}
#[derive(Debug, Error)]
pub enum MultipleError {
#[error("header")]
Header,
}
#[derive(Debug, Error)]
pub enum Error {
#[error("missing required field: {0}")]
Missing(MissingError),
#[error("singular field set multiple times: {0}")]
Multiple(MultipleError),
}
type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Default)]
pub struct Builder {
header: Option<header::Record>,
data: Option<NonEmpty<data::Record>>,
}
impl Builder {
pub fn header(mut self, record: header::Record) -> Result<Self> {
if self.header.is_some() {
return Err(Error::Multiple(MultipleError::Header));
}
self.header = Some(record);
Ok(self)
}
pub fn push_data(mut self, record: data::Record) -> Self {
let data = match self.data {
Some(mut data) => {
data.push(record);
data
}
None => NonEmpty::new(record),
};
self.data = Some(data);
self
}
pub fn try_build(self) -> Result<Section> {
let header = self.header.ok_or(Error::Missing(MissingError::Header))?;
let alignment_data = self.data.ok_or(Error::Missing(MissingError::Data))?;
Ok(Section {
header,
data: alignment_data,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fails_with_no_header() {
let err = Builder::default()
.push_data("1".parse().unwrap())
.try_build()
.unwrap_err();
assert_eq!(err.to_string(), "missing required field: header");
}
#[test]
fn fails_with_multiple_headers() {
let err = Builder::default()
.header("chain 0 seq0 2 + 0 2 seq0 2 - 0 2 1".parse().unwrap())
.unwrap()
.header("chain 0 seq0 2 + 0 2 seq0 2 - 0 2 1".parse().unwrap())
.unwrap_err();
assert_eq!(err.to_string(), "singular field set multiple times: header");
}
#[test]
fn fails_with_no_data() {
let err = Builder::default()
.header("chain 0 seq0 2 + 0 2 seq0 2 - 0 2 1".parse().unwrap())
.unwrap()
.try_build()
.unwrap_err();
assert_eq!(err.to_string(), "missing required field: data");
}
}