From e8f11c08eab0da20e6fd7194c184222ceecd8d47 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Mon, 23 Jun 2025 23:28:30 +0200 Subject: [PATCH] add parameter modifiers --- src/commands/bitmap_command.rs | 18 ++- src/commands/bitvec_command.rs | 12 +- src/commands/brightness_grid_command.rs | 16 ++- src/commands/char_grid_command.rs | 16 ++- src/commands/cp437_grid_command.rs | 16 ++- src/commands/generic_command.rs | 5 +- src/commands/global_brightness_command.rs | 2 +- src/commands/mod.rs | 31 ++--- src/containers/bitmap.rs | 19 ++- src/containers/bitvec.rs | 18 +-- src/containers/brightness_grid.rs | 15 +-- src/containers/char_grid.rs | 14 +-- src/containers/cp437_grid.rs | 8 +- src/containers/mod.rs | 10 +- src/macros.rs | 138 ++++++++++++---------- src/packet.rs | 94 +++++++-------- src/udp.rs | 12 +- 17 files changed, 214 insertions(+), 230 deletions(-) diff --git a/src/commands/bitmap_command.rs b/src/commands/bitmap_command.rs index 01e3620..5aaab26 100644 --- a/src/commands/bitmap_command.rs +++ b/src/commands/bitmap_command.rs @@ -1,7 +1,7 @@ use crate::{ commands::{wrap_command, wrap_origin_accessors}, macros::{wrap_fields, wrap_functions}, - mem::{heap_move_nonnull, heap_remove}, + mem::heap_move_nonnull, }; use servicepoint::{Bitmap, BitmapCommand, CompressionCode, Origin}; use std::ptr::NonNull; @@ -22,13 +22,13 @@ wrap_functions!(associate BitmapCommand; /// /// Returns: a new [BitmapCommand] instance. fn new( - bitmap: NonNull, - origin_x: usize, - origin_y: usize, - compression: CompressionCode, + bitmap: move NonNull, + origin_x: val usize, + origin_y: val usize, + compression: val CompressionCode, ) -> NonNull { heap_move_nonnull(BitmapCommand { - bitmap: unsafe { heap_remove(bitmap) }, + bitmap, origin: Origin::new(origin_x, origin_y), compression, }) @@ -38,9 +38,7 @@ wrap_functions!(associate BitmapCommand; /// leaving other fields as their default values. /// /// Rust equivalent: `BitmapCommand::from(bitmap)` - fn from_bitmap( - bitmap: NonNull, - ) -> NonNull { - heap_move_nonnull(unsafe { heap_remove(bitmap) }.into()) + fn from_bitmap(bitmap: move NonNull) -> NonNull { + heap_move_nonnull(bitmap.into()) } ); diff --git a/src/commands/bitvec_command.rs b/src/commands/bitvec_command.rs index e796380..4dd9ca9 100644 --- a/src/commands/bitvec_command.rs +++ b/src/commands/bitvec_command.rs @@ -1,7 +1,7 @@ use crate::{ commands::wrap_command, macros::{wrap_fields, wrap_functions}, - mem::{heap_move_nonnull, heap_remove}, + mem::heap_move_nonnull, }; use servicepoint::{ BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Offset, @@ -32,13 +32,13 @@ wrap_functions!(associate BitVecCommand; /// /// The contained [`DisplayBitVec`] is always uncompressed. fn new( - bitvec: NonNull, - offset: usize, - operation: BinaryOperation, - compression: CompressionCode, + bitvec: move NonNull, + offset: val usize, + operation: val BinaryOperation, + compression: val CompressionCode, ) -> NonNull { heap_move_nonnull(BitVecCommand { - bitvec: unsafe { heap_remove(bitvec) }, + bitvec, offset, operation, compression, diff --git a/src/commands/brightness_grid_command.rs b/src/commands/brightness_grid_command.rs index 853a3fe..f05b820 100644 --- a/src/commands/brightness_grid_command.rs +++ b/src/commands/brightness_grid_command.rs @@ -1,7 +1,7 @@ use crate::{ commands::{wrap_command, wrap_origin_accessors}, macros::{wrap_fields, wrap_functions}, - mem::{heap_move_nonnull, heap_remove}, + mem::heap_move_nonnull, }; use servicepoint::{BrightnessGrid, BrightnessGridCommand, Origin}; use std::ptr::NonNull; @@ -22,22 +22,20 @@ wrap_functions!(associate BrightnessGridCommand; /// /// Returns: a new [BrightnessGridCommand] instance. fn new( - grid: NonNull, - origin_x: usize, - origin_y: usize, + grid: move NonNull, + origin_x: val usize, + origin_y: val usize ) -> NonNull { heap_move_nonnull(BrightnessGridCommand { - grid: unsafe { heap_remove(grid) }, + grid, origin: Origin::new(origin_x, origin_y), }) } /// Moves the provided [BrightnessGrid] into a new [BrightnessGridCommand], /// leaving other fields as their default values. - fn from_grid( - grid: NonNull, - ) -> NonNull { - heap_move_nonnull(unsafe { heap_remove(grid) }.into()) + fn from_grid(grid: move NonNull) -> NonNull { + heap_move_nonnull(grid.into()) } ); diff --git a/src/commands/char_grid_command.rs b/src/commands/char_grid_command.rs index 41e5000..12b58ca 100644 --- a/src/commands/char_grid_command.rs +++ b/src/commands/char_grid_command.rs @@ -1,7 +1,7 @@ use crate::{ commands::{wrap_command, wrap_origin_accessors}, macros::{wrap_fields, wrap_functions}, - mem::{heap_move_nonnull, heap_remove}, + mem::heap_move_nonnull, }; use servicepoint::{CharGrid, CharGridCommand, Origin}; use std::ptr::NonNull; @@ -22,22 +22,20 @@ wrap_functions!(associate CharGridCommand; /// /// Returns: a new [CharGridCommand] instance. fn new( - grid: NonNull, - origin_x: usize, - origin_y: usize, + grid: move NonNull, + origin_x: val usize, + origin_y: val usize, ) -> NonNull { heap_move_nonnull(CharGridCommand { - grid: unsafe { heap_remove(grid) }, + grid, origin: Origin::new(origin_x, origin_y), }) } /// Moves the provided [CharGrid] into a new [CharGridCommand], /// leaving other fields as their default values. - fn from_grid( - grid: NonNull, - ) -> NonNull { - heap_move_nonnull(unsafe { heap_remove(grid) }.into()) + fn from_grid(grid: move NonNull) -> NonNull { + heap_move_nonnull(grid.into()) } ); diff --git a/src/commands/cp437_grid_command.rs b/src/commands/cp437_grid_command.rs index b43afb4..921e2a4 100644 --- a/src/commands/cp437_grid_command.rs +++ b/src/commands/cp437_grid_command.rs @@ -1,7 +1,7 @@ use crate::{ commands::{wrap_command, wrap_origin_accessors}, macros::{wrap_fields, wrap_functions}, - mem::{heap_move_nonnull, heap_remove}, + mem::heap_move_nonnull, }; use servicepoint::{Cp437Grid, Cp437GridCommand, Origin}; use std::ptr::NonNull; @@ -22,22 +22,20 @@ wrap_functions!(associate Cp437GridCommand; /// /// The origin is relative to the top-left of the display. fn new( - grid: NonNull, - origin_x: usize, - origin_y: usize, + grid: move NonNull, + origin_x: val usize, + origin_y: val usize, ) -> NonNull { heap_move_nonnull(Cp437GridCommand { - grid: unsafe { heap_remove(grid) }, + grid, origin: Origin::new(origin_x, origin_y), }) } /// Moves the provided [Cp437Grid] into a new [Cp437GridCommand], /// leaving other fields as their default values. - fn from_grid( - grid: NonNull, - ) -> NonNull { - heap_move_nonnull(unsafe { heap_remove(grid) }.into()) + fn from_grid(grid: move NonNull) -> NonNull { + heap_move_nonnull(grid.into()) } ); diff --git a/src/commands/generic_command.rs b/src/commands/generic_command.rs index dad7584..efd402c 100644 --- a/src/commands/generic_command.rs +++ b/src/commands/generic_command.rs @@ -178,10 +178,7 @@ wrap_functions!(associate GenericCommand; /// The packet is dropped in the process. /// /// Returns: pointer to new [GenericCommand] instance or NULL if parsing failed. - fn try_from_packet( - packet: NonNull, - ) -> NonNull { - let packet = unsafe { heap_remove(packet) }; + fn try_from_packet(packet: move NonNull) -> NonNull { let result = servicepoint::TypedCommand::try_from(packet) .map(|value| match value { TypedCommand::Clear(clear) => GenericCommand { diff --git a/src/commands/global_brightness_command.rs b/src/commands/global_brightness_command.rs index 76cbeb5..d2fef10 100644 --- a/src/commands/global_brightness_command.rs +++ b/src/commands/global_brightness_command.rs @@ -11,7 +11,7 @@ wrap_functions!(associate GlobalBrightnessCommand; /// Set the brightness of all tiles to the same value. /// /// Returns: a new [GlobalBrightnessCommand] instance. - fn new(brightness: Brightness) -> NonNull { + fn new(brightness: val Brightness) -> NonNull { heap_move_nonnull(GlobalBrightnessCommand::from(brightness)) } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 026d0f1..da16c18 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -17,31 +17,22 @@ pub use generic_command::*; macro_rules! wrap_origin_accessors { ( $object_type:ident ) => { ::paste::paste! { - $crate::macros::wrap_functions!(associate $object_type; + $crate::macros::wrap_methods!($object_type; #[doc = " Reads the origin field of the [`" $object_type "`]."] fn get_origin( - command: ::core::ptr::NonNull<$object_type>, - origin_x: ::core::ptr::NonNull, - origin_y: ::core::ptr::NonNull, + ref command, + origin_x: mut ::core::ptr::NonNull, + origin_y: mut ::core::ptr::NonNull ) { - unsafe { - let origin = &command.as_ref().origin; - *origin_x.as_ptr() = origin.x; - *origin_y.as_ptr() = origin.y; - } - } + let origin = command.origin; + *origin_x = origin.x; + *origin_y = origin.y; + }; #[doc = " Overwrites the origin field of the [`" $object_type "`]."] - fn set_origin( - command: ::core::ptr::NonNull<$object_type>, - origin_x: usize, - origin_y: usize, - ) { - unsafe { - $crate::macros::nonnull_as_mut!(command).origin = - ::servicepoint::Origin::new(origin_x, origin_y); - } - } + fn set_origin(mut command, origin_x: val usize, origin_y: val usize) { + command.origin = ::servicepoint::Origin::new(origin_x, origin_y); + }; ); } }; diff --git a/src/containers/bitmap.rs b/src/containers/bitmap.rs index 4fb55a2..1386a8d 100644 --- a/src/containers/bitmap.rs +++ b/src/containers/bitmap.rs @@ -1,7 +1,7 @@ use crate::{ containers::{wrap_grid, ByteSlice}, - macros::{derive_clone, derive_free, wrap_functions, wrap_methods}, - mem::{heap_move_nonnull, heap_move_ok, heap_move_some, heap_remove}, + macros::{wrap_functions, wrap_methods}, + mem::{heap_move_nonnull, heap_move_ok, heap_move_some}, }; use servicepoint::{ Bitmap, BitmapCommand, CompressionCode, DataRef, DisplayBitVec, Grid, @@ -35,7 +35,7 @@ wrap_functions!(associate Bitmap; /// sp_bitmap_set(grid, 0, 0, false); /// sp_bitmap_free(grid); /// ``` - fn new(width: usize, height: usize) -> *mut Bitmap { + fn new(width: val usize, height: val usize) -> *mut Bitmap { heap_move_some(Bitmap::new(width, height)) } @@ -55,9 +55,9 @@ wrap_functions!(associate Bitmap; /// /// returns: [Bitmap] that contains a copy of the provided data, or NULL in case of an error. fn load( - width: usize, - height: usize, - data: ByteSlice, + width: val usize, + height: val usize, + data: val ByteSlice, ) -> *mut Bitmap { let data = unsafe { data.as_slice() }; heap_move_ok(Bitmap::load(width, height, data)) @@ -69,10 +69,9 @@ wrap_functions!(associate Bitmap; /// /// Returns NULL in case of error. fn from_bitvec( - width: usize, - bitvec: NonNull, + width: val usize, + bitvec: move NonNull, ) -> *mut Bitmap { - let bitvec = unsafe { heap_remove(bitvec) }; heap_move_ok(Bitmap::from_bitvec(width, bitvec)) } ); @@ -88,7 +87,7 @@ wrap_methods!(Bitmap; /// The provided [Bitmap] gets consumed. /// /// Returns NULL in case of an error. - fn try_into_packet(move bitmap, x: usize, y: usize, compression: CompressionCode) -> *mut Packet { + fn try_into_packet(move bitmap, x: val usize, y: val usize, compression: val CompressionCode) -> *mut Packet { heap_move_ok(Packet::try_from(BitmapCommand { bitmap, origin: Origin::new(x, y), diff --git a/src/containers/bitvec.rs b/src/containers/bitvec.rs index 6ae2cf6..cdb7c36 100644 --- a/src/containers/bitvec.rs +++ b/src/containers/bitvec.rs @@ -1,6 +1,6 @@ use crate::{ containers::{wrap_container, ByteSlice}, - macros::{derive_clone, derive_free, wrap_functions, wrap_methods}, + macros::{wrap_functions, wrap_methods}, mem::{heap_move_nonnull, heap_move_ok}, }; use servicepoint::{ @@ -23,14 +23,14 @@ wrap_functions!(associate DisplayBitVec; /// # Panics /// /// - when `size` is not divisible by 8. - fn new(size: usize) -> NonNull { + fn new(size: val usize) -> NonNull { heap_move_nonnull(DisplayBitVec::repeat(false, size)) } /// Interpret the data as a series of bits and load then into a new [DisplayBitVec] instance. /// /// returns: [DisplayBitVec] instance containing data. - fn load(data: ByteSlice) -> NonNull { + fn load(data: val ByteSlice) -> NonNull { let data = unsafe { data.as_slice() }; heap_move_nonnull(DisplayBitVec::from_slice(data)) } @@ -45,9 +45,9 @@ wrap_methods!(DisplayBitVec; /// Returns NULL in case of an error. fn try_into_packet( move bitvec, - offset: usize, - operation: BinaryOperation, - compression: CompressionCode + offset: val usize, + operation: val BinaryOperation, + compression: val CompressionCode ) -> *mut Packet { heap_move_ok(Packet::try_from(BitVecCommand { bitvec, @@ -69,7 +69,7 @@ wrap_methods!(DisplayBitVec; /// # Panics /// /// - when accessing `index` out of bounds - fn get(ref instance, index: usize) -> bool { + fn get(ref instance, index: val usize) -> bool { instance.get(index).map(|x| *x).unwrap_or(false) }; @@ -83,14 +83,14 @@ wrap_methods!(DisplayBitVec; /// # Panics /// /// - when accessing `index` out of bounds - fn set(mut instance, index: usize, value: bool); + fn set(mut instance, index: val usize, value: val bool); /// Sets the value of all bits. /// /// # Arguments /// /// - `value`: the value to set all bits to - fn fill(mut instance, value: bool); + fn fill(mut instance, value: val bool); /// Gets the length in bits. fn len(ref instance) -> usize; diff --git a/src/containers/brightness_grid.rs b/src/containers/brightness_grid.rs index a71a953..b0da48a 100644 --- a/src/containers/brightness_grid.rs +++ b/src/containers/brightness_grid.rs @@ -1,6 +1,6 @@ use crate::{ containers::{wrap_grid, ByteSlice}, - macros::{derive_clone, derive_free, wrap_functions, wrap_methods}, + macros::{wrap_functions, wrap_methods}, mem::{heap_move_nonnull, heap_move_ok, heap_move_some}, }; use servicepoint::{ @@ -30,10 +30,7 @@ wrap_functions!(associate BrightnessGrid; /// TypedCommand *command = sp_command_char_brightness(grid); /// sp_udp_free(connection); /// ``` - fn new( - width: usize, - height: usize, - ) -> NonNull { + fn new(width: val usize, height: val usize) -> NonNull { heap_move_nonnull(BrightnessGrid::new(width, height)) } @@ -43,9 +40,9 @@ wrap_functions!(associate BrightnessGrid; /// /// returns: new [BrightnessGrid] instance, or NULL in case of an error. fn load( - width: usize, - height: usize, - data: ByteSlice, + width: val usize, + height: val usize, + data: val ByteSlice, ) -> *mut BrightnessGrid { let data = unsafe { data.as_slice() }; heap_move_some( @@ -62,7 +59,7 @@ wrap_methods!(BrightnessGrid; /// The provided [BrightnessGrid] gets consumed. /// /// Returns NULL in case of an error. - fn try_into_packet(move grid, x: usize, y: usize) -> *mut Packet { + fn try_into_packet(move grid, x: val usize, y: val usize) -> *mut Packet { heap_move_ok(Packet::try_from(BrightnessGridCommand { grid, origin: Origin::new(x, y), diff --git a/src/containers/char_grid.rs b/src/containers/char_grid.rs index a360a26..715588f 100644 --- a/src/containers/char_grid.rs +++ b/src/containers/char_grid.rs @@ -1,6 +1,6 @@ use crate::{ containers::{derive_get_width_height, wrap_container, ByteSlice}, - macros::{derive_clone, derive_free, wrap_functions, wrap_methods}, + macros::{wrap_functions, wrap_methods}, mem::{heap_move_nonnull, heap_move_ok}, }; use servicepoint::{CharGrid, CharGridCommand, Grid, Origin, Packet}; @@ -23,14 +23,14 @@ wrap_functions!(associate CharGrid; /// sp_char_grid_set(grid, 0, 0, '!'); /// sp_char_grid_free(grid); /// ``` - fn new(width: usize, height: usize) -> NonNull { + fn new(width: val usize, height: val usize) -> NonNull { heap_move_nonnull(CharGrid::new(width, height)) } /// Loads a [CharGrid] with the specified dimensions from the provided data. /// /// returns: new CharGrid or NULL in case of an error - fn load(width: usize, height: usize, data: ByteSlice) -> *mut CharGrid { + fn load(width: val usize, height: val usize, data: val ByteSlice) -> *mut CharGrid { let data = unsafe { data.as_slice() }; heap_move_ok(CharGrid::load_utf8(width, height, data.to_vec())) } @@ -49,7 +49,7 @@ wrap_methods!(CharGrid; /// # Panics /// /// - when accessing `x` or `y` out of bounds - fn get(ref instance, x: usize, y: usize) -> u32 { + fn get(ref instance, x: val usize, y: val usize) -> u32 { instance.get(x, y) as u32 }; @@ -66,7 +66,7 @@ wrap_methods!(CharGrid; /// /// - when accessing `x` or `y` out of bounds /// - when providing values that cannot be converted to Rust's `char`. - fn set(mut instance, x: usize, y: usize, value: u32) { + fn set(mut instance, x: val usize, y: val usize, value: val u32) { instance.set(x, y, char::from_u32(value).unwrap()) }; @@ -76,7 +76,7 @@ wrap_methods!(CharGrid; /// /// - `value`: the value to set all cells to /// - when providing values that cannot be converted to Rust's `char`. - fn fill(mut instance, value: u32) { + fn fill(mut instance, value: val u32) { instance.fill(char::from_u32(value).unwrap()) }; @@ -85,7 +85,7 @@ wrap_methods!(CharGrid; /// The provided [CharGrid] gets consumed. /// /// Returns NULL in case of an error. - fn try_into_packet(move grid, x: usize, y: usize) -> *mut Packet { + fn try_into_packet(move grid, x: val usize, y: val usize) -> *mut Packet { heap_move_ok(Packet::try_from(CharGridCommand { grid, origin: Origin::new(x, y), diff --git a/src/containers/cp437_grid.rs b/src/containers/cp437_grid.rs index d4ed8a1..ecc36c6 100644 --- a/src/containers/cp437_grid.rs +++ b/src/containers/cp437_grid.rs @@ -1,6 +1,6 @@ use crate::{ containers::{wrap_grid, ByteSlice}, - macros::{derive_clone, derive_free, wrap_functions, wrap_methods}, + macros::{wrap_functions, wrap_methods}, mem::{heap_move_nonnull, heap_move_ok, heap_move_some}, }; use servicepoint::{ @@ -14,12 +14,12 @@ wrap_functions!(associate Cp437Grid; /// Creates a new [Cp437Grid] with the specified dimensions. /// /// returns: [Cp437Grid] initialized to 0. - fn new(width: usize, height: usize) -> NonNull { + fn new(width: val usize, height: val usize) -> NonNull { heap_move_nonnull(Cp437Grid::new(width, height)) } /// Loads a [Cp437Grid] with the specified dimensions from the provided data. - fn load(width: usize, height: usize, data: ByteSlice) -> *mut Cp437Grid { + fn load(width: val usize, height: val usize, data: val ByteSlice) -> *mut Cp437Grid { let data = unsafe { data.as_slice() }; heap_move_some(Cp437Grid::load(width, height, data)) } @@ -31,7 +31,7 @@ wrap_methods!(Cp437Grid; /// The provided [Cp437Grid] gets consumed. /// /// Returns NULL in case of an error. - fn try_into_packet(move grid, x: usize, y: usize) -> *mut Packet { + fn try_into_packet(move grid, x: val usize, y: val usize) -> *mut Packet { heap_move_ok(Packet::try_from(Cp437GridCommand { grid, origin: Origin::new(x, y), diff --git a/src/containers/mod.rs b/src/containers/mod.rs index 0a9eb38..35bbe3b 100644 --- a/src/containers/mod.rs +++ b/src/containers/mod.rs @@ -14,8 +14,8 @@ pub use cp437_grid::*; macro_rules! wrap_container { ($object_type:ident) => { - derive_clone!($object_type); - derive_free!($object_type); + $crate::macros::derive_clone!($object_type); + $crate::macros::derive_free!($object_type); }; } @@ -45,7 +45,7 @@ macro_rules! wrap_grid { /// # Panics /// /// - when accessing `x` or `y` out of bounds - fn get(ref instance, x: usize, y: usize) -> $value_type; + fn get(ref instance, x: val usize, y: val usize) -> $value_type; /// Sets the value of the specified position. /// @@ -57,14 +57,14 @@ macro_rules! wrap_grid { /// # Panics /// /// - when accessing `x` or `y` out of bounds - fn set(mut instance, x: usize, y: usize, value: $value_type); + fn set(mut instance, x: val usize, y: val usize, value: val $value_type); /// Sets the state of all cells in the grid. /// /// # Arguments /// /// - `value`: the value to set all cells to - fn fill(mut instance, value: $value_type); + fn fill(mut instance, value: val $value_type); } }; } diff --git a/src/macros.rs b/src/macros.rs index d2b974c..8cae819 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -3,8 +3,9 @@ macro_rules! derive_free { ::paste::paste! { $crate::macros::wrap_functions!([< $typ:lower >]; #[doc = "Deallocates a [`" $typ "`] instance."] - fn free(instance: ::core::ptr::NonNull<$typ>) { - unsafe { $crate::mem::heap_drop(instance) } + #[allow(dropping_copy_types)] + fn free(instance: move ::core::ptr::NonNull<$typ>) { + ::std::mem::drop(instance) } ); } @@ -16,8 +17,8 @@ macro_rules! derive_clone { ::paste::paste! { $crate::macros::wrap_functions!([< $typ:lower >]; #[doc = "Clones a [`" $typ "`] instance."] - fn clone(instance: ::core::ptr::NonNull<$typ>) -> ::core::ptr::NonNull<$typ> { - unsafe { $crate::mem::heap_clone(instance) } + fn clone(instance: ref ::core::ptr::NonNull<$typ>) -> ::core::ptr::NonNull<$typ> { + $crate::mem::heap_move_nonnull(instance.clone()) } ); } @@ -36,24 +37,18 @@ macro_rules! nonnull_as_mut { }; } -macro_rules! nonnull_as_move { - ($ident:ident) => { - $crate::mem::heap_remove($ident) - }; -} - macro_rules! wrap_method { ( $object_type:ident; $(#[$meta:meta])+ - fn $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_type:ty),*)?) + fn $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_modifier:ident $param_type:ty),*)?) $(-> $return_type:ty)? ) => { ::paste::paste!{ $crate::macros::wrap_method!( $object_type; $(#[$meta])+ - fn $function($ref_or_mut $instance $(, $($param_name: $param_type),*)?) + fn $function($ref_or_mut $instance $(, $($param_name: $param_modifier $param_type),*)?) $(-> $return_type)? { $instance.$function($($($param_name),*)?) } @@ -62,7 +57,7 @@ macro_rules! wrap_method { }; ($object_type:ident; $(#[$meta:meta])+ - fn $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_type:ty),*)?) + fn $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_modifier:ident $param_type:ty),*)?) $(-> $return_type:ty)? $impl:block ) => { @@ -72,12 +67,10 @@ macro_rules! wrap_method { /// $(#[$meta])* fn $function( - $instance: ::core::ptr::NonNull<$object_type> - $(,$($param_name: $param_type),*)? - ) $(-> $return_type)? { - let $instance = unsafe { $crate::macros:: [< nonnull_as_ $ref_or_mut >] !($instance) }; - $impl - } + $instance: $ref_or_mut ::core::ptr::NonNull<$object_type> + $(,$($param_name: $param_modifier $param_type),*)? + ) $(-> $return_type)? + $impl ); } }; @@ -88,7 +81,7 @@ macro_rules! wrap_methods { $object_type:ident; $( $(#[$meta:meta])+ - fn $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_type:ty),*)?) + fn $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_modifier:ident $param_type:ty),*)?) $(-> $return_type:ty)? $($impl:block)?; )+ @@ -97,7 +90,7 @@ macro_rules! wrap_methods { $( $crate::macros::wrap_method!($object_type; $(#[$meta])* - fn $function($ref_or_mut $instance $(, $($param_name: $param_type),*)?) + fn $function($ref_or_mut $instance $(, $($param_name: $param_modifier $param_type),*)?) $(-> $return_type)? $($impl)? ); @@ -109,45 +102,35 @@ macro_rules! wrap_methods { macro_rules! wrap_fields_accessor { (get; $object_type:ident :: $prop_name:ident : $prop_type:ty) => { paste::paste! { - $crate::macros::wrap_functions! {associate $object_type; + $crate::macros::wrap_method! {$object_type; #[doc = " Gets the value of field `" $prop_name "` of the [`servicepoint::" $object_type "`]."] - fn []( - instance: ::core::ptr::NonNull<$object_type> - ) -> $prop_type { - let $prop_name = unsafe { $crate::macros::nonnull_as_ref!(instance).$prop_name }; - return $prop_name; + fn [](ref instance) -> $prop_type { + return instance.$prop_name; } } } }; (mut get; $object_type:ident :: $prop_name:ident : $prop_type:ty) => { paste::paste! { - $crate::macros::wrap_functions! {associate $object_type; + $crate::macros::wrap_method! {$object_type; #[doc = " Gets a reference to the field `" $prop_name "` of the [`servicepoint::" $object_type "`]."] /// /// - The returned reference inherits the lifetime of object in which it is contained. /// - The returned pointer may not be used in a function that consumes the instance, e.g. to create a command. - fn []( - instance: ::core::ptr::NonNull<$object_type> - ) -> ::core::ptr::NonNull<$prop_type> { - let $prop_name = unsafe { &mut $crate::macros::nonnull_as_mut!(instance).$prop_name }; - return ::core::ptr::NonNull::from($prop_name); + fn [](mut instance) -> ::core::ptr::NonNull<$prop_type> { + return ::core::ptr::NonNull::from(&mut instance.$prop_name); } } } }; (set; $object_type:ident :: $prop_name:ident : $prop_type:ty) => { paste::paste! { - $crate::macros::wrap_functions! {associate $object_type; + $crate::macros::wrap_method! {$object_type; #[doc = " Sets the value of field `" $prop_name "` of the [`servicepoint::" $object_type "`]."] - fn []( - instance: ::core::ptr::NonNull<$object_type>, - value: $prop_type, - ) { - let instance = unsafe { $crate::macros::nonnull_as_mut!(instance) }; + fn [](mut instance, value: val $prop_type) { instance.$prop_name = value; } } @@ -155,17 +138,12 @@ macro_rules! wrap_fields_accessor { }; (move set; $object_type:ident :: $prop_name:ident : $prop_type:ty) => { paste::paste! { - $crate::macros::wrap_functions! {associate $object_type; + $crate::macros::wrap_method! {$object_type; #[doc = " Sets the value of field `" $prop_name "` of the [`servicepoint::" $object_type "`]."] /// The provided value is moved into the instance, potentially invalidating previously taken references. - fn []( - instance: ::core::ptr::NonNull<$object_type>, - value: ::core::ptr::NonNull<$prop_type>, - ) { - let instance = unsafe { $crate::macros::nonnull_as_mut!(instance) }; - let $prop_name = unsafe { $crate::mem::heap_remove(value) }; - instance.$prop_name = $prop_name; + fn [](mut instance, value: move ::core::ptr::NonNull<$prop_type>) { + instance.$prop_name = value; } } } @@ -190,18 +168,30 @@ macro_rules! wrap_fields { }; } -macro_rules! wrap_functions { +macro_rules! apply_param_modifier { + (move, $param_name:ident) => { + unsafe { $crate::mem::heap_remove($param_name) } + }; + (val, $param_name:ident) => { + $param_name + }; + (mut, $param_name:ident) => { + unsafe { $crate::macros::nonnull_as_mut!($param_name) } + }; + (ref, $param_name:ident) => { + unsafe { $crate::macros::nonnull_as_ref!($param_name) } + }; +} + +macro_rules! wrap_function { ( $module:ident; - $( - $(#[$meta:meta])+ - fn $function:ident($($param_name:ident: $param_type:ty),*$(,)?) - $(-> $return_type:ty)? - $block:block - )+ + $(#[$meta:meta])+ + fn $function:ident($($param_name:ident: $param_modifier:ident $param_type:ty),*$(,)?) + $(-> $return_type:ty)? + $block:block ) => { ::paste::paste! { - $( $(#[$meta])* #[doc = ""] #[doc = " This function is part of the `" $module "` module."] @@ -209,7 +199,33 @@ macro_rules! wrap_functions { pub unsafe extern "C" fn [< sp_ $module _ $function >]( $($param_name: $param_type),* ) $(-> $return_type)? - $block + { + $( + let $param_name = $crate::macros::apply_param_modifier!($param_modifier, $param_name); + )* + $block + } + } + } +} + +macro_rules! wrap_functions { + ( + $module:ident; + $( + $(#[$meta:meta])+ + fn $function:ident($($param_name:ident: $param_modifier:ident $param_type:ty),*$(,)?) + $(-> $return_type:ty)? + $block:block + )+ + ) => { + ::paste::paste! { + $( + $crate::macros::wrap_function!($module; + $(#[$meta])+ + fn $function($($param_name: $param_modifier $param_type),*) $(-> $return_type)? + $block + ); )+ } }; @@ -217,7 +233,7 @@ macro_rules! wrap_functions { associate $object_type:ident; $( $(#[$meta:meta])+ - fn $function:ident($($param_name:ident: $param_type:ty),*$(,)?) + fn $function:ident($($param_name:ident: $param_modifier:ident $param_type:ty),*$(,)?) $(-> $return_type:ty)? $block:block )+ @@ -226,7 +242,7 @@ macro_rules! wrap_functions { $crate::macros::wrap_functions!{[< $object_type:lower >]; $( $(#[$meta])+ - fn $function($($param_name: $param_type),*) $(-> $return_type)? + fn $function($($param_name: $param_modifier $param_type),*) $(-> $return_type)? $block )+ } @@ -235,7 +251,7 @@ macro_rules! wrap_functions { } pub(crate) use { - derive_clone, derive_free, nonnull_as_move, nonnull_as_mut, nonnull_as_ref, - wrap_fields, wrap_fields_accessor, wrap_functions, wrap_method, - wrap_methods, + apply_param_modifier, derive_clone, derive_free, nonnull_as_mut, + nonnull_as_ref, wrap_fields, wrap_fields_accessor, wrap_function, + wrap_functions, wrap_method, wrap_methods, }; diff --git a/src/packet.rs b/src/packet.rs index 28ade85..5dc172d 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,17 +1,18 @@ use crate::{ containers::ByteSlice, - macros::{derive_clone, derive_free, wrap_fields, wrap_functions}, + macros::{ + derive_clone, derive_free, wrap_fields, wrap_functions, wrap_methods, + }, mem::{heap_move_nonnull, heap_move_ok}, }; use servicepoint::{CommandCode, Header, Packet}; use std::ptr::NonNull; -wrap_functions!(packet; - +wrap_functions!(associate Packet; /// Tries to load a [Packet] from the passed array with the specified length. /// /// returns: NULL in case of an error, pointer to the allocated packet otherwise - fn try_load(data: ByteSlice) -> *mut Packet { + fn try_load(data: val ByteSlice) -> *mut Packet { let data = unsafe { data.as_slice() }; heap_move_ok(servicepoint::Packet::try_from(data)) } @@ -19,7 +20,7 @@ wrap_functions!(packet; /// Creates a raw [Packet] from parts. /// /// returns: new instance. Will never return null. - fn from_parts(header: Header, payload: ByteSlice) -> NonNull { + fn from_parts(header: val Header, payload: val ByteSlice) -> NonNull { let payload = if payload == ByteSlice::INVALID { None } else { @@ -28,44 +29,6 @@ wrap_functions!(packet; heap_move_nonnull(Packet { header, payload }) } - - /// Returns a pointer to the current payload of the provided packet. - /// - /// Returns an [ByteSlice::INVALID] instance in case the packet does not have any payload. - /// - /// The returned memory can be changed and will be valid until a new payload is set. - fn get_payload(packet: NonNull) -> ByteSlice { - unsafe { - match &mut (*packet.as_ptr()).payload { - None => ByteSlice::INVALID, - Some(payload) => ByteSlice::from_slice(payload), - } - } - } - - /// Sets the payload of the provided packet to the provided data. - /// - /// This makes previous payload pointers invalid. - fn set_payload(packet: NonNull, data: ByteSlice) { - unsafe { - (*packet.as_ptr()).payload = if data == ByteSlice::INVALID { - None - } else { - Some(data.as_slice().to_vec()) - } - } - } - - /// Serialize the packet into the provided buffer. - /// - /// # Panics - /// - /// - if the buffer is not big enough to hold header+payload. - fn serialize_to(packet: NonNull, buffer: ByteSlice) -> usize { - unsafe { - packet.as_ref().serialize_to(buffer.as_slice_mut()).unwrap_or(0) - } - } ); derive_clone!(Packet); @@ -75,20 +38,51 @@ wrap_fields!(Packet; prop header: Header { get; get mut; set; }; ); +wrap_methods! { Packet; + /// Returns a pointer to the current payload of the provided packet. + /// + /// Returns an [ByteSlice::INVALID] instance in case the packet does not have any payload. + /// + /// The returned memory can be changed and will be valid until a new payload is set. + fn get_payload(mut packet) -> ByteSlice { + match &mut packet.payload { + None => ByteSlice::INVALID, + Some(payload) => unsafe { ByteSlice::from_slice(payload) }, + } + }; + + /// Sets the payload of the provided packet to the provided data. + /// + /// This makes previous payload pointers invalid. + fn set_payload(mut packet, data: val ByteSlice) { + packet.payload = if data == ByteSlice::INVALID { + None + } else { + Some(unsafe { data.as_slice().to_vec() }) + } + }; + + /// Serialize the packet into the provided buffer. + /// + /// # Panics + /// + /// - if the buffer is not big enough to hold header+payload. + fn serialize_to(mut packet, buffer: val ByteSlice) -> usize { + unsafe { + packet.serialize_to(buffer.as_slice_mut()).unwrap_or(0) + } + }; +} + wrap_functions!(sp; /// Converts u16 into [CommandCode]. /// /// If the provided value is not valid, false is returned and result is not changed. - fn u16_to_command_code( - code: u16, - result: *mut CommandCode, - ) -> bool { + fn u16_to_command_code(code: val u16, result: mut NonNull) -> bool { match CommandCode::try_from(code) { Ok(code) => { - unsafe { - *result = code; - } + *result = code; true } Err(_) => false, diff --git a/src/udp.rs b/src/udp.rs index aa307b0..13718f4 100644 --- a/src/udp.rs +++ b/src/udp.rs @@ -25,7 +25,7 @@ wrap_functions!(associate UdpSocket; /// if (connection != NULL) /// sp_udp_send_command(connection, sp_command_clear()); /// ``` - fn open(host: NonNull) -> *mut UdpSocket { + fn open(host: val NonNull) -> *mut UdpSocket { let host = unsafe { CStr::from_ptr(host.as_ptr()) } .to_str() .expect("Bad encoding"); @@ -44,7 +44,7 @@ wrap_functions!(associate UdpSocket; /// if (connection != NULL) /// sp_udp_send_command(connection, sp_command_clear()); /// ``` - fn open_ipv4(ip1: u8, ip2: u8, ip3: u8, ip4: u8, port: u16) -> *mut UdpSocket { + fn open_ipv4(ip1: val u8, ip2: val u8, ip3: val u8, ip4: val u8, port: val u16) -> *mut UdpSocket { let addr = SocketAddrV4::new(Ipv4Addr::from([ip1, ip2, ip3, ip4]), port); heap_move_ok(UdpSocket::bind_connect(addr)) } @@ -57,8 +57,7 @@ wrap_methods! {UdpSocket; /// The passed `packet` gets consumed. /// /// returns: true in case of success - fn send_packet(ref connection, packet: NonNull) -> bool { - let packet = unsafe { heap_remove(packet) }; + fn send_packet(ref connection, packet: move NonNull) -> bool { connection.send(&Vec::from(packet)).is_ok() }; @@ -73,9 +72,8 @@ wrap_methods! {UdpSocket; /// ```C /// sp_udp_send_command(connection, sp_command_brightness(5)); /// ``` - fn send_command(ref connection, command: NonNull) -> bool { + fn send_command(ref connection, command: mut NonNull) -> bool { unsafe { - let command = crate::macros::nonnull_as_mut!(command); let result = match command.tag { CommandTag::Invalid => return false, CommandTag::Bitmap => connection.send_command(heap_remove(command.data.bitmap)), @@ -103,7 +101,7 @@ wrap_methods! {UdpSocket; /// ```C /// sp_udp_send_header(connection, sp_command_brightness(5)); /// ``` - fn send_header(ref udp_connection, header: Header) -> bool { + fn send_header(ref udp_connection, header: val Header) -> bool { let packet = Packet { header, payload: None,