1#![warn(missing_debug_implementations)]
6#![warn(missing_docs)]
7
8use std::fmt;
14use std::iter;
15use std::ops;
16
17use super::error::Error;
18use super::grid;
19use super::pos::Pos;
20use super::postrait::PosT;
21
22macro_rules! impl_assert {
24 ($label:ident; $x:expr $(,)?) => {
25 const $label: usize = 0 - !$x as usize;
26 };
27}
28
29#[macro_export]
40macro_rules! gridbool_create {
41 ($sqrid: ty) => {
42 $crate::Gridbool<$crate::pos_create!($sqrid),
43 { ((<$sqrid>::XMAX as usize + 1) * (<$sqrid>::YMAX as usize + 1)).div_ceil(32) }>
44 };
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
59pub struct Gridbool<P: PosT, const WORDS: usize>([u32; WORDS], std::marker::PhantomData<P>);
60
61impl<P: PosT, const WORDS: usize> Gridbool<P, WORDS> {
62 impl_assert!(_ASSERTS;
66 P::WIDTH * P::HEIGHT <= WORDS * 32 &&
68 P::WIDTH * P::HEIGHT >= WORDS * 32 - 32);
70 const WORD_FALSE: u32 = 0;
72 const WORD_TRUE: u32 = 0xFFFFFFFF;
73 const TRUE: bool = true;
75 const FALSE: bool = false;
76
77 pub const ALL_TRUE: Self = Self::repeat(true);
79 pub const ALL_FALSE: Self = Self::repeat(false);
81
82 #[inline]
84 pub const fn repeat(value: bool) -> Self {
85 let _ = Self::_ASSERTS;
86 let v = if value {
87 Self::WORD_TRUE
88 } else {
89 Self::WORD_FALSE
90 };
91 Gridbool([v; WORDS], std::marker::PhantomData)
92 }
93
94 #[inline]
95 fn byte_bit(i: usize) -> (usize, u32) {
96 let byte = i / 32;
97 let bit = 0x80000000 >> (i % 32);
98 (byte, bit)
99 }
100
101 #[inline]
103 pub fn set_t(&mut self, posref: &P) {
104 let (byte, bit) = Self::byte_bit(posref.to_usize());
105 self.0[byte] |= bit;
106 }
107
108 #[inline]
110 pub fn set_f(&mut self, posref: &P) {
111 let (byte, bit) = Self::byte_bit(posref.to_usize());
112 self.0[byte] &= !bit;
113 }
114
115 #[inline]
117 pub fn set(&mut self, posref: &P, value: bool) {
118 if value {
119 self.set_t(posref)
120 } else {
121 self.set_f(posref)
122 }
123 }
124
125 #[inline]
127 pub fn get(&self, posref: &P) -> bool {
128 let (byte, bit) = Self::byte_bit(posref.to_usize());
129 self.0[byte] & bit != 0
130 }
131
132 #[inline]
134 pub fn into_inner(self) -> [u32; WORDS] {
135 self.0
136 }
137
138 #[inline]
140 pub fn as_inner(&self) -> &[u32; WORDS] {
141 &self.0
142 }
143
144 #[inline]
146 pub fn as_inner_mut(&mut self) -> &mut [u32; WORDS] {
147 &mut self.0
148 }
149
150 #[inline]
152 pub fn iter(&self) -> impl iter::Iterator<Item = bool> + '_ {
153 P::iter().map(|pos| self.get(&pos))
154 }
155
156 #[inline]
158 pub fn iter_pos(&self) -> impl iter::Iterator<Item = (P, bool)> + '_
159 where
160 P: Copy,
161 {
162 P::iter().map(move |pos| (pos, { self[pos] }))
163 }
164
165 #[inline]
167 pub fn iter_t(&self) -> impl Iterator<Item = P> + '_ {
168 P::iter().filter(move |pos| self[pos])
169 }
170
171 #[inline]
173 pub fn iter_f(&self) -> impl Iterator<Item = P> + '_ {
174 P::iter().filter(move |pos| !self[pos])
175 }
176
177 #[inline]
179 pub fn set_iter_t(&mut self, positer: impl Iterator<Item = P>) {
180 for pos in positer {
181 self.set_t(&pos);
182 }
183 }
184
185 #[inline]
187 pub fn set_iter_f(&mut self, positer: impl Iterator<Item = P>) {
188 for pos in positer {
189 self.set_f(&pos);
190 }
191 }
192
193 pub fn flip_h(&mut self) {
195 for y in P::iter_y() {
196 for x in 0..P::width() / 2 {
197 let pos1 = P::new(x, y).unwrap();
198 let pos2 = pos1.flip_h();
199 let tmp = self.get(&pos1);
200 self.set(&pos1, self.get(&pos2));
201 self.set(&pos2, tmp);
202 }
203 }
204 }
205
206 pub fn flip_v(&mut self) {
208 for y in 0..P::height() / 2 {
209 for x in P::iter_x() {
210 let pos1 = P::new(x, y).unwrap();
211 let pos2 = pos1.flip_v();
212 let tmp = self.get(&pos1);
213 self.set(&pos1, self.get(&pos2));
214 self.set(&pos2, tmp);
215 }
216 }
217 }
218
219 pub fn from_iter_bool<It>(iter: It) -> Result<Self, Error>
221 where
222 It: iter::IntoIterator<Item = bool>,
223 {
224 let mut gb = Self::ALL_FALSE;
225 let mut it = iter.into_iter();
226 for pos in P::iter() {
227 if let Some(value) = it.next() {
228 gb.set(&pos, value);
229 } else {
230 return Err(Error::IteratorTooShort(pos.to_usize(), P::dimensions()));
231 }
232 }
233 if it.next().is_some() {
234 return Err(Error::IteratorTooLong(P::dimensions()));
235 }
236 Ok(gb)
237 }
238}
239
240impl<const XYMAX: u16, const WORDS: usize> Gridbool<Pos<XYMAX, XYMAX>, WORDS> {
242 pub fn rotate_cw(&mut self) {
244 for y in 0..XYMAX / 2 {
245 for x in y..XYMAX - y {
246 let pos0 = Pos::<XYMAX, XYMAX>::try_from((x, y)).unwrap();
247 let pos1 = pos0.rotate_cw();
248 let pos2 = pos1.rotate_cw();
249 let pos3 = pos2.rotate_cw();
250 let values = [
251 self.get(&pos0),
252 self.get(&pos1),
253 self.get(&pos2),
254 self.get(&pos3),
255 ];
256 self.set(&pos0, values[3]);
257 self.set(&pos1, values[0]);
258 self.set(&pos2, values[1]);
259 self.set(&pos3, values[2]);
260 }
261 }
262 }
263 pub fn rotate_cc(&mut self) {
265 for y in 0..XYMAX / 2 {
266 for x in y..XYMAX - y {
267 let pos0 = Pos::<XYMAX, XYMAX>::try_from((x, y)).unwrap();
268 let pos1 = pos0.rotate_cw();
269 let pos2 = pos1.rotate_cw();
270 let pos3 = pos2.rotate_cw();
271 let values = [
272 self.get(&pos0),
273 self.get(&pos1),
274 self.get(&pos2),
275 self.get(&pos3),
276 ];
277 self.set(&pos0, values[1]);
278 self.set(&pos1, values[2]);
279 self.set(&pos2, values[3]);
280 self.set(&pos3, values[0]);
281 }
282 }
283 }
284}
285
286impl<P: PosT, const WORDS: usize> Default for Gridbool<P, WORDS> {
287 fn default() -> Self {
288 Self::ALL_FALSE
289 }
290}
291
292impl<P: PosT, const WORDS: usize> ops::Index<&P> for Gridbool<P, WORDS> {
295 type Output = bool;
296 #[inline]
297 fn index(&self, pos: &P) -> &Self::Output {
298 if self.get(pos) {
301 &Self::TRUE
302 } else {
303 &Self::FALSE
304 }
305 }
306}
307
308impl<P: PosT, const WORDS: usize> ops::Index<P> for Gridbool<P, WORDS> {
309 type Output = bool;
310 #[inline]
311 fn index(&self, pos: P) -> &Self::Output {
312 if self.get(&pos) {
315 &Self::TRUE
316 } else {
317 &Self::FALSE
318 }
319 }
320}
321
322impl<P: PosT, const WORDS: usize> iter::FromIterator<P> for Gridbool<P, WORDS> {
325 #[inline]
326 fn from_iter<I>(iter: I) -> Self
327 where
328 I: iter::IntoIterator<Item = P>,
329 {
330 let mut gb = Gridbool::<P, WORDS>::ALL_FALSE;
331 gb.set_iter_t(iter.into_iter());
332 gb
333 }
334}
335
336impl<P: PosT, const WORDS: usize> iter::FromIterator<bool> for Gridbool<P, WORDS> {
337 #[inline]
338 fn from_iter<I>(iter: I) -> Self
339 where
340 I: iter::IntoIterator<Item = bool>,
341 {
342 match Self::from_iter_bool(iter) {
343 Ok(gb) => gb,
344 Err(e) => {
345 panic!("{}", e);
346 }
347 }
348 }
349}
350
351impl<P: PosT, const WORDS: usize> fmt::Display for Gridbool<P, WORDS> {
354 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355 grid::display_fmt_helper(
356 f,
357 P::width(),
358 P::height(),
359 self.iter().map(|b| (if b { "#" } else { "." }).to_string()),
360 )
361 }
362}