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)" ) } }