use crate::base::Base;
use std::fmt;
use std::slice;
use std::vec;
#[derive(Debug, PartialEq)]
pub enum PatternItem {
Base(Base),
Skip(usize),
Search(Vec),
Open,
Close,
}
impl fmt::Display for PatternItem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self {
PatternItem::Base(b) => write!(f, "{}", b.to_char()),
PatternItem::Skip(n) => write!(f, "!{{{}}}", n),
PatternItem::Search(s) => {
write!(f, "?{{")?;
for b in s {
write!(f, "{}", b.to_char())?;
}
write!(f, "}}")?;
Ok(())
}
PatternItem::Open => write!(f, "("),
PatternItem::Close => write!(f, ")"),
}
}
}
#[derive(PartialEq, Debug)]
pub struct Pattern {
pattern: Vec,
}
impl Pattern {
pub fn new(pattern: Vec) -> Pattern {
Pattern { pattern: pattern }
}
pub fn iter<'a>(&'a self) -> slice::Iter<'a, PatternItem> {
self.pattern.iter()
}
pub fn into_iter<'a>(self) -> vec::IntoIter {
self.pattern.into_iter()
}
}
impl fmt::Display for Pattern {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for p in self.iter() {
write!(f, "{}", p)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_display_base() {
assert_eq!(
Pattern::new(vec![
PatternItem::Base(Base::I),
PatternItem::Base(Base::C),
PatternItem::Base(Base::F),
PatternItem::Base(Base::P)
])
.to_string(),
"ICFP"
);
}
#[test]
fn test_display_skip() {
assert_eq!(Pattern::new(vec![PatternItem::Skip(5)]).to_string(), "!{5}");
}
#[test]
fn test_display_search() {
assert_eq!(
Pattern::new(vec![PatternItem::Search(vec![
Base::I,
Base::C,
Base::F,
Base::P
])])
.to_string(),
"?{ICFP}"
);
}
#[test]
fn test_display_group() {
assert_eq!(
Pattern::new(vec![
PatternItem::Open,
PatternItem::Base(Base::I),
PatternItem::Base(Base::C),
PatternItem::Base(Base::F),
PatternItem::Base(Base::P),
PatternItem::Close,
])
.to_string(),
"(ICFP)"
)
}
}