use core::fmt;
use core::hash::Hash;
pub mod amino;
pub mod dna;
pub mod iupac;
#[cfg(feature = "extra_codecs")]
pub mod masked;
#[cfg(feature = "extra_codecs")]
pub mod degenerate;
pub mod text;
pub use bio_seq_derive::Codec;
pub trait Codec: fmt::Debug + Copy + Clone + PartialEq + Hash + Eq {
const BITS: u8;
fn unsafe_from_bits(b: u8) -> Self;
fn try_from_bits(b: u8) -> Option<Self>;
fn unsafe_from_ascii(c: u8) -> Self;
fn try_from_ascii(c: u8) -> Option<Self>;
fn to_char(self) -> char;
fn to_bits(self) -> u8;
fn items() -> impl Iterator<Item = Self>;
}
#[cfg(test)]
mod tests {
use crate::codec::{Codec, amino, dna::Dna, iupac::Iupac, text};
#[cfg(feature = "extra_codecs")]
use crate::codec::{degenerate, masked};
use crate::{ComplementMut, MaskableMut};
fn check_codec<C: Codec>() {
for symbol in C::items() {
assert_eq!(C::try_from_bits(symbol.to_bits()), Some(symbol));
assert_eq!(C::unsafe_from_bits(symbol.to_bits()), symbol);
assert_eq!(C::try_from_ascii(symbol.to_char() as u8), Some(symbol));
assert_eq!(C::unsafe_from_ascii(symbol.to_char() as u8), symbol);
}
}
fn check_comp_comp<C: Codec + ComplementMut>() {
for symbol in C::items() {
let mut symcomp = symbol;
symcomp.comp();
symcomp.comp();
assert_eq!(symcomp, symbol);
}
}
fn check_mask_comp<C: Codec + ComplementMut + MaskableMut>() {
for symbol in C::items() {
let mut symcomp = symbol;
symcomp.comp();
symcomp.mask();
symcomp.comp();
symcomp.unmask();
assert_eq!(symcomp, symbol);
}
}
#[test]
fn dna_to_iupac() {
assert_eq!(Iupac::from(Dna::A), Iupac::A);
assert_eq!(Iupac::from(Dna::C), Iupac::C);
assert_eq!(Iupac::from(Dna::G), Iupac::G);
assert_eq!(Iupac::from(Dna::T), Iupac::T);
assert_ne!(Iupac::from(Dna::A), Iupac::T);
assert_ne!(Iupac::from(Dna::T), Iupac::A);
assert_ne!(Iupac::from(Dna::C), Iupac::T);
assert_ne!(Iupac::from(Dna::G), Iupac::T);
}
#[test]
fn check_codecs() {
check_codec::<Dna>();
check_codec::<Iupac>();
check_codec::<amino::Amino>();
check_codec::<text::Dna>();
#[cfg(feature = "extra_codecs")]
check_codec::<degenerate::MK>();
#[cfg(feature = "extra_codecs")]
check_codec::<degenerate::RY>();
#[cfg(feature = "extra_codecs")]
check_codec::<degenerate::WS>();
}
#[test]
fn check_comp_codecs() {
check_comp_comp::<Dna>();
check_comp_comp::<Iupac>();
#[cfg(feature = "extra_codecs")]
check_comp_comp::<degenerate::MK>();
#[cfg(feature = "extra_codecs")]
check_comp_comp::<degenerate::RY>();
#[cfg(feature = "extra_codecs")]
check_comp_comp::<degenerate::WS>();
}
#[test]
#[cfg(feature = "extra_codecs")]
fn check_mask_comp_codecs() {
check_mask_comp::<masked::Dna>();
}
#[test]
fn derive_weird_codec() {
#[derive(Codec, PartialEq, Clone, Copy, Debug, Hash, Eq)]
enum Weird {
A = 0,
B = 0b01,
C = 16,
}
assert_eq!(Weird::BITS, 5);
}
}