line_ui/element/
gap.rs

1/*
2 * Copyright (c) 2025 Jasmine Tai. All rights reserved.
3 */
4
5use std::marker::PhantomData;
6
7use crate::Style;
8use crate::element::Element;
9use crate::render::RenderChunk;
10
11/// An element that renders a blank space of the specified width.
12#[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 = "                "; // 16 spaces
63
64#[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}