Skip to main content

use_oxidation_state/
roman.rs

1use std::fmt;
2
3use crate::{OxidationMagnitude, OxidationState};
4
5const ROMAN_NUMERALS: [&str; 8] = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII"];
6
7/// A Roman numeral representation of a common oxidation-state magnitude.
8#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
9pub struct RomanOxidationState {
10    magnitude: OxidationMagnitude,
11}
12
13impl RomanOxidationState {
14    /// Creates a Roman oxidation-state label from a nonzero magnitude.
15    #[must_use]
16    pub const fn new(magnitude: OxidationMagnitude) -> Option<Self> {
17        if magnitude.is_zero() {
18            None
19        } else {
20            Some(Self { magnitude })
21        }
22    }
23
24    /// Creates a Roman oxidation-state label from an oxidation state.
25    #[must_use]
26    pub const fn from_state(state: OxidationState) -> Option<Self> {
27        Self::new(state.magnitude())
28    }
29
30    /// Returns the magnitude represented by this Roman label.
31    #[must_use]
32    pub const fn magnitude(self) -> OxidationMagnitude {
33        self.magnitude
34    }
35
36    /// Returns the Roman numeral text.
37    #[must_use]
38    pub fn as_str(self) -> &'static str {
39        roman_numeral(self.magnitude.get()).unwrap_or("")
40    }
41}
42
43impl fmt::Display for RomanOxidationState {
44    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
45        formatter.write_str(self.as_str())
46    }
47}
48
49/// Returns the Roman numeral for a supported oxidation-state magnitude.
50#[must_use]
51pub const fn roman_numeral(magnitude: u8) -> Option<&'static str> {
52    match magnitude {
53        1..=8 => Some(ROMAN_NUMERALS[(magnitude - 1) as usize]),
54        _ => None,
55    }
56}