use super::{Error, pest::Rule};
use crate::version::Version;
use pest::iterators::Pair;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum VersionOperator {
Equal,
GreaterThan,
LessThan,
GreaterThanOrEqual,
LessThanOrEqual,
}
impl VersionOperator {
pub fn as_str(&self) -> &str {
match self {
Self::Equal => "=",
Self::GreaterThan => ">>",
Self::LessThan => "<<",
Self::GreaterThanOrEqual => ">=",
Self::LessThanOrEqual => "<=",
}
}
}
impl std::fmt::Display for VersionOperator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct VersionConstraint {
pub operator: VersionOperator,
pub version: Version,
}
impl std::fmt::Display for VersionConstraint {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} {}", self.operator, self.version)
}
}
impl TryFrom<Pair<'_, Rule>> for VersionConstraint {
type Error = Error;
fn try_from(token: Pair<'_, Rule>) -> Result<Self, Error> {
let mut operator: Option<VersionOperator> = None;
let mut version: Option<Version> = None;
for token in token.into_inner() {
match token.as_rule() {
Rule::version_operator => {
operator = Some(match token.as_str() {
"==" => VersionOperator::Equal,
"=" => VersionOperator::Equal,
"<<" => VersionOperator::LessThan,
">>" => VersionOperator::GreaterThan,
">=" => VersionOperator::GreaterThanOrEqual,
"<=" => VersionOperator::LessThanOrEqual,
_ => {
unreachable!();
}
});
}
Rule::version => {
version = Some(token.as_str().parse()?);
}
_ => continue,
};
}
let Some(operator) = operator else {
return Err(Error::InvalidVersionConstraint);
};
let Some(version) = version else {
return Err(Error::InvalidVersionConstraint);
};
Ok(VersionConstraint { operator, version })
}
}