mod bond;
mod eval;
mod expr;
pub(super) mod mol;
mod parse;
mod reaction;
mod write;
pub use expr::{AtomExpr, AtomPrim, BondExpr, BondPrim};
pub use bond::{parse_bond_expr, starts_bond_expr};
pub use eval::{allowed_elements, atom_matches, bond_matches, AtomProps, BondProps};
pub use mol::parse;
pub use parse::parse_atom_expr;
pub use reaction::{parse_reaction, Reaction};
pub use write::{atom_expr_string, bond_expr_string, write, write_reaction};
use omgkit_core::MolBuilder;
#[derive(Debug, Clone)]
pub struct QueryMol {
pub topology: MolBuilder,
pub atoms: Vec<AtomExpr>,
pub bonds: Vec<BondExpr>,
}
#[must_use]
pub fn required_chirality(expr: &AtomExpr) -> Option<omgkit_core::ChiralTag> {
fn walk(e: &AtomExpr) -> Option<omgkit_core::ChiralTag> {
match e {
AtomExpr::Prim(AtomPrim::Chirality(t)) => Some(*t),
AtomExpr::And(parts) => parts.iter().find_map(walk),
AtomExpr::Or(_) | AtomExpr::Not(_) => None,
AtomExpr::Prim(_) => None,
}
}
walk(expr)
}
#[must_use]
pub fn map_number(expr: &AtomExpr) -> Option<u16> {
match expr {
AtomExpr::Prim(AtomPrim::AtomMap(n)) => Some(*n),
AtomExpr::And(parts) => parts.iter().find_map(map_number),
_ => None,
}
}
impl PartialEq for QueryMol {
fn eq(&self, other: &Self) -> bool {
self.atoms == other.atoms
&& self.bonds == other.bonds
&& self.topology.atoms() == other.topology.atoms()
&& self.topology.bonds() == other.topology.bonds()
}
}
impl Eq for QueryMol {}
impl QueryMol {
#[must_use]
pub fn num_atoms(&self) -> usize {
self.atoms.len()
}
#[must_use]
pub fn num_bonds(&self) -> usize {
self.bonds.len()
}
#[must_use]
pub fn is_consistent(&self) -> bool {
self.atoms.len() == self.topology.num_atoms()
&& self.bonds.len() == self.topology.num_bonds()
}
}