use std::ops::Neg;
use crate::annot::contig::Contig;
use crate::annot::pos::Pos;
use crate::strand::*;
pub trait Loc {
type RefID;
type Strand;
fn refid(&self) -> &Self::RefID;
fn start(&self) -> isize;
fn length(&self) -> usize;
fn strand(&self) -> Self::Strand
where
Self::Strand: Copy;
fn pos_into<T>(&self, pos: &Pos<Self::RefID, T>) -> Option<Pos<(), T>>
where
Self::RefID: Eq,
Self::Strand: Into<ReqStrand> + Copy,
T: Neg<Output = T> + Copy;
fn pos_outof<Q, T>(&self, pos: &Pos<Q, T>) -> Option<Pos<Self::RefID, T>>
where
Self::RefID: Clone,
Self::Strand: Into<ReqStrand> + Copy,
T: Neg<Output = T> + Copy;
fn contig_intersection<T>(&self, other: &Contig<Self::RefID, T>) -> Option<Self>
where
Self: ::std::marker::Sized,
Self::RefID: PartialEq + Clone,
Self::Strand: Copy;
fn contig(&self) -> Contig<Self::RefID, Self::Strand>
where
Self::RefID: Clone,
Self::Strand: Copy,
{
Contig::new(
self.refid().clone(),
self.start(),
self.length(),
self.strand(),
)
}
fn first_pos(&self) -> Pos<Self::RefID, Self::Strand>
where
Self::RefID: Clone,
Self::Strand: Into<ReqStrand> + Copy,
{
match self.strand().into() {
ReqStrand::Forward => Pos::new(self.refid().clone(), self.start(), self.strand()),
ReqStrand::Reverse => {
if self.length() == 0 {
Pos::new(self.refid().clone(), self.start(), self.strand())
} else {
Pos::new(
self.refid().clone(),
self.start() + (self.length() as isize) - 1,
self.strand(),
)
}
}
}
}
fn last_pos(&self) -> Pos<Self::RefID, Self::Strand>
where
Self::RefID: Clone,
Self::Strand: Into<ReqStrand> + Copy,
{
match self.strand().into() {
ReqStrand::Forward => {
if self.length() == 0 {
Pos::new(self.refid().clone(), self.start(), self.strand())
} else {
Pos::new(
self.refid().clone(),
self.start() + (self.length() as isize) - 1,
self.strand(),
)
}
}
ReqStrand::Reverse => Pos::new(self.refid().clone(), self.start(), self.strand()),
}
}
}