use_molecule/
molecule_builder.rs1use use_chemical_formula::ChemicalFormula;
2
3use crate::{
4 AtomConnection, MolecularAtom, Molecule, MoleculeCharge, MoleculeKind, MoleculeValidationError,
5};
6
7#[derive(Clone, Debug, Default, Eq, PartialEq)]
9pub struct MoleculeBuilder {
10 name: String,
11 formula: Option<ChemicalFormula>,
12 atoms: Vec<MolecularAtom>,
13 connections: Vec<AtomConnection>,
14 charge: MoleculeCharge,
15 kinds: Vec<MoleculeKind>,
16}
17
18impl MoleculeBuilder {
19 #[must_use]
21 pub fn new(name: &str) -> Self {
22 Self {
23 name: name.to_owned(),
24 formula: None,
25 atoms: Vec::new(),
26 connections: Vec::new(),
27 charge: MoleculeCharge::NEUTRAL,
28 kinds: Vec::new(),
29 }
30 }
31
32 #[must_use]
34 pub fn formula(mut self, formula: ChemicalFormula) -> Self {
35 self.formula = Some(formula);
36 self
37 }
38
39 #[must_use]
41 pub fn atom(mut self, atom: MolecularAtom) -> Self {
42 self.atoms.push(atom);
43 self
44 }
45
46 #[must_use]
48 pub fn connection(mut self, connection: AtomConnection) -> Self {
49 self.connections.push(connection);
50 self
51 }
52
53 #[must_use]
55 pub const fn charge(mut self, charge: MoleculeCharge) -> Self {
56 self.charge = charge;
57 self
58 }
59
60 #[must_use]
62 pub fn kind(mut self, kind: MoleculeKind) -> Self {
63 if !self.kinds.contains(&kind) {
64 self.kinds.push(kind);
65 }
66 self
67 }
68
69 pub fn build(self) -> Result<Molecule, MoleculeValidationError> {
78 let Some(formula) = self.formula else {
79 return Err(MoleculeValidationError::MissingFormula);
80 };
81
82 let mut molecule = Molecule::new(&self.name, formula)?.with_charge(self.charge);
83 for kind in self.kinds {
84 molecule = molecule.with_kind(kind);
85 }
86 for atom in self.atoms {
87 molecule = molecule.with_atom(atom);
88 }
89 for connection in self.connections {
90 molecule = molecule.try_with_connection(connection)?;
91 }
92
93 Ok(molecule)
94 }
95}