wip BrightnessGrid
This commit is contained in:
		
							parent
							
								
									e0647bacd6
								
							
						
					
					
						commit
						c554fbd800
					
				
					 13 changed files with 162 additions and 86 deletions
				
			
		| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
 | 
			
		||||
use clap::Parser;
 | 
			
		||||
 | 
			
		||||
use servicepoint::{ByteGrid, Command, Connection, Grid, Origin};
 | 
			
		||||
use servicepoint::{Command, Connection, Cp473Grid, Grid, Origin};
 | 
			
		||||
 | 
			
		||||
#[derive(Parser, Debug)]
 | 
			
		||||
struct Cli {
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +33,7 @@ fn main() {
 | 
			
		|||
 | 
			
		||||
    let max_width = cli.text.iter().map(|t| t.len()).max().unwrap();
 | 
			
		||||
 | 
			
		||||
    let mut chars = ByteGrid::new(max_width, cli.text.len());
 | 
			
		||||
    let mut chars = Cp473Grid::new(max_width, cli.text.len());
 | 
			
		||||
    for y in 0..cli.text.len() {
 | 
			
		||||
        let row = &cli.text[y];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,9 +27,10 @@ fn main() {
 | 
			
		|||
        ))
 | 
			
		||||
        .expect("send failed");
 | 
			
		||||
 | 
			
		||||
    let mut brightnesses = ByteGrid::new(TILE_WIDTH, TILE_HEIGHT);
 | 
			
		||||
    let max_brightness = usize::from(u8::from(Brightness::MAX));
 | 
			
		||||
    let mut brightnesses = BrightnessGrid::new(TILE_WIDTH, TILE_HEIGHT);
 | 
			
		||||
    for (index, byte) in brightnesses.data_ref_mut().iter_mut().enumerate() {
 | 
			
		||||
        *byte = (index % u8::MAX as usize) as u8;
 | 
			
		||||
        *byte = Brightness::try_from((index % max_brightness) as u8).unwrap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    connection
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,8 +31,11 @@ fn main() {
 | 
			
		|||
        let mut filled_grid = PixelGrid::max_sized();
 | 
			
		||||
        filled_grid.fill(true);
 | 
			
		||||
 | 
			
		||||
        let command =
 | 
			
		||||
            BitmapLinearWin(Origin::new(0, 0), filled_grid, CompressionCode::Lzma);
 | 
			
		||||
        let command = BitmapLinearWin(
 | 
			
		||||
            Origin::new(0, 0),
 | 
			
		||||
            filled_grid,
 | 
			
		||||
            CompressionCode::Lzma,
 | 
			
		||||
        );
 | 
			
		||||
        connection.send(command).expect("send failed");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +53,7 @@ fn main() {
 | 
			
		|||
        let h = rng.gen_range(min_size..=TILE_HEIGHT - y);
 | 
			
		||||
 | 
			
		||||
        let origin = Origin::new(x, y);
 | 
			
		||||
        let mut luma = ByteGrid::new(w, h);
 | 
			
		||||
        let mut luma = BrightnessGrid::new(w, h);
 | 
			
		||||
 | 
			
		||||
        for y in 0..h {
 | 
			
		||||
            for x in 0..w {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
use crate::{Grid, PrimitiveGrid};
 | 
			
		||||
#[cfg(feature = "rand")]
 | 
			
		||||
use rand::{
 | 
			
		||||
    distributions::{Distribution, Standard},
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +9,9 @@ use rand::{
 | 
			
		|||
#[derive(Debug, Copy, Clone, PartialEq)]
 | 
			
		||||
pub struct Brightness(u8);
 | 
			
		||||
 | 
			
		||||
/// A grid containing brightness values.
 | 
			
		||||
pub type BrightnessGrid = PrimitiveGrid<Brightness>;
 | 
			
		||||
 | 
			
		||||
impl From<Brightness> for u8 {
 | 
			
		||||
    fn from(brightness: Brightness) -> Self {
 | 
			
		||||
        brightness.0
 | 
			
		||||
| 
						 | 
				
			
			@ -15,11 +19,11 @@ impl From<Brightness> for u8 {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
impl TryFrom<u8> for Brightness {
 | 
			
		||||
    type Error = ();
 | 
			
		||||
    type Error = u8;
 | 
			
		||||
 | 
			
		||||
    fn try_from(value: u8) -> Result<Self, Self::Error> {
 | 
			
		||||
        if value > Self::MAX.0 {
 | 
			
		||||
            Err(())
 | 
			
		||||
            Err(value)
 | 
			
		||||
        } else {
 | 
			
		||||
            Ok(Brightness(value))
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -33,6 +37,51 @@ impl Brightness {
 | 
			
		|||
    pub const MIN: Brightness = Brightness(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for Brightness {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self::MAX
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<BrightnessGrid> for Vec<u8> {
 | 
			
		||||
    fn from(value: PrimitiveGrid<Brightness>) -> Self {
 | 
			
		||||
        value
 | 
			
		||||
            .iter()
 | 
			
		||||
            .map(|brightness| (*brightness).into())
 | 
			
		||||
            .collect()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<BrightnessGrid> for PrimitiveGrid<u8> {
 | 
			
		||||
    fn from(value: PrimitiveGrid<Brightness>) -> Self {
 | 
			
		||||
        let u8s = value
 | 
			
		||||
            .iter()
 | 
			
		||||
            .map(|brightness| (*brightness).into())
 | 
			
		||||
            .collect::<Vec<u8>>();
 | 
			
		||||
        PrimitiveGrid::load(value.width(), value.height(), &u8s)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TryFrom<PrimitiveGrid<u8>> for BrightnessGrid {
 | 
			
		||||
    type Error = u8;
 | 
			
		||||
 | 
			
		||||
    fn try_from(value: PrimitiveGrid<u8>) -> Result<Self, Self::Error> {
 | 
			
		||||
        let brightnesses = value
 | 
			
		||||
            .iter()
 | 
			
		||||
            .map(|b| Brightness::try_from(*b))
 | 
			
		||||
            .collect::<Result<Vec<Brightness>, _>>();
 | 
			
		||||
        let brightnesses = match brightnesses {
 | 
			
		||||
            Ok(vec) => vec,
 | 
			
		||||
            Err(u8) => return Err(u8),
 | 
			
		||||
        };
 | 
			
		||||
        Ok(BrightnessGrid::load(
 | 
			
		||||
            value.width(),
 | 
			
		||||
            value.height(),
 | 
			
		||||
            &brightnesses,
 | 
			
		||||
        ))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "rand")]
 | 
			
		||||
impl Distribution<Brightness> for Standard {
 | 
			
		||||
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Brightness {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,13 +3,18 @@ use bitvec::prelude::BitVec;
 | 
			
		|||
use crate::{
 | 
			
		||||
    command_code::CommandCode,
 | 
			
		||||
    compression::{into_compressed, into_decompressed},
 | 
			
		||||
    Brightness, ByteGrid, CompressionCode, Grid, Header, Origin, Packet,
 | 
			
		||||
    PixelGrid, Pixels, SpBitVec, Tiles, TILE_SIZE,
 | 
			
		||||
    Brightness, BrightnessGrid, CompressionCode, Grid, Header, Origin, Packet,
 | 
			
		||||
    PixelGrid, Pixels, PrimitiveGrid, SpBitVec, Tiles, TILE_SIZE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Type alias for documenting the meaning of the u16 in enum values
 | 
			
		||||
pub type Offset = usize;
 | 
			
		||||
 | 
			
		||||
/// A grid containing codepage 437 characters.
 | 
			
		||||
///
 | 
			
		||||
/// The encoding is currently not enforced.
 | 
			
		||||
pub type Cp473Grid = PrimitiveGrid<u8>;
 | 
			
		||||
 | 
			
		||||
/// A command to send to the display.
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
pub enum Command {
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +27,7 @@ pub enum Command {
 | 
			
		|||
    ///     The library does not currently convert between UTF-8 and CP-437.
 | 
			
		||||
    ///     Because Rust expects UTF-8 strings, it might be necessary to only send ASCII for now.
 | 
			
		||||
    /// </div>
 | 
			
		||||
    Cp437Data(Origin<Tiles>, ByteGrid),
 | 
			
		||||
    Cp437Data(Origin<Tiles>, Cp473Grid),
 | 
			
		||||
 | 
			
		||||
    /// Sets a window of pixels to the specified values
 | 
			
		||||
    BitmapLinearWin(Origin<Pixels>, PixelGrid, CompressionCode),
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +36,7 @@ pub enum Command {
 | 
			
		|||
    Brightness(Brightness),
 | 
			
		||||
 | 
			
		||||
    /// Set the brightness of individual tiles in a rectangular area of the display.
 | 
			
		||||
    CharBrightness(Origin<Tiles>, ByteGrid),
 | 
			
		||||
    CharBrightness(Origin<Tiles>, BrightnessGrid),
 | 
			
		||||
 | 
			
		||||
    /// Set pixel data starting at the pixel offset on screen.
 | 
			
		||||
    ///
 | 
			
		||||
| 
						 | 
				
			
			@ -271,14 +276,24 @@ impl TryFrom<Packet> for Command {
 | 
			
		|||
                let Packet(_, payload) = packet;
 | 
			
		||||
                Ok(Command::Cp437Data(
 | 
			
		||||
                    Origin::new(a as usize, b as usize),
 | 
			
		||||
                    ByteGrid::load(c as usize, d as usize, &payload),
 | 
			
		||||
                    Cp473Grid::load(c as usize, d as usize, &payload),
 | 
			
		||||
                ))
 | 
			
		||||
            }
 | 
			
		||||
            CommandCode::CharBrightness => {
 | 
			
		||||
                let Packet(_, payload) = packet;
 | 
			
		||||
 | 
			
		||||
                let grid =
 | 
			
		||||
                    PrimitiveGrid::load(c as usize, d as usize, &payload);
 | 
			
		||||
                let grid = match BrightnessGrid::try_from(grid) {
 | 
			
		||||
                    Ok(grid) => grid,
 | 
			
		||||
                    Err(val) => {
 | 
			
		||||
                        return Err(TryFromPacketError::InvalidBrightness(val))
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                Ok(Command::CharBrightness(
 | 
			
		||||
                    Origin::new(a as usize, b as usize),
 | 
			
		||||
                    ByteGrid::load(c as usize, d as usize, &payload),
 | 
			
		||||
                    grid,
 | 
			
		||||
                ))
 | 
			
		||||
            }
 | 
			
		||||
            #[allow(deprecated)]
 | 
			
		||||
| 
						 | 
				
			
			@ -424,8 +439,8 @@ impl Command {
 | 
			
		|||
mod tests {
 | 
			
		||||
    use crate::{
 | 
			
		||||
        bitvec::prelude::BitVec, command::TryFromPacketError,
 | 
			
		||||
        command_code::CommandCode, origin::Pixels, Brightness, ByteGrid,
 | 
			
		||||
        Command, CompressionCode, Header, Origin, Packet, PixelGrid,
 | 
			
		||||
        command_code::CommandCode, origin::Pixels, Brightness, Command,
 | 
			
		||||
        CompressionCode, Header, Origin, Packet, PixelGrid, PrimitiveGrid,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    fn round_trip(original: Command) {
 | 
			
		||||
| 
						 | 
				
			
			@ -481,13 +496,16 @@ mod tests {
 | 
			
		|||
    fn round_trip_char_brightness() {
 | 
			
		||||
        round_trip(Command::CharBrightness(
 | 
			
		||||
            Origin::new(5, 2),
 | 
			
		||||
            ByteGrid::new(7, 5),
 | 
			
		||||
            PrimitiveGrid::new(7, 5),
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn round_trip_cp437_data() {
 | 
			
		||||
        round_trip(Command::Cp437Data(Origin::new(5, 2), ByteGrid::new(7, 5)));
 | 
			
		||||
        round_trip(Command::Cp437Data(
 | 
			
		||||
            Origin::new(5, 2),
 | 
			
		||||
            PrimitiveGrid::new(7, 5),
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,10 +2,10 @@
 | 
			
		|||
///
 | 
			
		||||
/// The expectation is that you can create an equal instance with this data given the additional
 | 
			
		||||
/// metadata needed.
 | 
			
		||||
pub trait DataRef {
 | 
			
		||||
pub trait DataRef<T> {
 | 
			
		||||
    /// Get the underlying bytes writable.
 | 
			
		||||
    fn data_ref_mut(&mut self) -> &mut [u8];
 | 
			
		||||
    fn data_ref_mut(&mut self) -> &mut [T];
 | 
			
		||||
 | 
			
		||||
    /// Get the underlying bytes read-only.
 | 
			
		||||
    fn data_ref(&self) -> &[u8];
 | 
			
		||||
    fn data_ref(&self) -> &[T];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,9 +5,8 @@ use std::time::Duration;
 | 
			
		|||
pub use bitvec;
 | 
			
		||||
use bitvec::prelude::{BitVec, Msb0};
 | 
			
		||||
 | 
			
		||||
pub use crate::brightness::Brightness;
 | 
			
		||||
pub use crate::byte_grid::ByteGrid;
 | 
			
		||||
pub use crate::command::{Command, Offset};
 | 
			
		||||
pub use crate::brightness::{Brightness, BrightnessGrid};
 | 
			
		||||
pub use crate::command::{Command, Cp473Grid, Offset};
 | 
			
		||||
pub use crate::compression_code::CompressionCode;
 | 
			
		||||
pub use crate::connection::Connection;
 | 
			
		||||
pub use crate::data_ref::DataRef;
 | 
			
		||||
| 
						 | 
				
			
			@ -15,11 +14,11 @@ pub use crate::grid::Grid;
 | 
			
		|||
pub use crate::origin::{Origin, Pixels, Tiles};
 | 
			
		||||
pub use crate::packet::{Header, Packet, Payload};
 | 
			
		||||
pub use crate::pixel_grid::PixelGrid;
 | 
			
		||||
pub use crate::primitive_grid::PrimitiveGrid;
 | 
			
		||||
 | 
			
		||||
type SpBitVec = BitVec<u8, Msb0>;
 | 
			
		||||
 | 
			
		||||
mod brightness;
 | 
			
		||||
mod byte_grid;
 | 
			
		||||
mod command;
 | 
			
		||||
mod command_code;
 | 
			
		||||
mod compression;
 | 
			
		||||
| 
						 | 
				
			
			@ -30,6 +29,7 @@ mod grid;
 | 
			
		|||
mod origin;
 | 
			
		||||
mod packet;
 | 
			
		||||
mod pixel_grid;
 | 
			
		||||
mod primitive_grid;
 | 
			
		||||
 | 
			
		||||
/// size of a single tile in one dimension
 | 
			
		||||
pub const TILE_SIZE: usize = 8;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -158,7 +158,7 @@ impl Grid<bool> for PixelGrid {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl DataRef for PixelGrid {
 | 
			
		||||
impl DataRef<u8> for PixelGrid {
 | 
			
		||||
    fn data_ref_mut(&mut self) -> &mut [u8] {
 | 
			
		||||
        self.bit_vec.as_raw_mut_slice()
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,26 +2,29 @@ use std::slice::{Iter, IterMut};
 | 
			
		|||
 | 
			
		||||
use crate::{DataRef, Grid};
 | 
			
		||||
 | 
			
		||||
pub trait PrimitiveGridType: Sized + Default + Copy + Clone {}
 | 
			
		||||
impl<T: Sized + Default + Copy + Clone> PrimitiveGridType for T {}
 | 
			
		||||
 | 
			
		||||
/// A 2D grid of bytes
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
pub struct ByteGrid {
 | 
			
		||||
pub struct PrimitiveGrid<T: PrimitiveGridType> {
 | 
			
		||||
    width: usize,
 | 
			
		||||
    height: usize,
 | 
			
		||||
    data: Vec<u8>,
 | 
			
		||||
    data: Vec<T>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ByteGrid {
 | 
			
		||||
    /// Creates a new `ByteGrid` with the specified dimensions.
 | 
			
		||||
impl<T: PrimitiveGridType> PrimitiveGrid<T> {
 | 
			
		||||
    /// Creates a new `PrimitiveGrid` with the specified dimensions.
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Arguments
 | 
			
		||||
    ///
 | 
			
		||||
    /// - width: size in x-direction
 | 
			
		||||
    /// - height: size in y-direction
 | 
			
		||||
    ///
 | 
			
		||||
    /// returns: `ByteGrid` initialized to 0.
 | 
			
		||||
    /// returns: `ByteGrid` initialized to default value.
 | 
			
		||||
    pub fn new(width: usize, height: usize) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            data: vec![0; width * height],
 | 
			
		||||
            data: vec![Default::default(); width * height],
 | 
			
		||||
            width,
 | 
			
		||||
            height,
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -35,7 +38,7 @@ impl ByteGrid {
 | 
			
		|||
    ///
 | 
			
		||||
    /// - when the dimensions and data size do not match exactly.
 | 
			
		||||
    #[must_use]
 | 
			
		||||
    pub fn load(width: usize, height: usize, data: &[u8]) -> Self {
 | 
			
		||||
    pub fn load(width: usize, height: usize, data: &[T]) -> Self {
 | 
			
		||||
        assert_eq!(width * height, data.len());
 | 
			
		||||
        Self {
 | 
			
		||||
            data: Vec::from(data),
 | 
			
		||||
| 
						 | 
				
			
			@ -48,20 +51,20 @@ impl ByteGrid {
 | 
			
		|||
    ///
 | 
			
		||||
    /// Order is equivalent to the following loop:
 | 
			
		||||
    /// ```
 | 
			
		||||
    /// # use servicepoint::{ByteGrid, Grid};
 | 
			
		||||
    /// # let grid = ByteGrid::new(2,2);
 | 
			
		||||
    /// # use servicepoint::{PrimitiveGrid, Grid};
 | 
			
		||||
    /// # let grid = PrimitiveGrid::<u8>::new(2,2);
 | 
			
		||||
    /// for y in 0..grid.height() {
 | 
			
		||||
    ///     for x in 0..grid.width() {
 | 
			
		||||
    ///         grid.get(x, y);
 | 
			
		||||
    ///     }
 | 
			
		||||
    /// }
 | 
			
		||||
    /// ```
 | 
			
		||||
    pub fn iter(&self) -> Iter<u8> {
 | 
			
		||||
    pub fn iter(&self) -> Iter<T> {
 | 
			
		||||
        self.data.iter()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Iterate over all rows in `ByteGrid` top to bottom.
 | 
			
		||||
    pub fn iter_rows(&self) -> IterRows {
 | 
			
		||||
    pub fn iter_rows(&self) -> IterRows<T> {
 | 
			
		||||
        IterRows {
 | 
			
		||||
            byte_grid: self,
 | 
			
		||||
            row: 0,
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +74,7 @@ impl ByteGrid {
 | 
			
		|||
    /// Returns an iterator that allows modifying each value.
 | 
			
		||||
    ///
 | 
			
		||||
    /// The iterator yields all cells from top left to bottom right.
 | 
			
		||||
    pub fn iter_mut(&mut self) -> IterMut<u8> {
 | 
			
		||||
    pub fn iter_mut(&mut self) -> IterMut<T> {
 | 
			
		||||
        self.data.iter_mut()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +87,7 @@ impl ByteGrid {
 | 
			
		|||
    /// # Panics
 | 
			
		||||
    ///
 | 
			
		||||
    /// When accessing `x` or `y` out of bounds.
 | 
			
		||||
    pub fn get_ref_mut(&mut self, x: usize, y: usize) -> &mut u8 {
 | 
			
		||||
    pub fn get_ref_mut(&mut self, x: usize, y: usize) -> &mut T {
 | 
			
		||||
        self.assert_in_bounds(x, y);
 | 
			
		||||
        &mut self.data[x + y * self.width]
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -100,7 +103,7 @@ impl ByteGrid {
 | 
			
		|||
        &mut self,
 | 
			
		||||
        x: isize,
 | 
			
		||||
        y: isize,
 | 
			
		||||
    ) -> Option<&mut u8> {
 | 
			
		||||
    ) -> Option<&mut T> {
 | 
			
		||||
        if self.is_in_bounds(x, y) {
 | 
			
		||||
            Some(&mut self.data[x as usize + y as usize * self.width])
 | 
			
		||||
        } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -109,7 +112,7 @@ impl ByteGrid {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Grid<u8> for ByteGrid {
 | 
			
		||||
impl<T: PrimitiveGridType> Grid<T> for PrimitiveGrid<T> {
 | 
			
		||||
    /// Sets the value of the cell at the specified position in the `ByteGrid.
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Arguments
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +123,7 @@ impl Grid<u8> for ByteGrid {
 | 
			
		|||
    /// # Panics
 | 
			
		||||
    ///
 | 
			
		||||
    /// When accessing `x` or `y` out of bounds.
 | 
			
		||||
    fn set(&mut self, x: usize, y: usize, value: u8) {
 | 
			
		||||
    fn set(&mut self, x: usize, y: usize, value: T) {
 | 
			
		||||
        self.assert_in_bounds(x, y);
 | 
			
		||||
        self.data[x + y * self.width] = value;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -134,12 +137,12 @@ impl Grid<u8> for ByteGrid {
 | 
			
		|||
    /// # Panics
 | 
			
		||||
    ///
 | 
			
		||||
    /// When accessing `x` or `y` out of bounds.
 | 
			
		||||
    fn get(&self, x: usize, y: usize) -> u8 {
 | 
			
		||||
    fn get(&self, x: usize, y: usize) -> T {
 | 
			
		||||
        self.assert_in_bounds(x, y);
 | 
			
		||||
        self.data[x + y * self.width]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn fill(&mut self, value: u8) {
 | 
			
		||||
    fn fill(&mut self, value: T) {
 | 
			
		||||
        self.data.fill(value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -152,32 +155,32 @@ impl Grid<u8> for ByteGrid {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl DataRef for ByteGrid {
 | 
			
		||||
impl<T: PrimitiveGridType> DataRef<T> for PrimitiveGrid<T> {
 | 
			
		||||
    /// Get the underlying byte rows mutable
 | 
			
		||||
    fn data_ref_mut(&mut self) -> &mut [u8] {
 | 
			
		||||
    fn data_ref_mut(&mut self) -> &mut [T] {
 | 
			
		||||
        self.data.as_mut_slice()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Get the underlying byte rows read only
 | 
			
		||||
    fn data_ref(&self) -> &[u8] {
 | 
			
		||||
    fn data_ref(&self) -> &[T] {
 | 
			
		||||
        self.data.as_slice()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<ByteGrid> for Vec<u8> {
 | 
			
		||||
impl<T: PrimitiveGridType> From<PrimitiveGrid<T>> for Vec<T> {
 | 
			
		||||
    /// Turn into the underlying `Vec<u8>` containing the rows of bytes.
 | 
			
		||||
    fn from(value: ByteGrid) -> Self {
 | 
			
		||||
    fn from(value: PrimitiveGrid<T>) -> Self {
 | 
			
		||||
        value.data
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct IterRows<'t> {
 | 
			
		||||
    byte_grid: &'t ByteGrid,
 | 
			
		||||
pub struct IterRows<'t, T: PrimitiveGridType> {
 | 
			
		||||
    byte_grid: &'t PrimitiveGrid<T>,
 | 
			
		||||
    row: usize,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'t> Iterator for IterRows<'t> {
 | 
			
		||||
    type Item = Iter<'t, u8>;
 | 
			
		||||
impl<'t, T: PrimitiveGridType> Iterator for IterRows<'t, T> {
 | 
			
		||||
    type Item = Iter<'t, T>;
 | 
			
		||||
 | 
			
		||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
        if self.row >= self.byte_grid.height {
 | 
			
		||||
| 
						 | 
				
			
			@ -194,11 +197,11 @@ impl<'t> Iterator for IterRows<'t> {
 | 
			
		|||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    use crate::{ByteGrid, DataRef, Grid};
 | 
			
		||||
    use crate::{DataRef, Grid, PrimitiveGrid};
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn fill() {
 | 
			
		||||
        let mut grid = ByteGrid::new(2, 2);
 | 
			
		||||
        let mut grid = PrimitiveGrid::<usize>::new(2, 2);
 | 
			
		||||
        assert_eq!(grid.data, [0x00, 0x00, 0x00, 0x00]);
 | 
			
		||||
 | 
			
		||||
        grid.fill(42);
 | 
			
		||||
| 
						 | 
				
			
			@ -207,7 +210,7 @@ mod tests {
 | 
			
		|||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn get_set() {
 | 
			
		||||
        let mut grid = ByteGrid::new(2, 2);
 | 
			
		||||
        let mut grid = PrimitiveGrid::new(2, 2);
 | 
			
		||||
        assert_eq!(grid.get(0, 0), 0);
 | 
			
		||||
        assert_eq!(grid.get(1, 1), 0);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -222,7 +225,7 @@ mod tests {
 | 
			
		|||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn load() {
 | 
			
		||||
        let mut grid = ByteGrid::new(2, 3);
 | 
			
		||||
        let mut grid = PrimitiveGrid::new(2, 3);
 | 
			
		||||
        for x in 0..grid.width {
 | 
			
		||||
            for y in 0..grid.height {
 | 
			
		||||
                grid.set(x, y, (x + y) as u8);
 | 
			
		||||
| 
						 | 
				
			
			@ -233,13 +236,13 @@ mod tests {
 | 
			
		|||
 | 
			
		||||
        let data: Vec<u8> = grid.into();
 | 
			
		||||
 | 
			
		||||
        let grid = ByteGrid::load(2, 3, &data);
 | 
			
		||||
        let grid = PrimitiveGrid::load(2, 3, &data);
 | 
			
		||||
        assert_eq!(grid.data, [0, 1, 1, 2, 2, 3]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn mut_data_ref() {
 | 
			
		||||
        let mut vec = ByteGrid::new(2, 2);
 | 
			
		||||
        let mut vec = PrimitiveGrid::new(2, 2);
 | 
			
		||||
 | 
			
		||||
        let data_ref = vec.data_ref_mut();
 | 
			
		||||
        data_ref.copy_from_slice(&[1, 2, 3, 4]);
 | 
			
		||||
| 
						 | 
				
			
			@ -250,7 +253,7 @@ mod tests {
 | 
			
		|||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn iter() {
 | 
			
		||||
        let mut vec = ByteGrid::new(2, 2);
 | 
			
		||||
        let mut vec = PrimitiveGrid::new(2, 2);
 | 
			
		||||
        vec.set(1, 1, 5);
 | 
			
		||||
 | 
			
		||||
        let mut iter = vec.iter();
 | 
			
		||||
| 
						 | 
				
			
			@ -262,7 +265,7 @@ mod tests {
 | 
			
		|||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn iter_mut() {
 | 
			
		||||
        let mut vec = ByteGrid::new(2, 3);
 | 
			
		||||
        let mut vec = PrimitiveGrid::new(2, 3);
 | 
			
		||||
        for (index, cell) in vec.iter_mut().enumerate() {
 | 
			
		||||
            *cell = index as u8;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -272,7 +275,7 @@ mod tests {
 | 
			
		|||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn iter_rows() {
 | 
			
		||||
        let vec = ByteGrid::load(2, 3, &[0, 1, 1, 2, 2, 3]);
 | 
			
		||||
        let vec = PrimitiveGrid::load(2, 3, &[0, 1, 1, 2, 2, 3]);
 | 
			
		||||
        for (y, row) in vec.iter_rows().enumerate() {
 | 
			
		||||
            for (x, val) in row.enumerate() {
 | 
			
		||||
                assert_eq!(*val, (x + y) as u8);
 | 
			
		||||
| 
						 | 
				
			
			@ -283,20 +286,20 @@ mod tests {
 | 
			
		|||
    #[test]
 | 
			
		||||
    #[should_panic]
 | 
			
		||||
    fn out_of_bounds_x() {
 | 
			
		||||
        let mut vec = ByteGrid::load(2, 2, &[0, 1, 2, 3]);
 | 
			
		||||
        let mut vec = PrimitiveGrid::load(2, 2, &[0, 1, 2, 3]);
 | 
			
		||||
        vec.set(2, 1, 5);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    #[should_panic]
 | 
			
		||||
    fn out_of_bounds_y() {
 | 
			
		||||
        let vec = ByteGrid::load(2, 2, &[0, 1, 2, 3]);
 | 
			
		||||
        let vec = PrimitiveGrid::load(2, 2, &[0, 1, 2, 3]);
 | 
			
		||||
        vec.get(1, 2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn ref_mut() {
 | 
			
		||||
        let mut vec = ByteGrid::load(2, 2, &[0, 1, 2, 3]);
 | 
			
		||||
        let mut vec = PrimitiveGrid::load(2, 2, &[0, 1, 2, 3]);
 | 
			
		||||
 | 
			
		||||
        let top_left = vec.get_ref_mut(0, 0);
 | 
			
		||||
        *top_left += 5;
 | 
			
		||||
| 
						 | 
				
			
			@ -307,7 +310,7 @@ mod tests {
 | 
			
		|||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn optional() {
 | 
			
		||||
        let mut grid = ByteGrid::load(2, 2, &[0, 1, 2, 3]);
 | 
			
		||||
        let mut grid = PrimitiveGrid::load(2, 2, &[0, 1, 2, 3]);
 | 
			
		||||
        grid.set_optional(0, 0, 5);
 | 
			
		||||
        grid.set_optional(-1, 0, 8);
 | 
			
		||||
        grid.set_optional(0, 8, 42);
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue