jean_core 0.1.0

Core package of jean
Documentation
use num_enum::{IntoPrimitive, FromPrimitive};
use strum_macros::EnumCount;

use crate::{
  prelude::{Complement, Transcribe, Gap},
  sequence::dna,
};

#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, IntoPrimitive, FromPrimitive, EnumCount)]
pub enum Base {
  A,
  C,
  G,
  U,

  #[default]
  GAP,
}

impl Gap for Base {
  fn gap() -> Self {
    Self::GAP
  }
}

impl TryFrom<char> for Base {
  type Error = String;

  fn try_from(c: char) -> Result<Self, Self::Error> {
    match c.to_ascii_uppercase() {
      'A' => Ok(Self::A),
      'C' => Ok(Self::C),
      'G' => Ok(Self::G),
      'U' => Ok(Self::U),
      '-' => Ok(Self::GAP),
      _ => Err(format!("Invalid RNA base '{c}'.")),
    }
  }
}

impl From<Base> for char {
  fn from(base: Base) -> Self {
    match base {
      Base::A => 'A',
      Base::C => 'C',
      Base::G => 'G',
      Base::U => 'U',
      Base::GAP => '-',
    }
  }
}

impl Complement for Base {
  fn complement(&self) -> Self {
    match self {
      Self::A => Self::U,
      Self::C => Self::G,
      Self::G => Self::C,
      Self::U => Self::A,
      Self::GAP => Self::GAP,
    }
  }
}

impl Transcribe<dna::Base> for Base {
  fn transcribe(&self) -> dna::Base {
    match self {
      Self::A => dna::Base::A,
      Self::C => dna::Base::C,
      Self::G => dna::Base::G,
      Self::U => dna::Base::T,
      Self::GAP => dna::Base::GAP,
    }
  }
}