Skip to main content

use_atomic_number/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4//! Atomic-number validation and lookup helpers.
5
6use use_element::{all_elements, element_by_symbol};
7
8/// Returns `true` when the atomic number is between 1 and 118 inclusive.
9///
10/// # Examples
11///
12/// ```rust
13/// use use_atomic_number::is_valid_atomic_number;
14///
15/// assert!(is_valid_atomic_number(118));
16/// assert!(!is_valid_atomic_number(0));
17/// ```
18#[must_use]
19pub const fn is_valid_atomic_number(value: u8) -> bool {
20    matches!(value, 1..=118)
21}
22
23/// Looks up an atomic number from a symbol.
24#[must_use]
25pub fn atomic_number_from_symbol(symbol: &str) -> Option<u8> {
26    element_by_symbol(symbol).map(|element| element.atomic_number)
27}
28
29/// Looks up an atomic number from an element name using ASCII case-insensitive matching.
30#[must_use]
31pub fn atomic_number_from_name(name: &str) -> Option<u8> {
32    let normalized = name.trim();
33
34    if normalized.is_empty() {
35        return None;
36    }
37
38    all_elements()
39        .iter()
40        .find(|element| element.name.eq_ignore_ascii_case(normalized))
41        .map(|element| element.atomic_number)
42}
43
44/// Returns the proton count for a valid atomic number.
45#[must_use]
46pub fn proton_count(atomic_number: u8) -> Option<u8> {
47    is_valid_atomic_number(atomic_number).then_some(atomic_number)
48}
49
50/// Returns the electron count for a neutral atom with the given atomic number.
51#[must_use]
52pub fn electron_count_neutral_atom(atomic_number: u8) -> Option<u8> {
53    proton_count(atomic_number)
54}
55
56#[cfg(test)]
57mod tests {
58    use super::{
59        atomic_number_from_name, atomic_number_from_symbol, electron_count_neutral_atom,
60        is_valid_atomic_number, proton_count,
61    };
62
63    #[test]
64    fn validates_range() {
65        assert!(is_valid_atomic_number(1));
66        assert!(is_valid_atomic_number(118));
67        assert!(!is_valid_atomic_number(0));
68        assert!(!is_valid_atomic_number(119));
69    }
70
71    #[test]
72    fn looks_up_symbols_and_names() {
73        assert_eq!(atomic_number_from_symbol("H"), Some(1));
74        assert_eq!(atomic_number_from_symbol("C"), Some(6));
75        assert_eq!(atomic_number_from_symbol("O"), Some(8));
76        assert_eq!(atomic_number_from_symbol("Na"), Some(11));
77        assert_eq!(atomic_number_from_symbol("Fe"), Some(26));
78        assert_eq!(atomic_number_from_symbol("Au"), Some(79));
79        assert_eq!(atomic_number_from_symbol("bad"), None);
80
81        assert_eq!(atomic_number_from_name("Hydrogen"), Some(1));
82        assert_eq!(atomic_number_from_name("carbon"), Some(6));
83        assert_eq!(atomic_number_from_name(" oxygen "), Some(8));
84        assert_eq!(atomic_number_from_name("Sodium"), Some(11));
85        assert_eq!(atomic_number_from_name("Iron"), Some(26));
86        assert_eq!(atomic_number_from_name("Gold"), Some(79));
87        assert_eq!(atomic_number_from_name("Uranium"), Some(92));
88        assert_eq!(atomic_number_from_name("Oganesson"), Some(118));
89        assert_eq!(atomic_number_from_name("invalid"), None);
90    }
91
92    #[test]
93    fn exposes_neutral_atom_counts() {
94        assert_eq!(proton_count(6), Some(6));
95        assert_eq!(electron_count_neutral_atom(6), Some(6));
96        assert_eq!(proton_count(79), Some(79));
97        assert_eq!(electron_count_neutral_atom(79), Some(79));
98        assert_eq!(proton_count(0), None);
99        assert_eq!(electron_count_neutral_atom(119), None);
100    }
101}