use std::fmt;
use crate::FormulaValidationError;
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct ElementSymbol(String);
impl ElementSymbol {
pub fn new(symbol: &str) -> Result<Self, FormulaValidationError> {
if is_valid_element_symbol(symbol) {
Ok(Self(symbol.to_owned()))
} else {
Err(FormulaValidationError::InvalidSymbol(symbol.to_owned()))
}
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
#[must_use]
pub fn into_string(self) -> String {
self.0
}
}
impl AsRef<str> for ElementSymbol {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl TryFrom<&str> for ElementSymbol {
type Error = FormulaValidationError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
Self::new(value)
}
}
impl fmt::Display for ElementSymbol {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(self.as_str())
}
}
#[must_use]
pub fn is_valid_element_symbol(symbol: &str) -> bool {
let mut characters = symbol.chars();
let Some(first) = characters.next() else {
return false;
};
if !first.is_ascii_uppercase() {
return false;
}
match characters.next() {
None => true,
Some(second) if second.is_ascii_lowercase() => characters.next().is_none(),
Some(_) => false,
}
}