1use core::marker::PhantomData;
2
3use crate::grid::config::HorizontalLine;
4use crate::grid::config::VerticalLine as Line;
5use crate::settings::style::On;
6use crate::settings::Style;
7
8#[derive(Debug, Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
10pub struct VerticalLine<T, B, I> {
11 line: Line<char>,
12 _top: PhantomData<T>,
13 _bottom: PhantomData<B>,
14 _intersection: PhantomData<I>,
15}
16
17impl VerticalLine<(), (), ()> {
18 pub const fn new(main: char) -> Self {
20 Self::update(Line::new(Some(main), None, None, None))
21 }
22}
23
24impl<T, B, I> VerticalLine<T, B, I> {
25 pub const fn empty() -> Self {
27 Self::update(Line::empty())
28 }
29
30 pub const fn inherit<L, R, const HSIZE: usize, const VSIZE: usize>(
32 style: Style<T, B, L, R, I, On, HSIZE, VSIZE>,
33 ) -> Self {
34 let borders = style.get_borders();
35 let line = Line::new(
36 borders.vertical,
37 borders.intersection,
38 borders.top_intersection,
39 borders.bottom_intersection,
40 );
41
42 Self::update(line)
43 }
44
45 pub const fn inherit_left<R, V, const HSIZE: usize, const VSIZE: usize>(
47 style: Style<T, B, On, R, I, V, HSIZE, VSIZE>,
48 ) -> Self {
49 let borders = style.get_borders();
50 let line = Line::new(
51 borders.left,
52 borders.left_intersection,
53 borders.top_left,
54 borders.bottom_left,
55 );
56
57 Self::update(line)
58 }
59
60 pub const fn inherit_right<L, V, const HSIZE: usize, const VSIZE: usize>(
62 style: Style<T, B, L, On, I, V, HSIZE, VSIZE>,
63 ) -> Self {
64 let borders = style.get_borders();
65 let line = Line::new(
66 borders.right,
67 borders.right_intersection,
68 borders.top_right,
69 borders.bottom_right,
70 );
71
72 Self::update(line)
73 }
74}
75
76impl VerticalLine<On, On, On> {
77 pub const fn full(main: char, intersection: char, top: char, bottom: char) -> Self {
79 Self::update(Line::new(
80 Some(main),
81 Some(intersection),
82 Some(top),
83 Some(bottom),
84 ))
85 }
86
87 pub const fn filled(main: char) -> Self {
89 Self::full(main, main, main, main)
90 }
91}
92
93impl<T, B, I> VerticalLine<T, B, I> {
94 pub const fn vertical(mut self, c: char) -> VerticalLine<T, B, I> {
96 self.line.main = Some(c);
97 VerticalLine::update(self.line)
98 }
99
100 pub const fn intersection(mut self, c: char) -> VerticalLine<T, B, On> {
102 self.line.intersection = Some(c);
103 VerticalLine::update(self.line)
104 }
105
106 pub const fn top(mut self, c: char) -> VerticalLine<On, B, I> {
108 self.line.top = Some(c);
109 VerticalLine::update(self.line)
110 }
111
112 pub const fn bottom(mut self, c: char) -> VerticalLine<T, On, I> {
114 self.line.bottom = Some(c);
115 VerticalLine::update(self.line)
116 }
117}
118
119impl<T, B, I> VerticalLine<T, B, I> {
120 pub(crate) const fn update(line: Line<char>) -> VerticalLine<T, B, I> {
121 Self {
122 line,
123 _top: PhantomData,
124 _bottom: PhantomData,
125 _intersection: PhantomData,
126 }
127 }
128
129 pub const fn get_vertical(&self) -> char {
131 match self.line.main {
132 Some(c) => c,
133 None => unreachable!(),
134 }
135 }
136
137 pub const fn into_inner(&self) -> Line<char> {
139 self.line
140 }
141}
142
143impl<T, B> VerticalLine<T, B, On> {
144 pub const fn get_intersection(&self) -> char {
146 match self.line.intersection {
147 Some(c) => c,
148 None => unreachable!(),
149 }
150 }
151
152 pub const fn remove_intersection(mut self) -> VerticalLine<T, B, ()> {
154 self.line.intersection = None;
155 VerticalLine::update(self.line)
156 }
157}
158
159impl<B, I> VerticalLine<On, B, I> {
160 pub const fn get_top(&self) -> char {
162 opt_get(self.line.top)
163 }
164
165 pub const fn remove_top(mut self) -> VerticalLine<(), B, I> {
167 self.line.top = None;
168 VerticalLine::update(self.line)
169 }
170}
171
172impl<T, I> VerticalLine<T, On, I> {
173 pub const fn get_bottom(&self) -> char {
175 opt_get(self.line.bottom)
176 }
177
178 pub const fn remove_bottom(mut self) -> VerticalLine<T, (), I> {
180 self.line.bottom = None;
181 VerticalLine::update(self.line)
182 }
183}
184
185impl<T, B, I> From<VerticalLine<T, B, I>> for Line<char> {
186 fn from(value: VerticalLine<T, B, I>) -> Self {
187 value.line
188 }
189}
190
191impl<T, B, I> From<VerticalLine<T, B, I>> for HorizontalLine<char> {
192 fn from(value: VerticalLine<T, B, I>) -> Self {
193 HorizontalLine::new(
194 value.line.main,
195 value.line.intersection,
196 value.line.top,
197 value.line.bottom,
198 )
199 }
200}
201
202impl<T, B, I> From<Line<char>> for VerticalLine<T, B, I> {
203 fn from(value: Line<char>) -> Self {
204 let mut line = Self::empty();
205 line.line = value;
206 line
207 }
208}
209
210const fn opt_get(opt: Option<char>) -> char {
211 match opt {
212 Some(value) => value,
213 None => unreachable!(),
214 }
215}