Skip to main content

use_molecule/
atom_connection.rs

1use std::fmt;
2
3use crate::{AtomIndex, MoleculeValidationError};
4
5/// A simple connection between explicit atoms.
6#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
7pub struct AtomConnection {
8    /// The source atom index.
9    pub from: AtomIndex,
10    /// The target atom index.
11    pub to: AtomIndex,
12    /// Optional connection order. This crate does not assign bonding semantics to the value.
13    pub order: Option<u8>,
14}
15
16impl AtomConnection {
17    /// Creates an atom connection.
18    ///
19    /// # Errors
20    ///
21    /// Returns [`MoleculeValidationError::SelfConnection`] when `from` equals `to`, or
22    /// [`MoleculeValidationError::ZeroConnectionOrder`] when `order` is `Some(0)`.
23    pub fn new(
24        from: AtomIndex,
25        to: AtomIndex,
26        order: Option<u8>,
27    ) -> Result<Self, MoleculeValidationError> {
28        if from == to {
29            return Err(MoleculeValidationError::SelfConnection { index: from.get() });
30        }
31
32        if order == Some(0) {
33            return Err(MoleculeValidationError::ZeroConnectionOrder);
34        }
35
36        Ok(Self { from, to, order })
37    }
38
39    pub(crate) fn validate_indices(
40        self,
41        atom_count: usize,
42    ) -> Result<Self, MoleculeValidationError> {
43        for index in [self.from, self.to] {
44            if index.get() >= atom_count {
45                return Err(MoleculeValidationError::InvalidConnectionIndex {
46                    index: index.get(),
47                    atom_count,
48                });
49            }
50        }
51
52        Ok(self)
53    }
54}
55
56impl fmt::Display for AtomConnection {
57    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
58        match self.order {
59            Some(order) => write!(formatter, "{}-{}({order})", self.from, self.to),
60            None => write!(formatter, "{}-{}", self.from, self.to),
61        }
62    }
63}