use alloc::borrow::Cow;
use alloc::string::String;
use core::fmt::Display;
use core::str::FromStr;
use crate::account::name_validation::{self, NameValidationError};
use crate::errors::AccountComponentNameError;
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct AccountComponentName(Cow<'static, str>);
impl AccountComponentName {
pub const fn from_static_str(name: &'static str) -> Self {
match name_validation::validate(name) {
Ok(()) => Self(Cow::Borrowed(name)),
Err(_) => panic!("invalid AccountComponentName: see the type-level documentation"),
}
}
pub fn new(name: impl Into<Cow<'static, str>>) -> Result<Self, AccountComponentNameError> {
let name = name.into();
name_validation::validate(&name).map_err(AccountComponentNameError::from_internal)?;
Ok(Self(name))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl AccountComponentNameError {
pub(crate) fn from_internal(error: NameValidationError) -> Self {
match error {
NameValidationError::TooShort => Self::TooShort,
NameValidationError::TooLong => Self::TooLong,
NameValidationError::UnexpectedColon => Self::UnexpectedColon,
NameValidationError::UnexpectedUnderscore => Self::UnexpectedUnderscore,
NameValidationError::InvalidCharacter => Self::InvalidCharacter,
}
}
}
impl Display for AccountComponentName {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(self.as_str())
}
}
impl FromStr for AccountComponentName {
type Err = AccountComponentNameError;
fn from_str(string: &str) -> Result<Self, Self::Err> {
Self::new(String::from(string))
}
}
impl TryFrom<&str> for AccountComponentName {
type Error = AccountComponentNameError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
value.parse()
}
}
impl TryFrom<String> for AccountComponentName {
type Error = AccountComponentNameError;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::new(value)
}
}
impl From<AccountComponentName> for String {
fn from(name: AccountComponentName) -> Self {
name.0.into_owned()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic(expected = "invalid AccountComponentName")]
fn from_static_str_panics_on_invalid_input() {
AccountComponentName::from_static_str("not_two_components");
}
}