ak_core/geometry/
atomic_number.rs

1#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2pub struct AtomicNumber(u8);
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum AtomicNumberError {
6    OutOfRange { z: u8, max: u8 },
7    ConversionFailed,
8}
9
10impl AtomicNumber {
11    pub const MAX: u8 = 110;
12
13    pub fn new<T>(z: T) -> Result<Self, AtomicNumberError>
14    where
15        T: TryInto<u8>,
16    {
17        let z_u8: u8 = z
18            .try_into()
19            .map_err(|_| AtomicNumberError::ConversionFailed)?;
20
21        if z_u8 > 0 && z_u8 <= Self::MAX {
22            Ok(Self(z_u8))
23        } else {
24            Err(AtomicNumberError::OutOfRange {
25                z: z_u8,
26                max: Self::MAX,
27            })
28        }
29    }
30
31    pub const fn get(self) -> u8 {
32        self.0
33    }
34}
35
36#[cfg(test)]
37mod tests {
38
39    use crate::geometry::{AtomicNumber, AtomicNumberError};
40
41    #[test]
42    fn test_new() {
43        let z = AtomicNumber::new(100).unwrap();
44        assert_eq!(z.get(), 100);
45    }
46
47    #[test]
48    fn test_out_of_range_error() {
49        let z = AtomicNumber::new(111);
50        assert_eq!(z, Err(AtomicNumberError::OutOfRange { z: 111, max: 110 }));
51    }
52
53    #[test]
54    fn test_conversion_error() {
55        let z = AtomicNumber::new(2000);
56        assert_eq!(z, Err(AtomicNumberError::ConversionFailed));
57    }
58}