chemistru_elements/
lib.rs

1//! # chemistru-elements
2
3#![no_std]
4#![forbid(clippy::pedantic)]
5#![forbid(clippy::unwrap_used)]
6#![forbid(unsafe_code)]
7
8mod atomic;
9mod electron;
10mod misc;
11mod physical;
12mod raw;
13mod table;
14pub mod utils;
15
16extern crate alloc;
17
18use alloc::vec::Vec;
19use core::fmt::Display;
20
21use lazy_static::lazy_static;
22
23use crate::{
24    atomic::AtomicData, electron::ElectronData, misc::MiscData, physical::PhysicalData,
25    raw::RawElement, table::TableData,
26};
27
28// pub static ELEMENTS: LazyLock<Vec<Element>> = LazyLock::new(|| );
29
30lazy_static! {
31    pub static ref ELEMENTS: Vec<Element> = {
32        let raw_elements: Vec<RawElement> =
33            serde_json::from_str(include_str!("../db.json")).expect("Failed to load json data");
34        raw_elements.iter().map(|e| e.clone().sanitise()).collect()
35    };
36}
37
38#[derive(Clone, Debug, PartialEq, PartialOrd)]
39pub struct Element {
40    pub(crate) name: &'static str,
41    pub(crate) symbol: &'static str,
42    pub(crate) atomic_data: AtomicData,
43    pub(crate) electron_data: ElectronData,
44    pub(crate) physical_data: PhysicalData,
45    pub(crate) table_data: TableData,
46    pub(crate) misc_data: MiscData,
47}
48
49impl Element {
50    #[must_use]
51    pub fn name(&self) -> &'static str {
52        self.name
53    }
54
55    #[must_use]
56    pub fn symbol(&self) -> &'static str {
57        self.symbol
58    }
59
60    #[must_use]
61    pub fn atomic_data(&self) -> &AtomicData {
62        &self.atomic_data
63    }
64
65    #[must_use]
66    pub fn electron_data(&self) -> &ElectronData {
67        &self.electron_data
68    }
69
70    #[must_use]
71    pub fn physical_data(&self) -> &PhysicalData {
72        &self.physical_data
73    }
74
75    #[must_use]
76    pub fn table_data(&self) -> &TableData {
77        &self.table_data
78    }
79
80    #[must_use]
81    pub fn misc_data(&self) -> &MiscData {
82        &self.misc_data
83    }
84}
85
86impl Display for Element {
87    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
88        f.write_fmt(format_args!(
89            "{}-{}",
90            self.name, self.atomic_data.atomic_number
91        ))
92    }
93}
94
95pub mod prelude {
96    pub use super::ELEMENTS;
97    pub use super::Element;
98    pub use super::utils::element_from_atomic_number;
99    pub use super::utils::element_from_name;
100    pub use super::utils::preload_elements;
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106
107    #[test]
108    fn test_getting_elements_by_atomic_number() {
109        utils::preload_elements();
110
111        let hydrogen = utils::element_from_atomic_number(1);
112        let helium = utils::element_from_atomic_number(2);
113
114        assert_eq!(
115            hydrogen.expect("We know this exists").name().to_lowercase(),
116            "hydrogen"
117        );
118        assert_eq!(
119            helium.expect("We know this exists").name().to_lowercase(),
120            "helium"
121        );
122    }
123
124    #[test]
125    fn test_getting_elements_by_name() {
126        utils::preload_elements();
127
128        let hydrogen = utils::element_from_name("hydrogen");
129        let helium = utils::element_from_name("helium");
130
131        assert_eq!(
132            hydrogen
133                .expect("We know this exists")
134                .atomic_data
135                .atomic_number,
136            1
137        );
138        assert_eq!(
139            helium
140                .expect("We know this exists")
141                .atomic_data
142                .atomic_number,
143            2
144        );
145    }
146}