1use std::marker::PhantomData;
6
7use crate::Style;
8use crate::element::Element;
9use crate::render::RenderChunk;
10
11#[derive(Debug, Clone, Copy)]
13pub struct Gap(pub usize);
14
15impl<'s> Element<'s> for Gap {
16 fn width(&self) -> usize {
17 self.0
18 }
19
20 fn render(&self) -> impl DoubleEndedIterator<Item = RenderChunk<'s>> {
21 GapIter {
22 size: self.0,
23 phantom: PhantomData,
24 }
25 }
26}
27
28struct GapIter<'s> {
29 size: usize,
30 phantom: PhantomData<&'s ()>,
31}
32
33impl<'s> Iterator for GapIter<'s> {
34 type Item = RenderChunk<'s>;
35
36 fn size_hint(&self) -> (usize, Option<usize>) {
37 let value = self.size.div_ceil(GAP.len());
38 (value, Some(value))
39 }
40
41 fn next(&mut self) -> Option<Self::Item> {
42 if self.size == 0 {
43 None
44 } else {
45 let spaces = self.size.min(GAP.len());
46 self.size -= spaces;
47 Some(RenderChunk::with_known_width(
48 &GAP[..spaces],
49 spaces,
50 Style::EMPTY,
51 ))
52 }
53 }
54}
55
56impl<'s> DoubleEndedIterator for GapIter<'s> {
57 fn next_back(&mut self) -> Option<Self::Item> {
58 self.next()
59 }
60}
61
62const GAP: &str = " "; #[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn empty() {
70 let element = Gap(0);
71 let render: Vec<_> = element.render().collect();
72 assert_eq!(render, []);
73 }
74
75 #[test]
76 fn short() {
77 let element = Gap(7);
78 let render: Vec<_> = element.render().collect();
79 assert_eq!(render, [" ".into()]);
80 }
81
82 #[test]
83 fn long() {
84 let element = Gap(GAP.len() + 2);
85 let render: Vec<_> = element.render().collect();
86 assert_eq!(render, [GAP.into(), " ".into()]);
87 }
88}