pub(crate) mod op;
use std::{error, fmt};
use self::op::parse_op;
use crate::alignment::record_buf::Cigar;
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ParseError {
Empty,
InvalidOp(op::ParseError),
}
impl error::Error for ParseError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
Self::InvalidOp(e) => Some(e),
_ => None,
}
}
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Empty => write!(f, "empty input"),
Self::InvalidOp(_) => write!(f, "invalid op"),
}
}
}
pub(super) fn parse_cigar(mut src: &[u8], cigar: &mut Cigar) -> Result<(), ParseError> {
if src.is_empty() {
return Err(ParseError::Empty);
}
cigar.as_mut().clear();
while !src.is_empty() {
let op = parse_op(&mut src).map_err(ParseError::InvalidOp)?;
cigar.as_mut().push(op);
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_cigar() -> Result<(), ParseError> {
use crate::alignment::record::cigar::{Op, op::Kind};
let mut cigar = Cigar::default();
cigar.as_mut().clear();
parse_cigar(b"8M13N", &mut cigar)?;
assert_eq!(
cigar,
[Op::new(Kind::Match, 8), Op::new(Kind::Skip, 13),]
.into_iter()
.collect()
);
cigar.as_mut().clear();
parse_cigar(b"8M13N144S", &mut cigar)?;
assert_eq!(
cigar,
[
Op::new(Kind::Match, 8),
Op::new(Kind::Skip, 13),
Op::new(Kind::SoftClip, 144),
]
.into_iter()
.collect()
);
cigar.as_mut().clear();
assert_eq!(parse_cigar(b"", &mut cigar), Err(ParseError::Empty));
cigar.as_mut().clear();
assert!(matches!(
parse_cigar(b"8Z", &mut cigar),
Err(ParseError::InvalidOp(_))
));
Ok(())
}
}