molrs 0.1.1

A cheminformatics toolkit written in Rust.
Documentation
use pertable::Element;

#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum PointChirality {
    #[default]
    Undefined,
    Achiral,
    Clockwise,
    CounterClockwise,
}

impl ToString for PointChirality {
    fn to_string(&self) -> String {
        match self {
            PointChirality::Undefined => "",
            PointChirality::Achiral => "",
            PointChirality::CounterClockwise => "@",
            PointChirality::Clockwise => "@@",
        }
        .to_owned()
    }
}

#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Atom {
    pub element: Element,
    pub isotope: Option<u16>,
    pub charge: i8,
    pub delocalized: bool,
    pub n_implicit_hydrogens: Option<u8>,
    pub n_radical_electrons: Option<u8>,
    pub point_chirality: PointChirality,
}

impl ToString for Atom {
    fn to_string(&self) -> String {
        let mut s = String::new();
        if self.isotope.is_none()
            && self.charge == 0
            && self.n_radical_electrons == Some(0)
            && (self.point_chirality == PointChirality::Undefined
                || self.point_chirality == PointChirality::Achiral)
        {
            let atomic_symbol = match self.delocalized {
                true => self.element.to_string().to_lowercase(),
                false => self.element.to_string(),
            };

            s = match self.element {
                Element::Any
                | Element::B
                | Element::C
                | Element::N
                | Element::O
                | Element::S
                | Element::P
                | Element::F
                | Element::Cl
                | Element::Br
                | Element::I => atomic_symbol,
                _ => format!("[{atomic_symbol}]"),
            };
        } else {
            s.push('[');
            if self.isotope.is_some() {
                s += &self.isotope.unwrap().to_string();
            };
            s += &self.element.to_string();
            if self.point_chirality != PointChirality::Undefined
                || self.point_chirality != PointChirality::Achiral
            {
                s += &self.point_chirality.to_string();
            }
            s += &match self.n_implicit_hydrogens {
                None => "".to_owned(),
                Some(n_implicit_hydrogens) => match n_implicit_hydrogens {
                    0 => "".to_owned(),
                    1 => "H".to_owned(),
                    _ => format!("H{n_implicit_hydrogens}"),
                },
            };
            if self.charge == 1 {
                s += "+";
            } else if self.charge == -1 {
                s += "-";
            } else if self.charge > 0 {
                s += &format!("+{}", self.charge);
            } else if self.charge < 0 {
                s += &format!("-{}", self.charge);
            }
            s.push(']');
        }

        s
    }
}