use std::fmt::{Display, Formatter, Result as FmtResult};
use std::str::FromStr;
use crate::ProviderRegistryError;
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ProviderName(String);
impl ProviderName {
#[inline]
pub fn new(name: &str) -> Result<Self, ProviderRegistryError> {
let trimmed = name.trim();
if trimmed.is_empty() {
return Err(ProviderRegistryError::EmptyProviderName);
}
if !trimmed.is_ascii() {
return Err(invalid_provider_name(
trimmed,
"provider names must be ASCII",
));
}
if !trimmed.bytes().all(is_allowed_provider_name_byte) {
return Err(invalid_provider_name(
trimmed,
"provider names may contain only ASCII letters, digits, '.', '_' or '-'",
));
}
Ok(Self(trimmed.to_ascii_lowercase()))
}
#[inline]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl AsRef<str> for ProviderName {
#[inline]
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl Display for ProviderName {
#[inline]
fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
formatter.write_str(self.as_str())
}
}
impl FromStr for ProviderName {
type Err = ProviderRegistryError;
#[inline]
fn from_str(name: &str) -> Result<Self, Self::Err> {
Self::new(name)
}
}
fn is_allowed_provider_name_byte(byte: u8) -> bool {
byte.is_ascii_alphanumeric() || matches!(byte, b'.' | b'_' | b'-')
}
fn invalid_provider_name(name: &str, reason: &str) -> ProviderRegistryError {
ProviderRegistryError::InvalidProviderName {
name: name.to_owned(),
reason: reason.to_owned(),
}
}