pub mod cigar;
pub mod cost;
use std::cmp::Ordering;
pub use cigar::*;
pub use cost::*;
pub type Base = u8;
pub type Sequence = Vec<Base>;
pub type Seq<'a> = &'a [Base];
pub fn seq_to_string(seq: Seq) -> String {
String::from_utf8(seq.to_vec()).unwrap()
}
pub type I = i32;
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Hash,
Default,
derive_more::Add,
derive_more::Sub,
derive_more::AddAssign,
derive_more::SubAssign,
)]
pub struct Pos(pub I, pub I);
impl std::fmt::Display for Pos {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
<Self as std::fmt::Debug>::fmt(self, f)
}
}
impl PartialOrd for Pos {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
let a = self.0.cmp(&other.0);
let b = self.1.cmp(&other.1);
if a == b {
return Some(a);
}
if a == Ordering::Equal {
return Some(b);
}
if b == Ordering::Equal {
return Some(a);
}
None
}
#[inline]
fn le(&self, other: &Self) -> bool {
self.0 <= other.0 && self.1 <= other.1
}
}
pub type Path = Vec<Pos>;
impl Pos {
pub fn start() -> Self {
Pos(0, 0)
}
pub fn target(a: Seq, b: Seq) -> Self {
Pos(a.len() as I, b.len() as I)
}
pub fn diag(&self) -> I {
self.0 - self.1
}
pub fn anti_diag(&self) -> I {
self.0 + self.1
}
pub fn mirror(&self) -> Pos {
Pos(self.1, self.0)
}
pub fn from<T>(i: T, j: T) -> Self
where
T: TryInto<I>,
<T as TryInto<i32>>::Error: std::fmt::Debug,
{
Pos(i.try_into().unwrap(), j.try_into().unwrap())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LexPos(pub Pos);
impl PartialOrd for LexPos {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
#[inline]
fn lt(&self, other: &Self) -> bool {
(self.0 .0, self.0 .1) < (other.0 .0, other.0 .1)
}
}
impl Ord for LexPos {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
(self.0 .0, self.0 .1).cmp(&(other.0 .0, other.0 .1))
}
}
pub trait Aligner: std::fmt::Debug {
fn align(&mut self, a: Seq, b: Seq) -> (Cost, Option<Cigar>);
}