use serde::{Deserialize, Serialize};
use super::scoring::MatchType;
#[derive(
Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default, Serialize, Deserialize,
)]
pub struct Piece {
pub score: isize,
pub local_score: isize,
pub match_type: MatchType,
pub step_a: u16,
pub step_b: u16,
}
impl Piece {
pub const fn new(
score: isize,
local_score: isize,
match_type: MatchType,
step_a: u16,
step_b: u16,
) -> Self {
Self {
score,
local_score,
match_type,
step_a,
step_b,
}
}
pub(crate) fn cigar(path: &[Self], start_a: usize, start_b: usize) -> String {
#[derive(Eq, PartialEq)]
enum StepType {
Insertion,
Deletion,
Match,
Mismatch,
Massmismatch,
Rotation(u16),
IsobaricIdentical(u16),
Isobaric(u16, u16),
}
impl std::fmt::Display for StepType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", match self {
Self::Insertion => String::from("I"),
Self::Deletion => String::from("D"),
Self::Match => String::from("="),
Self::Mismatch => String::from("X"),
Self::Massmismatch => String::from("m"),
Self::Rotation(a) => format!("{a}r"),
Self::IsobaricIdentical(a) => format!("{a}i"),
Self::Isobaric(a, b) => format!("{a}:{b}i"),
})
}
}
let (_, _, output, last) = path.iter().fold(
(start_a, start_b, String::new(), None),
|(a, b, output, last), step| {
let current_type = match (step.match_type, step.step_a, step.step_b) {
(MatchType::Isobaric, a, b) => {
if a == b {
StepType::IsobaricIdentical(a)
} else {
StepType::Isobaric(a, b)
}
}
(_, 0, 1) => StepType::Insertion,
(_, 1, 0) => StepType::Deletion,
(MatchType::IdentityMassMismatch, 1, 1) => StepType::Massmismatch,
(MatchType::FullIdentity, 1, 1) => StepType::Match,
(MatchType::Mismatch, 1, 1) => StepType::Mismatch,
(MatchType::Rotation, a, _) => StepType::Rotation(a),
_ => unreachable!("Invalid step types while creating CIGAR"),
};
let (str, last) = match last {
Some((
t @ (StepType::Rotation(..)
| StepType::Isobaric(..)
| StepType::IsobaricIdentical(..)),
_,
)) => (format!("{output}{t}"), Some((current_type, 1))),
Some((t, n)) if t == current_type => (output, Some((t, n + 1))),
Some((t, n)) => (format!("{output}{n}{t}"), Some((current_type, 1))),
None => (output, Some((current_type, 1))),
};
(
a + step.step_a as usize,
b + step.step_b as usize,
str,
last,
)
},
);
match last {
Some((
t @ (StepType::Rotation(..)
| StepType::Isobaric(..)
| StepType::IsobaricIdentical(..)),
_,
)) => {
format!("{output}{t}")
}
Some((t, n)) => format!("{output}{n}{t}"),
_ => output,
}
}
}