jean_core 0.1.0

Core package of jean
Documentation
use std::fmt::Display;

use super::{
  rna::{self, Rna},
  Seq,
};

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Codon((u8, u8, u8));

impl Codon {
  pub fn new(values: (u8, u8, u8)) -> Self {
    Self(values)
  }
}

impl Display for Codon {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    write!(
      f,
      "{}{}{}",
      self.0 .0 as char, self.0 .1 as char, self.0 .2 as char
    )
  }
}

impl<T> From<(T, T, T)> for Codon
where
  T: Into<char>,
{
  fn from(values: (T, T, T)) -> Self {
    Self((
      values.0.into() as u8,
      values.1.into() as u8,
      values.2.into() as u8,
    ))
  }
}

impl<T> From<Codon> for (T, T, T)
where
  T: From<char>,
{
  fn from(codon: Codon) -> Self {
    (
      T::from(codon.0 .0 as char),
      T::from(codon.0 .1 as char),
      T::from(codon.0 .2 as char),
    )
  }
}

impl TryFrom<&str> for Codon {
  type Error = String;

  fn try_from(value: &str) -> Result<Self, Self::Error> {
    match value.len() {
      3 => {
        let chars = value.chars().collect::<Vec<char>>();
        Ok(Self::new((chars[0] as u8, chars[1] as u8, chars[2] as u8)))
      }
      n => Err(format!("Invalid codon length (expected 3, found {n})")),
    }
  }
}

impl TryFrom<Codon> for Rna {
  type Error = String;

  fn try_from(value: Codon) -> Result<Self, Self::Error> {
    let b0: rna::Base = match (value.0 .0 as char).try_into() {
      Ok(base) => base,
      Err(_) => {
        return Err(format!(
          "Invalid RNA base at position 0: '{}'",
          value.0 .0 as char
        ))
      }
    };
    let b1: rna::Base = match (value.0 .1 as char).try_into() {
      Ok(base) => base,
      Err(_) => {
        return Err(format!(
          "Invalid RNA base at position 1: '{}'",
          value.0 .1 as char
        ))
      }
    };

    let b2: rna::Base = match (value.0 .2 as char).try_into() {
      Ok(base) => base,
      Err(_) => {
        return Err(format!(
          "Invalid RNA base at position 2: '{}'",
          value.0 .2 as char
        ))
      }
    };

    Ok(Seq(vec![b0, b1, b2]))
  }
}