implement return modifiers

This commit is contained in:
Vinzenz Schroeter 2025-06-26 18:59:46 +02:00
parent 0968605d0b
commit 39c7c27c86
18 changed files with 144 additions and 146 deletions

View file

@ -1,7 +1,6 @@
use crate::{ use crate::{
commands::{wrap_command, wrap_origin_accessors}, commands::{wrap_command, wrap_origin_accessors},
macros::{wrap_fields, wrap_functions}, macros::{wrap_fields, wrap_functions},
mem::heap_move_nonnull,
}; };
use servicepoint::{Bitmap, BitmapCommand, CompressionCode, Origin}; use servicepoint::{Bitmap, BitmapCommand, CompressionCode, Origin};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -26,19 +25,19 @@ wrap_functions!(associate BitmapCommand;
origin_x: val usize, origin_x: val usize,
origin_y: val usize, origin_y: val usize,
compression: val CompressionCode, compression: val CompressionCode,
) -> NonNull<BitmapCommand> { ) -> move NonNull<BitmapCommand> {
heap_move_nonnull(BitmapCommand { BitmapCommand {
bitmap, bitmap,
origin: Origin::new(origin_x, origin_y), origin: Origin::new(origin_x, origin_y),
compression, compression,
}) }
}; };
/// Move the provided [Bitmap] into a new [BitmapCommand], /// Move the provided [Bitmap] into a new [BitmapCommand],
/// leaving other fields as their default values. /// leaving other fields as their default values.
/// ///
/// Rust equivalent: `BitmapCommand::from(bitmap)` /// Rust equivalent: `BitmapCommand::from(bitmap)`
fn from_bitmap(bitmap: move NonNull<Bitmap>) -> NonNull<BitmapCommand> { fn from_bitmap(bitmap: move NonNull<Bitmap>) -> move NonNull<BitmapCommand> {
heap_move_nonnull(bitmap.into()) bitmap.into()
}; };
); );

View file

@ -1,7 +1,6 @@
use crate::{ use crate::{
commands::wrap_command, commands::wrap_command,
macros::{wrap_fields, wrap_functions}, macros::{wrap_fields, wrap_functions},
mem::heap_move_nonnull,
}; };
use servicepoint::{ use servicepoint::{
BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Offset, BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Offset,
@ -35,12 +34,12 @@ wrap_functions!(associate BitVecCommand;
offset: val usize, offset: val usize,
operation: val BinaryOperation, operation: val BinaryOperation,
compression: val CompressionCode, compression: val CompressionCode,
) -> NonNull<BitVecCommand> { ) -> move NonNull<BitVecCommand> {
heap_move_nonnull(BitVecCommand { BitVecCommand {
bitvec, bitvec,
offset, offset,
operation, operation,
compression, compression,
}) }
}; };
); );

View file

@ -1,7 +1,6 @@
use crate::{ use crate::{
commands::{wrap_command, wrap_origin_accessors}, commands::{wrap_command, wrap_origin_accessors},
macros::{wrap_fields, wrap_functions}, macros::{wrap_fields, wrap_functions},
mem::heap_move_nonnull,
}; };
use servicepoint::{BrightnessGrid, BrightnessGridCommand, Origin}; use servicepoint::{BrightnessGrid, BrightnessGridCommand, Origin};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -24,16 +23,16 @@ wrap_functions!(associate BrightnessGridCommand;
grid: move NonNull<BrightnessGrid>, grid: move NonNull<BrightnessGrid>,
origin_x: val usize, origin_x: val usize,
origin_y: val usize origin_y: val usize
) -> NonNull<BrightnessGridCommand> { ) -> move NonNull<BrightnessGridCommand> {
heap_move_nonnull(BrightnessGridCommand { BrightnessGridCommand {
grid, grid,
origin: Origin::new(origin_x, origin_y), origin: Origin::new(origin_x, origin_y),
}) }
}; };
/// Moves the provided [BrightnessGrid] into a new [BrightnessGridCommand], /// Moves the provided [BrightnessGrid] into a new [BrightnessGridCommand],
/// leaving other fields as their default values. /// leaving other fields as their default values.
fn from_grid(grid: move NonNull<BrightnessGrid>) -> NonNull<BrightnessGridCommand> { fn from_grid(grid: move NonNull<BrightnessGrid>) -> move NonNull<BrightnessGridCommand> {
heap_move_nonnull(grid.into()) grid.into()
}; };
); );

View file

@ -1,6 +1,4 @@
use crate::{ use crate::{commands::wrap_command, macros::wrap_functions};
commands::wrap_command, macros::wrap_functions, mem::heap_move_nonnull,
};
use servicepoint::{ClearCommand, FadeOutCommand, HardResetCommand}; use servicepoint::{ClearCommand, FadeOutCommand, HardResetCommand};
macro_rules! wrap_cc_only { macro_rules! wrap_cc_only {
@ -12,8 +10,8 @@ macro_rules! wrap_cc_only {
$(#[$meta])* $(#[$meta])*
/// ///
#[doc = " Returns: a new [`" [< $command Command >] "`] instance."] #[doc = " Returns: a new [`" [< $command Command >] "`] instance."]
fn new() -> ::core::ptr::NonNull<[< $command Command >]> { fn new() -> move ::core::ptr::NonNull<[< $command Command >]> {
heap_move_nonnull([< $command Command >]) [< $command Command >]
}; };
); );
} }

View file

@ -1,7 +1,6 @@
use crate::{ use crate::{
commands::{wrap_command, wrap_origin_accessors}, commands::{wrap_command, wrap_origin_accessors},
macros::{wrap_fields, wrap_functions}, macros::{wrap_fields, wrap_functions},
mem::heap_move_nonnull,
}; };
use servicepoint::{CharGrid, CharGridCommand, Origin}; use servicepoint::{CharGrid, CharGridCommand, Origin};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -24,16 +23,16 @@ wrap_functions!(associate CharGridCommand;
grid: move NonNull<CharGrid>, grid: move NonNull<CharGrid>,
origin_x: val usize, origin_x: val usize,
origin_y: val usize, origin_y: val usize,
) -> NonNull<CharGridCommand> { ) -> move NonNull<CharGridCommand> {
heap_move_nonnull(CharGridCommand { CharGridCommand {
grid, grid,
origin: Origin::new(origin_x, origin_y), origin: Origin::new(origin_x, origin_y),
}) }
}; };
/// Moves the provided [CharGrid] into a new [CharGridCommand], /// Moves the provided [CharGrid] into a new [CharGridCommand],
/// leaving other fields as their default values. /// leaving other fields as their default values.
fn from_grid(grid: move NonNull<CharGrid>) -> NonNull<CharGridCommand> { fn from_grid(grid: move NonNull<CharGrid>) -> move NonNull<CharGridCommand> {
heap_move_nonnull(grid.into()) grid.into()
}; };
); );

View file

@ -1,7 +1,6 @@
use crate::{ use crate::{
commands::{wrap_command, wrap_origin_accessors}, commands::{wrap_command, wrap_origin_accessors},
macros::{wrap_fields, wrap_functions}, macros::{wrap_fields, wrap_functions},
mem::heap_move_nonnull,
}; };
use servicepoint::{Cp437Grid, Cp437GridCommand, Origin}; use servicepoint::{Cp437Grid, Cp437GridCommand, Origin};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -24,16 +23,16 @@ wrap_functions!(associate Cp437GridCommand;
grid: move NonNull<Cp437Grid>, grid: move NonNull<Cp437Grid>,
origin_x: val usize, origin_x: val usize,
origin_y: val usize, origin_y: val usize,
) -> NonNull<Cp437GridCommand> { ) -> move NonNull<Cp437GridCommand> {
heap_move_nonnull(Cp437GridCommand { Cp437GridCommand {
grid, grid,
origin: Origin::new(origin_x, origin_y), origin: Origin::new(origin_x, origin_y),
}) }
}; };
/// Moves the provided [Cp437Grid] into a new [Cp437GridCommand], /// Moves the provided [Cp437Grid] into a new [Cp437GridCommand],
/// leaving other fields as their default values. /// leaving other fields as their default values.
fn from_grid(grid: move NonNull<Cp437Grid>) -> NonNull<Cp437GridCommand> { fn from_grid(grid: move NonNull<Cp437Grid>) -> move NonNull<Cp437GridCommand> {
heap_move_nonnull(grid.into()) grid.into()
}; };
); );

View file

@ -178,8 +178,8 @@ wrap_functions!(associate GenericCommand;
/// The packet is dropped in the process. /// The packet is dropped in the process.
/// ///
/// Returns: pointer to new [GenericCommand] instance or NULL if parsing failed. /// Returns: pointer to new [GenericCommand] instance or NULL if parsing failed.
fn try_from_packet(packet: move NonNull<Packet>) -> NonNull<GenericCommand> { fn try_from_packet(packet: move NonNull<Packet>) -> move NonNull<GenericCommand> {
let result = servicepoint::TypedCommand::try_from(packet) servicepoint::TypedCommand::try_from(packet)
.map(|value| match value { .map(|value| match value {
TypedCommand::Clear(clear) => GenericCommand { TypedCommand::Clear(clear) => GenericCommand {
tag: CommandTag::Clear, tag: CommandTag::Clear,
@ -246,8 +246,7 @@ wrap_functions!(associate GenericCommand;
.unwrap_or_else(move |_| GenericCommand { .unwrap_or_else(move |_| GenericCommand {
tag: CommandTag::Invalid, tag: CommandTag::Invalid,
data: CommandUnion { null: null_mut() }, data: CommandUnion { null: null_mut() },
}); })
heap_move_nonnull(result)
}; };
); );
@ -256,7 +255,7 @@ wrap_methods! { GenericCommand;
/// 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) -> *mut Packet { fn 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,7 +1,6 @@
use crate::{ use crate::{
commands::wrap_command, commands::wrap_command,
macros::{wrap_fields, wrap_functions}, macros::{wrap_fields, wrap_functions},
mem::heap_move_nonnull,
}; };
use servicepoint::{Brightness, GlobalBrightnessCommand}; use servicepoint::{Brightness, GlobalBrightnessCommand};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -10,8 +9,8 @@ wrap_functions!(associate GlobalBrightnessCommand;
/// Set the brightness of all tiles to the same value. /// Set the brightness of all tiles to the same value.
/// ///
/// Returns: a new [GlobalBrightnessCommand] instance. /// Returns: a new [GlobalBrightnessCommand] instance.
fn new(brightness: val Brightness) -> NonNull<GlobalBrightnessCommand> { fn new(brightness: val Brightness) -> move NonNull<GlobalBrightnessCommand> {
heap_move_nonnull(GlobalBrightnessCommand::from(brightness)) GlobalBrightnessCommand::from(brightness)
}; };
); );

View file

@ -62,8 +62,8 @@ macro_rules! derive_command_into_packet {
#[doc = "Tries to turn a [`" $command_type "`] into a [Packet]."] #[doc = "Tries to turn a [`" $command_type "`] into a [Packet]."]
/// ///
/// Returns: NULL or a [Packet] containing the command. /// Returns: NULL or a [Packet] containing the command.
fn try_into_packet(move instance) -> *mut ::servicepoint::Packet { fn try_into_packet(move instance) -> move_ok *mut ::servicepoint::Packet {
$crate::mem::heap_move_ok(instance.try_into()) instance.try_into()
}; };
); );
} }

View file

@ -1,7 +1,6 @@
use crate::{ use crate::{
containers::{wrap_grid, ByteSlice}, containers::{wrap_grid, ByteSlice},
macros::{wrap_functions, wrap_methods}, macros::{wrap_functions, wrap_methods},
mem::{heap_move_nonnull, heap_move_ok, heap_move_some},
}; };
use servicepoint::{ use servicepoint::{
Bitmap, BitmapCommand, CompressionCode, DataRef, DisplayBitVec, Grid, Bitmap, BitmapCommand, CompressionCode, DataRef, DisplayBitVec, Grid,
@ -35,15 +34,15 @@ wrap_functions!(associate Bitmap;
/// sp_bitmap_set(grid, 0, 0, false); /// sp_bitmap_set(grid, 0, 0, false);
/// sp_bitmap_free(grid); /// sp_bitmap_free(grid);
/// ``` /// ```
fn new(width: val usize, height: val usize) -> *mut Bitmap { fn new(width: val usize, height: val usize) -> move_some *mut Bitmap {
heap_move_some(Bitmap::new(width, height)) Bitmap::new(width, height)
}; };
/// Creates a new [Bitmap] with a size matching the screen. /// Creates a new [Bitmap] with a size matching the screen.
/// ///
/// returns: [Bitmap] initialized to all pixels off. /// returns: [Bitmap] initialized to all pixels off.
fn new_max_sized() -> NonNull<Bitmap> { fn new_max_sized() -> move NonNull<Bitmap> {
heap_move_nonnull(Bitmap::max_sized()) Bitmap::max_sized()
}; };
/// Loads a [Bitmap] with the specified dimensions from the provided data. /// Loads a [Bitmap] with the specified dimensions from the provided data.
@ -58,9 +57,9 @@ wrap_functions!(associate Bitmap;
width: val usize, width: val usize,
height: val usize, height: val usize,
data: val ByteSlice, data: val ByteSlice,
) -> *mut Bitmap { ) -> move_ok *mut Bitmap {
let data = unsafe { data.as_slice() }; let data = unsafe { data.as_slice() };
heap_move_ok(Bitmap::load(width, height, data)) Bitmap::load(width, height, data)
}; };
/// Tries to convert the BitVec to a Bitmap. /// Tries to convert the BitVec to a Bitmap.
@ -71,15 +70,15 @@ wrap_functions!(associate Bitmap;
fn from_bitvec( fn from_bitvec(
width: val usize, width: val usize,
bitvec: move NonNull<DisplayBitVec>, bitvec: move NonNull<DisplayBitVec>,
) -> *mut Bitmap { ) -> move_ok *mut Bitmap {
heap_move_ok(Bitmap::from_bitvec(width, bitvec)) Bitmap::from_bitvec(width, bitvec)
}; };
); );
wrap_methods!(Bitmap; wrap_methods!(Bitmap;
/// Consumes the Bitmap and returns the contained BitVec. /// Consumes the Bitmap and returns the contained BitVec.
fn into_bitvec(move bitmap) -> NonNull<DisplayBitVec> { fn into_bitvec(move bitmap) -> move NonNull<DisplayBitVec> {
heap_move_nonnull(bitmap.into()) bitmap.into()
}; };
/// Creates a [BitmapCommand] and immediately turns that into a [Packet]. /// Creates a [BitmapCommand] and immediately turns that into a [Packet].
@ -87,18 +86,18 @@ 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) -> *mut Packet { fn try_into_packet(move bitmap, x: val usize, y: val usize, compression: val CompressionCode) -> move_ok *mut Packet {
heap_move_ok(Packet::try_from(BitmapCommand { Packet::try_from(BitmapCommand {
bitmap, bitmap,
origin: Origin::new(x, y), origin: Origin::new(x, y),
compression, compression,
})) })
}; };
/// 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) -> ByteSlice { fn data_ref_mut(mut instance) -> val ByteSlice {
unsafe { ByteSlice::from_slice(instance.data_ref_mut()) } unsafe { ByteSlice::from_slice(instance.data_ref_mut()) }
}; };
); );

View file

@ -1,7 +1,6 @@
use crate::{ use crate::{
containers::{wrap_container, ByteSlice}, containers::{wrap_container, ByteSlice},
macros::{wrap_functions, wrap_methods}, macros::{wrap_functions, wrap_methods},
mem::{heap_move_nonnull, heap_move_ok},
}; };
use servicepoint::{ use servicepoint::{
BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Packet, BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Packet,
@ -22,16 +21,16 @@ wrap_functions!(associate DisplayBitVec;
/// # Panics /// # Panics
/// ///
/// - when `size` is not divisible by 8. /// - when `size` is not divisible by 8.
fn new(size: val usize) -> NonNull<DisplayBitVec> { fn new(size: val usize) -> move NonNull<DisplayBitVec> {
heap_move_nonnull(DisplayBitVec::repeat(false, size)) DisplayBitVec::repeat(false, size)
}; };
/// Interpret the data as a series of bits and load then into a new [DisplayBitVec] instance. /// Interpret the data as a series of bits and load then into a new [DisplayBitVec] instance.
/// ///
/// returns: [DisplayBitVec] instance containing data. /// returns: [DisplayBitVec] instance containing data.
fn load(data: val ByteSlice) -> NonNull<DisplayBitVec> { fn load(data: val ByteSlice) -> move NonNull<DisplayBitVec> {
let data = unsafe { data.as_slice() }; let data = unsafe { data.as_slice() };
heap_move_nonnull(DisplayBitVec::from_slice(data)) DisplayBitVec::from_slice(data)
}; };
); );
@ -46,13 +45,13 @@ wrap_methods!(DisplayBitVec;
offset: val usize, offset: val usize,
operation: val BinaryOperation, operation: val BinaryOperation,
compression: val CompressionCode compression: val CompressionCode
) -> *mut Packet { ) -> move_ok *mut Packet {
heap_move_ok(Packet::try_from(BitVecCommand { Packet::try_from(BitVecCommand {
bitvec, bitvec,
offset, offset,
operation, operation,
compression, compression,
})) })
}; };
/// Gets the value of a bit. /// Gets the value of a bit.
@ -67,7 +66,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) -> bool { fn 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)
}; };
@ -91,15 +90,15 @@ wrap_methods!(DisplayBitVec;
fn fill(mut instance, value: val bool); fn fill(mut instance, value: val bool);
/// Gets the length in bits. /// Gets the length in bits.
fn len(ref instance) -> usize; fn len(ref instance) -> val usize;
/// Returns true if length is 0. /// Returns true if length is 0.
fn is_empty(ref instance) -> bool; fn 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) -> ByteSlice { fn as_raw_mut_slice(mut instance) -> val ByteSlice {
unsafe { ByteSlice::from_slice(instance.as_raw_mut_slice()) } unsafe { ByteSlice::from_slice(instance.as_raw_mut_slice()) }
}; };
); );

View file

@ -1,7 +1,6 @@
use crate::{ use crate::{
containers::{wrap_grid, ByteSlice}, containers::{wrap_grid, ByteSlice},
macros::{wrap_functions, wrap_methods}, macros::{wrap_functions, wrap_methods},
mem::{heap_move_nonnull, heap_move_ok, heap_move_some},
}; };
use servicepoint::{ use servicepoint::{
Brightness, BrightnessGrid, BrightnessGridCommand, ByteGrid, DataRef, Grid, Brightness, BrightnessGrid, BrightnessGridCommand, ByteGrid, DataRef, Grid,
@ -12,7 +11,6 @@ use std::{mem::transmute, ptr::NonNull};
wrap_grid!(BrightnessGrid, Brightness); wrap_grid!(BrightnessGrid, Brightness);
wrap_functions!(associate BrightnessGrid; wrap_functions!(associate BrightnessGrid;
/// Creates a new [BrightnessGrid] with the specified dimensions. /// Creates a new [BrightnessGrid] with the specified dimensions.
/// ///
/// returns: [BrightnessGrid] initialized to 0. /// returns: [BrightnessGrid] initialized to 0.
@ -30,8 +28,8 @@ wrap_functions!(associate BrightnessGrid;
/// TypedCommand *command = sp_command_char_brightness(grid); /// TypedCommand *command = sp_command_char_brightness(grid);
/// sp_udp_free(connection); /// sp_udp_free(connection);
/// ``` /// ```
fn new(width: val usize, height: val usize) -> NonNull<BrightnessGrid> { fn new(width: val usize, height: val usize) -> move NonNull<BrightnessGrid> {
heap_move_nonnull(BrightnessGrid::new(width, height)) BrightnessGrid::new(width, height)
}; };
/// Loads a [BrightnessGrid] with the specified dimensions from the provided data. /// Loads a [BrightnessGrid] with the specified dimensions from the provided data.
@ -43,14 +41,11 @@ wrap_functions!(associate BrightnessGrid;
width: val usize, width: val usize,
height: val usize, height: val usize,
data: val ByteSlice, data: val ByteSlice,
) -> *mut BrightnessGrid { ) -> move_some *mut BrightnessGrid {
let data = unsafe { data.as_slice() }; let data = unsafe { data.as_slice() };
heap_move_some(
ByteGrid::load(width, height, data) ByteGrid::load(width, height, data)
.map(move |grid| grid.map(Brightness::saturating_from)), .map(move |grid| grid.map(Brightness::saturating_from))
)
}; };
); );
wrap_methods!(BrightnessGrid; wrap_methods!(BrightnessGrid;
@ -59,17 +54,17 @@ wrap_methods!(BrightnessGrid;
/// 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) -> *mut Packet { fn try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet {
heap_move_ok(Packet::try_from(BrightnessGridCommand { Packet::try_from(BrightnessGridCommand {
grid, grid,
origin: Origin::new(x, y), origin: Origin::new(x, y),
})) })
}; };
/// 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) -> ByteSlice { fn data_ref_mut(mut instance) -> val ByteSlice {
//noinspection RsAssertEqual //noinspection RsAssertEqual
const _: () = assert!(size_of::<Brightness>() == 1); const _: () = assert!(size_of::<Brightness>() == 1);

View file

@ -1,7 +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_functions, wrap_methods},
mem::{heap_move_nonnull, heap_move_ok},
}; };
use servicepoint::{CharGrid, CharGridCommand, Grid, Origin, Packet}; use servicepoint::{CharGrid, CharGridCommand, Grid, Origin, Packet};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -22,16 +21,16 @@ wrap_functions!(associate CharGrid;
/// sp_char_grid_set(grid, 0, 0, '!'); /// sp_char_grid_set(grid, 0, 0, '!');
/// sp_char_grid_free(grid); /// sp_char_grid_free(grid);
/// ``` /// ```
fn new(width: val usize, height: val usize) -> NonNull<CharGrid> { fn new(width: val usize, height: val usize) -> move NonNull<CharGrid> {
heap_move_nonnull(CharGrid::new(width, height)) CharGrid::new(width, height)
}; };
/// Loads a [CharGrid] with the specified dimensions from the provided data. /// Loads a [CharGrid] with the specified dimensions from the provided data.
/// ///
/// returns: new CharGrid or NULL in case of an error /// returns: new CharGrid or NULL in case of an error
fn load(width: val usize, height: val usize, data: val ByteSlice) -> *mut CharGrid { fn load(width: val usize, height: val usize, data: val ByteSlice) -> move_ok *mut CharGrid {
let data = unsafe { data.as_slice() }; let data = unsafe { data.as_slice() };
heap_move_ok(CharGrid::load_utf8(width, height, data.to_vec())) CharGrid::load_utf8(width, height, data.to_vec())
}; };
); );
@ -46,7 +45,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) -> u32 { fn get(ref instance, x: val usize, y: val usize) -> val u32 {
instance.get(x, y) as u32 instance.get(x, y) as u32
}; };
@ -82,10 +81,10 @@ 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) -> *mut Packet { fn try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet {
heap_move_ok(Packet::try_from(CharGridCommand { Packet::try_from(CharGridCommand {
grid, grid,
origin: Origin::new(x, y), origin: Origin::new(x, y),
})) })
}; };
); );

View file

@ -1,7 +1,6 @@
use crate::{ use crate::{
containers::{wrap_grid, ByteSlice}, containers::{wrap_grid, ByteSlice},
macros::{wrap_functions, wrap_methods}, macros::{wrap_functions, wrap_methods},
mem::{heap_move_nonnull, heap_move_ok, heap_move_some},
}; };
use servicepoint::{ use servicepoint::{
Cp437Grid, Cp437GridCommand, DataRef, Grid, Origin, Packet, Cp437Grid, Cp437GridCommand, DataRef, Grid, Origin, Packet,
@ -14,14 +13,14 @@ wrap_functions!(associate Cp437Grid;
/// Creates a new [Cp437Grid] with the specified dimensions. /// Creates a new [Cp437Grid] with the specified dimensions.
/// ///
/// returns: [Cp437Grid] initialized to 0. /// returns: [Cp437Grid] initialized to 0.
fn new(width: val usize, height: val usize) -> NonNull<Cp437Grid> { fn new(width: val usize, height: val usize) -> move NonNull<Cp437Grid> {
heap_move_nonnull(Cp437Grid::new(width, height)) Cp437Grid::new(width, height)
}; };
/// Loads a [Cp437Grid] with the specified dimensions from the provided data. /// Loads a [Cp437Grid] with the specified dimensions from the provided data.
fn load(width: val usize, height: val usize, data: val ByteSlice) -> *mut Cp437Grid { fn load(width: val usize, height: val usize, data: val ByteSlice) -> move_some *mut Cp437Grid {
let data = unsafe { data.as_slice() }; let data = unsafe { data.as_slice() };
heap_move_some(Cp437Grid::load(width, height, data)) Cp437Grid::load(width, height, data)
}; };
); );
@ -31,17 +30,17 @@ wrap_methods!(Cp437Grid;
/// 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) -> *mut Packet { fn try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet {
heap_move_ok(Packet::try_from(Cp437GridCommand { Packet::try_from(Cp437GridCommand {
grid, grid,
origin: Origin::new(x, y), origin: Origin::new(x, y),
})) })
}; };
/// 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) -> ByteSlice { fn data_ref_mut(mut instance) -> val ByteSlice {
unsafe { ByteSlice::from_slice(instance.data_ref_mut()) } unsafe { ByteSlice::from_slice(instance.data_ref_mut()) }
}; };
); );

View file

@ -23,10 +23,10 @@ macro_rules! derive_get_width_height {
($object_type:ident) => { ($object_type:ident) => {
$crate::macros::wrap_methods! {$object_type; $crate::macros::wrap_methods! {$object_type;
/// Gets the width. /// Gets the width.
fn width(ref instance) -> usize; fn width(ref instance) -> val usize;
/// Gets the height. /// Gets the height.
fn height(ref instance) -> usize; fn height(ref instance) -> val usize;
} }
}; };
} }
@ -45,7 +45,7 @@ macro_rules! wrap_grid {
/// # 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) -> $value_type; fn get(ref instance, x: val usize, y: val usize) -> val $value_type;
/// Sets the value of the specified position. /// Sets the value of the specified position.
/// ///

View file

@ -17,8 +17,8 @@ macro_rules! derive_clone {
::paste::paste! { ::paste::paste! {
$crate::macros::wrap_method!($object_type; $crate::macros::wrap_method!($object_type;
#[doc = "Clones a [`" $object_type "`] instance."] #[doc = "Clones a [`" $object_type "`] instance."]
fn clone(ref instance) -> ::core::ptr::NonNull<$object_type> { fn clone(ref instance) -> move ::core::ptr::NonNull<$object_type> {
$crate::mem::heap_move_nonnull(instance.clone()) instance.clone()
}; };
); );
} }
@ -30,14 +30,14 @@ macro_rules! wrap_method {
$object_type:ident; $object_type:ident;
$(#[$meta:meta])+ $(#[$meta:meta])+
fn $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_modifier: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)?; $(-> $return_modifier:ident $return_type:ty)?;
) => { ) => {
::paste::paste!{ ::paste::paste!{
$crate::macros::wrap_method!( $crate::macros::wrap_method!(
$object_type; $object_type;
$(#[$meta])+ $(#[$meta])+
fn $function($ref_or_mut $instance $(, $($param_name: $param_modifier $param_type),*)?) fn $function($ref_or_mut $instance $(, $($param_name: $param_modifier $param_type),*)?)
$(-> $return_type)? { $(-> $return_modifier $return_type)? {
$instance.$function($($($param_name),*)?) $instance.$function($($($param_name),*)?)
}; };
); );
@ -46,7 +46,7 @@ macro_rules! wrap_method {
($object_type:ident; ($object_type:ident;
$(#[$meta:meta])+ $(#[$meta:meta])+
fn $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_modifier: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)? $(-> $return_modifier:ident $return_type:ty)?
$impl:block; $impl:block;
) => { ) => {
paste::paste! { paste::paste! {
@ -57,7 +57,7 @@ macro_rules! wrap_method {
fn $function( fn $function(
$instance: $ref_or_mut ::core::ptr::NonNull<$object_type> $instance: $ref_or_mut ::core::ptr::NonNull<$object_type>
$(,$($param_name: $param_modifier $param_type),*)? $(,$($param_name: $param_modifier $param_type),*)?
) $(-> $return_type)? ) $(-> $return_modifier $return_type)?
$impl; $impl;
); );
} }
@ -70,7 +70,7 @@ macro_rules! wrap_methods {
$( $(
$(#[$meta:meta])+ $(#[$meta:meta])+
fn $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_modifier: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)? $(-> $return_modifier:ident $return_type:ty)?
$($impl:block)?; $($impl:block)?;
)+ )+
) => { ) => {
@ -79,7 +79,7 @@ macro_rules! wrap_methods {
$crate::macros::wrap_method!($object_type; $crate::macros::wrap_method!($object_type;
$(#[$meta])* $(#[$meta])*
fn $function($ref_or_mut $instance $(, $($param_name: $param_modifier $param_type),*)?) fn $function($ref_or_mut $instance $(, $($param_name: $param_modifier $param_type),*)?)
$(-> $return_type)? $(-> $return_modifier $return_type)?
$($impl)?; $($impl)?;
); );
)+ )+
@ -93,8 +93,8 @@ macro_rules! wrap_fields_accessor {
$crate::macros::wrap_method! {$object_type; $crate::macros::wrap_method! {$object_type;
#[doc = " Gets the value of field `" $prop_name #[doc = " Gets the value of field `" $prop_name
"` of the [`servicepoint::" $object_type "`]."] "` of the [`servicepoint::" $object_type "`]."]
fn [<get _ $prop_name>](ref instance) -> $prop_type { fn [<get _ $prop_name>](ref instance) -> val $prop_type {
return instance.$prop_name; instance.$prop_name
}; };
} }
} }
@ -107,8 +107,8 @@ macro_rules! wrap_fields_accessor {
/// ///
/// - The returned reference inherits the lifetime of object in which it is contained. /// - 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. /// - The returned pointer may not be used in a function that consumes the instance, e.g. to create a command.
fn [<get _ $prop_name _mut>](mut instance) -> ::core::ptr::NonNull<$prop_type> { fn [<get _ $prop_name _mut>](mut instance) -> val ::core::ptr::NonNull<$prop_type> {
return ::core::ptr::NonNull::from(&mut instance.$prop_name); ::core::ptr::NonNull::from(&mut instance.$prop_name)
}; };
} }
} }
@ -171,16 +171,31 @@ macro_rules! apply_param_modifier {
}; };
} }
macro_rules! apply_return_modifier {
(val, $result:ident) => {
$result
};
(move, $result:ident) => {
$crate::mem::heap_move_nonnull($result)
};
(move_ok, $result:ident) => {
$crate::mem::heap_move_ok($result)
};
(move_some, $result:ident) => {
$crate::mem::heap_move_some($result)
};
}
macro_rules! wrap_function { macro_rules! wrap_function {
( (
$module:ident; $module:ident;
$(#[$meta:meta])+ $(#[$meta:meta])+
fn $function:ident($($param_name:ident: $param_modifier:ident $param_type:ty),*$(,)?) fn $function:ident($($param_name:ident: $param_modifier:ident $param_type:ty),*$(,)?)
$(-> $return_type:ty)? $(-> $return_modifier:ident $return_type:ty)?
$block:block; $block:block;
) => { ) => {
::paste::paste! { ::paste::paste! {
$(#[$meta])* $(#[$meta])+
#[doc = ""] #[doc = ""]
#[doc = " This function is part of the `" $module "` module."] #[doc = " This function is part of the `" $module "` module."]
#[no_mangle] #[no_mangle]
@ -191,10 +206,14 @@ macro_rules! wrap_function {
$( $(
let $param_name = $crate::macros::apply_param_modifier!($param_modifier, $param_name); let $param_name = $crate::macros::apply_param_modifier!($param_modifier, $param_name);
)* )*
$block let result = $block;
} $(
let result = $crate::macros::apply_return_modifier!($return_modifier, result);
)?
result
} }
} }
};
} }
macro_rules! wrap_functions { macro_rules! wrap_functions {
@ -203,7 +222,7 @@ macro_rules! wrap_functions {
$( $(
$(#[$meta:meta])+ $(#[$meta:meta])+
fn $function:ident($($param_name:ident: $param_modifier:ident $param_type:ty),*$(,)?) fn $function:ident($($param_name:ident: $param_modifier:ident $param_type:ty),*$(,)?)
$(-> $return_type:ty)? $(-> $return_modifier:ident $return_type:ty)?
$block:block; $block:block;
)+ )+
) => { ) => {
@ -211,7 +230,7 @@ macro_rules! wrap_functions {
$( $(
$crate::macros::wrap_function!($module; $crate::macros::wrap_function!($module;
$(#[$meta])+ $(#[$meta])+
fn $function($($param_name: $param_modifier $param_type),*) $(-> $return_type)? fn $function($($param_name: $param_modifier $param_type),*) $(-> $return_modifier $return_type)?
$block; $block;
); );
)+ )+
@ -222,7 +241,7 @@ macro_rules! wrap_functions {
$( $(
$(#[$meta:meta])+ $(#[$meta:meta])+
fn $function:ident($($param_name:ident: $param_modifier:ident $param_type:ty),*$(,)?) fn $function:ident($($param_name:ident: $param_modifier:ident $param_type:ty),*$(,)?)
$(-> $return_type:ty)? $(-> $return_modifier:ident $return_type:ty)?
$block:block; $block:block;
)+ )+
) => { ) => {
@ -230,7 +249,7 @@ macro_rules! wrap_functions {
$crate::macros::wrap_functions!{[< $object_type:lower >]; $crate::macros::wrap_functions!{[< $object_type:lower >];
$( $(
$(#[$meta])+ $(#[$meta])+
fn $function($($param_name: $param_modifier $param_type),*) $(-> $return_type)? fn $function($($param_name: $param_modifier $param_type),*) $(-> $return_modifier $return_type)?
$block; $block;
)+ )+
} }
@ -239,7 +258,7 @@ macro_rules! wrap_functions {
} }
pub(crate) use { pub(crate) use {
apply_param_modifier, derive_clone, derive_free, apply_param_modifier, apply_return_modifier, derive_clone, derive_free,
wrap_fields, wrap_fields_accessor, wrap_function, wrap_fields, wrap_fields_accessor, wrap_function, wrap_functions,
wrap_functions, wrap_method, wrap_methods, wrap_method, wrap_methods,
}; };

View file

@ -3,7 +3,6 @@ use crate::{
macros::{ macros::{
derive_clone, derive_free, wrap_fields, wrap_functions, wrap_methods, derive_clone, derive_free, wrap_fields, wrap_functions, wrap_methods,
}, },
mem::{heap_move_nonnull, heap_move_ok},
}; };
use servicepoint::{CommandCode, Header, Packet}; use servicepoint::{CommandCode, Header, Packet};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -12,22 +11,22 @@ wrap_functions!(associate Packet;
/// Tries to load a [Packet] from the passed array with the specified length. /// 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 /// returns: NULL in case of an error, pointer to the allocated packet otherwise
fn try_load(data: val ByteSlice) -> *mut Packet { fn try_load(data: val ByteSlice) -> move_ok *mut Packet {
let data = unsafe { data.as_slice() }; let data = unsafe { data.as_slice() };
heap_move_ok(servicepoint::Packet::try_from(data)) servicepoint::Packet::try_from(data)
}; };
/// Creates a raw [Packet] from parts. /// Creates a raw [Packet] from parts.
/// ///
/// returns: new instance. Will never return null. /// returns: new instance. Will never return null.
fn from_parts(header: val Header, payload: val ByteSlice) -> NonNull<Packet> { fn from_parts(header: val Header, payload: val ByteSlice) -> move NonNull<Packet> {
let payload = if payload == ByteSlice::INVALID { let payload = if payload == ByteSlice::INVALID {
None None
} else { } else {
Some(Vec::from(unsafe { payload.as_slice() })) Some(Vec::from(unsafe { payload.as_slice() }))
}; };
heap_move_nonnull(Packet { header, payload }) Packet { header, payload }
}; };
); );
@ -44,7 +43,7 @@ wrap_methods! { 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) -> ByteSlice { fn 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) },
@ -67,7 +66,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) -> usize { fn 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)
} }
@ -79,7 +78,7 @@ wrap_functions!(sp;
/// Converts u16 into [CommandCode]. /// Converts u16 into [CommandCode].
/// ///
/// If the provided value is not valid, false is returned and result is not changed. /// If the provided value is not valid, false is returned and result is not changed.
fn u16_to_command_code(code: val u16, result: mut NonNull<CommandCode>) -> bool { fn u16_to_command_code(code: val u16, result: mut NonNull<CommandCode>) -> val bool {
match CommandCode::try_from(code) { match CommandCode::try_from(code) {
Ok(code) => { Ok(code) => {
*result = code; *result = code;

View file

@ -1,7 +1,7 @@
use crate::{ use crate::{
commands::{CommandTag, GenericCommand}, commands::{CommandTag, GenericCommand},
macros::{derive_free, wrap_functions, wrap_methods}, macros::{derive_free, wrap_functions, wrap_methods},
mem::{heap_move_ok, heap_remove}, mem::heap_remove,
}; };
use servicepoint::{Header, Packet, UdpSocketExt}; use servicepoint::{Header, Packet, UdpSocketExt};
use std::{ use std::{
@ -13,7 +13,6 @@ use std::{
derive_free!(UdpSocket); derive_free!(UdpSocket);
wrap_functions!(associate UdpSocket; wrap_functions!(associate UdpSocket;
/// Creates a new instance of [UdpSocket]. /// Creates a new instance of [UdpSocket].
/// ///
/// returns: NULL if connection fails, or connected instance /// returns: NULL if connection fails, or connected instance
@ -25,11 +24,11 @@ wrap_functions!(associate UdpSocket;
/// if (connection != NULL) /// if (connection != NULL)
/// sp_udp_send_command(connection, sp_command_clear()); /// sp_udp_send_command(connection, sp_command_clear());
/// ``` /// ```
fn open(host: val NonNull<c_char>) -> *mut UdpSocket { fn open(host: val NonNull<c_char>) -> move_ok *mut UdpSocket {
let host = unsafe { CStr::from_ptr(host.as_ptr()) } let host = unsafe { CStr::from_ptr(host.as_ptr()) }
.to_str() .to_str()
.expect("Bad encoding"); .expect("Bad encoding");
heap_move_ok(UdpSocket::bind_connect(host)) UdpSocket::bind_connect(host)
}; };
/// Creates a new instance of [UdpSocket]. /// Creates a new instance of [UdpSocket].
@ -43,11 +42,10 @@ wrap_functions!(associate UdpSocket;
/// if (connection != NULL) /// if (connection != NULL)
/// sp_udp_send_command(connection, sp_command_clear()); /// sp_udp_send_command(connection, sp_command_clear());
/// ``` /// ```
fn open_ipv4(ip1: val u8, ip2: val u8, ip3: val u8, ip4: val u8, port: val u16) -> *mut UdpSocket { fn open_ipv4(ip1: val u8, ip2: val u8, ip3: val u8, ip4: val u8, port: val u16) -> move_ok *mut UdpSocket {
let addr = SocketAddrV4::new(Ipv4Addr::from([ip1, ip2, ip3, ip4]), port); let addr = SocketAddrV4::new(Ipv4Addr::from([ip1, ip2, ip3, ip4]), port);
heap_move_ok(UdpSocket::bind_connect(addr)) UdpSocket::bind_connect(addr)
}; };
); );
wrap_methods! {UdpSocket; wrap_methods! {UdpSocket;
@ -56,7 +54,7 @@ wrap_methods! {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>) -> bool { fn send_packet(ref connection, packet: move NonNull<Packet>) -> val bool {
connection.send(&Vec::from(packet)).is_ok() connection.send(&Vec::from(packet)).is_ok()
}; };
@ -71,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>) -> bool { fn 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,
@ -100,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) -> bool { fn send_header(ref udp_connection, header: val Header) -> val bool {
let packet = Packet { let packet = Packet {
header, header,
payload: None, payload: None,