wip generic wrap

This commit is contained in:
Vinzenz Schroeter 2025-06-26 20:42:31 +02:00
parent 82696b2d1a
commit 5beea6151a
15 changed files with 83 additions and 59 deletions

View file

@ -1,13 +1,13 @@
use crate::{ use crate::{
commands::{wrap_command, wrap_origin_accessors}, commands::{wrap_command, wrap_origin_accessors},
macros::{wrap_fields, wrap_functions}, macros::{wrap, wrap_functions},
}; };
use servicepoint::{Bitmap, BitmapCommand, CompressionCode, Origin}; use servicepoint::{Bitmap, BitmapCommand, CompressionCode, Origin};
use std::ptr::NonNull; use std::ptr::NonNull;
wrap_command!(Bitmap); wrap_command!(Bitmap);
wrap_fields!(BitmapCommand; wrap!(BitmapCommand;
prop bitmap: Bitmap { get mut; set move; }; prop bitmap: Bitmap { get mut; set move; };
prop compression: CompressionCode { get; set; }; prop compression: CompressionCode { get; set; };
); );

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
commands::wrap_command, commands::wrap_command,
macros::{wrap_fields, wrap_functions}, macros::{wrap, wrap_functions},
}; };
use servicepoint::{ use servicepoint::{
BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Offset, BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Offset,
@ -9,7 +9,7 @@ use std::ptr::NonNull;
wrap_command!(BitVec); wrap_command!(BitVec);
wrap_fields!(BitVecCommand; wrap!(BitVecCommand;
prop bitvec: DisplayBitVec { get mut; set move; }; prop bitvec: DisplayBitVec { get mut; set move; };
prop offset: Offset { get; set; }; prop offset: Offset { get; set; };
prop operation: BinaryOperation { get; set; }; prop operation: BinaryOperation { get; set; };

View file

@ -1,13 +1,13 @@
use crate::{ use crate::{
commands::{wrap_command, wrap_origin_accessors}, commands::{wrap_command, wrap_origin_accessors},
macros::{wrap_fields, wrap_functions}, macros::{wrap, wrap_functions},
}; };
use servicepoint::{BrightnessGrid, BrightnessGridCommand, Origin}; use servicepoint::{BrightnessGrid, BrightnessGridCommand, Origin};
use std::ptr::NonNull; use std::ptr::NonNull;
wrap_command!(BrightnessGrid); wrap_command!(BrightnessGrid);
wrap_fields!(BrightnessGridCommand; wrap!(BrightnessGridCommand;
prop grid: BrightnessGrid { get mut; set move; }; prop grid: BrightnessGrid { get mut; set move; };
); );

View file

@ -1,13 +1,13 @@
use crate::{ use crate::{
commands::{wrap_command, wrap_origin_accessors}, commands::{wrap_command, wrap_origin_accessors},
macros::{wrap_fields, wrap_functions}, macros::{wrap, wrap_functions},
}; };
use servicepoint::{CharGrid, CharGridCommand, Origin}; use servicepoint::{CharGrid, CharGridCommand, Origin};
use std::ptr::NonNull; use std::ptr::NonNull;
wrap_command!(CharGrid); wrap_command!(CharGrid);
wrap_fields!(CharGridCommand; wrap!(CharGridCommand;
prop grid: CharGrid { get mut; set move; }; prop grid: CharGrid { get mut; set move; };
); );

View file

@ -1,13 +1,13 @@
use crate::{ use crate::{
commands::{wrap_command, wrap_origin_accessors}, commands::{wrap_command, wrap_origin_accessors},
macros::{wrap_fields, wrap_functions}, macros::{wrap, wrap_functions},
}; };
use servicepoint::{Cp437Grid, Cp437GridCommand, Origin}; use servicepoint::{Cp437Grid, Cp437GridCommand, Origin};
use std::ptr::NonNull; use std::ptr::NonNull;
wrap_command!(Cp437Grid); wrap_command!(Cp437Grid);
wrap_fields!(Cp437GridCommand; wrap!(Cp437GridCommand;
prop grid: Cp437Grid { get mut; set move; }; prop grid: Cp437Grid { get mut; set move; };
); );

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
macros::{derive_clone, derive_free, wrap_functions, wrap_methods}, macros::{derive_clone, derive_free, wrap, wrap_functions},
mem::{ mem::{
heap_clone, heap_drop, heap_move, heap_move_nonnull, heap_move_ok, heap_clone, heap_drop, heap_move, heap_move_nonnull, heap_move_ok,
heap_remove, heap_remove,
@ -250,12 +250,12 @@ wrap_functions!(associate GenericCommand;
}; };
); );
wrap_methods! { GenericCommand; wrap! { GenericCommand;
/// Tries to turn a [GenericCommand] into a [Packet]. /// Tries to turn a [GenericCommand] into a [Packet].
/// The [GenericCommand] gets consumed. /// The [GenericCommand] gets consumed.
/// ///
/// Returns tag [CommandTag::Invalid] in case of an error. /// Returns tag [CommandTag::Invalid] in case of an error.
fn try_into_packet(move command) -> val *mut Packet { method try_into_packet(move command) -> val *mut Packet {
match command.tag { match command.tag {
CommandTag::Invalid => null_mut(), CommandTag::Invalid => null_mut(),
CommandTag::Bitmap => { CommandTag::Bitmap => {

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
commands::wrap_command, commands::wrap_command,
macros::{wrap_fields, wrap_functions}, macros::{wrap, wrap_functions},
}; };
use servicepoint::{Brightness, GlobalBrightnessCommand}; use servicepoint::{Brightness, GlobalBrightnessCommand};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -16,6 +16,6 @@ wrap_functions!(associate GlobalBrightnessCommand;
wrap_command!(GlobalBrightness); wrap_command!(GlobalBrightness);
wrap_fields!(GlobalBrightnessCommand; wrap!(GlobalBrightnessCommand;
prop brightness: Brightness { get; set; }; prop brightness: Brightness { get; set; };
); );

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
containers::{wrap_grid, ByteSlice}, containers::{wrap_grid, ByteSlice},
macros::{wrap_functions, wrap_methods}, macros::{wrap, wrap_functions},
}; };
use servicepoint::{ use servicepoint::{
Bitmap, BitmapCommand, CompressionCode, DataRef, DisplayBitVec, Grid, Bitmap, BitmapCommand, CompressionCode, DataRef, DisplayBitVec, Grid,
@ -74,9 +74,9 @@ wrap_functions!(associate Bitmap;
}; };
); );
wrap_methods!(Bitmap; wrap!(Bitmap;
/// Consumes the Bitmap and returns the contained BitVec. /// Consumes the Bitmap and returns the contained BitVec.
fn into_bitvec(move bitmap) -> move NonNull<DisplayBitVec> { method into_bitvec(move bitmap) -> move NonNull<DisplayBitVec> {
bitmap.into() bitmap.into()
}; };
@ -85,7 +85,7 @@ wrap_methods!(Bitmap;
/// The provided [Bitmap] gets consumed. /// The provided [Bitmap] gets consumed.
/// ///
/// Returns NULL in case of an error. /// Returns NULL in case of an error.
fn try_into_packet(move bitmap, x: val usize, y: val usize, compression: val CompressionCode) -> move_ok *mut Packet { method try_into_packet(move bitmap, x: val usize, y: val usize, compression: val CompressionCode) -> move_ok *mut Packet {
Packet::try_from(BitmapCommand { Packet::try_from(BitmapCommand {
bitmap, bitmap,
origin: Origin::new(x, y), origin: Origin::new(x, y),
@ -96,5 +96,5 @@ wrap_methods!(Bitmap;
/// Gets an unsafe reference to the data of the [Bitmap] instance. /// Gets an unsafe reference to the data of the [Bitmap] instance.
/// ///
/// The returned memory is valid for the lifetime of the bitmap. /// The returned memory is valid for the lifetime of the bitmap.
fn data_ref_mut(mut instance) -> slice ByteSlice; method data_ref_mut(mut instance) -> slice ByteSlice;
); );

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
containers::{wrap_container, ByteSlice}, containers::{wrap_container, ByteSlice},
macros::{wrap_functions, wrap_methods}, macros::{wrap, wrap_functions},
}; };
use servicepoint::{ use servicepoint::{
BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Packet, BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Packet,
@ -33,13 +33,13 @@ wrap_functions!(associate DisplayBitVec;
}; };
); );
wrap_methods!(DisplayBitVec; wrap!(DisplayBitVec;
/// Creates a [BitVecCommand] and immediately turns that into a [Packet]. /// Creates a [BitVecCommand] and immediately turns that into a [Packet].
/// ///
/// The provided [DisplayBitVec] gets consumed. /// The provided [DisplayBitVec] gets consumed.
/// ///
/// Returns NULL in case of an error. /// Returns NULL in case of an error.
fn try_into_packet( method try_into_packet(
move bitvec, move bitvec,
offset: val usize, offset: val usize,
operation: val BinaryOperation, operation: val BinaryOperation,
@ -65,7 +65,7 @@ wrap_methods!(DisplayBitVec;
/// # Panics /// # Panics
/// ///
/// - when accessing `index` out of bounds /// - when accessing `index` out of bounds
fn get(ref instance, index: val usize) -> val bool { method get(ref instance, index: val usize) -> val bool {
instance.get(index).map(|x| *x).unwrap_or(false) instance.get(index).map(|x| *x).unwrap_or(false)
}; };
@ -79,23 +79,23 @@ wrap_methods!(DisplayBitVec;
/// # Panics /// # Panics
/// ///
/// - when accessing `index` out of bounds /// - when accessing `index` out of bounds
fn set(mut instance, index: val usize, value: val bool); method set(mut instance, index: val usize, value: val bool);
/// Sets the value of all bits. /// Sets the value of all bits.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - `value`: the value to set all bits to /// - `value`: the value to set all bits to
fn fill(mut instance, value: val bool); method fill(mut instance, value: val bool);
/// Gets the length in bits. /// Gets the length in bits.
fn len(ref instance) -> val usize; method len(ref instance) -> val usize;
/// Returns true if length is 0. /// Returns true if length is 0.
fn is_empty(ref instance) -> val bool; method is_empty(ref instance) -> val bool;
/// Gets an unsafe reference to the data of the [DisplayBitVec] instance. /// Gets an unsafe reference to the data of the [DisplayBitVec] instance.
/// ///
/// The returned memory is valid for the lifetime of the bitvec. /// The returned memory is valid for the lifetime of the bitvec.
fn as_raw_mut_slice(mut instance) -> slice ByteSlice; method as_raw_mut_slice(mut instance) -> slice ByteSlice;
); );

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
containers::{wrap_grid, ByteSlice}, containers::{wrap_grid, ByteSlice},
macros::{wrap_functions, wrap_methods}, macros::{wrap, wrap_functions},
}; };
use servicepoint::{ use servicepoint::{
Brightness, BrightnessGrid, BrightnessGridCommand, ByteGrid, DataRef, Grid, Brightness, BrightnessGrid, BrightnessGridCommand, ByteGrid, DataRef, Grid,
@ -47,13 +47,13 @@ wrap_functions!(associate BrightnessGrid;
}; };
); );
wrap_methods!(BrightnessGrid; wrap!(BrightnessGrid;
/// Creates a [BrightnessGridCommand] and immediately turns that into a [Packet]. /// Creates a [BrightnessGridCommand] and immediately turns that into a [Packet].
/// ///
/// The provided [BrightnessGrid] gets consumed. /// The provided [BrightnessGrid] gets consumed.
/// ///
/// Returns NULL in case of an error. /// Returns NULL in case of an error.
fn try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet { method try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet {
Packet::try_from(BrightnessGridCommand { Packet::try_from(BrightnessGridCommand {
grid, grid,
origin: Origin::new(x, y), origin: Origin::new(x, y),
@ -63,7 +63,7 @@ wrap_methods!(BrightnessGrid;
/// Gets an unsafe reference to the data of the instance. /// Gets an unsafe reference to the data of the instance.
/// ///
/// The returned memory is valid for the lifetime of the grid. /// The returned memory is valid for the lifetime of the grid.
fn data_ref_mut(mut instance) -> slice ByteSlice { method data_ref_mut(mut instance) -> slice ByteSlice {
//noinspection RsAssertEqual //noinspection RsAssertEqual
const _: () = assert!(size_of::<Brightness>() == 1); const _: () = assert!(size_of::<Brightness>() == 1);

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
containers::{derive_get_width_height, wrap_container, ByteSlice}, containers::{derive_get_width_height, wrap_container, ByteSlice},
macros::{wrap_functions, wrap_methods}, macros::{wrap, wrap_functions},
}; };
use servicepoint::{CharGrid, CharGridCommand, Grid, Origin, Packet}; use servicepoint::{CharGrid, CharGridCommand, Grid, Origin, Packet};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -33,8 +33,7 @@ wrap_functions!(associate CharGrid;
}; };
); );
wrap_methods!(CharGrid; wrap!(CharGrid;
/// Returns the current value at the specified position. /// Returns the current value at the specified position.
/// ///
/// # Arguments /// # Arguments
@ -44,7 +43,7 @@ wrap_methods!(CharGrid;
/// # Panics /// # Panics
/// ///
/// - when accessing `x` or `y` out of bounds /// - when accessing `x` or `y` out of bounds
fn get(ref instance, x: val usize, y: val usize) -> val u32 { method get(ref instance, x: val usize, y: val usize) -> val u32 {
instance.get(x, y) as u32 instance.get(x, y) as u32
}; };
@ -61,7 +60,7 @@ wrap_methods!(CharGrid;
/// ///
/// - when accessing `x` or `y` out of bounds /// - when accessing `x` or `y` out of bounds
/// - when providing values that cannot be converted to Rust's `char`. /// - when providing values that cannot be converted to Rust's `char`.
fn set(mut instance, x: val usize, y: val usize, value: val u32) { method set(mut instance, x: val usize, y: val usize, value: val u32) {
instance.set(x, y, char::from_u32(value).unwrap()) instance.set(x, y, char::from_u32(value).unwrap())
}; };
@ -71,7 +70,7 @@ wrap_methods!(CharGrid;
/// ///
/// - `value`: the value to set all cells to /// - `value`: the value to set all cells to
/// - when providing values that cannot be converted to Rust's `char`. /// - when providing values that cannot be converted to Rust's `char`.
fn fill(mut instance, value: val u32) { method fill(mut instance, value: val u32) {
instance.fill(char::from_u32(value).unwrap()) instance.fill(char::from_u32(value).unwrap())
}; };
@ -80,7 +79,7 @@ wrap_methods!(CharGrid;
/// The provided [CharGrid] gets consumed. /// The provided [CharGrid] gets consumed.
/// ///
/// Returns NULL in case of an error. /// Returns NULL in case of an error.
fn try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet { method try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet {
Packet::try_from(CharGridCommand { Packet::try_from(CharGridCommand {
grid, grid,
origin: Origin::new(x, y), origin: Origin::new(x, y),

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
containers::{wrap_grid, ByteSlice}, containers::{wrap_grid, ByteSlice},
macros::{wrap_functions, wrap_methods}, macros::{wrap, wrap_functions},
}; };
use servicepoint::{ use servicepoint::{
Cp437Grid, Cp437GridCommand, DataRef, Grid, Origin, Packet, Cp437Grid, Cp437GridCommand, DataRef, Grid, Origin, Packet,
@ -23,13 +23,13 @@ wrap_functions!(associate Cp437Grid;
}; };
); );
wrap_methods!(Cp437Grid; wrap!(Cp437Grid;
/// Creates a [Cp437GridCommand] and immediately turns that into a [Packet]. /// Creates a [Cp437GridCommand] and immediately turns that into a [Packet].
/// ///
/// The provided [Cp437Grid] gets consumed. /// The provided [Cp437Grid] gets consumed.
/// ///
/// Returns NULL in case of an error. /// Returns NULL in case of an error.
fn try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet { method try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet {
Packet::try_from(Cp437GridCommand { Packet::try_from(Cp437GridCommand {
grid, grid,
origin: Origin::new(x, y), origin: Origin::new(x, y),
@ -39,5 +39,5 @@ wrap_methods!(Cp437Grid;
/// Gets an unsafe reference to the data of the grid. /// Gets an unsafe reference to the data of the grid.
/// ///
/// The returned memory is valid for the lifetime of the instance. /// The returned memory is valid for the lifetime of the instance.
fn data_ref_mut(mut instance) -> slice ByteSlice; method data_ref_mut(mut instance) -> slice ByteSlice;
); );

View file

@ -263,8 +263,37 @@ macro_rules! wrap_functions {
}; };
} }
macro_rules! wrap {
(
$object_type:ident;
$(
prop $prop_name:ident : $prop_type:ty { $($accessor:ident $($modifier:ident)?;)+ };
)*
$(
$(#[$meta:meta])+
method $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_modifier:ident $param_type:ty),*)?)
$(-> $return_modifier:ident $return_type:ty)?
$($impl:block)?;
)*
) => {
$(
$crate::macros::wrap_fields!($object_type;
prop $prop_name : $prop_type { $($accessor $($modifier)?;)+ };
);
)*
$(
$crate::macros::wrap_method!($object_type;
$(#[$meta])+
fn $function($ref_or_mut $instance $(, $($param_name: $param_modifier $param_type),*)?)
$(-> $return_modifier $return_type)?
$($impl)?;
);
)*
};
}
pub(crate) use { pub(crate) use {
apply_param_modifier, apply_return_modifier, derive_clone, derive_free, apply_param_modifier, apply_return_modifier, derive_clone, derive_free,
wrap_fields, wrap_fields_accessor, wrap_function, wrap_functions, wrap, wrap_fields, wrap_fields_accessor, wrap_function, wrap_functions,
wrap_method, wrap_methods, wrap_method, wrap_methods,
}; };

View file

@ -1,8 +1,6 @@
use crate::{ use crate::{
containers::ByteSlice, containers::ByteSlice,
macros::{ macros::{derive_clone, derive_free, wrap, wrap_functions},
derive_clone, derive_free, wrap_fields, wrap_functions, wrap_methods,
},
}; };
use servicepoint::{CommandCode, Header, Packet}; use servicepoint::{CommandCode, Header, Packet};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -32,17 +30,15 @@ wrap_functions!(associate Packet;
derive_clone!(Packet); derive_clone!(Packet);
derive_free!(Packet); derive_free!(Packet);
wrap_fields!(Packet; wrap! {Packet;
prop header: Header { get; get mut; set; }; prop header: Header { get; get mut; set; };
);
wrap_methods! { Packet;
/// Returns a pointer to the current payload of the provided 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. /// 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. /// The returned memory can be changed and will be valid until a new payload is set.
fn get_payload(mut packet) -> val ByteSlice { method get_payload(mut packet) -> val ByteSlice {
match &mut packet.payload { match &mut packet.payload {
None => ByteSlice::INVALID, None => ByteSlice::INVALID,
Some(payload) => unsafe { ByteSlice::from_slice(payload) }, Some(payload) => unsafe { ByteSlice::from_slice(payload) },
@ -52,7 +48,7 @@ wrap_methods! { Packet;
/// Sets the payload of the provided packet to the provided data. /// Sets the payload of the provided packet to the provided data.
/// ///
/// This makes previous payload pointers invalid. /// This makes previous payload pointers invalid.
fn set_payload(mut packet, data: val ByteSlice) { method set_payload(mut packet, data: val ByteSlice) {
packet.payload = if data == ByteSlice::INVALID { packet.payload = if data == ByteSlice::INVALID {
None None
} else { } else {
@ -65,7 +61,7 @@ wrap_methods! { Packet;
/// # Panics /// # Panics
/// ///
/// - if the buffer is not big enough to hold header+payload. /// - if the buffer is not big enough to hold header+payload.
fn serialize_to(mut packet, buffer: val ByteSlice) -> val usize { method serialize_to(mut packet, buffer: val ByteSlice) -> val usize {
unsafe { unsafe {
packet.serialize_to(buffer.as_slice_mut()).unwrap_or(0) packet.serialize_to(buffer.as_slice_mut()).unwrap_or(0)
} }

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
commands::{CommandTag, GenericCommand}, commands::{CommandTag, GenericCommand},
macros::{derive_free, wrap_functions, wrap_methods}, macros::{derive_free, wrap, wrap_functions},
mem::heap_remove, mem::heap_remove,
}; };
use servicepoint::{Header, Packet, UdpSocketExt}; use servicepoint::{Header, Packet, UdpSocketExt};
@ -48,13 +48,13 @@ wrap_functions!(associate UdpSocket;
}; };
); );
wrap_methods! {UdpSocket; wrap! {UdpSocket;
/// Sends a [Packet] to the display using the [UdpSocket]. /// Sends a [Packet] to the display using the [UdpSocket].
/// ///
/// The passed `packet` gets consumed. /// The passed `packet` gets consumed.
/// ///
/// returns: true in case of success /// returns: true in case of success
fn send_packet(ref connection, packet: move NonNull<Packet>) -> val bool { method send_packet(ref connection, packet: move NonNull<Packet>) -> val bool {
connection.send(&Vec::from(packet)).is_ok() connection.send(&Vec::from(packet)).is_ok()
}; };
@ -69,7 +69,7 @@ wrap_methods! {UdpSocket;
/// ```C /// ```C
/// sp_udp_send_command(connection, sp_command_brightness(5)); /// sp_udp_send_command(connection, sp_command_brightness(5));
/// ``` /// ```
fn send_command(ref connection, command: mut NonNull<GenericCommand>) -> val bool { method send_command(ref connection, command: mut NonNull<GenericCommand>) -> val bool {
unsafe { unsafe {
let result = match command.tag { let result = match command.tag {
CommandTag::Invalid => return false, CommandTag::Invalid => return false,
@ -98,7 +98,7 @@ wrap_methods! {UdpSocket;
/// ```C /// ```C
/// sp_udp_send_header(connection, sp_command_brightness(5)); /// sp_udp_send_header(connection, sp_command_brightness(5));
/// ``` /// ```
fn send_header(ref udp_connection, header: val Header) -> val bool { method send_header(ref udp_connection, header: val Header) -> val bool {
let packet = Packet { let packet = Packet {
header, header,
payload: None, payload: None,