use serde::Serialize;
use std::fmt::Display;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
pub enum Card {
ZeroOrOne,
One,
ZeroOrMore,
OneOrMore,
Range(usize, Max),
}
impl Card {
pub fn range(min: usize, max: Max) -> Self {
Card::Range(min, max)
}
pub fn contains(&self, count: usize) -> bool {
match self {
Card::ZeroOrOne => count <= 1,
Card::One => count == 1,
Card::ZeroOrMore => true,
Card::OneOrMore => count >= 1,
Card::Range(min, max) => match max {
Max::Unbounded => count >= *min,
Max::Bounded(max) => count >= *min && count <= *max,
},
}
}
pub fn intersection(&self, other: &Card) -> Card {
match (self, other) {
(Card::ZeroOrOne, _) | (_, Card::ZeroOrOne) => Card::ZeroOrOne,
(Card::One, _) | (_, Card::One) => Card::One,
(Card::ZeroOrMore, _) | (_, Card::ZeroOrMore) => Card::ZeroOrMore,
(Card::OneOrMore, _) | (_, Card::OneOrMore) => Card::OneOrMore,
(Card::Range(min1, max1), Card::Range(min2, max2)) => Card::Range(*min1.max(min2), max1.min(max2)),
}
}
}
impl Display for Card {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Card::ZeroOrOne => write!(f, "0..1"),
Card::One => write!(f, "1"),
Card::ZeroOrMore => write!(f, "0..*"),
Card::OneOrMore => write!(f, "1..*"),
Card::Range(min, max) => write!(f, "{}..{}", min, max),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
pub enum Max {
Unbounded,
Bounded(usize),
}
impl Max {
pub fn min(&self, other: &Max) -> Max {
match (self, other) {
(Max::Unbounded, _) => Max::Unbounded,
(_, Max::Unbounded) => Max::Unbounded,
(Max::Bounded(a), Max::Bounded(b)) => Max::Bounded(*a.min(b)),
}
}
}
impl Display for Max {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Max::Unbounded => write!(f, "∞"),
Max::Bounded(n) => write!(f, "{}", n),
}
}
}