use crate::{
kmer::{
KmerEncoder, SupportedKmerLen,
encoders::{
three_bit::{ThreeBitEncodedKmer, ThreeBitKmerLen},
two_bit::{TwoBitEncodedKmer, TwoBitKmerLen},
},
},
private::Sealed,
};
use std::{iter::Enumerate, ops::Range};
pub trait KmerEncode<const MAX_LEN: usize, E: KmerEncoder<MAX_LEN>> {
#[must_use]
fn encode_kmer(&self, encoder: &E) -> E::EncodedKmer;
}
impl<const MAX_LEN: usize, E> KmerEncode<MAX_LEN, E> for ThreeBitEncodedKmer<MAX_LEN>
where
ThreeBitKmerLen<MAX_LEN>: SupportedKmerLen,
E: KmerEncoder<MAX_LEN, EncodedKmer = Self>,
{
#[inline]
fn encode_kmer(&self, _encoder: &E) -> E::EncodedKmer {
*self
}
}
impl<const MAX_LEN: usize, E> KmerEncode<MAX_LEN, E> for &ThreeBitEncodedKmer<MAX_LEN>
where
ThreeBitKmerLen<MAX_LEN>: SupportedKmerLen,
E: KmerEncoder<MAX_LEN, EncodedKmer = ThreeBitEncodedKmer<MAX_LEN>>,
{
#[inline]
fn encode_kmer(&self, _encoder: &E) -> E::EncodedKmer {
**self
}
}
impl<const MAX_LEN: usize, E> KmerEncode<MAX_LEN, E> for TwoBitEncodedKmer<MAX_LEN>
where
TwoBitKmerLen<MAX_LEN>: SupportedKmerLen,
E: KmerEncoder<MAX_LEN, EncodedKmer = Self>,
{
#[inline]
fn encode_kmer(&self, _encoder: &E) -> E::EncodedKmer {
*self
}
}
impl<const MAX_LEN: usize, E> KmerEncode<MAX_LEN, E> for &TwoBitEncodedKmer<MAX_LEN>
where
TwoBitKmerLen<MAX_LEN>: SupportedKmerLen,
E: KmerEncoder<MAX_LEN, EncodedKmer = TwoBitEncodedKmer<MAX_LEN>>,
{
#[inline]
fn encode_kmer(&self, _encoder: &E) -> E::EncodedKmer {
**self
}
}
impl<T: AsRef<[u8]>, const MAX_LEN: usize, E: KmerEncoder<MAX_LEN>> KmerEncode<MAX_LEN, E> for T {
#[inline]
fn encode_kmer(&self, encoder: &E) -> E::EncodedKmer {
encoder.encode_kmer(self)
}
}
pub trait EncodedKmerCollection<const MAX_LEN: usize>: Sealed {
type Encoder: KmerEncoder<MAX_LEN, EncodedKmer = Self::EncodedKmer>;
type EncodedKmer: KmerEncode<MAX_LEN, Self::Encoder>;
#[must_use]
fn encoder(&self) -> &Self::Encoder;
#[inline]
#[must_use]
fn kmer_length(&self) -> usize {
self.encoder().kmer_length()
}
}
pub trait FindKmersInSeq<const MAX_LEN: usize>: EncodedKmerCollection<MAX_LEN> + Sealed {
#[must_use]
fn contains<K>(&self, kmer: &K) -> bool
where
K: KmerEncode<MAX_LEN, Self::Encoder>;
#[must_use]
fn find_in_seq(&self, seq: impl AsRef<[u8]>) -> Option<Range<usize>> {
for (i, kmer) in self.encoder().iter_from_sequence(&seq).enumerate() {
if self.contains(&kmer) {
return Some(i..i + self.kmer_length());
}
}
None
}
#[must_use]
fn find_in_seq_rev(&self, seq: impl AsRef<[u8]>) -> Option<Range<usize>> {
for (i, kmer) in self.encoder().iter_from_sequence_rev(&seq).enumerate() {
if self.contains(&kmer) {
let end = seq.as_ref().len() - i;
return Some(end - self.kmer_length()..end);
}
}
None
}
#[inline]
#[must_use]
fn find_all_in_seq<'a>(&'a self, seq: &'a (impl AsRef<[u8]> + ?Sized)) -> KmerMatchesInSeq<'a, MAX_LEN, Self> {
let seq = seq.as_ref();
KmerMatchesInSeq::new(self, seq)
}
#[inline]
#[must_use]
fn find_all_in_seq_rev<'a>(&'a self, seq: &'a (impl AsRef<[u8]> + ?Sized)) -> KmerMatchesInSeqRev<'a, MAX_LEN, Self> {
let seq = seq.as_ref();
KmerMatchesInSeqRev::new(self, seq)
}
}
pub struct KmerMatchesInSeq<'a, const MAX_LEN: usize, T: FindKmersInSeq<MAX_LEN> + ?Sized> {
collection: &'a T,
seq_iterator: Enumerate<<<T as EncodedKmerCollection<MAX_LEN>>::Encoder as KmerEncoder<MAX_LEN>>::SeqIter<'a>>,
}
impl<'a, const MAX_LEN: usize, T: FindKmersInSeq<MAX_LEN> + ?Sized> KmerMatchesInSeq<'a, MAX_LEN, T> {
#[inline]
fn new(collection: &'a T, seq: &'a [u8]) -> Self {
Self {
collection,
seq_iterator: collection.encoder().iter_from_sequence(seq).enumerate(),
}
}
}
impl<const MAX_LEN: usize, T> Iterator for KmerMatchesInSeq<'_, MAX_LEN, T>
where
T: FindKmersInSeq<MAX_LEN>,
{
type Item = Range<usize>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
for (i, kmer) in &mut self.seq_iterator {
if self.collection.contains(&kmer) {
return Some(i..i + self.collection.kmer_length());
}
}
None
}
}
pub struct KmerMatchesInSeqRev<'a, const MAX_LEN: usize, T: FindKmersInSeq<MAX_LEN> + ?Sized> {
collection: &'a T,
seq_iterator: Enumerate<<<T as EncodedKmerCollection<MAX_LEN>>::Encoder as KmerEncoder<MAX_LEN>>::SeqIterRev<'a>>,
seq_len: usize,
}
impl<'a, const MAX_LEN: usize, T: FindKmersInSeq<MAX_LEN> + ?Sized> KmerMatchesInSeqRev<'a, MAX_LEN, T> {
#[inline]
fn new(collection: &'a T, seq: &'a [u8]) -> Self {
Self {
collection,
seq_iterator: collection.encoder().iter_from_sequence_rev(seq).enumerate(),
seq_len: seq.len(),
}
}
}
impl<const MAX_LEN: usize, T> Iterator for KmerMatchesInSeqRev<'_, MAX_LEN, T>
where
T: FindKmersInSeq<MAX_LEN>,
{
type Item = Range<usize>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
for (i, kmer) in &mut self.seq_iterator {
if self.collection.contains(&kmer) {
let end = self.seq_len - i;
return Some(end - self.collection.kmer_length()..end);
}
}
None
}
}
pub trait FindKmers<const MAX_LEN: usize>: AsRef<[u8]> {
#[inline]
#[must_use]
fn find_kmers<T: FindKmersInSeq<MAX_LEN>>(&self, kmers: &T) -> Option<Range<usize>> {
kmers.find_in_seq(self)
}
#[inline]
#[must_use]
fn find_kmers_rev<T: FindKmersInSeq<MAX_LEN>>(&self, kmers: &T) -> Option<Range<usize>> {
kmers.find_in_seq_rev(self)
}
#[inline]
#[must_use]
fn find_all_kmers<'a, T: FindKmersInSeq<MAX_LEN>>(&'a self, kmers: &'a T) -> impl Iterator<Item = Range<usize>> + 'a {
kmers.find_all_in_seq(self)
}
#[inline]
#[must_use]
fn find_all_kmers_rev<'a, T: FindKmersInSeq<MAX_LEN>>(
&'a self, kmers: &'a T,
) -> impl Iterator<Item = Range<usize>> + 'a {
kmers.find_all_in_seq_rev(self)
}
}
impl<const MAX_LEN: usize, Q: AsRef<[u8]>> FindKmers<MAX_LEN> for Q {}