use mago_phpdoc_syntax::cst::TemplateTagValueVariance;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Variance {
Invariant,
Covariant,
Contravariant,
}
impl From<TemplateTagValueVariance> for Variance {
fn from(variance: TemplateTagValueVariance) -> Self {
match variance {
TemplateTagValueVariance::Invariant => Variance::Invariant,
TemplateTagValueVariance::Covariant => Variance::Covariant,
TemplateTagValueVariance::Contravariant => Variance::Contravariant,
}
}
}
impl Variance {
#[inline]
#[must_use]
pub const fn is_invariant(&self) -> bool {
matches!(self, Variance::Invariant)
}
#[inline]
#[must_use]
pub const fn is_covariant(&self) -> bool {
matches!(self, Variance::Covariant)
}
#[inline]
#[must_use]
pub const fn is_contravariant(&self) -> bool {
matches!(self, Variance::Contravariant)
}
#[inline]
#[must_use]
pub const fn is_readonly(&self) -> bool {
matches!(self, Variance::Covariant | Variance::Invariant)
}
#[inline]
#[must_use]
pub const fn combine(outer_variance: Self, inner_variance: Self) -> Self {
match (outer_variance, inner_variance) {
(Variance::Invariant, _) | (_, Variance::Invariant) => Variance::Invariant,
(Variance::Covariant, Variance::Covariant) => Variance::Covariant,
(Variance::Contravariant, Variance::Contravariant) => Variance::Covariant,
(Variance::Covariant, Variance::Contravariant) => Variance::Contravariant,
(Variance::Contravariant, Variance::Covariant) => Variance::Contravariant,
}
}
}
impl std::fmt::Display for Variance {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Variance::Invariant => write!(f, "invariant"),
Variance::Covariant => write!(f, "covariant"),
Variance::Contravariant => write!(f, "contravariant"),
}
}
}