move grid functions to trait

This commit is contained in:
Vinzenz Schroeter 2024-05-18 10:50:35 +02:00
parent 314bec36f3
commit bcf040911d
11 changed files with 96 additions and 88 deletions

View file

@ -63,15 +63,13 @@ int main(void) {
sp2_PixelGrid *pixels = sp2_pixel_grid_new(sp2_PIXEL_WIDTH, sp2_PIXEL_HEIGHT); sp2_PixelGrid *pixels = sp2_pixel_grid_new(sp2_PIXEL_WIDTH, sp2_PIXEL_HEIGHT);
sp2_pixel_grid_fill(pixels, true); sp2_pixel_grid_fill(pixels, true);
command = sp2_command_bitmap_linear_win(0, 0, pixels); // pixels get consumed here
if (command == NULL)
return 4;
if (!sp2_connection_send(connection, command)) // command gets consumed here
return 5;
// connection does not get consumed and has to be freed manually sp2_Command *command = sp2_command_bitmap_linear_win(0, 0, pixels, Uncompressed);
sp2_connection_dealloc(connection); sp2_Packet *packet = sp2_packet_from_command(command);
if (!sp2_connection_send(connection, packet))
return 1;
sp2_connection_dealloc(connection);
return 0; return 0;
} }
``` ```

View file

@ -1,6 +1,6 @@
use clap::Parser; use clap::Parser;
use servicepoint2::{ByteGrid, Command, Connection, Origin}; use servicepoint2::{ByteGrid, Command, Connection, Grid, Origin};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
struct Cli { struct Cli {

View file

@ -3,9 +3,7 @@ use std::thread;
use clap::Parser; use clap::Parser;
use rand::{distributions, Rng}; use rand::{distributions, Rng};
use servicepoint2::{ use servicepoint2::{Command, CompressionCode, Connection, Origin, PixelGrid, FRAME_PACING, Grid};
Command, CompressionCode, Connection, Origin, PixelGrid, FRAME_PACING,
};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
struct Cli { struct Cli {

View file

@ -2,10 +2,7 @@ use std::thread;
use clap::Parser; use clap::Parser;
use servicepoint2::{ use servicepoint2::{Command, CompressionCode, Connection, Origin, PixelGrid, FRAME_PACING, PIXEL_HEIGHT, PIXEL_WIDTH, Grid};
Command, CompressionCode, Connection, Origin, PixelGrid, FRAME_PACING,
PIXEL_HEIGHT, PIXEL_WIDTH,
};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
struct Cli { struct Cli {

View file

@ -4,10 +4,7 @@ use clap::Parser;
use rand::Rng; use rand::Rng;
use servicepoint2::Command::{BitmapLinearWin, Brightness, CharBrightness}; use servicepoint2::Command::{BitmapLinearWin, Brightness, CharBrightness};
use servicepoint2::{ use servicepoint2::{ByteGrid, CompressionCode, Connection, Grid, Origin, PixelGrid, TILE_HEIGHT, TILE_WIDTH};
ByteGrid, CompressionCode, Connection, Origin, PixelGrid, TILE_HEIGHT,
TILE_WIDTH,
};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
struct Cli { struct Cli {

View file

@ -3,10 +3,7 @@ use std::time::Duration;
use clap::Parser; use clap::Parser;
use servicepoint2::{ use servicepoint2::{BitVec, Command, CompressionCode, Connection, PixelGrid, FRAME_PACING, PIXEL_HEIGHT, PIXEL_WIDTH, Grid};
BitVec, Command, CompressionCode, Connection, PixelGrid, FRAME_PACING,
PIXEL_HEIGHT, PIXEL_WIDTH,
};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
struct Cli { struct Cli {

View file

@ -1,3 +1,5 @@
use crate::Grid;
/// A 2D grid of bytes /// A 2D grid of bytes
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct ByteGrid { pub struct ByteGrid {
@ -34,40 +36,11 @@ impl ByteGrid {
} }
} }
/// Get the current value at the specified position
///
/// returns: current byte value
pub fn get(&self, x: usize, y: usize) -> u8 {
self.check_indexes(x, y);
self.data[x + y * self.width]
}
/// Sets the byte value at the specified position
pub fn set(&mut self, x: usize, y: usize, value: u8) {
self.check_indexes(x, y);
self.data[x + y * self.width] = value;
}
/// Sets all bytes in the grid to the specified value
pub fn fill(&mut self, value: u8) {
self.data.fill(value)
}
/// Get the underlying byte rows /// Get the underlying byte rows
pub fn mut_data_ref(&mut self) -> &mut [u8] { pub fn mut_data_ref(&mut self) -> &mut [u8] {
self.data.as_mut_slice() self.data.as_mut_slice()
} }
/// the size in x-direction
pub fn width(&self) -> usize {
self.width
}
/// the height in y-direction
pub fn height(&self) -> usize {
self.height
}
fn check_indexes(&self, x: usize, y: usize) { fn check_indexes(&self, x: usize, y: usize) {
if x >= self.width { if x >= self.width {
panic!("cannot access byte {x}-{y} because x is outside of bounds 0..{}", self.width) panic!("cannot access byte {x}-{y} because x is outside of bounds 0..{}", self.width)
@ -78,6 +51,34 @@ impl ByteGrid {
} }
} }
impl Grid<u8> for ByteGrid {
fn set(&mut self, x: usize, y: usize, value: u8) -> u8 {
self.check_indexes(x, y);
let pos = &mut self.data[x + y * self.width];
let old_val = *pos;
*pos = value;
old_val
}
fn get(&self, x: usize, y: usize) -> u8 {
self.check_indexes(x, y);
self.data[x + y * self.width]
}
fn fill(&mut self, value: u8) {
self.data.fill(value)
}
fn width(&self) -> usize {
self.width
}
fn height(&self) -> usize {
self.height
}
}
impl From<ByteGrid> for Vec<u8> { impl From<ByteGrid> for Vec<u8> {
/// Turn into the underlying `Vec<u8>` containing the rows of bytes. /// Turn into the underlying `Vec<u8>` containing the rows of bytes.
fn from(value: ByteGrid) -> Self { fn from(value: ByteGrid) -> Self {
@ -88,6 +89,7 @@ impl From<ByteGrid> for Vec<u8> {
#[cfg(feature = "c_api")] #[cfg(feature = "c_api")]
pub mod c_api { pub mod c_api {
use crate::{ByteGrid, CByteSlice}; use crate::{ByteGrid, CByteSlice};
use crate::grid::Grid;
/// Creates a new `ByteGrid` instance. /// Creates a new `ByteGrid` instance.
/// The returned instance has to be freed with `byte_grid_dealloc`. /// The returned instance has to be freed with `byte_grid_dealloc`.
@ -198,7 +200,7 @@ pub mod c_api {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::ByteGrid; use crate::{ByteGrid, Grid};
#[test] #[test]
fn fill() { fn fill() {

View file

@ -1,8 +1,6 @@
use crate::command_code::CommandCode; use crate::command_code::CommandCode;
use crate::compression::{into_compressed, into_decompressed}; use crate::compression::{into_compressed, into_decompressed};
use crate::{ use crate::{BitVec, ByteGrid, CompressionCode, Grid, Header, Packet, PixelGrid, TILE_SIZE};
BitVec, ByteGrid, CompressionCode, Header, Packet, PixelGrid, TILE_SIZE,
};
/// An origin marks the top left position of a window sent to the display. /// An origin marks the top left position of a window sent to the display.
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
@ -728,6 +726,7 @@ mod tests {
if compression != CompressionCode::Uncompressed { if compression != CompressionCode::Uncompressed {
assert_eq!(result, Err(TryFromPacketError::DecompressionFailed)) assert_eq!(result, Err(TryFromPacketError::DecompressionFailed))
} else { } else {
// when not compressing, there is no way to detect corrupted data
assert!(result.is_ok()); assert!(result.is_ok());
} }
} }

18
servicepoint2/src/grid.rs Normal file
View file

@ -0,0 +1,18 @@
pub trait Grid<T> {
/// Sets the value at the specified position
///
/// returns: the old value
fn set(&mut self, x: usize, y: usize, value: T) -> T;
/// Get the current value at the specified position
fn get(&self, x: usize, y: usize) -> T;
/// Sets all cells in the grid to the specified value
fn fill(&mut self, value: T);
/// the size in x-direction
fn width(&self) -> usize;
/// the height in y-direction
fn height(&self) -> usize;
}

View file

@ -5,6 +5,7 @@ pub use crate::compression_code::CompressionCode;
pub use crate::connection::Connection; pub use crate::connection::Connection;
pub use crate::packet::{Header, Packet, Payload}; pub use crate::packet::{Header, Packet, Payload};
pub use crate::pixel_grid::PixelGrid; pub use crate::pixel_grid::PixelGrid;
pub use crate::grid::Grid;
use std::time::Duration; use std::time::Duration;
#[cfg(feature = "c_api")] #[cfg(feature = "c_api")]
@ -20,17 +21,23 @@ mod compression_code;
mod connection; mod connection;
mod packet; mod packet;
mod pixel_grid; mod pixel_grid;
mod grid;
/// size of a single tile in one dimension /// size of a single tile in one dimension
pub const TILE_SIZE: u16 = 8; pub const TILE_SIZE: u16 = 8;
/// tile count in the x-direction /// tile count in the x-direction
pub const TILE_WIDTH: u16 = 56; pub const TILE_WIDTH: u16 = 56;
/// tile count in the y-direction /// tile count in the y-direction
pub const TILE_HEIGHT: u16 = 20; pub const TILE_HEIGHT: u16 = 20;
/// screen width in pixels /// screen width in pixels
pub const PIXEL_WIDTH: u16 = TILE_WIDTH * TILE_SIZE; pub const PIXEL_WIDTH: u16 = TILE_WIDTH * TILE_SIZE;
/// screen height in pixels /// screen height in pixels
pub const PIXEL_HEIGHT: u16 = TILE_HEIGHT * TILE_SIZE; pub const PIXEL_HEIGHT: u16 = TILE_HEIGHT * TILE_SIZE;
/// pixel count on whole screen /// pixel count on whole screen
pub const PIXEL_COUNT: usize = PIXEL_WIDTH as usize * PIXEL_HEIGHT as usize; pub const PIXEL_COUNT: usize = PIXEL_WIDTH as usize * PIXEL_HEIGHT as usize;

View file

@ -1,4 +1,4 @@
use crate::{BitVec, PIXEL_HEIGHT, PIXEL_WIDTH}; use crate::{BitVec, Grid, PIXEL_HEIGHT, PIXEL_WIDTH};
/// A grid of pixels stored in packed bytes. /// A grid of pixels stored in packed bytes.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -58,38 +58,10 @@ impl PixelGrid {
} }
} }
/// Sets the byte value at the specified position
pub fn set(&mut self, x: usize, y: usize, value: bool) -> bool {
self.check_indexes(x, y);
self.bit_vec.set(x + y * self.width, value)
}
/// Get the current value at the specified position
///
/// returns: current pixel value
pub fn get(&self, x: usize, y: usize) -> bool {
self.bit_vec.get(x + y * self.width)
}
/// Sets all pixels in the grid to the specified value
pub fn fill(&mut self, value: bool) {
self.bit_vec.fill(value);
}
pub fn mut_data_ref(&mut self) -> &mut [u8] { pub fn mut_data_ref(&mut self) -> &mut [u8] {
self.bit_vec.mut_data_ref() self.bit_vec.mut_data_ref()
} }
/// the size in x-direction in pixels
pub fn width(&self) -> usize {
self.width
}
/// the height in y-direction in pixels
pub fn height(&self) -> usize {
self.height
}
fn check_indexes(&self, x: usize, y: usize) { fn check_indexes(&self, x: usize, y: usize) {
if x >= self.width { if x >= self.width {
panic!("cannot access pixel {x}-{y} because x is outside of bounds 0..{}", self.width) panic!("cannot access pixel {x}-{y} because x is outside of bounds 0..{}", self.width)
@ -100,6 +72,29 @@ impl PixelGrid {
} }
} }
impl Grid<bool> for PixelGrid {
fn set(&mut self, x: usize, y: usize, value: bool) -> bool {
self.check_indexes(x, y);
self.bit_vec.set(x + y * self.width, value)
}
fn get(&self, x: usize, y: usize) -> bool {
self.bit_vec.get(x + y * self.width)
}
fn fill(&mut self, value: bool) {
self.bit_vec.fill(value);
}
fn width(&self) -> usize {
self.width
}
fn height(&self) -> usize {
self.height
}
}
impl From<PixelGrid> for Vec<u8> { impl From<PixelGrid> for Vec<u8> {
/// Turns a `PixelGrid` into the underlying `Vec<u8>`. /// Turns a `PixelGrid` into the underlying `Vec<u8>`.
fn from(value: PixelGrid) -> Self { fn from(value: PixelGrid) -> Self {
@ -110,7 +105,7 @@ impl From<PixelGrid> for Vec<u8> {
#[cfg(feature = "c_api")] #[cfg(feature = "c_api")]
pub mod c_api { pub mod c_api {
use crate::c_slice::CByteSlice; use crate::c_slice::CByteSlice;
use crate::PixelGrid; use crate::{Grid, PixelGrid};
/// Creates a new `PixelGrid` instance. /// Creates a new `PixelGrid` instance.
/// The returned instance has to be freed with `pixel_grid_dealloc`. /// The returned instance has to be freed with `pixel_grid_dealloc`.
@ -221,7 +216,7 @@ pub mod c_api {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::PixelGrid; use crate::{Grid, PixelGrid};
#[test] #[test]
fn fill() { fn fill() {