equt_md_ext/
link.rs

1use crate::{MarkdownExt, Share};
2use equt_md_frontmatter::FrontMatter;
3use std::cell::RefCell;
4
5enum LinkState {
6    Front,
7    Back,
8}
9
10/// An iterator links two [`MarkdownExt`].
11///
12/// This `struct` is created by [`link`] method on [`MarkdownExt`].
13///
14/// [`link`]: trait.MarkdownExt.html#method.link
15/// [`MarkdownExt`]: trait.MarkdownExt.html
16#[derive(new)]
17pub struct Link<A, B> {
18    frontmatter: Share<RefCell<Option<FrontMatter>>>,
19    a: A,
20    b: B,
21
22    #[new(value = "LinkState::Front")]
23    state: LinkState,
24}
25
26impl<A, B, T> MarkdownExt<T> for Link<A, B>
27where
28    A: Iterator<Item = T>,
29    B: Iterator<Item = T>,
30{
31    fn frontmatter(&mut self) -> &mut Share<RefCell<Option<FrontMatter>>> {
32        &mut self.frontmatter
33    }
34}
35
36impl<A, B, T> Iterator for Link<A, B>
37where
38    A: Iterator<Item = T>,
39    B: Iterator<Item = T>,
40{
41    type Item = T;
42
43    fn next(&mut self) -> Option<Self::Item> {
44        match self.state {
45            LinkState::Front => match self.a.next() {
46                node @ Some(_) => node,
47                None => {
48                    self.state = LinkState::Back;
49                    self.b.next()
50                }
51            },
52            LinkState::Back => self.b.next(),
53        }
54    }
55}
56
57#[cfg(test)]
58mod test {
59    use super::*;
60    use std::rc::Rc;
61
62    struct TestIter {
63        frontmatter: Share<RefCell<Option<FrontMatter>>>,
64        range: std::ops::Range<u8>,
65    }
66
67    impl From<std::ops::Range<u8>> for TestIter {
68        fn from(r: std::ops::Range<u8>) -> Self {
69            Self {
70                frontmatter: Rc::new(RefCell::new(None)).into(),
71                range: r,
72            }
73        }
74    }
75
76    impl Iterator for TestIter {
77        type Item = u8;
78
79        fn next(&mut self) -> Option<Self::Item> {
80            self.range.next()
81        }
82    }
83
84    impl MarkdownExt<u8> for TestIter {
85        fn frontmatter(&mut self) -> &mut Share<RefCell<Option<FrontMatter>>> {
86            &mut self.frontmatter
87        }
88    }
89
90    #[test]
91    fn iter() {
92        assert_eq!(
93            Link::new(
94                Rc::new(RefCell::new(None)).into(),
95                TestIter::from(1..4),
96                TestIter::from(4..7),
97            )
98            .collect::<Vec<_>>(),
99            (1..7).collect::<Vec<_>>()
100        );
101    }
102}