chemistru_elements/
lib.rs1#![forbid(clippy::pedantic)]
66#![forbid(clippy::unwrap_used)]
67#![forbid(clippy::missing_const_for_fn)]
68#![forbid(unsafe_code)]
69
70#[cfg(feature = "to_tokens")]
71mod tokens;
72
73mod raw;
74
75pub mod atomic;
76pub mod electron;
77pub mod misc;
78pub mod physical;
79pub mod table;
80pub mod utils;
81
82use crate::{
83 atomic::AtomicData, electron::ElectronData, misc::MiscData, physical::PhysicalData,
84 raw::RawElement, table::TableData,
85};
86
87use std::fmt::Display;
88use std::sync::LazyLock;
89
90#[rustfmt::skip]
91pub static ELEMENTS: LazyLock<Vec<Element>> = LazyLock::new(|| {
92 let raw_elements: Vec<RawElement> = serde_json::from_str(include_str!("../db.json")).expect("Failed to load json data");
93 raw_elements.iter().map(|e| e.clone().sanitise()).collect()
94});
95
96#[derive(Clone, Debug, PartialEq, PartialOrd)]
98pub struct Element {
99 pub(crate) name: &'static str,
100 pub(crate) symbol: &'static str,
101 pub(crate) atomic_data: AtomicData,
102 pub(crate) electron_data: ElectronData,
103 pub(crate) physical_data: PhysicalData,
104 pub(crate) table_data: TableData,
105 pub(crate) misc_data: MiscData,
106}
107
108impl Element {
109 #[must_use]
110 pub const fn name(&self) -> &'static str {
111 self.name
112 }
113
114 #[must_use]
115 pub const fn symbol(&self) -> &'static str {
116 self.symbol
117 }
118
119 #[must_use]
120 pub const fn atomic_data(&self) -> &AtomicData {
121 &self.atomic_data
122 }
123
124 #[must_use]
125 pub const fn electron_data(&self) -> &ElectronData {
126 &self.electron_data
127 }
128
129 #[must_use]
130 pub const fn physical_data(&self) -> &PhysicalData {
131 &self.physical_data
132 }
133
134 #[must_use]
135 pub const fn table_data(&self) -> &TableData {
136 &self.table_data
137 }
138
139 #[must_use]
140 pub const fn misc_data(&self) -> &MiscData {
141 &self.misc_data
142 }
143
144 #[must_use]
145 pub const fn new(
146 name: &'static str,
147 symbol: &'static str,
148 atomic_data: AtomicData,
149 electron_data: ElectronData,
150 physical_data: PhysicalData,
151 table_data: TableData,
152 misc_data: MiscData,
153 ) -> Self {
154 Self {
155 name,
156 symbol,
157 atomic_data,
158 electron_data,
159 physical_data,
160 table_data,
161 misc_data,
162 }
163 }
164}
165
166impl Display for Element {
167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168 f.write_fmt(format_args!(
169 "{}-{}",
170 self.name, self.atomic_data.atomic_number
171 ))
172 }
173}
174
175pub mod prelude {
176 pub use super::ELEMENTS;
177 pub use super::Element;
178 pub use super::utils::element_from_atomic_number;
179 pub use super::utils::element_from_name;
180 pub use super::utils::preload_elements;
181}
182
183#[cfg(test)]
184mod tests {
185 use super::*;
186
187 #[test]
188 fn test_getting_elements_by_atomic_number() {
189 utils::preload_elements();
190
191 let hydrogen = utils::element_from_atomic_number(1);
192 let helium = utils::element_from_atomic_number(2);
193
194 assert_eq!(
195 hydrogen.expect("We know this exists").name().to_lowercase(),
196 "hydrogen"
197 );
198 assert_eq!(
199 helium.expect("We know this exists").name().to_lowercase(),
200 "helium"
201 );
202 }
203
204 #[test]
205 fn test_getting_elements_by_name() {
206 utils::preload_elements();
207
208 let hydrogen = utils::element_from_name("hydrogen");
209 let helium = utils::element_from_name("helium");
210
211 assert_eq!(
212 hydrogen
213 .expect("We know this exists")
214 .atomic_data
215 .atomic_number,
216 1
217 );
218 assert_eq!(
219 helium
220 .expect("We know this exists")
221 .atomic_data
222 .atomic_number,
223 2
224 );
225 }
226}