wip rework to be range based
This commit is contained in:
		
							parent
							
								
									d5e288f727
								
							
						
					
					
						commit
						ae0f10b48c
					
				
					 3 changed files with 147 additions and 112 deletions
				
			
		| 
						 | 
					@ -4,6 +4,7 @@ use crate::{
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use ::bitvec::{order::Msb0, prelude::BitSlice, slice::IterMut};
 | 
					use ::bitvec::{order::Msb0, prelude::BitSlice, slice::IterMut};
 | 
				
			||||||
use inherent::inherent;
 | 
					use inherent::inherent;
 | 
				
			||||||
 | 
					use std::ops::{Index, Range};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A fixed-size 2D grid of booleans.
 | 
					/// A fixed-size 2D grid of booleans.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
| 
						 | 
					@ -183,12 +184,10 @@ impl Bitmap {
 | 
				
			||||||
    #[must_use]
 | 
					    #[must_use]
 | 
				
			||||||
    pub fn window(
 | 
					    pub fn window(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        x: usize,
 | 
					        xs: Range<usize>,
 | 
				
			||||||
        y: usize,
 | 
					        ys: Range<usize>,
 | 
				
			||||||
        width: usize,
 | 
					 | 
				
			||||||
        height: usize,
 | 
					 | 
				
			||||||
    ) -> Option<Window<bool, Self>> {
 | 
					    ) -> Option<Window<bool, Self>> {
 | 
				
			||||||
        Window::new(self, x, y, width, height)
 | 
					        Window::new(self, xs, ys)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Creates a mutable window into the bitmap.
 | 
					    /// Creates a mutable window into the bitmap.
 | 
				
			||||||
| 
						 | 
					@ -196,12 +195,10 @@ impl Bitmap {
 | 
				
			||||||
    /// Returns None in case the window does not fit.
 | 
					    /// Returns None in case the window does not fit.
 | 
				
			||||||
    pub fn window_mut(
 | 
					    pub fn window_mut(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        x: usize,
 | 
					        xs: Range<usize>,
 | 
				
			||||||
        y: usize,
 | 
					        ys: Range<usize>,
 | 
				
			||||||
        width: usize,
 | 
					 | 
				
			||||||
        height: usize,
 | 
					 | 
				
			||||||
    ) -> Option<WindowMut<bool, Self>> {
 | 
					    ) -> Option<WindowMut<bool, Self>> {
 | 
				
			||||||
        WindowMut::new(self, x, y, width, height)
 | 
					        WindowMut::new(self, xs, ys)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,10 @@
 | 
				
			||||||
use crate::{DataRef, Grid, GridMut, Window, WindowMut};
 | 
					use crate::{DataRef, Grid, GridMut, Window, WindowMut};
 | 
				
			||||||
use inherent::inherent;
 | 
					use inherent::inherent;
 | 
				
			||||||
use std::fmt::Debug;
 | 
					use std::{
 | 
				
			||||||
use std::slice::{Iter, IterMut};
 | 
					    fmt::Debug,
 | 
				
			||||||
 | 
					    ops::Range,
 | 
				
			||||||
 | 
					    slice::{Iter, IterMut},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A type that can be stored in a [`ValueGrid`], e.g. [char], [u8].
 | 
					/// A type that can be stored in a [`ValueGrid`], e.g. [char], [u8].
 | 
				
			||||||
pub trait Value: Sized + Default + Copy + Clone + Debug {}
 | 
					pub trait Value: Sized + Default + Copy + Clone + Debug {}
 | 
				
			||||||
| 
						 | 
					@ -317,12 +320,10 @@ impl<T: Value> ValueGrid<T> {
 | 
				
			||||||
    /// Returns None in case the window does not fit.
 | 
					    /// Returns None in case the window does not fit.
 | 
				
			||||||
    pub fn window(
 | 
					    pub fn window(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        x: usize,
 | 
					        xs: Range<usize>,
 | 
				
			||||||
        y: usize,
 | 
					        ys: Range<usize>,
 | 
				
			||||||
        width: usize,
 | 
					 | 
				
			||||||
        height: usize,
 | 
					 | 
				
			||||||
    ) -> Option<Window<T, Self>> {
 | 
					    ) -> Option<Window<T, Self>> {
 | 
				
			||||||
        Window::new(self, x, y, width, height)
 | 
					        Window::new(self, xs, ys)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Creates a mutable window into the grid.
 | 
					    /// Creates a mutable window into the grid.
 | 
				
			||||||
| 
						 | 
					@ -330,12 +331,10 @@ impl<T: Value> ValueGrid<T> {
 | 
				
			||||||
    /// Returns None in case the window does not fit.
 | 
					    /// Returns None in case the window does not fit.
 | 
				
			||||||
    pub fn window_mut(
 | 
					    pub fn window_mut(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        x: usize,
 | 
					        xs: Range<usize>,
 | 
				
			||||||
        y: usize,
 | 
					        ys: Range<usize>,
 | 
				
			||||||
        width: usize,
 | 
					 | 
				
			||||||
        height: usize,
 | 
					 | 
				
			||||||
    ) -> Option<WindowMut<T, Self>> {
 | 
					    ) -> Option<WindowMut<T, Self>> {
 | 
				
			||||||
        WindowMut::new(self, x, y, width, height)
 | 
					        WindowMut::new(self, xs, ys)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@ use crate::{
 | 
				
			||||||
    containers::char_grid::{CharGridExt, CharGridMutExt},
 | 
					    containers::char_grid::{CharGridExt, CharGridMutExt},
 | 
				
			||||||
    Grid, GridMut,
 | 
					    Grid, GridMut,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use std::marker::PhantomData;
 | 
					use std::{marker::PhantomData, ops::Range};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
macro_rules! define_window {
 | 
					macro_rules! define_window {
 | 
				
			||||||
    ($name:ident, $grid:ty) => {
 | 
					    ($name:ident, $grid:ty) => {
 | 
				
			||||||
| 
						 | 
					@ -13,10 +13,8 @@ macro_rules! define_window {
 | 
				
			||||||
        #[derive(Debug)]
 | 
					        #[derive(Debug)]
 | 
				
			||||||
        pub struct $name<'t, TElement: Copy, TGrid: Grid<TElement>> {
 | 
					        pub struct $name<'t, TElement: Copy, TGrid: Grid<TElement>> {
 | 
				
			||||||
            grid: $grid,
 | 
					            grid: $grid,
 | 
				
			||||||
            x: usize,
 | 
					            xs: Range<usize>,
 | 
				
			||||||
            y: usize,
 | 
					            ys: Range<usize>,
 | 
				
			||||||
            width: usize,
 | 
					 | 
				
			||||||
            height: usize,
 | 
					 | 
				
			||||||
            phantom: PhantomData<TElement>,
 | 
					            phantom: PhantomData<TElement>,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,22 +26,18 @@ macro_rules! define_window {
 | 
				
			||||||
            #[allow(unused, reason = "False positive because of #[inherent]")]
 | 
					            #[allow(unused, reason = "False positive because of #[inherent]")]
 | 
				
			||||||
            pub fn new(
 | 
					            pub fn new(
 | 
				
			||||||
                grid: $grid,
 | 
					                grid: $grid,
 | 
				
			||||||
                x: usize,
 | 
					                xs: Range<usize>,
 | 
				
			||||||
                y: usize,
 | 
					                ys: Range<usize>,
 | 
				
			||||||
                width: usize,
 | 
					 | 
				
			||||||
                height: usize,
 | 
					 | 
				
			||||||
            ) -> Option<Self> {
 | 
					            ) -> Option<Self> {
 | 
				
			||||||
                if !grid.is_in_bounds(x + width - 1, y + height - 1) {
 | 
					                if !grid.is_in_bounds(xs.end - 1, ys.end - 1) {
 | 
				
			||||||
                    return None;
 | 
					                    return None;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Some(Self {
 | 
					                Some(Self {
 | 
				
			||||||
                    grid,
 | 
					                    grid,
 | 
				
			||||||
                    x,
 | 
					                    xs,
 | 
				
			||||||
                    y,
 | 
					                    ys,
 | 
				
			||||||
                    width,
 | 
					                    phantom: PhantomData::default(),
 | 
				
			||||||
                    height,
 | 
					 | 
				
			||||||
                    phantom: PhantomData,
 | 
					 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,15 +47,18 @@ macro_rules! define_window {
 | 
				
			||||||
            /// Returns None in case the window does not fit.
 | 
					            /// Returns None in case the window does not fit.
 | 
				
			||||||
            pub fn window(
 | 
					            pub fn window(
 | 
				
			||||||
                &self,
 | 
					                &self,
 | 
				
			||||||
                x: usize,
 | 
					                xs: Range<usize>,
 | 
				
			||||||
                y: usize,
 | 
					                ys: Range<usize>,
 | 
				
			||||||
                width: usize,
 | 
					 | 
				
			||||||
                height: usize,
 | 
					 | 
				
			||||||
            ) -> Option<Window<TElement, TGrid>> {
 | 
					            ) -> Option<Window<TElement, TGrid>> {
 | 
				
			||||||
                if x + width >= self.width || y + height >= self.height {
 | 
					                if !self.is_in_bounds(xs.end - 1, ys.end - 1) {
 | 
				
			||||||
                    return None;
 | 
					                    return None;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Window::new(self.grid, self.x + x, self.y + y, width, height)
 | 
					                Window::new(
 | 
				
			||||||
 | 
					                    self.grid,
 | 
				
			||||||
 | 
					                    // TODO off by one
 | 
				
			||||||
 | 
					                    (self.xs.start + xs.start)..(self.xs.end + xs.end),
 | 
				
			||||||
 | 
					                    (self.ys.start + ys.start)..(self.ys.end + ys.end),
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            #[must_use]
 | 
					            #[must_use]
 | 
				
			||||||
| 
						 | 
					@ -72,20 +69,14 @@ macro_rules! define_window {
 | 
				
			||||||
                Window<'t, TElement, TGrid>,
 | 
					                Window<'t, TElement, TGrid>,
 | 
				
			||||||
                Window<'t, TElement, TGrid>,
 | 
					                Window<'t, TElement, TGrid>,
 | 
				
			||||||
            )> {
 | 
					            )> {
 | 
				
			||||||
 | 
					                let middle_abs = self.xs.start + left_width;
 | 
				
			||||||
                let left = Window::new(
 | 
					                let left = Window::new(
 | 
				
			||||||
                    self.grid,
 | 
					                    self.grid,
 | 
				
			||||||
                    self.x,
 | 
					                    self.xs.start..middle_abs,
 | 
				
			||||||
                    self.y,
 | 
					                    self.ys.clone(),
 | 
				
			||||||
                    left_width,
 | 
					 | 
				
			||||||
                    self.height,
 | 
					 | 
				
			||||||
                )?;
 | 
					 | 
				
			||||||
                let right = Window::new(
 | 
					 | 
				
			||||||
                    self.grid,
 | 
					 | 
				
			||||||
                    self.x + left_width,
 | 
					 | 
				
			||||||
                    self.y,
 | 
					 | 
				
			||||||
                    self.width - left_width,
 | 
					 | 
				
			||||||
                    self.height,
 | 
					 | 
				
			||||||
                )?;
 | 
					                )?;
 | 
				
			||||||
 | 
					                let right =
 | 
				
			||||||
 | 
					                    Window::new(self.grid, middle_abs..self.xs.end, self.ys)?;
 | 
				
			||||||
                Some((left, right))
 | 
					                Some((left, right))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,16 +88,14 @@ macro_rules! define_window {
 | 
				
			||||||
                Window<'t, TElement, TGrid>,
 | 
					                Window<'t, TElement, TGrid>,
 | 
				
			||||||
                Window<'t, TElement, TGrid>,
 | 
					                Window<'t, TElement, TGrid>,
 | 
				
			||||||
            )> {
 | 
					            )> {
 | 
				
			||||||
 | 
					                let middle_abs = self.ys.start + top_height;
 | 
				
			||||||
                let top = Window::new(
 | 
					                let top = Window::new(
 | 
				
			||||||
                    self.grid, self.x, self.y, self.width, top_height,
 | 
					 | 
				
			||||||
                )?;
 | 
					 | 
				
			||||||
                let bottom = Window::new(
 | 
					 | 
				
			||||||
                    self.grid,
 | 
					                    self.grid,
 | 
				
			||||||
                    self.x,
 | 
					                    self.xs.clone(),
 | 
				
			||||||
                    self.y + top_height,
 | 
					                    self.ys.start..middle_abs,
 | 
				
			||||||
                    self.width,
 | 
					 | 
				
			||||||
                    self.height - top_height,
 | 
					 | 
				
			||||||
                )?;
 | 
					                )?;
 | 
				
			||||||
 | 
					                let bottom =
 | 
				
			||||||
 | 
					                    Window::new(self.grid, self.xs, middle_abs..self.ys.end)?;
 | 
				
			||||||
                Some((top, bottom))
 | 
					                Some((top, bottom))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -118,19 +107,19 @@ macro_rules! define_window {
 | 
				
			||||||
            #[must_use]
 | 
					            #[must_use]
 | 
				
			||||||
            #[allow(unused, reason = "False positive because of #[inherent]")]
 | 
					            #[allow(unused, reason = "False positive because of #[inherent]")]
 | 
				
			||||||
            pub fn get(&self, x: usize, y: usize) -> TElement {
 | 
					            pub fn get(&self, x: usize, y: usize) -> TElement {
 | 
				
			||||||
                self.grid.get(x + self.x, y + self.y)
 | 
					                self.grid.get(self.xs.start + x, self.ys.start + y)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            #[must_use]
 | 
					            #[must_use]
 | 
				
			||||||
            #[allow(unused, reason = "False positive because of #[inherent]")]
 | 
					            #[allow(unused, reason = "False positive because of #[inherent]")]
 | 
				
			||||||
            pub fn width(&self) -> usize {
 | 
					            pub fn width(&self) -> usize {
 | 
				
			||||||
                self.width
 | 
					                self.xs.len()
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            #[must_use]
 | 
					            #[must_use]
 | 
				
			||||||
            #[allow(unused, reason = "False positive because of #[inherent]")]
 | 
					            #[allow(unused, reason = "False positive because of #[inherent]")]
 | 
				
			||||||
            pub fn height(&self) -> usize {
 | 
					            pub fn height(&self) -> usize {
 | 
				
			||||||
                self.height
 | 
					                self.ys.len()
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,13 +137,13 @@ impl<TElement: Copy, TGrid: GridMut<TElement>> GridMut<TElement>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    #[allow(unused, reason = "False positive because of #[inherent]")]
 | 
					    #[allow(unused, reason = "False positive because of #[inherent]")]
 | 
				
			||||||
    pub fn set(&mut self, x: usize, y: usize, value: TElement) {
 | 
					    pub fn set(&mut self, x: usize, y: usize, value: TElement) {
 | 
				
			||||||
        self.grid.set(x + self.x, y + self.y, value);
 | 
					        self.grid.set(self.xs.start + x, self.ys.start + y, value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[allow(unused, reason = "False positive because of #[inherent]")]
 | 
					    #[allow(unused, reason = "False positive because of #[inherent]")]
 | 
				
			||||||
    pub fn fill(&mut self, value: TElement) {
 | 
					    pub fn fill(&mut self, value: TElement) {
 | 
				
			||||||
        for y in self.y..(self.y + self.height) {
 | 
					        for y in self.ys.clone() {
 | 
				
			||||||
            for x in self.x..(self.x + self.width) {
 | 
					            for x in self.xs.clone() {
 | 
				
			||||||
                self.grid.set(x, y, value);
 | 
					                self.grid.set(x, y, value);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -170,22 +159,25 @@ impl<TElement: Copy, TGrid: GridMut<TElement>> WindowMut<'_, TElement, TGrid> {
 | 
				
			||||||
    /// Returns None in case the window does not fit.
 | 
					    /// Returns None in case the window does not fit.
 | 
				
			||||||
    pub fn window_mut(
 | 
					    pub fn window_mut(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        x: usize,
 | 
					        xs: Range<usize>,
 | 
				
			||||||
        y: usize,
 | 
					        ys: Range<usize>,
 | 
				
			||||||
        width: usize,
 | 
					 | 
				
			||||||
        height: usize,
 | 
					 | 
				
			||||||
    ) -> Option<WindowMut<TElement, TGrid>> {
 | 
					    ) -> Option<WindowMut<TElement, TGrid>> {
 | 
				
			||||||
        if x + width > self.width || y + height > self.height {
 | 
					        if self.is_in_bounds(xs.end - 1, ys.end - 1) {
 | 
				
			||||||
            return None;
 | 
					            return None;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        WindowMut::new(self.grid, self.x + x, self.y + y, width, height)
 | 
					
 | 
				
			||||||
 | 
					        WindowMut::new(
 | 
				
			||||||
 | 
					            self.grid,
 | 
				
			||||||
 | 
					            (self.xs.start + xs.start)..(self.xs.end + xs.end),
 | 
				
			||||||
 | 
					            (self.ys.start + ys.start)..(self.ys.end + ys.end),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn deref_assign<O: Grid<TElement>>(&mut self, other: &O) {
 | 
					    pub fn deref_assign<O: Grid<TElement>>(&mut self, other: &O) {
 | 
				
			||||||
        assert!(self.width() == other.width());
 | 
					        assert_eq!(self.width(), other.width());
 | 
				
			||||||
        assert!(self.height() == other.height());
 | 
					        assert_eq!(self.height(), other.height());
 | 
				
			||||||
        for y in 0..self.height {
 | 
					        for y in self.ys.clone() {
 | 
				
			||||||
            for x in 0..self.width {
 | 
					            for x in self.xs.clone() {
 | 
				
			||||||
                self.set(x, y, other.get(x, y));
 | 
					                self.set(x, y, other.get(x, y));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -197,34 +189,20 @@ impl<TElement: Copy, TGrid: GridMut<TElement>> WindowMut<'_, TElement, TGrid> {
 | 
				
			||||||
        left_width: usize,
 | 
					        left_width: usize,
 | 
				
			||||||
    ) -> Option<(Self, Self)> {
 | 
					    ) -> Option<(Self, Self)> {
 | 
				
			||||||
        let (grid1, grid2) = unsafe { Self::duplicate_mutable_ref(self.grid) };
 | 
					        let (grid1, grid2) = unsafe { Self::duplicate_mutable_ref(self.grid) };
 | 
				
			||||||
 | 
					        let middle_abs = self.xs.start + left_width;
 | 
				
			||||||
        let left =
 | 
					        let left =
 | 
				
			||||||
            WindowMut::new(grid1, self.x, self.y, left_width, self.height)?;
 | 
					            WindowMut::new(grid1, self.xs.start..middle_abs, self.ys.clone())?;
 | 
				
			||||||
        let right = WindowMut::new(
 | 
					        let right = WindowMut::new(grid2, middle_abs..self.xs.end, self.ys)?;
 | 
				
			||||||
            grid2,
 | 
					 | 
				
			||||||
            self.x + left_width,
 | 
					 | 
				
			||||||
            self.y,
 | 
					 | 
				
			||||||
            self.width - left_width,
 | 
					 | 
				
			||||||
            self.height,
 | 
					 | 
				
			||||||
        )?;
 | 
					 | 
				
			||||||
        Some((left, right))
 | 
					        Some((left, right))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[must_use]
 | 
					    #[must_use]
 | 
				
			||||||
    pub fn split_vertical_mut(self, top_height: usize) -> Option<(Self, Self)> {
 | 
					    pub fn split_vertical_mut(self, top_height: usize) -> Option<(Self, Self)> {
 | 
				
			||||||
        let (grid1, grid2) = unsafe { Self::duplicate_mutable_ref(self.grid) };
 | 
					        let (grid1, grid2) = unsafe { Self::duplicate_mutable_ref(self.grid) };
 | 
				
			||||||
 | 
					        let middle_abs = self.ys.start + top_height;
 | 
				
			||||||
        let top =
 | 
					        let top =
 | 
				
			||||||
            WindowMut::new(grid1, self.x, self.y, self.width, top_height)?;
 | 
					            WindowMut::new(grid1, self.xs.clone(), self.ys.start..middle_abs)?;
 | 
				
			||||||
        let bottom = WindowMut::new(
 | 
					        let bottom = WindowMut::new(grid2, self.xs, middle_abs..self.ys.end)?;
 | 
				
			||||||
            grid2,
 | 
					 | 
				
			||||||
            self.x,
 | 
					 | 
				
			||||||
            self.y + top_height,
 | 
					 | 
				
			||||||
            self.width,
 | 
					 | 
				
			||||||
            self.height - top_height,
 | 
					 | 
				
			||||||
        )?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let foo = &mut [..];
 | 
					 | 
				
			||||||
        *foo = [..];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Some((top, bottom))
 | 
					        Some((top, bottom))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -247,7 +225,7 @@ mod tests {
 | 
				
			||||||
        let mut bitmap = Bitmap::new(8, 4).unwrap();
 | 
					        let mut bitmap = Bitmap::new(8, 4).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // non-byte-aligned views work
 | 
					        // non-byte-aligned views work
 | 
				
			||||||
        let mut view = bitmap.window_mut(3, 1, 4, 2).unwrap();
 | 
					        let mut view = bitmap.window_mut(3..7, 1..3).unwrap();
 | 
				
			||||||
        view.fill(true);
 | 
					        view.fill(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert_eq!(bitmap.data_ref(), &[0, 30, 30, 0]);
 | 
					        assert_eq!(bitmap.data_ref(), &[0, 30, 30, 0]);
 | 
				
			||||||
| 
						 | 
					@ -255,17 +233,17 @@ mod tests {
 | 
				
			||||||
        assert_eq!(bitmap.set_optional(99, 99, false), false);
 | 
					        assert_eq!(bitmap.set_optional(99, 99, false), false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // full size view works
 | 
					        // full size view works
 | 
				
			||||||
        bitmap.window(0, 0, 8, 4).unwrap();
 | 
					        bitmap.window(0..8, 0..4).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // zero size view works
 | 
					        // zero size view works
 | 
				
			||||||
        assert!(Window::new(&mut bitmap, 1, 2, 3, 0).is_some());
 | 
					        assert!(Window::new(&mut bitmap, 1..4, 2..2).is_some());
 | 
				
			||||||
        assert!(WindowMut::new(&mut bitmap, 1, 2, 0, 1)
 | 
					        assert!(WindowMut::new(&mut bitmap, 1..1, 2..3)
 | 
				
			||||||
            .is_some_and(|w| w.get_optional(0, 0).is_none()));
 | 
					            .is_some_and(|w| w.get_optional(0, 0).is_none()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // oob does not work
 | 
					        // oob does not work
 | 
				
			||||||
        assert!(Window::new(&mut bitmap, 30, 43, 3, 1).is_none());
 | 
					        assert!(Window::new(&mut bitmap, 30..33, 43..44).is_none());
 | 
				
			||||||
        assert!(WindowMut::new(&mut bitmap, 0, 0, 9, 1).is_none());
 | 
					        assert!(WindowMut::new(&mut bitmap, 0..9, 0..1).is_none());
 | 
				
			||||||
        assert!(Window::new(&mut bitmap, 0, 0, 1, 5).is_none());
 | 
					        assert!(Window::new(&mut bitmap, 0..1, 0..5).is_none());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
| 
						 | 
					@ -273,7 +251,7 @@ mod tests {
 | 
				
			||||||
        let mut grid = CharGrid::new(3, 4);
 | 
					        let mut grid = CharGrid::new(3, 4);
 | 
				
			||||||
        grid.fill(' ');
 | 
					        grid.fill(' ');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut view = grid.window_mut(1, 1, 1, 3).unwrap();
 | 
					        let mut view = grid.window_mut(1..2, 1..4).unwrap();
 | 
				
			||||||
        view.fill('#');
 | 
					        view.fill('#');
 | 
				
			||||||
        view.set(0, 0, '!');
 | 
					        view.set(0, 0, '!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -283,30 +261,30 @@ mod tests {
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // full size view works
 | 
					        // full size view works
 | 
				
			||||||
        _ = grid.window(0, 0, 3, 4).unwrap();
 | 
					        _ = grid.window(0..3, 0..4).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // zero size view works
 | 
					        // zero size view works
 | 
				
			||||||
        assert!(grid
 | 
					        assert!(grid
 | 
				
			||||||
            .window(1, 2, 2, 0)
 | 
					            .window(1..3, 2..2)
 | 
				
			||||||
            .is_some_and(|w| w.get_optional(0, 0).is_none()));
 | 
					            .is_some_and(|w| w.get_optional(0, 0).is_none()));
 | 
				
			||||||
        assert!(grid.window(1, 2, 0, 1).is_some());
 | 
					        assert!(grid.window(1..1, 2..3).is_some());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn round_trip_bitmap() {
 | 
					    fn round_trip_bitmap() {
 | 
				
			||||||
        let bitmap = Bitmap::new(8, 4).unwrap();
 | 
					        let bitmap = Bitmap::new(8, 4).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let non_aligned = bitmap.window(3, 1, 4, 2).unwrap();
 | 
					        let non_aligned = bitmap.window(3..7, 1..3).unwrap();
 | 
				
			||||||
        assert_eq!(Bitmap::try_from(&non_aligned), Err(()));
 | 
					        assert_eq!(Bitmap::try_from(&non_aligned), Err(()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let aligned = bitmap.window(0, 1, 8, 2).unwrap();
 | 
					        let aligned = bitmap.window(0..8, 1..3).unwrap();
 | 
				
			||||||
        assert!(matches!(Bitmap::try_from(&aligned), Ok(_)));
 | 
					        assert!(matches!(Bitmap::try_from(&aligned), Ok(_)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn split_vertical() {
 | 
					    fn split_vertical() {
 | 
				
			||||||
        let grid = ByteGrid::new(5, 4);
 | 
					        let grid = ByteGrid::new(5, 4);
 | 
				
			||||||
        let window = grid.window(0, 0, grid.width(), grid.height()).unwrap();
 | 
					        let window = grid.window(0..grid.width(), 0..grid.height()).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (left, right) = window.split_vertical(3).unwrap();
 | 
					        let (left, right) = window.split_vertical(3).unwrap();
 | 
				
			||||||
        assert_eq!(3, left.height());
 | 
					        assert_eq!(3, left.height());
 | 
				
			||||||
| 
						 | 
					@ -318,7 +296,7 @@ mod tests {
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn split_horizontal() {
 | 
					    fn split_horizontal() {
 | 
				
			||||||
        let grid = ByteGrid::new(4, 5);
 | 
					        let grid = ByteGrid::new(4, 5);
 | 
				
			||||||
        let window = grid.window(0, 0, grid.width(), grid.height()).unwrap();
 | 
					        let window = grid.window(0..grid.width(), 0..grid.height()).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (top, bottom) = window.split_horizontal(3).unwrap();
 | 
					        let (top, bottom) = window.split_horizontal(3).unwrap();
 | 
				
			||||||
        assert_eq!(3, top.width());
 | 
					        assert_eq!(3, top.width());
 | 
				
			||||||
| 
						 | 
					@ -326,4 +304,65 @@ mod tests {
 | 
				
			||||||
        assert_eq!(5, top.height());
 | 
					        assert_eq!(5, top.height());
 | 
				
			||||||
        assert_eq!(5, bottom.height())
 | 
					        assert_eq!(5, bottom.height())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn window_in_window() {
 | 
				
			||||||
 | 
					        let mut grid = ByteGrid::new(6, 7);
 | 
				
			||||||
 | 
					        grid.fill(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut w1 = grid
 | 
				
			||||||
 | 
					            .window_mut(1..grid.width() - 2, 1..grid.height() - 2)
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					        w1.fill(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let w1_1 = w1.window(0..w1.width(), 0..w1.height()).unwrap();
 | 
				
			||||||
 | 
					        assert_eq!(w1_1.get(0, 0), 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert!(matches!(w1.window(0..w1.width(), 1..w1.height()), None));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut w2 = w1
 | 
				
			||||||
 | 
					            .window_mut(1..w1.width() - 2, 1..w1.height() - 2)
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					        w2.fill(3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // zero-sized
 | 
				
			||||||
 | 
					        let mut w3 = w2
 | 
				
			||||||
 | 
					            .window_mut(1..w2.width() - 2, 1..w2.height() - 2)
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					        w3.fill(4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #[rustfmt::skip]
 | 
				
			||||||
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            grid.data_ref(),
 | 
				
			||||||
 | 
					            &[
 | 
				
			||||||
 | 
					                1, 1, 1, 1, 1, 1,
 | 
				
			||||||
 | 
					                1, 2, 2, 2, 2, 1,
 | 
				
			||||||
 | 
					                1, 2, 3, 3, 2, 1,
 | 
				
			||||||
 | 
					                1, 2, 3, 3, 2, 1,
 | 
				
			||||||
 | 
					                1, 2, 3, 3, 2, 1,
 | 
				
			||||||
 | 
					                1, 2, 2, 2, 2, 1,
 | 
				
			||||||
 | 
					                1, 1, 1, 1, 1, 1
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn width_height() {
 | 
				
			||||||
 | 
					        let grid = ByteGrid::new(4, 4);
 | 
				
			||||||
 | 
					        let w1 = grid.window(0..grid.width(), 0..grid.height()).unwrap();
 | 
				
			||||||
 | 
					        assert_eq!(grid.width(), w1.width());
 | 
				
			||||||
 | 
					        assert_eq!(grid.height(), w1.height());
 | 
				
			||||||
 | 
					        let w2 = w1.window(0..w1.width(), 0..w1.height()).unwrap();
 | 
				
			||||||
 | 
					        assert_eq!(grid.width(), w2.width());
 | 
				
			||||||
 | 
					        assert_eq!(grid.height(), w2.height());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn split_mut() {
 | 
				
			||||||
 | 
					        let mut grid = ByteGrid::new(5, 5);
 | 
				
			||||||
 | 
					        grid.fill(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert_eq!((0..5).len(), 5);
 | 
				
			||||||
 | 
					        //let mut w1 = grid
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue