move data_ref to trait

This commit is contained in:
Vinzenz Schroeter 2024-05-18 11:11:15 +02:00
parent bcf040911d
commit d5e08faeb1
11 changed files with 81 additions and 45 deletions

View file

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

View file

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

View file

@ -4,7 +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::{ByteGrid, CompressionCode, Connection, Grid, Origin, PixelGrid, TILE_HEIGHT, TILE_WIDTH}; use servicepoint2::*;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
struct Cli { struct Cli {

View file

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

View file

@ -1,3 +1,5 @@
use crate::DataRef;
/// A vector of bits /// A vector of bits
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub struct BitVec { pub struct BitVec {
@ -83,11 +85,6 @@ impl BitVec {
self.data.is_empty() self.data.is_empty()
} }
/// Get the underlying bits in their raw packed bytes form
pub fn mut_data_ref(&mut self) -> &mut [u8] {
self.data.as_mut_slice()
}
/// Calculates the byte index and bitmask for a specific bit in the vector /// Calculates the byte index and bitmask for a specific bit in the vector
fn get_indexes(&self, bit_index: usize) -> (usize, u8) { fn get_indexes(&self, bit_index: usize) -> (usize, u8) {
if bit_index >= self.size { if bit_index >= self.size {
@ -104,6 +101,16 @@ impl BitVec {
} }
} }
impl DataRef for BitVec {
fn data_ref_mut(&mut self) -> &mut [u8] {
self.data.as_mut_slice()
}
fn data_ref(&self) -> &[u8] {
self.data.as_slice()
}
}
impl From<BitVec> for Vec<u8> { impl From<BitVec> for Vec<u8> {
/// Turns the `BitVec` into the underlying `Vec<u8>` /// Turns the `BitVec` into the underlying `Vec<u8>`
fn from(value: BitVec) -> Self { fn from(value: BitVec) -> Self {
@ -133,7 +140,7 @@ impl std::fmt::Debug for BitVec {
#[cfg(feature = "c_api")] #[cfg(feature = "c_api")]
pub mod c_api { pub mod c_api {
use crate::{BitVec, CByteSlice}; use crate::{BitVec, CByteSlice, DataRef};
/// Creates a new `BitVec` instance. /// Creates a new `BitVec` instance.
/// The returned instance has to be freed with `bit_vec_dealloc`. /// The returned instance has to be freed with `bit_vec_dealloc`.
@ -220,7 +227,7 @@ pub mod c_api {
pub unsafe extern "C" fn sp2_bit_vec_unsafe_data_ref( pub unsafe extern "C" fn sp2_bit_vec_unsafe_data_ref(
this: *mut BitVec, this: *mut BitVec,
) -> CByteSlice { ) -> CByteSlice {
let data = (*this).mut_data_ref(); let data = (*this).data_ref_mut();
CByteSlice { CByteSlice {
start: data.as_mut_ptr_range().start, start: data.as_mut_ptr_range().start,
length: data.len(), length: data.len(),
@ -230,7 +237,7 @@ pub mod c_api {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::BitVec; use crate::{BitVec, DataRef};
#[test] #[test]
fn fill() { fn fill() {
@ -280,7 +287,7 @@ mod tests {
fn mut_data_ref() { fn mut_data_ref() {
let mut vec = BitVec::new(8 * 3); let mut vec = BitVec::new(8 * 3);
let data_ref = vec.mut_data_ref(); let data_ref = vec.data_ref_mut();
data_ref.copy_from_slice(&[0x40, 0x10, 0x00]); data_ref.copy_from_slice(&[0x40, 0x10, 0x00]);
assert_eq!(vec.data, [0x40, 0x10, 0x00]); assert_eq!(vec.data, [0x40, 0x10, 0x00]);

View file

@ -1,4 +1,4 @@
use crate::Grid; use crate::{DataRef, Grid};
/// A 2D grid of bytes /// A 2D grid of bytes
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -36,11 +36,6 @@ impl ByteGrid {
} }
} }
/// Get the underlying byte rows
pub fn mut_data_ref(&mut self) -> &mut [u8] {
self.data.as_mut_slice()
}
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 +73,17 @@ impl Grid<u8> for ByteGrid {
} }
} }
impl DataRef for ByteGrid {
/// Get the underlying byte rows mutable
fn data_ref_mut(&mut self) -> &mut [u8] {
self.data.as_mut_slice()
}
/// Get the underlying byte rows read only
fn data_ref(&self) -> &[u8] {
self.data.as_slice()
}
}
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.
@ -88,8 +94,9 @@ 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::data_ref::DataRef;
use crate::grid::Grid; use crate::grid::Grid;
use crate::{ByteGrid, CByteSlice};
/// 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`.
@ -190,7 +197,7 @@ pub mod c_api {
pub unsafe extern "C" fn sp2_byte_grid_unsafe_data_ref( pub unsafe extern "C" fn sp2_byte_grid_unsafe_data_ref(
this: *mut ByteGrid, this: *mut ByteGrid,
) -> CByteSlice { ) -> CByteSlice {
let data = (*this).mut_data_ref(); let data = (*this).data_ref_mut();
CByteSlice { CByteSlice {
start: data.as_mut_ptr_range().start, start: data.as_mut_ptr_range().start,
length: data.len(), length: data.len(),
@ -200,7 +207,7 @@ pub mod c_api {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ByteGrid, Grid}; use crate::{ByteGrid, DataRef, Grid};
#[test] #[test]
fn fill() { fn fill() {
@ -247,7 +254,7 @@ mod tests {
fn mut_data_ref() { fn mut_data_ref() {
let mut vec = ByteGrid::new(2, 2); let mut vec = ByteGrid::new(2, 2);
let data_ref = vec.mut_data_ref(); let data_ref = vec.data_ref_mut();
data_ref.copy_from_slice(&[1, 2, 3, 4]); data_ref.copy_from_slice(&[1, 2, 3, 4]);
assert_eq!(vec.data, [1, 2, 3, 4]); assert_eq!(vec.data, [1, 2, 3, 4]);

View file

@ -1,6 +1,9 @@
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::{BitVec, ByteGrid, CompressionCode, Grid, Header, Packet, PixelGrid, TILE_SIZE}; use crate::{
BitVec, ByteGrid, CompressionCode, Grid, 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)]

View file

@ -38,20 +38,20 @@ impl Connection {
/// # Examples /// # Examples
/// ///
/// ```rust /// ```rust
/// use servicepoint2::CompressionCode; /// use servicepoint2::{Command, CompressionCode, Grid, PixelGrid};
/// let connection = servicepoint2::Connection::open("172.23.42.29:2342") /// let connection = servicepoint2::Connection::open("172.23.42.29:2342")
/// .expect("connection failed"); /// .expect("connection failed");
/// ///
/// // turn off all pixels /// // turn off all pixels
/// connection.send(servicepoint2::Command::Clear.into()) /// connection.send(Command::Clear.into())
/// .expect("send failed"); /// .expect("send failed");
/// ///
/// // turn on all pixels /// // turn on all pixels
/// let mut pixels = servicepoint2::PixelGrid::max_sized(); /// let mut pixels = PixelGrid::max_sized();
/// pixels.fill(true); /// pixels.fill(true);
/// ///
/// // send pixels to display /// // send pixels to display
/// connection.send(servicepoint2::Command::BitmapLinearWin(servicepoint2::Origin(0, 0), pixels, CompressionCode::Lzma).into()) /// connection.send(Command::BitmapLinearWin(servicepoint2::Origin(0, 0), pixels, CompressionCode::Uncompressed).into())
/// .expect("send failed"); /// .expect("send failed");
/// ``` /// ```
pub fn send(&self, packet: Packet) -> Result<(), std::io::Error> { pub fn send(&self, packet: Packet) -> Result<(), std::io::Error> {

View file

@ -0,0 +1,11 @@
/// A trait for getting the underlying raw byte slices of data containers.
///
/// The expectation is that you can create an equal instance with this data given the additional
/// metadata needed.
pub trait DataRef {
/// Get the underlying bytes writable.
fn data_ref_mut(&mut self) -> &mut [u8];
/// Get the underlying bytes read-only.
fn data_ref(&self) -> &[u8];
}

View file

@ -3,9 +3,10 @@ pub use crate::byte_grid::ByteGrid;
pub use crate::command::{Brightness, Command, Offset, Origin, Size}; pub use crate::command::{Brightness, Command, Offset, Origin, Size};
pub use crate::compression_code::CompressionCode; pub use crate::compression_code::CompressionCode;
pub use crate::connection::Connection; pub use crate::connection::Connection;
pub use crate::data_ref::DataRef;
pub use crate::grid::Grid;
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")]
@ -19,9 +20,10 @@ mod command_code;
mod compression; mod compression;
mod compression_code; mod compression_code;
mod connection; mod connection;
mod data_ref;
mod grid;
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;

View file

@ -1,4 +1,4 @@
use crate::{BitVec, Grid, PIXEL_HEIGHT, PIXEL_WIDTH}; use crate::{BitVec, DataRef, 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,10 +58,6 @@ impl PixelGrid {
} }
} }
pub fn mut_data_ref(&mut self) -> &mut [u8] {
self.bit_vec.mut_data_ref()
}
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)
@ -95,6 +91,16 @@ impl Grid<bool> for PixelGrid {
} }
} }
impl DataRef for PixelGrid {
fn data_ref_mut(&mut self) -> &mut [u8] {
self.bit_vec.data_ref_mut()
}
fn data_ref(&self) -> &[u8] {
self.bit_vec.data_ref()
}
}
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 {
@ -105,7 +111,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::{Grid, PixelGrid}; use crate::{DataRef, 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`.
@ -206,7 +212,7 @@ pub mod c_api {
pub unsafe extern "C" fn sp2_pixel_grid_unsafe_data_ref( pub unsafe extern "C" fn sp2_pixel_grid_unsafe_data_ref(
this: *mut PixelGrid, this: *mut PixelGrid,
) -> CByteSlice { ) -> CByteSlice {
let data = (*this).mut_data_ref(); let data = (*this).data_ref_mut();
CByteSlice { CByteSlice {
start: data.as_mut_ptr_range().start, start: data.as_mut_ptr_range().start,
length: data.len(), length: data.len(),
@ -216,18 +222,18 @@ pub mod c_api {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{Grid, PixelGrid}; use crate::{DataRef, Grid, PixelGrid};
#[test] #[test]
fn fill() { fn fill() {
let mut grid = PixelGrid::new(8, 2); let mut grid = PixelGrid::new(8, 2);
assert_eq!(grid.mut_data_ref(), [0x00, 0x00]); assert_eq!(grid.data_ref(), [0x00, 0x00]);
grid.fill(true); grid.fill(true);
assert_eq!(grid.mut_data_ref(), [0xFF, 0xFF]); assert_eq!(grid.data_ref(), [0xFF, 0xFF]);
grid.fill(false); grid.fill(false);
assert_eq!(grid.mut_data_ref(), [0x00, 0x00]); assert_eq!(grid.data_ref(), [0x00, 0x00]);
} }
#[test] #[test]
@ -238,7 +244,7 @@ mod tests {
grid.set(5, 0, true); grid.set(5, 0, true);
grid.set(1, 1, true); grid.set(1, 1, true);
assert_eq!(grid.mut_data_ref(), [0x04, 0x40]); assert_eq!(grid.data_ref(), [0x04, 0x40]);
assert!(grid.get(5, 0)); assert!(grid.get(5, 0));
assert!(grid.get(1, 1)); assert!(grid.get(1, 1));
@ -254,11 +260,11 @@ mod tests {
} }
} }
assert_eq!(grid.mut_data_ref(), [0xAA, 0x55, 0xAA]); assert_eq!(grid.data_ref(), [0xAA, 0x55, 0xAA]);
let data: Vec<u8> = grid.into(); let data: Vec<u8> = grid.into();
let mut grid = PixelGrid::load(8, 3, &data); let grid = PixelGrid::load(8, 3, &data);
assert_eq!(grid.mut_data_ref(), [0xAA, 0x55, 0xAA]); assert_eq!(grid.data_ref(), [0xAA, 0x55, 0xAA]);
} }
} }