use crate::plugin::{MAX_PLUGIN_IDENTITY_BYTES, PluginIdentityError};
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct PluginIdentity(String);
impl PluginIdentity {
pub fn try_new(identity: impl Into<String>) -> Result<Self, PluginIdentityError> {
let identity = identity.into();
validate_plugin_identity(&identity)?;
Ok(Self(identity))
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
#[must_use]
pub fn into_string(self) -> String {
self.0
}
}
fn validate_plugin_identity(identity: &str) -> Result<(), PluginIdentityError> {
if identity.is_empty() {
return Err(PluginIdentityError::Empty);
}
if identity.len() > MAX_PLUGIN_IDENTITY_BYTES {
return Err(PluginIdentityError::TooLong);
}
let mut bytes = identity.bytes();
let first = bytes.next().expect("empty identity returned above");
if !first.is_ascii_lowercase() && !first.is_ascii_digit() {
return Err(PluginIdentityError::InvalidStart);
}
if bytes.any(|byte| {
!byte.is_ascii_lowercase() && !byte.is_ascii_digit() && !matches!(byte, b'.' | b'_' | b'-')
}) {
return Err(PluginIdentityError::InvalidCharacter);
}
Ok(())
}