From d385d8e1d4f3ffbb68c5d2e43f3ed511056eb280 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Thu, 29 Aug 2024 22:21:21 +0200 Subject: [PATCH] add packet clone --- crates/servicepoint/src/packet.rs | 4 +-- .../examples/lang_c/include/servicepoint.h | 14 ++++++++ crates/servicepoint_binding_c/src/bit_vec.rs | 9 ++++- .../src/brightness_grid.rs | 36 +++++++++++-------- crates/servicepoint_binding_c/src/command.rs | 4 +-- .../servicepoint_binding_c/src/cp437_grid.rs | 36 ++++++++++++------- crates/servicepoint_binding_c/src/packet.rs | 15 ++++++++ 7 files changed, 87 insertions(+), 31 deletions(-) diff --git a/crates/servicepoint/src/packet.rs b/crates/servicepoint/src/packet.rs index 80ce052..3718e34 100644 --- a/crates/servicepoint/src/packet.rs +++ b/crates/servicepoint/src/packet.rs @@ -8,14 +8,14 @@ use crate::{ }; /// A raw header. Should probably not be used directly. -#[derive(Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub struct Header(pub u16, pub u16, pub u16, pub u16, pub u16); /// The raw payload. Should probably not be used directly. pub type Payload = Vec; /// The raw packet. Should probably not be used directly. -#[derive(Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct Packet(pub Header, pub Payload); impl From for Vec { diff --git a/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h b/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h index d2f69b1..eaf2e40 100644 --- a/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h +++ b/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h @@ -994,6 +994,20 @@ struct sp_CByteSlice sp_cp437_grid_unsafe_data_ref(struct sp_CCp437Grid *this_); */ size_t sp_cp437_grid_width(const struct sp_CCp437Grid *this_); +/** + * Clones a `Packet`. + * + * # Safety + * + * The caller has to make sure that: + * + * - `this` points to a valid `Packet` + * - `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_packet_dealloc`. + */ +struct sp_Packet *sp_packet_clone(const struct sp_Packet *this_); + /** * Deallocates a `Packet`. * diff --git a/crates/servicepoint_binding_c/src/bit_vec.rs b/crates/servicepoint_binding_c/src/bit_vec.rs index 73aeefb..6a52a63 100644 --- a/crates/servicepoint_binding_c/src/bit_vec.rs +++ b/crates/servicepoint_binding_c/src/bit_vec.rs @@ -9,7 +9,6 @@ use servicepoint::bitvec::prelude::{BitVec, Msb0}; type SpBitVec = BitVec; /// A vector of bits -#[derive(Clone)] pub struct CBitVec { actual: SpBitVec, } @@ -26,6 +25,14 @@ impl From for SpBitVec { } } +impl Clone for CBitVec { + fn clone(&self) -> Self { + CBitVec { + actual: self.actual.clone(), + } + } +} + /// Creates a new `BitVec` instance. /// /// # Arguments diff --git a/crates/servicepoint_binding_c/src/brightness_grid.rs b/crates/servicepoint_binding_c/src/brightness_grid.rs index 8f89906..0ca0ec6 100644 --- a/crates/servicepoint_binding_c/src/brightness_grid.rs +++ b/crates/servicepoint_binding_c/src/brightness_grid.rs @@ -2,14 +2,22 @@ //! //! prefix `sp_brightness_grid_` +use crate::c_slice::CByteSlice; use servicepoint::{Brightness, BrightnessGrid, DataRef, Grid, PrimitiveGrid}; use std::intrinsics::transmute; -use crate::c_slice::CByteSlice; - /// C-wrapper for grid containing brightness values. -#[derive(Clone)] -pub struct CBrightnessGrid(pub(crate) BrightnessGrid); +pub struct CBrightnessGrid { + pub(crate) actual: BrightnessGrid, +} + +impl Clone for CBrightnessGrid { + fn clone(&self) -> Self { + CBrightnessGrid { + actual: self.actual.clone(), + } + } +} /// Creates a new `BrightnessGrid` with the specified dimensions. /// @@ -26,9 +34,9 @@ pub unsafe extern "C" fn sp_brightness_grid_new( width: usize, height: usize, ) -> *mut CBrightnessGrid { - Box::into_raw(Box::new(CBrightnessGrid(BrightnessGrid::new( - width, height, - )))) + Box::into_raw(Box::new(CBrightnessGrid { + actual: BrightnessGrid::new(width, height), + })) } /// Loads a `BrightnessGrid` with the specified dimensions from the provided data. @@ -56,7 +64,7 @@ pub unsafe extern "C" fn sp_brightness_grid_load( let grid = PrimitiveGrid::load(width, height, data); let grid = BrightnessGrid::try_from(grid).expect("invalid brightness value"); - Box::into_raw(Box::new(CBrightnessGrid(grid))) + Box::into_raw(Box::new(CBrightnessGrid { actual: grid })) } /// Clones a `BrightnessGrid`. @@ -115,7 +123,7 @@ pub unsafe extern "C" fn sp_brightness_grid_get( x: usize, y: usize, ) -> u8 { - (*this).0.get(x, y).into() + (*this).actual.get(x, y).into() } /// Sets the value of the specified position in the `BrightnessGrid`. @@ -148,7 +156,7 @@ pub unsafe extern "C" fn sp_brightness_grid_set( ) { let brightness = Brightness::try_from(value).expect("invalid brightness value"); - (*this).0.set(x, y, brightness); + (*this).actual.set(x, y, brightness); } /// Sets the value of all cells in the `BrightnessGrid`. @@ -175,7 +183,7 @@ pub unsafe extern "C" fn sp_brightness_grid_fill( ) { let brightness = Brightness::try_from(value).expect("invalid brightness value"); - (*this).0.fill(brightness); + (*this).actual.fill(brightness); } /// Gets the width of the `BrightnessGrid` instance. @@ -193,7 +201,7 @@ pub unsafe extern "C" fn sp_brightness_grid_fill( pub unsafe extern "C" fn sp_brightness_grid_width( this: *const CBrightnessGrid, ) -> usize { - (*this).0.width() + (*this).actual.width() } /// Gets the height of the `BrightnessGrid` instance. @@ -211,7 +219,7 @@ pub unsafe extern "C" fn sp_brightness_grid_width( pub unsafe extern "C" fn sp_brightness_grid_height( this: *const CBrightnessGrid, ) -> usize { - (*this).0.height() + (*this).actual.height() } /// Gets an unsafe reference to the data of the `BrightnessGrid` instance. @@ -229,7 +237,7 @@ pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( ) -> CByteSlice { assert_eq!(std::mem::size_of::(), 1); - let data = (*this).0.data_ref_mut(); + let data = (*this).actual.data_ref_mut(); let data: &mut [u8] = transmute(data); CByteSlice { start: data.as_mut_ptr_range().start, diff --git a/crates/servicepoint_binding_c/src/command.rs b/crates/servicepoint_binding_c/src/command.rs index 3a34bcf..6126284 100644 --- a/crates/servicepoint_binding_c/src/command.rs +++ b/crates/servicepoint_binding_c/src/command.rs @@ -147,7 +147,7 @@ pub unsafe extern "C" fn sp_command_char_brightness( let byte_grid = *Box::from_raw(byte_grid); Box::into_raw(Box::new(CCommand(Command::CharBrightness( Origin::new(x, y), - byte_grid.0, + byte_grid.actual, )))) } @@ -275,7 +275,7 @@ pub unsafe extern "C" fn sp_command_cp437_data( let byte_grid = *Box::from_raw(byte_grid); Box::into_raw(Box::new(CCommand(Command::Cp437Data( Origin::new(x, y), - byte_grid.0, + byte_grid.actual, )))) } diff --git a/crates/servicepoint_binding_c/src/cp437_grid.rs b/crates/servicepoint_binding_c/src/cp437_grid.rs index a1d84a6..79651bf 100644 --- a/crates/servicepoint_binding_c/src/cp437_grid.rs +++ b/crates/servicepoint_binding_c/src/cp437_grid.rs @@ -2,15 +2,23 @@ //! //! prefix `sp_cp437_grid_` -use servicepoint::{Cp437Grid, DataRef, Grid}; - use crate::c_slice::CByteSlice; +use servicepoint::{Cp437Grid, DataRef, Grid}; /// A C-wrapper for grid containing codepage 437 characters. /// /// The encoding is currently not enforced. -#[derive(Clone)] -pub struct CCp437Grid(pub(crate) Cp437Grid); +pub struct CCp437Grid { + pub(crate) actual: Cp437Grid, +} + +impl Clone for CCp437Grid { + fn clone(&self) -> Self { + CCp437Grid { + actual: self.actual.clone(), + } + } +} /// Creates a new `Cp437Grid` with the specified dimensions. /// @@ -27,7 +35,9 @@ pub unsafe extern "C" fn sp_cp437_grid_new( width: usize, height: usize, ) -> *mut CCp437Grid { - Box::into_raw(Box::new(CCp437Grid(Cp437Grid::new(width, height)))) + Box::into_raw(Box::new(CCp437Grid { + actual: Cp437Grid::new(width, height), + })) } /// Loads a `Cp437Grid` with the specified dimensions from the provided data. @@ -52,7 +62,9 @@ pub unsafe extern "C" fn sp_cp437_grid_load( data_length: usize, ) -> *mut CCp437Grid { let data = std::slice::from_raw_parts(data, data_length); - Box::into_raw(Box::new(CCp437Grid(Cp437Grid::load(width, height, data)))) + Box::into_raw(Box::new(CCp437Grid { + actual: Cp437Grid::load(width, height, data), + })) } /// Clones a `Cp437Grid`. @@ -109,7 +121,7 @@ pub unsafe extern "C" fn sp_cp437_grid_get( x: usize, y: usize, ) -> u8 { - (*this).0.get(x, y) + (*this).actual.get(x, y) } /// Sets the value of the specified position in the `Cp437Grid`. @@ -139,7 +151,7 @@ pub unsafe extern "C" fn sp_cp437_grid_set( y: usize, value: u8, ) { - (*this).0.set(x, y, value); + (*this).actual.set(x, y, value); } /// Sets the value of all cells in the `Cp437Grid`. @@ -157,7 +169,7 @@ pub unsafe extern "C" fn sp_cp437_grid_set( /// - `this` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_fill(this: *mut CCp437Grid, value: u8) { - (*this).0.fill(value); + (*this).actual.fill(value); } /// Gets the width of the `Cp437Grid` instance. @@ -173,7 +185,7 @@ pub unsafe extern "C" fn sp_cp437_grid_fill(this: *mut CCp437Grid, value: u8) { /// - `this` points to a valid `Cp437Grid` #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_width(this: *const CCp437Grid) -> usize { - (*this).0.width() + (*this).actual.width() } /// Gets the height of the `Cp437Grid` instance. @@ -191,7 +203,7 @@ pub unsafe extern "C" fn sp_cp437_grid_width(this: *const CCp437Grid) -> usize { pub unsafe extern "C" fn sp_cp437_grid_height( this: *const CCp437Grid, ) -> usize { - (*this).0.height() + (*this).actual.height() } /// Gets an unsafe reference to the data of the `Cp437Grid` instance. @@ -207,7 +219,7 @@ pub unsafe extern "C" fn sp_cp437_grid_height( pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref( this: *mut CCp437Grid, ) -> CByteSlice { - let data = (*this).0.data_ref_mut(); + let data = (*this).actual.data_ref_mut(); CByteSlice { start: data.as_mut_ptr_range().start, length: data.len(), diff --git a/crates/servicepoint_binding_c/src/packet.rs b/crates/servicepoint_binding_c/src/packet.rs index 402418f..8c69410 100644 --- a/crates/servicepoint_binding_c/src/packet.rs +++ b/crates/servicepoint_binding_c/src/packet.rs @@ -51,6 +51,21 @@ pub unsafe extern "C" fn sp_packet_try_load( } } +/// Clones a `Packet`. +/// +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - `this` points to a valid `Packet` +/// - `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_packet_dealloc`. +#[no_mangle] +pub unsafe extern "C" fn sp_packet_clone(this: *const Packet) -> *mut Packet { + Box::into_raw(Box::new((*this).clone())) +} + /// Deallocates a `Packet`. /// /// # Safety