use thiserror::Error;
#[derive(Debug, Clone, PartialEq, Eq, Hash, bincode::Encode, bincode::Decode)]
pub struct Applicability {
pub raw: String,
pub entity: String,
pub predefined_type: Option<String>,
}
impl Applicability {
pub fn entity(entity: impl Into<String>) -> Self {
let entity = entity.into();
Self {
raw: entity.clone(),
entity,
predefined_type: None,
}
}
pub fn parse(raw: impl Into<String>) -> Result<Self, ApplicabilityError> {
let raw = raw.into();
let value = raw.trim();
if value.is_empty() {
return Err(ApplicabilityError::Empty);
}
let (entity, predefined_type) = match value.split_once('/') {
Some((entity, predefined))
if !entity.trim().is_empty() && !predefined.trim().is_empty() =>
{
if predefined.contains('/') {
return Err(ApplicabilityError::Invalid(raw));
}
(entity.trim().to_owned(), Some(predefined.trim().to_owned()))
}
Some(_) => return Err(ApplicabilityError::Invalid(raw)),
None => (value.to_owned(), None),
};
Ok(Self {
raw,
entity,
predefined_type,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Error)]
#[non_exhaustive]
pub enum ApplicabilityError {
#[error("applicability selector is empty")]
Empty,
#[error("invalid applicability selector `{0}`")]
Invalid(String),
}