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