1use crate::{MarkdownExt, Share};
2use equt_md_frontmatter::FrontMatter;
3use std::cell::{Ref, RefCell};
4
5enum WithinState {
6 External,
7 Internal,
8}
9
10#[derive(new)]
17pub struct Within<I, P, Q, F, T>
18where
19 I: Iterator<Item = T>,
20 P: Fn(&T) -> bool,
21 Q: Fn(&T) -> bool,
22 F: FnMut(Ref<Option<FrontMatter>>, T) -> Option<T>,
23{
24 frontmatter: Share<RefCell<Option<FrontMatter>>>,
25 iter: I,
26 start: P,
27 end: Q,
28 f: F,
29
30 #[new(value = "WithinState::External")]
31 state: WithinState,
32}
33
34impl<I, P, Q, F, T> Iterator for Within<I, P, Q, F, T>
35where
36 I: Iterator<Item = T>,
37 P: Fn(&T) -> bool,
38 Q: Fn(&T) -> bool,
39 F: FnMut(Ref<Option<FrontMatter>>, T) -> Option<T>,
40{
41 type Item = T;
42
43 fn next(&mut self) -> Option<Self::Item> {
44 match self.state {
45 WithinState::External => match self.iter.next() {
46 Some(e) if (self.start)(&e) => {
47 self.state = WithinState::Internal;
48 Some(e)
49 }
50 node => node,
51 },
52 WithinState::Internal => match self.iter.next() {
53 Some(e) if (self.end)(&e) => {
54 self.state = WithinState::External;
55 Some(e)
56 }
57 Some(e) => match (self.f)(self.frontmatter.upgrade().unwrap().borrow(), e) {
58 node @ Some(_) => node,
59 None => self.next(),
60 },
61 node => node,
62 },
63 }
64 }
65}
66
67impl<I, P, Q, F, T> MarkdownExt<T> for Within<I, P, Q, F, T>
68where
69 I: Iterator<Item = T>,
70 P: Fn(&T) -> bool,
71 Q: Fn(&T) -> bool,
72 F: FnMut(Ref<Option<FrontMatter>>, T) -> Option<T>,
73{
74 fn frontmatter(&mut self) -> &mut Share<RefCell<Option<FrontMatter>>> {
75 &mut self.frontmatter
76 }
77}
78
79#[cfg(test)]
80mod test {
81 use super::*;
82 use std::rc::Rc;
83
84 #[test]
85 fn normal() {
86 assert_eq!(
87 Within::new(
88 Rc::new(RefCell::new(None)).into(),
89 1..9,
90 |&n| n == 3,
91 |&n| n == 6,
92 |_, n| Some(n + 1)
93 ).collect::<Vec<_>>(),
94 vec![1, 2, 3, 5, 6, 6, 7, 8]
95 );
96 }
97}