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); | ||||
|  | @ -2,10 +2,12 @@ | |||
| //!
 | ||||
| //! prefix `sp_byte_grid_`
 | ||||
| 
 | ||||
| use servicepoint::{ByteGrid, DataRef, Grid}; | ||||
| use servicepoint::{DataRef, Grid, PrimitiveGrid}; | ||||
| 
 | ||||
| use crate::c_slice::CByteSlice; | ||||
| 
 | ||||
| pub type ByteGrid = PrimitiveGrid<u8>; | ||||
| 
 | ||||
| /// Creates a new `ByteGrid` with the specified dimensions.
 | ||||
| ///
 | ||||
| /// returns: `ByteGrid` initialized to 0.
 | ||||
|  |  | |||
|  | @ -5,8 +5,8 @@ | |||
| use std::ptr::null_mut; | ||||
| 
 | ||||
| use servicepoint::{ | ||||
|     Brightness, ByteGrid, Command, CompressionCode, Offset, Origin, Packet, | ||||
|     PixelGrid, | ||||
|     Brightness, BrightnessGrid, Command, CompressionCode, Cp473Grid, Offset, | ||||
|     Origin, Packet, PixelGrid, | ||||
| }; | ||||
| 
 | ||||
| use crate::bit_vec::CBitVec; | ||||
|  | @ -126,7 +126,7 @@ pub unsafe extern "C" fn sp_command_brightness(brightness: u8) -> *mut Command { | |||
| pub unsafe extern "C" fn sp_command_char_brightness( | ||||
|     x: usize, | ||||
|     y: usize, | ||||
|     byte_grid: *mut ByteGrid, | ||||
|     byte_grid: *mut BrightnessGrid, | ||||
| ) -> *mut Command { | ||||
|     let byte_grid = *Box::from_raw(byte_grid); | ||||
|     Box::into_raw(Box::new(Command::CharBrightness( | ||||
|  | @ -254,7 +254,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor( | |||
| pub unsafe extern "C" fn sp_command_cp437_data( | ||||
|     x: usize, | ||||
|     y: usize, | ||||
|     byte_grid: *mut ByteGrid, | ||||
|     byte_grid: *mut Cp473Grid, | ||||
| ) -> *mut Command { | ||||
|     let byte_grid = *Box::from_raw(byte_grid); | ||||
|     Box::into_raw(Box::new(Command::Cp437Data(Origin::new(x, y), byte_grid))) | ||||
|  |  | |||
|  | @ -63,43 +63,43 @@ namespace ServicePoint.BindGen | |||
| 
 | ||||
|         /// <summary>Creates a new `ByteGrid` with the specified dimensions.  returns: `ByteGrid` initialized to 0.  # Safety  The caller has to make sure that:  - the returned instance is freed in some way, either by using a consuming function or by explicitly calling `sp_byte_grid_dealloc`.</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_byte_grid_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|         public static extern ByteGrid* sp_byte_grid_new(nuint width, nuint height); | ||||
|         public static extern PrimitiveGrid* sp_byte_grid_new(nuint width, nuint height); | ||||
| 
 | ||||
|         /// <summary>Loads a `ByteGrid` with the specified dimensions from the provided data.  # Panics  When the provided `data_length` is not sufficient for the `height` and `width`  # Safety  The caller has to make sure that:  - `data` points to a valid memory location of at least `data_length` bytes in size. - the returned instance is freed in some way, either by using a consuming function or by explicitly calling `sp_byte_grid_dealloc`.</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_byte_grid_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|         public static extern ByteGrid* sp_byte_grid_load(nuint width, nuint height, byte* data, nuint data_length); | ||||
|         public static extern PrimitiveGrid* sp_byte_grid_load(nuint width, nuint height, byte* data, nuint data_length); | ||||
| 
 | ||||
|         /// <summary>Clones a `ByteGrid`.  # Safety  The caller has to make sure that:  - `this` points to a valid `ByteGrid` - `this` is not written to concurrently - the returned instance is freed in some way, either by using a consuming function or by explicitly calling `sp_byte_grid_dealloc`.</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_byte_grid_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|         public static extern ByteGrid* sp_byte_grid_clone(ByteGrid* @this); | ||||
|         public static extern PrimitiveGrid* sp_byte_grid_clone(PrimitiveGrid* @this); | ||||
| 
 | ||||
|         /// <summary>Deallocates a `ByteGrid`.  # Safety  The caller has to make sure that:  - `this` points to a valid `ByteGrid` - `this` is not used concurrently or after this call - `this` was not passed to another consuming function, e.g. to create a `Command`</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_byte_grid_dealloc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|         public static extern void sp_byte_grid_dealloc(ByteGrid* @this); | ||||
|         public static extern void sp_byte_grid_dealloc(PrimitiveGrid* @this); | ||||
| 
 | ||||
|         /// <summary>Gets the current value at the specified position.  # Arguments  * `this`: instance to read from * `x` and `y`: position of the cell to read  # Panics  When accessing `x` or `y` out of bounds.  # Safety  The caller has to make sure that:  - `this` points to a valid `ByteGrid` - `this` is not written to concurrently</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_byte_grid_get", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|         public static extern byte sp_byte_grid_get(ByteGrid* @this, nuint x, nuint y); | ||||
|         public static extern byte sp_byte_grid_get(PrimitiveGrid* @this, nuint x, nuint y); | ||||
| 
 | ||||
|         /// <summary>Sets the value of the specified position in the `ByteGrid`.  # Arguments  * `this`: instance to write to * `x` and `y`: position of the cell * `value`: the value to write to the cell  returns: old value of the cell  # Panics  When accessing `x` or `y` out of bounds.  # Safety  The caller has to make sure that:  - `this` points to a valid `BitVec` - `this` is not written to or read from concurrently</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_byte_grid_set", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|         public static extern void sp_byte_grid_set(ByteGrid* @this, nuint x, nuint y, byte value); | ||||
|         public static extern void sp_byte_grid_set(PrimitiveGrid* @this, nuint x, nuint y, byte value); | ||||
| 
 | ||||
|         /// <summary>Sets the value of all cells in the `ByteGrid`.  # Arguments  * `this`: instance to write to * `value`: the value to set all cells to  # Safety  The caller has to make sure that:  - `this` points to a valid `ByteGrid` - `this` is not written to or read from concurrently</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_byte_grid_fill", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|         public static extern void sp_byte_grid_fill(ByteGrid* @this, byte value); | ||||
|         public static extern void sp_byte_grid_fill(PrimitiveGrid* @this, byte value); | ||||
| 
 | ||||
|         /// <summary>Gets the width of the `ByteGrid` instance.  # Arguments  * `this`: instance to read from  # Safety  The caller has to make sure that:  - `this` points to a valid `ByteGrid`</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_byte_grid_width", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|         public static extern nuint sp_byte_grid_width(ByteGrid* @this); | ||||
|         public static extern nuint sp_byte_grid_width(PrimitiveGrid* @this); | ||||
| 
 | ||||
|         /// <summary>Gets the height of the `ByteGrid` instance.  # Arguments  * `this`: instance to read from  # Safety  The caller has to make sure that:  - `this` points to a valid `ByteGrid`</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_byte_grid_height", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|         public static extern nuint sp_byte_grid_height(ByteGrid* @this); | ||||
|         public static extern nuint sp_byte_grid_height(PrimitiveGrid* @this); | ||||
| 
 | ||||
|         /// <summary>Gets an unsafe reference to the data of the `ByteGrid` instance.  ## Safety  The caller has to make sure that:  - `this` points to a valid `ByteGrid` - the returned memory range is never accessed after the passed `ByteGrid` has been freed - the returned memory range is never accessed concurrently, either via the `ByteGrid` or directly</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_byte_grid_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|         public static extern CByteSlice sp_byte_grid_unsafe_data_ref(ByteGrid* @this); | ||||
|         public static extern CByteSlice sp_byte_grid_unsafe_data_ref(PrimitiveGrid* @this); | ||||
| 
 | ||||
|         /// <summary>Tries to turn a `Packet` into a `Command`. The packet is deallocated in the process.  Returns: pointer to new `Command` instance or NULL  # Safety  The caller has to make sure that:  - `packet` points to a valid instance of `Packet` - `packet` is not used concurrently or after this call - the result is checked for NULL - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_command_try_from_packet", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|  | @ -127,7 +127,7 @@ namespace ServicePoint.BindGen | |||
| 
 | ||||
|         /// <summary>Allocates a new `Command::CharBrightness` instance. The passed `ByteGrid` gets consumed.  # Safety  The caller has to make sure that:  - `byte_grid` points to a valid instance of `ByteGrid` - `byte_grid` is not used concurrently or after this call - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_command_char_brightness", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|         public static extern Command* sp_command_char_brightness(nuint x, nuint y, ByteGrid* byte_grid); | ||||
|         public static extern Command* sp_command_char_brightness(nuint x, nuint y, BrightnessGrid* byte_grid); | ||||
| 
 | ||||
|         /// <summary>Allocates a new `Command::BitmapLinear` instance. The passed `BitVec` gets consumed.  # Safety  The caller has to make sure that:  - `bit_vec` points to a valid instance of `BitVec` - `bit_vec` is not used concurrently or after this call - `compression` matches one of the allowed enum values - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|  | @ -147,7 +147,7 @@ namespace ServicePoint.BindGen | |||
| 
 | ||||
|         /// <summary>Allocates a new `Command::Cp437Data` instance. The passed `ByteGrid` gets consumed.  # Safety  The caller has to make sure that:  - `byte_grid` points to a valid instance of `ByteGrid` - `byte_grid` is not used concurrently or after this call - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_command_cp437_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|         public static extern Command* sp_command_cp437_data(nuint x, nuint y, ByteGrid* byte_grid); | ||||
|         public static extern Command* sp_command_cp437_data(nuint x, nuint y, PrimitiveGrid* byte_grid); | ||||
| 
 | ||||
|         /// <summary>Allocates a new `Command::BitmapLinearWin` instance. The passed `PixelGrid` gets consumed.  # Safety  The caller has to make sure that:  - `pixel_grid` points to a valid instance of `PixelGrid` - `pixel_grid` is not used concurrently or after this call - `compression` matches one of the allowed enum values - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary> | ||||
|         [DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_win", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] | ||||
|  | @ -239,7 +239,7 @@ namespace ServicePoint.BindGen | |||
|     } | ||||
| 
 | ||||
|     [StructLayout(LayoutKind.Sequential)] | ||||
|     public unsafe partial struct ByteGrid | ||||
|     public unsafe partial struct PrimitiveGrid | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ fn main() { | |||
|         .input_extern_file("../servicepoint_binding_c/src/lib.rs") | ||||
|         .input_extern_file("../servicepoint_binding_c/src/c_slice.rs") | ||||
|         .input_extern_file("../servicepoint_binding_c/src/packet.rs") | ||||
|         .input_extern_file("../servicepoint/src/byte_grid.rs") | ||||
|         .input_extern_file("../servicepoint/src/primitive_grid.rs") | ||||
|         .input_extern_file("../servicepoint/src/command.rs") | ||||
|         .input_extern_file("../servicepoint/src/connection.rs") | ||||
|         .input_extern_file("../servicepoint/src/pixel_grid.rs") | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vinzenz Schroeter
						Vinzenz Schroeter