use crate::{
data::{
id_types::FastaIDs,
types::{
amino_acids::AminoAcids,
nucleotides::{Nucleotides, ToDNA, Translate},
},
views::{AssocViewMutType, AssocViewType},
},
prelude::{AminoAcidsView, NucleotidesView},
};
mod reader;
mod std_traits;
mod taxon;
mod view_traits;
pub use reader::*;
pub use taxon::*;
#[derive(Clone, Eq, PartialEq, Hash, Debug, Default)]
pub struct Fasta<S = Vec<u8>> {
pub header: String,
pub sequence: S,
}
#[derive(Eq, PartialEq, Hash, Debug, Default)]
pub struct FastaView<'a, S = Vec<u8>>
where
S: AssocViewType, {
pub header: &'a str,
pub sequence: S::View<'a>,
}
#[derive(Eq, PartialEq, Hash, Debug)]
pub struct FastaViewMut<'a, S = Vec<u8>>
where
S: AssocViewMutType, {
pub header: &'a mut String,
pub sequence: S::ViewMut<'a>,
}
impl Fasta<Vec<u8>> {
#[inline]
#[must_use]
pub fn new() -> Self {
Self {
header: String::new(),
sequence: Vec::<u8>::new(),
}
}
}
impl Fasta<Nucleotides> {
#[inline]
#[must_use]
pub fn new() -> Self {
Self {
header: String::new(),
sequence: Nucleotides::new(),
}
}
}
impl Fasta<AminoAcids> {
#[inline]
#[must_use]
pub fn new() -> Self {
Self {
header: String::new(),
sequence: AminoAcids::new(),
}
}
}
impl FastaView<'_, Vec<u8>> {
#[inline]
#[must_use]
pub fn new() -> Self {
Self {
header: "",
sequence: &[],
}
}
}
impl FastaView<'_, Nucleotides> {
#[inline]
#[must_use]
pub fn new() -> Self {
Self {
header: "",
sequence: NucleotidesView::new(),
}
}
}
impl FastaView<'_, AminoAcids> {
#[inline]
#[must_use]
pub fn new() -> Self {
Self {
header: "",
sequence: AminoAcidsView::new(),
}
}
}
impl<S> Fasta<S> {
#[inline]
#[must_use]
pub fn with_annot<M>(self, annot: M) -> FastaAnnot<M, S> {
FastaAnnot {
header: self.header,
sequence: self.sequence,
annot,
}
}
pub fn annotate_taxon(self) -> Result<FastaAnnot<Taxon, S>, Fasta<S>> {
if let Some((id, taxon)) = self.header.get_id_taxon() {
Ok(FastaAnnot {
header: id.to_string(),
sequence: self.sequence,
annot: Taxon::from(taxon),
})
} else {
Err(self)
}
}
#[inline]
#[must_use]
pub fn get_id_taxon(&self) -> Option<(&str, TaxonView<'_>)> {
let (id, taxon) = self.header.get_id_taxon()?;
Some((id, TaxonView::from(taxon)))
}
}
impl<'a, S> FastaView<'a, S>
where
S: AssocViewType,
{
#[inline]
#[must_use]
pub fn with_annot<M>(self, annot: M::View<'a>) -> FastaAnnotView<'a, M, S>
where
M: AssocViewType, {
FastaAnnotView {
header: self.header,
sequence: self.sequence,
annot,
}
}
pub fn annotate_taxon(self) -> Result<FastaAnnotView<'a, Taxon, S>, FastaView<'a, S>> {
if let Some((id, taxon)) = self.header.get_id_taxon() {
Ok(FastaAnnotView {
header: id,
sequence: self.sequence,
annot: TaxonView::from(taxon),
})
} else {
Err(self)
}
}
#[inline]
#[must_use]
pub fn get_id_taxon(&self) -> Option<(&str, TaxonView<'_>)> {
let (id, taxon) = self.header.get_id_taxon()?;
Some((id, TaxonView::from(taxon)))
}
}
impl<'a, S> FastaViewMut<'a, S>
where
S: AssocViewMutType,
{
#[inline]
#[must_use]
pub fn with_annot<M>(self, annot: M::ViewMut<'a>) -> FastaAnnotViewMut<'a, M, S>
where
M: AssocViewMutType, {
FastaAnnotViewMut {
header: self.header,
sequence: self.sequence,
annot,
}
}
#[inline]
#[must_use]
pub fn get_id_taxon(&self) -> Option<(&str, TaxonView<'_>)> {
let (id, taxon) = self.header.get_id_taxon()?;
Some((id, TaxonView::from(taxon)))
}
}
#[derive(Clone, Eq, PartialEq, Hash, Debug, Default)]
pub struct FastaAnnot<M, S = Vec<u8>> {
pub header: String,
pub sequence: S,
pub annot: M,
}
#[derive(Eq, PartialEq, Hash, Debug)]
pub struct FastaAnnotView<'a, M, S = Vec<u8>>
where
S: AssocViewType,
M: AssocViewType, {
pub header: &'a str,
pub sequence: S::View<'a>,
pub annot: M::View<'a>,
}
#[derive(Eq, PartialEq, Hash, Debug)]
pub struct FastaAnnotViewMut<'a, M, S = Vec<u8>>
where
S: AssocViewMutType,
M: AssocViewMutType, {
pub header: &'a mut String,
pub sequence: S::ViewMut<'a>,
pub annot: M::ViewMut<'a>,
}
impl<S> Fasta<S> {
#[inline]
#[must_use]
pub fn map_header<F>(self, f: F) -> Self
where
F: FnOnce(String) -> String, {
Self {
header: f(self.header),
sequence: self.sequence,
}
}
#[inline]
#[must_use]
pub fn map_sequence<U, F>(self, f: F) -> Fasta<U>
where
F: FnOnce(S) -> U, {
Fasta {
header: self.header,
sequence: f(self.sequence),
}
}
}
impl<M, S> FastaAnnot<M, S> {
#[inline]
#[must_use]
pub fn map_header<F>(self, f: F) -> Self
where
F: FnOnce(String) -> String, {
Self {
header: f(self.header),
sequence: self.sequence,
annot: self.annot,
}
}
#[inline]
#[must_use]
pub fn map_sequence<U, F>(self, f: F) -> FastaAnnot<M, U>
where
F: FnOnce(S) -> U, {
FastaAnnot {
header: self.header,
sequence: f(self.sequence),
annot: self.annot,
}
}
#[inline]
#[must_use]
pub fn map_annot<U, F>(self, f: F) -> FastaAnnot<U, S>
where
F: FnOnce(M) -> U, {
FastaAnnot {
header: self.header,
sequence: self.sequence,
annot: f(self.annot),
}
}
}
impl Fasta<Vec<u8>> {
#[inline]
#[must_use]
pub fn recode_to_dna(self) -> Fasta<Nucleotides> {
self.map_sequence(ToDNA::recode_to_dna)
}
#[inline]
#[must_use]
pub fn filter_to_dna(self) -> Fasta<Nucleotides> {
self.map_sequence(ToDNA::filter_to_dna)
}
#[inline]
#[must_use]
pub fn filter_to_dna_unaligned(self) -> Fasta<Nucleotides> {
self.map_sequence(ToDNA::filter_to_dna_unaligned)
}
#[inline]
#[must_use]
pub fn into_dna(self) -> Fasta<Nucleotides> {
self.map_sequence(Into::into)
}
#[inline]
#[must_use]
pub fn into_aa(self) -> Fasta<AminoAcids> {
self.map_sequence(Into::into)
}
}
impl<M> FastaAnnot<M, Vec<u8>> {
#[inline]
#[must_use]
pub fn recode_to_dna(self) -> FastaAnnot<M, Nucleotides> {
self.map_sequence(ToDNA::recode_to_dna)
}
#[inline]
#[must_use]
pub fn filter_to_dna(self) -> FastaAnnot<M, Nucleotides> {
self.map_sequence(ToDNA::filter_to_dna)
}
#[inline]
#[must_use]
pub fn filter_to_dna_unaligned(self) -> FastaAnnot<M, Nucleotides> {
self.map_sequence(ToDNA::filter_to_dna_unaligned)
}
#[inline]
#[must_use]
pub fn into_dna(self) -> FastaAnnot<M, Nucleotides> {
self.map_sequence(Into::into)
}
#[inline]
#[must_use]
pub fn into_aa(self) -> FastaAnnot<M, AminoAcids> {
self.map_sequence(Into::into)
}
}
impl Fasta<Nucleotides> {
#[inline]
pub fn make_reverse_complement(&mut self) {
self.sequence.make_reverse_complement();
}
#[must_use]
pub fn translate(self) -> Fasta<AminoAcids> {
self.map_sequence(|x| Translate::translate(&x))
}
}
impl<M> FastaAnnot<M, Nucleotides> {
#[inline]
pub fn make_reverse_complement(&mut self) {
self.sequence.make_reverse_complement();
}
#[must_use]
pub fn translate(self) -> FastaAnnot<M, AminoAcids> {
self.map_sequence(|x| Translate::translate(&x))
}
}