use {core::iter::FromIterator, cur::*, test_log::test}; macro_rules! assert_catch { ($cur:ident, $id:expr => ($begin:expr, $end:expr, $s:expr)) => { if let Some(catch) = $cur.next() { if let Some(find) = catch.get($id) { assert_eq!( find.begin(), $begin, "expected find begin {}, got {}", $begin, find.begin() ); assert_eq!( find.end(), $end, "expected find end {}, got {}", $end, find.end() ); assert_eq!( find.as_str(), $s, "expected find '{}', got '{:?}'", $s, find.as_str() ); } else { panic!("Expected mark of `{}` was not found", $id); } } else { panic!("Expected catch was not found"); } }; } fn surround_odor(odor: Odor) -> Odor { Odor::from_iter(vec![ Scent::Repetition(Odor::from_iter(vec![Scent::Range('\u{0}', '\u{10ffff}')])), Scent::Marked(odor), Scent::Repetition(Odor::from_iter(vec![Scent::Range('\u{0}', '\u{10ffff}')])), ]) } #[test] fn empty() { let odor = surround_odor(Odor::default().mark("id").unwrap()); let mut cur = Cur::new(&odor); cur.set_search(""); assert_catch!(cur, "id" => (0, 0, "")); assert!(cur.next().is_none()); cur.set_search("a"); assert_catch!(cur, "id" => (0, 0, "")); assert_catch!(cur, "id" => (1, 1, "")); assert!(cur.next().is_none()); } #[test] fn char() { let odor = surround_odor(Odor::from_iter(vec![Scent::Char('a')]).mark("id").unwrap()); let mut cur = Cur::new(&odor); cur.set_search("a"); assert_catch!(cur, "id" => (0, 1, "a")); assert!(cur.next().is_none()); cur.set_search("ab"); assert_catch!(cur, "id" => (0, 1, "a")); assert!(cur.next().is_none()); cur.set_search("ba"); assert_catch!(cur, "id" => (1, 2, "a")); assert!(cur.next().is_none()); cur.set_search("bbbab"); assert_catch!(cur, "id" => (3, 4, "a")); assert!(cur.next().is_none()); cur.set_search(""); assert!(cur.next().is_none()); cur.set_search("b"); assert!(cur.next().is_none()); } #[test] fn range() { let odor = surround_odor( Odor::from_iter(vec![Scent::Range('b', 'd')]) .mark("id") .unwrap(), ); let mut cur = Cur::new(&odor); cur.set_search("b"); assert_catch!(cur, "id" => (0, 1, "b")); assert!(cur.next().is_none()); cur.set_search("cc"); assert_catch!(cur, "id" => (0, 1, "c")); assert_catch!(cur, "id" => (1, 2, "c")); assert!(cur.next().is_none()); cur.set_search("de"); assert_catch!(cur, "id" => (0, 1, "d")); assert!(cur.next().is_none()); cur.set_search("ad"); assert_catch!(cur, "id" => (1, 2, "d")); assert!(cur.next().is_none()); cur.set_search(""); assert!(cur.next().is_none()); cur.set_search("a"); assert!(cur.next().is_none()); cur.set_search("e"); assert!(cur.next().is_none()); } #[test] fn union_of_chars() { let odor = surround_odor( Odor::from_iter(vec![Scent::Union(MultipleOdors::new( Odor::from_iter(vec![Scent::Char('a')]), Odor::from_iter(vec![Scent::Char('b')]), vec![Odor::from_iter(vec![Scent::Char('c')])], ))]) .mark("id") .unwrap(), ); let mut cur = Cur::new(&odor); cur.set_search("a"); assert_catch!(cur, "id" => (0, 1, "a")); assert!(cur.next().is_none()); cur.set_search("bb"); assert_catch!(cur, "id" => (0, 1, "b")); assert_catch!(cur, "id" => (1, 2, "b")); assert!(cur.next().is_none()); cur.set_search("cd"); assert_catch!(cur, "id" => (0, 1, "c")); assert!(cur.next().is_none()); cur.set_search("ea"); assert_catch!(cur, "id" => (1, 2, "a")); assert!(cur.next().is_none()); cur.set_search(""); assert!(cur.next().is_none()); cur.set_search("d"); assert!(cur.next().is_none()); } #[test] fn sequence_of_chars() { let odor = surround_odor( Odor::from_iter(vec![Scent::Char('a'), Scent::Char('b'), Scent::Char('c')]) .mark("id") .unwrap(), ); let mut cur = Cur::new(&odor); cur.set_search("abc"); assert_catch!(cur, "id" => (0, 3, "abc")); assert!(cur.next().is_none()); cur.set_search("abcd"); assert_catch!(cur, "id" => (0, 3, "abc")); assert!(cur.next().is_none()); cur.set_search("dabc"); assert_catch!(cur, "id" => (1, 4, "abc")); assert!(cur.next().is_none()); cur.set_search(""); assert!(cur.next().is_none()); cur.set_search("a"); assert!(cur.next().is_none()); cur.set_search("ab"); assert!(cur.next().is_none()); cur.set_search("aaa"); assert!(cur.next().is_none()); } #[test] fn union_sequences() { let odor = surround_odor( Odor::from_iter(vec![Scent::Union(MultipleOdors::new( Odor::from_iter(vec![Scent::Char('a'), Scent::Char('b'), Scent::Char('c')]), Odor::from_iter(vec![Scent::Char('d'), Scent::Char('e')]), vec![Odor::from_iter(vec![Scent::Char('f')])], ))]) .mark("id") .unwrap(), ); let mut cur = Cur::new(&odor); cur.set_search("abc"); assert_catch!(cur, "id" => (0, 3, "abc")); assert!(cur.next().is_none()); cur.set_search("de"); assert_catch!(cur, "id" => (0, 2, "de")); assert!(cur.next().is_none()); cur.set_search("f"); assert_catch!(cur, "id" => (0, 1, "f")); assert!(cur.next().is_none()); cur.set_search("fd"); assert_catch!(cur, "id" => (0, 1, "f")); assert!(cur.next().is_none()); cur.set_search("df"); assert_catch!(cur, "id" => (1, 2, "f")); assert!(cur.next().is_none()); cur.set_search(""); assert!(cur.next().is_none()); cur.set_search("ab"); assert!(cur.next().is_none()); cur.set_search("d"); assert!(cur.next().is_none()); } #[test] fn repetition() { let odor = surround_odor( Odor::from_iter(vec![Scent::Repetition(Odor::from_iter(vec![Scent::Char( 'a', )]))]) .mark("id") .unwrap(), ); let mut cur = Cur::new(&odor); cur.set_search(""); assert_catch!(cur, "id" => (0, 0, "")); assert!(cur.next().is_none()); cur.set_search("a"); assert_catch!(cur, "id" => (0, 0, "")); assert_catch!(cur, "id" => (0, 1, "a")); assert_catch!(cur, "id" => (1, 1, "")); assert!(cur.next().is_none()); cur.set_search("aa"); assert_catch!(cur, "id" => (0, 0, "")); assert_catch!(cur, "id" => (0, 1, "a")); assert_catch!(cur, "id" => (0, 2, "aa")); assert_catch!(cur, "id" => (1, 1, "")); assert_catch!(cur, "id" => (1, 2, "a")); assert_catch!(cur, "id" => (2, 2, "")); assert!(cur.next().is_none()); cur.set_search("b"); assert_catch!(cur, "id" => (0, 0, "")); assert_catch!(cur, "id" => (1, 1, "")); assert!(cur.next().is_none()); } #[test] fn sequence_repetition_and_repeat() { let odor = surround_odor( Odor::from_iter(vec![ Scent::Char('b'), Scent::Repetition(Odor::from_iter(vec![Scent::Char('a')])), Scent::Char('b'), ]) .mark("id") .unwrap(), ); let mut cur = Cur::new(&odor); cur.set_search("bb"); assert_catch!(cur, "id" => (0, 2, "bb")); assert!(cur.next().is_none()); cur.set_search("bab"); assert_catch!(cur, "id" => (0, 3, "bab")); assert!(cur.next().is_none()); cur.set_search("baab"); assert_catch!(cur, "id" => (0, 4, "baab")); assert!(cur.next().is_none()); cur.set_search("bba"); assert_catch!(cur, "id" => (0, 2, "bb")); assert!(cur.next().is_none()); cur.set_search("abab"); assert_catch!(cur, "id" => (1, 4, "bab")); assert!(cur.next().is_none()); cur.set_search(""); assert!(cur.next().is_none()); cur.set_search("a"); assert!(cur.next().is_none()); cur.set_search("b"); assert!(cur.next().is_none()); cur.set_search("ba"); assert!(cur.next().is_none()); cur.set_search("baa"); assert!(cur.next().is_none()); }