From 323ba6128e0af019bc66f41bbc04bfee300149ef Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Mon, 23 Jun 2025 20:26:07 +0200 Subject: [PATCH] add move fn to dsl, rename SPCommand to GenericCommand, remove DisplayBitVec command --- example/src/header_logger.c | 24 +-- example/src/undefined.c | 4 +- example/src/wiping_clear.c | 2 +- include/servicepoint.h | 180 +++++++++++--------- src/commands/generic_command.rs | 265 +++++++++++++++--------------- src/commands/mod.rs | 10 +- src/containers/bitmap.rs | 24 +-- src/containers/bitvec.rs | 18 +- src/containers/brightness_grid.rs | 17 +- src/containers/char_grid.rs | 41 ++--- src/containers/cp437_grid.rs | 17 +- src/macros.rs | 11 +- src/udp.rs | 78 ++++----- 13 files changed, 335 insertions(+), 356 deletions(-) diff --git a/example/src/header_logger.c b/example/src/header_logger.c index ec421dd..5793da9 100644 --- a/example/src/header_logger.c +++ b/example/src/header_logger.c @@ -15,8 +15,8 @@ void handle_error(const char *msg) { exit(EXIT_FAILURE); } -bool log_command(struct Command command) { - switch (command.tag) { +bool log_command(struct GenericCommand *command) { + switch (command->tag) { case COMMAND_TAG_INVALID: { printf("-> this is an invalid command\n"); break; @@ -26,7 +26,7 @@ bool log_command(struct Command command) { return true; } case COMMAND_TAG_BITMAP: { - BitmapCommand *bitmapCommand = command.data.bitmap; + BitmapCommand *bitmapCommand = command->data.bitmap; CompressionCode compression = sp_bitmapcommand_get_compression(bitmapCommand); @@ -42,7 +42,7 @@ bool log_command(struct Command command) { break; } case COMMAND_TAG_BRIGHTNESS_GRID: { - BrightnessGridCommand *gridCommand = command.data.brightness_grid; + BrightnessGridCommand *gridCommand = command->data.brightness_grid; size_t x, y; sp_brightnessgridcommand_get_origin(gridCommand, &x, &y); @@ -56,7 +56,7 @@ bool log_command(struct Command command) { break; } case COMMAND_TAG_CHAR_GRID: { - CharGridCommand *gridCommand = command.data.char_grid; + CharGridCommand *gridCommand = command->data.char_grid; size_t x, y; sp_chargridcommand_get_origin(gridCommand, &x, &y); @@ -70,7 +70,7 @@ bool log_command(struct Command command) { break; } case COMMAND_TAG_CP437_GRID: { - Cp437GridCommand *gridCommand = command.data.cp437_grid; + Cp437GridCommand *gridCommand = command->data.cp437_grid; size_t x, y; sp_cp437gridcommand_get_origin(gridCommand, &x, &y); @@ -84,7 +84,7 @@ bool log_command(struct Command command) { break; } case COMMAND_TAG_BIT_VEC: { - BitVecCommand *bitvecCommand = command.data.bit_vec; + BitVecCommand *bitvecCommand = command->data.bit_vec; size_t offset = sp_bitveccommand_get_offset(bitvecCommand); CompressionCode compression = sp_bitveccommand_get_compression(bitvecCommand); @@ -109,7 +109,7 @@ bool log_command(struct Command command) { break; } - BitVec *bitvec = sp_bitveccommand_get_bitvec_mut(bitvecCommand); + DisplayBitVec *bitvec = sp_bitveccommand_get_bitvec_mut(bitvecCommand); size_t len = sp_displaybitvec_len(bitvec); printf("-> BitVecCommand with params: offset=%zu, length=%zu, compression=%hu, operation=%s\n", @@ -129,12 +129,12 @@ bool log_command(struct Command command) { break; } case COMMAND_TAG_GLOBAL_BRIGHTNESS: { - Brightness brightness = sp_globalbrightnesscommand_get_brightness(command.data.global_brightness); + Brightness brightness = sp_globalbrightnesscommand_get_brightness(command->data.global_brightness); printf("-> GlobalBrightnessCommand with params: brightness=%hu\n", brightness); break; } default: { - printf("-> unknown command tag %d\n", command.tag); + printf("-> unknown command tag %d\n", command->tag); break; } } @@ -198,10 +198,10 @@ int main(int argc, char **argv) { header->command_code, header->a, header->b, header->c, header->d, payload.start, payload.length); - struct Command command = sp_cmd_generic_try_from_packet(packet); + struct GenericCommand *command = sp_genericcommand_try_from_packet(packet); done = log_command(command); - sp_cmd_generic_free(command); + sp_genericcommand_free(command); } close(udp_socket); diff --git a/example/src/undefined.c b/example/src/undefined.c index 44aaf6d..b869d71 100644 --- a/example/src/undefined.c +++ b/example/src/undefined.c @@ -9,14 +9,14 @@ int main(void) { sp_bitveccommand_free(bvcmd); uint8_t *data = calloc(1024, 1); - struct Command generic = { + struct GenericCommand generic = { .tag = COMMAND_TAG_BRIGHTNESS_GRID, .data = {.null = data}, }; sock_init(); - sp_udpsocket_send_command(sock, generic); + sp_udpsocket_send_command(sock, &generic); return 0; } diff --git a/example/src/wiping_clear.c b/example/src/wiping_clear.c index 3984169..1d0440b 100644 --- a/example/src/wiping_clear.c +++ b/example/src/wiping_clear.c @@ -13,7 +13,7 @@ int main() { sp_bitmap_set(enabled_pixels, x, y, false); } - BitVec *bitvec = sp_bitmap_into_bitvec(sp_bitmap_clone(enabled_pixels)); + DisplayBitVec *bitvec = sp_bitmap_into_bitvec(sp_bitmap_clone(enabled_pixels)); BitVecCommand *command = sp_bitveccommand_new(bitvec, 0, BINARY_OPERATION_AND, COMPRESSION_CODE_LZMA); Packet *packet = sp_bitveccommand_try_into_packet(command); if (packet == NULL) { diff --git a/include/servicepoint.h b/include/servicepoint.h index 4d77ba8..095c6cc 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -355,7 +355,7 @@ typedef struct Cp437GridCommand Cp437GridCommand; /** * This is a type only used by cbindgen to have a type for pointers. */ -typedef struct BitVec BitVec; +typedef struct DisplayBitVec DisplayBitVec; /** *
Untested
@@ -578,7 +578,7 @@ typedef union CommandUnion { * * Rust equivalent: [TypedCommand]. */ -typedef struct Command { +typedef struct GenericCommand { /** * Specifies which kind of command struct is contained in `data` */ @@ -587,7 +587,7 @@ typedef struct Command { * The pointer to the command struct */ union CommandUnion data; -} Command; +} GenericCommand; /** * A raw header. @@ -682,7 +682,8 @@ void sp_bitmap_free(struct Bitmap */*notnull*/ instance); * * This function is part of the `bitmap` module. */ -struct Bitmap *sp_bitmap_from_bitvec(size_t width, BitVec */*notnull*/ bitvec); +struct Bitmap *sp_bitmap_from_bitvec(size_t width, + DisplayBitVec */*notnull*/ bitvec); /** * Calls method [`servicepoint::Bitmap::get`]. @@ -711,11 +712,13 @@ bool sp_bitmap_get(struct Bitmap */*notnull*/ instance, size_t x, size_t y); size_t sp_bitmap_height(struct Bitmap */*notnull*/ instance); /** + * Calls method [`servicepoint::Bitmap::into_bitvec`]. + * * Consumes the Bitmap and returns the contained BitVec. * * This function is part of the `bitmap` module. */ -BitVec */*notnull*/ sp_bitmap_into_bitvec(struct Bitmap */*notnull*/ bitmap); +DisplayBitVec */*notnull*/ sp_bitmap_into_bitvec(struct Bitmap */*notnull*/ bitmap); /** * Loads a [Bitmap] with the specified dimensions from the provided data. @@ -793,6 +796,8 @@ void sp_bitmap_set(struct Bitmap */*notnull*/ instance, bool value); /** + * Calls method [`servicepoint::Bitmap::try_into_packet`]. + * * Creates a [BitmapCommand] and immediately turns that into a [Packet]. * * The provided [Bitmap] gets consumed. @@ -906,13 +911,15 @@ void sp_bitmapcommand_set_origin(struct BitmapCommand */*notnull*/ command, size_t origin_y); /** + * Calls method [`servicepoint::BitmapCommand::try_into_packet`]. + * *Tries to turn a [`BitmapCommand`] into a [Packet]. * * Returns: NULL or a [Packet] containing the command. * * This function is part of the `bitmapcommand` module. */ -struct Packet *sp_bitmapcommand_try_into_packet(struct BitmapCommand */*notnull*/ command); +struct Packet *sp_bitmapcommand_try_into_packet(struct BitmapCommand */*notnull*/ instance); /** *Clones a [`BitVecCommand`] instance. @@ -936,7 +943,7 @@ void sp_bitveccommand_free(struct BitVecCommand */*notnull*/ instance); * * This function is part of the `bitveccommand` module. */ -BitVec */*notnull*/ sp_bitveccommand_get_bitvec_mut(struct BitVecCommand */*notnull*/ instance); +DisplayBitVec */*notnull*/ sp_bitveccommand_get_bitvec_mut(struct BitVecCommand */*notnull*/ instance); /** * Gets the value of field `compression` of the [`servicepoint::BitVecCommand`]. @@ -975,7 +982,7 @@ BinaryOperation sp_bitveccommand_get_operation(struct BitVecCommand */*notnull*/ * * This function is part of the `bitveccommand` module. */ -struct BitVecCommand */*notnull*/ sp_bitveccommand_new(BitVec */*notnull*/ bitvec, +struct BitVecCommand */*notnull*/ sp_bitveccommand_new(DisplayBitVec */*notnull*/ bitvec, size_t offset, BinaryOperation operation, CompressionCode compression); @@ -987,7 +994,7 @@ struct BitVecCommand */*notnull*/ sp_bitveccommand_new(BitVec */*notnull*/ bitve * This function is part of the `bitveccommand` module. */ void sp_bitveccommand_set_bitvec(struct BitVecCommand */*notnull*/ instance, - BitVec */*notnull*/ value); + DisplayBitVec */*notnull*/ value); /** * Sets the value of field `compression` of the [`servicepoint::BitVecCommand`]. @@ -1014,13 +1021,15 @@ void sp_bitveccommand_set_operation(struct BitVecCommand */*notnull*/ instance, BinaryOperation value); /** + * Calls method [`servicepoint::BitVecCommand::try_into_packet`]. + * *Tries to turn a [`BitVecCommand`] into a [Packet]. * * Returns: NULL or a [Packet] containing the command. * * This function is part of the `bitveccommand` module. */ -struct Packet *sp_bitveccommand_try_into_packet(struct BitVecCommand */*notnull*/ command); +struct Packet *sp_bitveccommand_try_into_packet(struct BitVecCommand */*notnull*/ instance); /** *Clones a [`BrightnessGrid`] instance. @@ -1147,6 +1156,8 @@ void sp_brightnessgrid_set(BrightnessGrid */*notnull*/ instance, Brightness value); /** + * Calls method [`servicepoint::BrightnessGrid::try_into_packet`]. + * * Creates a [BrightnessGridCommand] and immediately turns that into a [Packet]. * * The provided [BrightnessGrid] gets consumed. @@ -1241,13 +1252,15 @@ void sp_brightnessgridcommand_set_origin(struct BrightnessGridCommand */*notnull size_t origin_y); /** + * Calls method [`servicepoint::BrightnessGridCommand::try_into_packet`]. + * *Tries to turn a [`BrightnessGridCommand`] into a [Packet]. * * Returns: NULL or a [Packet] containing the command. * * This function is part of the `brightnessgridcommand` module. */ -struct Packet *sp_brightnessgridcommand_try_into_packet(struct BrightnessGridCommand */*notnull*/ command); +struct Packet *sp_brightnessgridcommand_try_into_packet(struct BrightnessGridCommand */*notnull*/ instance); /** *Clones a [`CharGrid`] instance. @@ -1355,6 +1368,8 @@ void sp_chargrid_set(CharGrid */*notnull*/ instance, uint32_t value); /** + * Calls method [`servicepoint::CharGrid::try_into_packet`]. + * * Creates a [CharGridCommand] and immediately turns that into a [Packet]. * * The provided [CharGrid] gets consumed. @@ -1428,13 +1443,15 @@ void sp_chargridcommand_set_origin(struct CharGridCommand */*notnull*/ command, size_t origin_y); /** + * Calls method [`servicepoint::CharGridCommand::try_into_packet`]. + * *Tries to turn a [`CharGridCommand`] into a [Packet]. * * Returns: NULL or a [Packet] containing the command. * * This function is part of the `chargridcommand` module. */ -struct Packet *sp_chargridcommand_try_into_packet(struct CharGridCommand */*notnull*/ command); +struct Packet *sp_chargridcommand_try_into_packet(struct CharGridCommand */*notnull*/ instance); /** *Clones a [`ClearCommand`] instance. @@ -1462,13 +1479,15 @@ void sp_clearcommand_free(struct ClearCommand */*notnull*/ instance); struct ClearCommand */*notnull*/ sp_clearcommand_new(void); /** + * Calls method [`servicepoint::ClearCommand::try_into_packet`]. + * *Tries to turn a [`ClearCommand`] into a [Packet]. * * Returns: NULL or a [Packet] containing the command. * * This function is part of the `clearcommand` module. */ -struct Packet *sp_clearcommand_try_into_packet(struct ClearCommand */*notnull*/ command); +struct Packet *sp_clearcommand_try_into_packet(struct ClearCommand */*notnull*/ instance); /** * Moves the provided [CharGrid] into a new [CharGridCommand], @@ -1512,52 +1531,6 @@ struct Cp437GridCommand */*notnull*/ sp_cmd_cp437grid_new(Cp437Grid */*notnull*/ size_t origin_x, size_t origin_y); -/** - * Clones an [SPCommand] instance. - * - * returns: a new [SPCommand] instance. - * - * This function is part of the `cmd_generic` module. - */ -struct Command sp_cmd_generic_clone(struct Command command); - -/** - * Deallocates an [SPCommand]. - * - * Commands with an invalid `tag` do not have to be freed as the `data` pointer should be null. - * - * # Examples - * - * ```C - * SPCommand c = sp_cmd_clear_into_generic(sp_cmd_clear_new()); - * sp_command_free(c); - * ``` - * - * This function is part of the `cmd_generic` module. - */ -void sp_cmd_generic_free(struct Command command); - -/** - * Tries to turn a [SPCommand] into a [Packet]. - * The [SPCommand] gets consumed. - * - * Returns tag [CommandTag::Invalid] in case of an error. - * - * This function is part of the `cmd_generic` module. - */ -struct Packet *sp_cmd_generic_into_packet(struct Command command); - -/** - * Tries to turn a [Packet] into a [SPCommand]. - * - * The packet is dropped in the process. - * - * Returns: pointer to new [SPCommand] instance or NULL if parsing failed. - * - * This function is part of the `cmd_generic` module. - */ -struct Command sp_cmd_generic_try_from_packet(struct Packet */*notnull*/ packet); - /** *Clones a [`Cp437Grid`] instance. * @@ -1662,6 +1635,8 @@ void sp_cp437grid_set(Cp437Grid */*notnull*/ instance, uint8_t value); /** + * Calls method [`servicepoint::Cp437Grid::try_into_packet`]. + * * Creates a [Cp437GridCommand] and immediately turns that into a [Packet]. * * The provided [Cp437Grid] gets consumed. @@ -1735,13 +1710,15 @@ void sp_cp437gridcommand_set_origin(struct Cp437GridCommand */*notnull*/ command size_t origin_y); /** + * Calls method [`servicepoint::Cp437GridCommand::try_into_packet`]. + * *Tries to turn a [`Cp437GridCommand`] into a [Packet]. * * Returns: NULL or a [Packet] containing the command. * * This function is part of the `cp437gridcommand` module. */ -struct Packet *sp_cp437gridcommand_try_into_packet(struct Cp437GridCommand */*notnull*/ command); +struct Packet *sp_cp437gridcommand_try_into_packet(struct Cp437GridCommand */*notnull*/ instance); /** * Calls method [`servicepoint::DisplayBitVec::as_raw_mut_slice`]. @@ -1752,14 +1729,14 @@ struct Packet *sp_cp437gridcommand_try_into_packet(struct Cp437GridCommand */*no * * This function is part of the `displaybitvec` module. */ -struct ByteSlice sp_displaybitvec_as_raw_mut_slice(BitVec */*notnull*/ instance); +struct ByteSlice sp_displaybitvec_as_raw_mut_slice(DisplayBitVec */*notnull*/ instance); /** *Clones a [`DisplayBitVec`] instance. * * This function is part of the `displaybitvec` module. */ -BitVec */*notnull*/ sp_displaybitvec_clone(BitVec */*notnull*/ instance); +DisplayBitVec */*notnull*/ sp_displaybitvec_clone(DisplayBitVec */*notnull*/ instance); /** * Calls method [`servicepoint::DisplayBitVec::fill`]. @@ -1772,14 +1749,14 @@ BitVec */*notnull*/ sp_displaybitvec_clone(BitVec */*notnull*/ instance); * * This function is part of the `displaybitvec` module. */ -void sp_displaybitvec_fill(BitVec */*notnull*/ instance, bool value); +void sp_displaybitvec_fill(DisplayBitVec */*notnull*/ instance, bool value); /** *Deallocates a [`DisplayBitVec`] instance. * * This function is part of the `displaybitvec` module. */ -void sp_displaybitvec_free(BitVec */*notnull*/ instance); +void sp_displaybitvec_free(DisplayBitVec */*notnull*/ instance); /** * Calls method [`servicepoint::DisplayBitVec::get`]. @@ -1799,7 +1776,7 @@ void sp_displaybitvec_free(BitVec */*notnull*/ instance); * * This function is part of the `displaybitvec` module. */ -bool sp_displaybitvec_get(BitVec */*notnull*/ instance, size_t index); +bool sp_displaybitvec_get(DisplayBitVec */*notnull*/ instance, size_t index); /** * Calls method [`servicepoint::DisplayBitVec::is_empty`]. @@ -1808,7 +1785,7 @@ bool sp_displaybitvec_get(BitVec */*notnull*/ instance, size_t index); * * This function is part of the `displaybitvec` module. */ -bool sp_displaybitvec_is_empty(BitVec */*notnull*/ instance); +bool sp_displaybitvec_is_empty(DisplayBitVec */*notnull*/ instance); /** * Calls method [`servicepoint::DisplayBitVec::len`]. @@ -1817,7 +1794,7 @@ bool sp_displaybitvec_is_empty(BitVec */*notnull*/ instance); * * This function is part of the `displaybitvec` module. */ -size_t sp_displaybitvec_len(BitVec */*notnull*/ instance); +size_t sp_displaybitvec_len(DisplayBitVec */*notnull*/ instance); /** * Interpret the data as a series of bits and load then into a new [DisplayBitVec] instance. @@ -1826,7 +1803,7 @@ size_t sp_displaybitvec_len(BitVec */*notnull*/ instance); * * This function is part of the `displaybitvec` module. */ -BitVec */*notnull*/ sp_displaybitvec_load(struct ByteSlice data); +DisplayBitVec */*notnull*/ sp_displaybitvec_load(struct ByteSlice data); /** * Creates a new [DisplayBitVec] instance. @@ -1843,7 +1820,7 @@ BitVec */*notnull*/ sp_displaybitvec_load(struct ByteSlice data); * * This function is part of the `displaybitvec` module. */ -BitVec */*notnull*/ sp_displaybitvec_new(size_t size); +DisplayBitVec */*notnull*/ sp_displaybitvec_new(size_t size); /** * Calls method [`servicepoint::DisplayBitVec::set`]. @@ -1861,11 +1838,13 @@ BitVec */*notnull*/ sp_displaybitvec_new(size_t size); * * This function is part of the `displaybitvec` module. */ -void sp_displaybitvec_set(BitVec */*notnull*/ instance, +void sp_displaybitvec_set(DisplayBitVec */*notnull*/ instance, size_t index, bool value); /** + * Calls method [`servicepoint::DisplayBitVec::try_into_packet`]. + * * Creates a [BitVecCommand] and immediately turns that into a [Packet]. * * The provided [DisplayBitVec] gets consumed. @@ -1874,7 +1853,7 @@ void sp_displaybitvec_set(BitVec */*notnull*/ instance, * * This function is part of the `displaybitvec` module. */ -struct Packet *sp_displaybitvec_try_into_packet(BitVec */*notnull*/ bitvec, +struct Packet *sp_displaybitvec_try_into_packet(DisplayBitVec */*notnull*/ bitvec, size_t offset, BinaryOperation operation, CompressionCode compression); @@ -1911,13 +1890,52 @@ void sp_fadeoutcommand_free(struct FadeOutCommand */*notnull*/ instance); struct FadeOutCommand */*notnull*/ sp_fadeoutcommand_new(void); /** + * Calls method [`servicepoint::FadeOutCommand::try_into_packet`]. + * *Tries to turn a [`FadeOutCommand`] into a [Packet]. * * Returns: NULL or a [Packet] containing the command. * * This function is part of the `fadeoutcommand` module. */ -struct Packet *sp_fadeoutcommand_try_into_packet(struct FadeOutCommand */*notnull*/ command); +struct Packet *sp_fadeoutcommand_try_into_packet(struct FadeOutCommand */*notnull*/ instance); + +/** + *Clones a [`GenericCommand`] instance. + * + * This function is part of the `genericcommand` module. + */ +struct GenericCommand */*notnull*/ sp_genericcommand_clone(struct GenericCommand */*notnull*/ instance); + +/** + *Deallocates a [`GenericCommand`] instance. + * + * This function is part of the `genericcommand` module. + */ +void sp_genericcommand_free(struct GenericCommand */*notnull*/ instance); + +/** + * Tries to turn a [Packet] into a [GenericCommand]. + * + * The packet is dropped in the process. + * + * Returns: pointer to new [GenericCommand] instance or NULL if parsing failed. + * + * This function is part of the `genericcommand` module. + */ +struct GenericCommand */*notnull*/ sp_genericcommand_try_from_packet(struct Packet */*notnull*/ packet); + +/** + * Calls method [`servicepoint::GenericCommand::try_into_packet`]. + * + * Tries to turn a [GenericCommand] into a [Packet]. + * The [GenericCommand] gets consumed. + * + * Returns tag [CommandTag::Invalid] in case of an error. + * + * This function is part of the `genericcommand` module. + */ +struct Packet *sp_genericcommand_try_into_packet(struct GenericCommand */*notnull*/ command); /** *Clones a [`GlobalBrightnessCommand`] instance. @@ -1958,13 +1976,15 @@ void sp_globalbrightnesscommand_set_brightness(struct GlobalBrightnessCommand */ Brightness value); /** + * Calls method [`servicepoint::GlobalBrightnessCommand::try_into_packet`]. + * *Tries to turn a [`GlobalBrightnessCommand`] into a [Packet]. * * Returns: NULL or a [Packet] containing the command. * * This function is part of the `globalbrightnesscommand` module. */ -struct Packet *sp_globalbrightnesscommand_try_into_packet(struct GlobalBrightnessCommand */*notnull*/ command); +struct Packet *sp_globalbrightnesscommand_try_into_packet(struct GlobalBrightnessCommand */*notnull*/ instance); /** *Clones a [`HardResetCommand`] instance. @@ -1992,13 +2012,15 @@ void sp_hardresetcommand_free(struct HardResetCommand */*notnull*/ instance); struct HardResetCommand */*notnull*/ sp_hardresetcommand_new(void); /** + * Calls method [`servicepoint::HardResetCommand::try_into_packet`]. + * *Tries to turn a [`HardResetCommand`] into a [Packet]. * * Returns: NULL or a [Packet] containing the command. * * This function is part of the `hardresetcommand` module. */ -struct Packet *sp_hardresetcommand_try_into_packet(struct HardResetCommand */*notnull*/ command); +struct Packet *sp_hardresetcommand_try_into_packet(struct HardResetCommand */*notnull*/ instance); /** *Clones a [`Packet`] instance. @@ -2147,7 +2169,9 @@ struct UdpSocket *sp_udpsocket_open_ipv4(uint8_t ip1, uint16_t port); /** - * Sends a [SPCommand] to the display using the [UdpSocket]. + * Calls method [`servicepoint::UdpSocket::send_command`]. + * + * Sends a [GenericCommand] to the display using the [UdpSocket]. * * The passed `command` gets consumed. * @@ -2162,9 +2186,11 @@ struct UdpSocket *sp_udpsocket_open_ipv4(uint8_t ip1, * This function is part of the `udpsocket` module. */ bool sp_udpsocket_send_command(struct UdpSocket */*notnull*/ connection, - struct Command command); + struct GenericCommand */*notnull*/ command); /** + * Calls method [`servicepoint::UdpSocket::send_header`]. + * * Sends a [Header] to the display using the [UdpSocket]. * * returns: true in case of success @@ -2181,6 +2207,8 @@ bool sp_udpsocket_send_header(struct UdpSocket */*notnull*/ udp_connection, struct Header header); /** + * Calls method [`servicepoint::UdpSocket::send_packet`]. + * * Sends a [Packet] to the display using the [UdpSocket]. * * The passed `packet` gets consumed. diff --git a/src/commands/generic_command.rs b/src/commands/generic_command.rs index a4775d9..609daac 100644 --- a/src/commands/generic_command.rs +++ b/src/commands/generic_command.rs @@ -1,5 +1,5 @@ use crate::{ - macros::wrap_functions, + macros::{derive_clone, derive_free, wrap_functions}, mem::{ heap_clone, heap_drop, heap_move, heap_move_nonnull, heap_move_ok, heap_remove, @@ -11,6 +11,7 @@ use servicepoint::{ HardResetCommand, Packet, TypedCommand, }; use std::ptr::{null_mut, NonNull}; +use crate::macros::wrap_methods; /// Pointer to one of the available command structs. #[repr(C)] @@ -55,214 +56,211 @@ pub enum CommandTag { /// /// Rust equivalent: [TypedCommand]. #[repr(C)] -pub struct SPCommand { +pub struct GenericCommand { /// Specifies which kind of command struct is contained in `data` pub tag: CommandTag, /// The pointer to the command struct pub data: CommandUnion, } -impl SPCommand { - const INVALID: SPCommand = SPCommand { +impl GenericCommand { + pub(crate) const INVALID: GenericCommand = GenericCommand { tag: CommandTag::Invalid, data: CommandUnion { null: null_mut() }, }; } -wrap_functions!(cmd_generic; +derive_clone!(GenericCommand); - /// Tries to turn a [Packet] into a [SPCommand]. +impl Clone for GenericCommand { + fn clone(&self) -> Self { + unsafe { + match self.tag { + CommandTag::Clear => GenericCommand { + tag: CommandTag::Clear, + data: CommandUnion { + clear: heap_clone(self.data.clear), + }, + }, + CommandTag::CharGrid => GenericCommand { + tag: CommandTag::CharGrid, + data: CommandUnion { + char_grid: heap_clone(self.data.char_grid), + }, + }, + CommandTag::Cp437Grid => GenericCommand { + tag: CommandTag::Cp437Grid, + data: CommandUnion { + cp437_grid: heap_clone(self.data.cp437_grid), + }, + }, + CommandTag::Bitmap => GenericCommand { + tag: CommandTag::Bitmap, + data: CommandUnion { + bitmap: heap_clone(self.data.bitmap), + }, + }, + CommandTag::GlobalBrightness => GenericCommand { + tag: CommandTag::GlobalBrightness, + data: CommandUnion { + global_brightness: heap_clone( + self.data.global_brightness, + ), + }, + }, + CommandTag::BrightnessGrid => GenericCommand { + tag: CommandTag::BrightnessGrid, + data: CommandUnion { + brightness_grid: heap_clone(self.data.brightness_grid), + }, + }, + CommandTag::BitVec => GenericCommand { + tag: CommandTag::BitVec, + data: CommandUnion { + bit_vec: heap_clone(self.data.bit_vec), + }, + }, + CommandTag::HardReset => GenericCommand { + tag: CommandTag::HardReset, + data: CommandUnion { + hard_reset: heap_clone(self.data.hard_reset), + }, + }, + CommandTag::FadeOut => GenericCommand { + tag: CommandTag::FadeOut, + data: CommandUnion { + fade_out: heap_clone(self.data.fade_out), + }, + }, + #[allow(deprecated)] + CommandTag::BitmapLegacy => GenericCommand { + tag: CommandTag::BitmapLegacy, + data: CommandUnion { + bitmap_legacy: heap_clone(self.data.bitmap_legacy), + }, + }, + CommandTag::Invalid => GenericCommand::INVALID, + } + } + } +} + +derive_free!(GenericCommand); + +impl Drop for GenericCommand { + fn drop(&mut self) { + unsafe { + match self.tag { + CommandTag::Invalid => (), + CommandTag::Bitmap => heap_drop(self.data.bitmap), + CommandTag::BitVec => heap_drop(self.data.bit_vec), + CommandTag::BrightnessGrid => { + heap_drop(self.data.brightness_grid) + } + CommandTag::CharGrid => heap_drop(self.data.char_grid), + CommandTag::Cp437Grid => heap_drop(self.data.cp437_grid), + CommandTag::GlobalBrightness => { + heap_drop(self.data.global_brightness) + } + CommandTag::Clear => heap_drop(self.data.clear), + CommandTag::HardReset => heap_drop(self.data.hard_reset), + CommandTag::FadeOut => heap_drop(self.data.fade_out), + CommandTag::BitmapLegacy => heap_drop(self.data.bitmap_legacy), + } + } + } +} + +wrap_functions!(associate GenericCommand; + + /// Tries to turn a [Packet] into a [GenericCommand]. /// /// The packet is dropped in the process. /// - /// Returns: pointer to new [SPCommand] instance or NULL if parsing failed. + /// Returns: pointer to new [GenericCommand] instance or NULL if parsing failed. fn try_from_packet( packet: NonNull, - ) -> SPCommand { + ) -> NonNull { let packet = *unsafe { Box::from_raw(packet.as_ptr()) }; - servicepoint::TypedCommand::try_from(packet) + let result = servicepoint::TypedCommand::try_from(packet) .map(|value| match value { - TypedCommand::Clear(clear) => SPCommand { + TypedCommand::Clear(clear) => GenericCommand { tag: CommandTag::Clear, data: CommandUnion { clear: heap_move_nonnull(clear), }, }, - TypedCommand::CharGrid(char_grid) => SPCommand { + TypedCommand::CharGrid(char_grid) => GenericCommand { tag: CommandTag::CharGrid, data: CommandUnion { char_grid: heap_move_nonnull(char_grid), }, }, - TypedCommand::Cp437Grid(cp437_grid) => SPCommand { + TypedCommand::Cp437Grid(cp437_grid) => GenericCommand { tag: CommandTag::Cp437Grid, data: CommandUnion { cp437_grid: heap_move_nonnull(cp437_grid), }, }, - TypedCommand::Bitmap(bitmap) => SPCommand { + TypedCommand::Bitmap(bitmap) => GenericCommand { tag: CommandTag::Bitmap, data: CommandUnion { bitmap: heap_move_nonnull(bitmap), }, }, - TypedCommand::Brightness(global_brightness) => SPCommand { + TypedCommand::Brightness(global_brightness) => GenericCommand { tag: CommandTag::GlobalBrightness, data: CommandUnion { global_brightness: heap_move_nonnull(global_brightness), }, }, - TypedCommand::BrightnessGrid(brightness_grid) => SPCommand { + TypedCommand::BrightnessGrid(brightness_grid) => GenericCommand { tag: CommandTag::BrightnessGrid, data: CommandUnion { brightness_grid: heap_move_nonnull(brightness_grid), }, }, - TypedCommand::BitVec(bitvec) => SPCommand { + TypedCommand::BitVec(bitvec) => GenericCommand { tag: CommandTag::BitVec, data: CommandUnion { bit_vec: heap_move_nonnull(bitvec), }, }, - TypedCommand::HardReset(hard_reset) => SPCommand { + TypedCommand::HardReset(hard_reset) => GenericCommand { tag: CommandTag::HardReset, data: CommandUnion { hard_reset: heap_move_nonnull(hard_reset), }, }, - TypedCommand::FadeOut(fade_out) => SPCommand { + TypedCommand::FadeOut(fade_out) => GenericCommand { tag: CommandTag::FadeOut, data: CommandUnion { fade_out: heap_move_nonnull(fade_out), }, }, #[allow(deprecated)] - TypedCommand::BitmapLegacy(bitmap_legacy) => SPCommand { + TypedCommand::BitmapLegacy(bitmap_legacy) => GenericCommand { tag: CommandTag::BitmapLegacy, data: CommandUnion { bitmap_legacy: heap_move_nonnull(bitmap_legacy), }, }, }) - .unwrap_or_else(move |_| SPCommand { + .unwrap_or_else(move |_| GenericCommand { tag: CommandTag::Invalid, data: CommandUnion { null: null_mut() }, - }) + }); + heap_move_nonnull(result) } - /// Clones an [SPCommand] instance. - /// - /// returns: a new [SPCommand] instance. - fn clone(command: SPCommand) -> SPCommand { - unsafe { - match command.tag { - CommandTag::Clear => SPCommand { - tag: CommandTag::Clear, - data: CommandUnion { - clear: heap_clone(command.data.clear), - }, - }, - CommandTag::CharGrid => SPCommand { - tag: CommandTag::CharGrid, - data: CommandUnion { - char_grid: heap_clone(command.data.char_grid), - }, - }, - CommandTag::Cp437Grid => SPCommand { - tag: CommandTag::Cp437Grid, - data: CommandUnion { - cp437_grid: heap_clone(command.data.cp437_grid), - }, - }, - CommandTag::Bitmap => SPCommand { - tag: CommandTag::Bitmap, - data: CommandUnion { - bitmap: heap_clone(command.data.bitmap), - }, - }, - CommandTag::GlobalBrightness => SPCommand { - tag: CommandTag::GlobalBrightness, - data: CommandUnion { - global_brightness: heap_clone( - command.data.global_brightness, - ), - }, - }, - CommandTag::BrightnessGrid => SPCommand { - tag: CommandTag::BrightnessGrid, - data: CommandUnion { - brightness_grid: heap_clone(command.data.brightness_grid), - }, - }, - CommandTag::BitVec => SPCommand { - tag: CommandTag::BitVec, - data: CommandUnion { - bit_vec: heap_clone(command.data.bit_vec), - }, - }, - CommandTag::HardReset => SPCommand { - tag: CommandTag::HardReset, - data: CommandUnion { - hard_reset: heap_clone(command.data.hard_reset), - }, - }, - CommandTag::FadeOut => SPCommand { - tag: CommandTag::FadeOut, - data: CommandUnion { - fade_out: heap_clone(command.data.fade_out), - }, - }, - #[allow(deprecated)] - CommandTag::BitmapLegacy => SPCommand { - tag: CommandTag::BitmapLegacy, - data: CommandUnion { - bitmap_legacy: heap_clone(command.data.bitmap_legacy), - }, - }, - CommandTag::Invalid => SPCommand::INVALID, - } - } - } +); - /// Deallocates an [SPCommand]. - /// - /// Commands with an invalid `tag` do not have to be freed as the `data` pointer should be null. - /// - /// # Examples - /// - /// ```C - /// SPCommand c = sp_cmd_clear_into_generic(sp_cmd_clear_new()); - /// sp_command_free(c); - /// ``` - fn free(command: SPCommand) { - unsafe { - match command.tag { - CommandTag::Invalid => (), - CommandTag::Bitmap => heap_drop(command.data.bitmap), - CommandTag::BitVec => heap_drop(command.data.bit_vec), - CommandTag::BrightnessGrid => { - heap_drop(command.data.brightness_grid) - } - CommandTag::CharGrid => heap_drop(command.data.char_grid), - CommandTag::Cp437Grid => heap_drop(command.data.cp437_grid), - CommandTag::GlobalBrightness => { - heap_drop(command.data.global_brightness) - } - CommandTag::Clear => heap_drop(command.data.clear), - CommandTag::HardReset => heap_drop(command.data.hard_reset), - CommandTag::FadeOut => heap_drop(command.data.fade_out), - CommandTag::BitmapLegacy => heap_drop(command.data.bitmap_legacy), - } - } - } - - /// Tries to turn a [SPCommand] into a [Packet]. - /// The [SPCommand] gets consumed. +wrap_methods!{GenericCommand; + /// Tries to turn a [GenericCommand] into a [Packet]. + /// The [GenericCommand] gets consumed. /// /// Returns tag [CommandTag::Invalid] in case of an error. - fn into_packet( - command: SPCommand, - ) -> *mut Packet { + move fn try_into_packet(command) -> *mut Packet { match command.tag { CommandTag::Invalid => null_mut(), CommandTag::Bitmap => { @@ -296,6 +294,5 @@ wrap_functions!(cmd_generic; heap_move(unsafe { heap_remove(command.data.bitmap_legacy).into() }) } } - } - -); + }; +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 58e5957..74d22e3 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -50,7 +50,7 @@ macro_rules! wrap_origin_accessors { macro_rules! derive_command_from { ($command:ident) => { ::paste::paste! { - impl From<::servicepoint::[< $command Command >]> for $crate::commands::SPCommand { + impl From<::servicepoint::[< $command Command >]> for $crate::commands::GenericCommand { fn from(command: ::servicepoint::[< $command Command >]) -> Self { Self { tag: $crate::commands::CommandTag::$command, @@ -67,14 +67,12 @@ macro_rules! derive_command_from { macro_rules! derive_command_into_packet { ($command_type:ident) => { ::paste::paste! { - $crate::macros::wrap_functions!(associate $command_type; + $crate::macros::wrap_method!($command_type; #[doc = "Tries to turn a [`" $command_type "`] into a [Packet]."] /// /// Returns: NULL or a [Packet] containing the command. - fn try_into_packet( - command: ::core::ptr::NonNull<$command_type>, - ) -> *mut ::servicepoint::Packet { - $crate::mem::heap_move_ok(unsafe { $crate::mem::heap_remove(command) }.try_into()) + move fn try_into_packet(instance) -> *mut ::servicepoint::Packet { + $crate::mem::heap_move_ok(instance.try_into()) } ); } diff --git a/src/containers/bitmap.rs b/src/containers/bitmap.rs index 9bae852..4ce7972 100644 --- a/src/containers/bitmap.rs +++ b/src/containers/bitmap.rs @@ -12,7 +12,6 @@ use std::ptr::NonNull; wrap_grid!(Bitmap, bool); wrap_functions!(bitmap; - /// Creates a new [Bitmap] with the specified dimensions. /// /// # Arguments @@ -76,35 +75,26 @@ wrap_functions!(bitmap; let bitvec = unsafe { heap_remove(bitvec) }; heap_move_ok(Bitmap::from_bitvec(width, bitvec)) } +); + +wrap_methods!(Bitmap; /// Consumes the Bitmap and returns the contained BitVec. - fn into_bitvec( - bitmap: NonNull - ) -> NonNull { - let bitmap = unsafe { heap_remove(bitmap) }; + move fn into_bitvec(bitmap) -> NonNull { heap_move_nonnull(bitmap.into()) - } + }; /// Creates a [BitmapCommand] and immediately turns that into a [Packet]. /// /// The provided [Bitmap] gets consumed. /// /// Returns NULL in case of an error. - fn try_into_packet( - bitmap: NonNull, - x: usize, - y: usize, - compression: CompressionCode, - ) -> *mut Packet { - let bitmap = unsafe { heap_remove(bitmap) }; + move fn try_into_packet(bitmap, x: usize, y: usize, compression: CompressionCode) -> *mut Packet { heap_move_ok(Packet::try_from(BitmapCommand { bitmap, origin: Origin::new(x, y), compression, })) - } -); - -wrap_methods!(Bitmap; + }; /// Gets an unsafe reference to the data of the [Bitmap] instance. /// diff --git a/src/containers/bitvec.rs b/src/containers/bitvec.rs index 2a76cf7..bc5da06 100644 --- a/src/containers/bitvec.rs +++ b/src/containers/bitvec.rs @@ -1,7 +1,7 @@ use crate::{ containers::{wrap_container, ByteSlice}, macros::{derive_clone, derive_free, wrap_functions, wrap_methods}, - mem::{heap_move_nonnull, heap_move_ok, heap_remove}, + mem::{heap_move_nonnull, heap_move_ok}, }; use servicepoint::{ BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Packet, @@ -35,29 +35,27 @@ wrap_functions!(associate DisplayBitVec; heap_move_nonnull(DisplayBitVec::from_slice(data)) } +); + +wrap_methods!(DisplayBitVec; /// Creates a [BitVecCommand] and immediately turns that into a [Packet]. /// /// The provided [DisplayBitVec] gets consumed. /// /// Returns NULL in case of an error. - fn try_into_packet( - bitvec: NonNull, + move fn try_into_packet( + bitvec, offset: usize, operation: BinaryOperation, - compression: CompressionCode, + compression: CompressionCode ) -> *mut Packet { - let bitvec = unsafe { heap_remove(bitvec) }; heap_move_ok(Packet::try_from(BitVecCommand { bitvec, offset, operation, compression, })) - } - -); - -wrap_methods!(DisplayBitVec; + }; /// Gets the value of a bit. /// diff --git a/src/containers/brightness_grid.rs b/src/containers/brightness_grid.rs index a5d01f2..7c27d5c 100644 --- a/src/containers/brightness_grid.rs +++ b/src/containers/brightness_grid.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}, + mem::{heap_move_nonnull, heap_move_ok, heap_move_some}, }; use servicepoint::{ Brightness, BrightnessGrid, BrightnessGridCommand, ByteGrid, DataRef, Grid, @@ -54,26 +54,21 @@ wrap_functions!(associate BrightnessGrid; ) } +); + +wrap_methods!(BrightnessGrid; /// Creates a [BrightnessGridCommand] and immediately turns that into a [Packet]. /// /// The provided [BrightnessGrid] gets consumed. /// /// Returns NULL in case of an error. - fn try_into_packet( - grid: NonNull, - x: usize, - y: usize, - ) -> *mut Packet { - let grid = unsafe { heap_remove(grid) }; + move fn try_into_packet(grid, x: usize, y: usize) -> *mut Packet { heap_move_ok(Packet::try_from(BrightnessGridCommand { grid, origin: Origin::new(x, y), })) - } + }; -); - -wrap_methods!(BrightnessGrid; /// Gets an unsafe reference to the data of the instance. /// /// The returned memory is valid for the lifetime of the grid. diff --git a/src/containers/char_grid.rs b/src/containers/char_grid.rs index 1a59fdd..1966f4a 100644 --- a/src/containers/char_grid.rs +++ b/src/containers/char_grid.rs @@ -1,7 +1,7 @@ use crate::{ containers::{derive_get_width_height, wrap_container, ByteSlice}, macros::{derive_clone, derive_free, wrap_functions, wrap_methods}, - mem::{heap_move_nonnull, heap_move_ok, heap_remove}, + mem::{heap_move_nonnull, heap_move_ok}, }; use servicepoint::{CharGrid, CharGridCommand, Grid, Origin, Packet}; use std::ptr::NonNull; @@ -23,41 +23,18 @@ 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: usize, height: 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: usize, height: usize, data: ByteSlice) -> *mut CharGrid { let data = unsafe { data.as_slice() }; heap_move_ok(CharGrid::load_utf8(width, height, data.to_vec())) } - /// Creates a [CharGridCommand] and immediately turns that into a [Packet]. - /// - /// The provided [CharGrid] gets consumed. - /// - /// Returns NULL in case of an error. - fn try_into_packet( - grid: NonNull, - x: usize, - y: usize, - ) -> *mut Packet { - let grid = unsafe { heap_remove(grid) }; - heap_move_ok(Packet::try_from(CharGridCommand { - grid, - origin: Origin::new(x, y), - })) - } ); @@ -102,4 +79,16 @@ wrap_methods!(CharGrid; mut fn fill(instance, value: u32) { instance.fill(char::from_u32(value).unwrap()) }; + + /// Creates a [CharGridCommand] and immediately turns that into a [Packet]. + /// + /// The provided [CharGrid] gets consumed. + /// + /// Returns NULL in case of an error. + move fn try_into_packet(grid, x: usize, y: 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 fc31d13..38efc58 100644 --- a/src/containers/cp437_grid.rs +++ b/src/containers/cp437_grid.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}, + mem::{heap_move_nonnull, heap_move_ok, heap_move_some}, }; use servicepoint::{ Cp437Grid, Cp437GridCommand, DataRef, Grid, Origin, Packet, @@ -32,26 +32,21 @@ wrap_functions!(cp437grid; heap_move_some(Cp437Grid::load(width, height, data)) } +); + +wrap_methods!(Cp437Grid; /// Creates a [Cp437GridCommand] and immediately turns that into a [Packet]. /// /// The provided [Cp437Grid] gets consumed. /// /// Returns NULL in case of an error. - fn try_into_packet( - grid: NonNull, - x: usize, - y: usize, - ) -> *mut Packet { - let grid = unsafe { heap_remove(grid) }; + move fn try_into_packet(grid, x: usize, y: usize) -> *mut Packet { heap_move_ok(Packet::try_from(Cp437GridCommand { grid, origin: Origin::new(x, y), })) - } + }; -); - -wrap_methods!(Cp437Grid; /// Gets an unsafe reference to the data of the grid. /// /// The returned memory is valid for the lifetime of the instance. diff --git a/src/macros.rs b/src/macros.rs index e0560f5..768254b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -36,6 +36,12 @@ macro_rules! nonnull_as_mut { }; } +macro_rules! nonnull_as_move { + ($ident:ident) => { + $crate::mem::heap_remove($ident) + }; +} + macro_rules! wrap_method { ( $object_type:ident; @@ -229,6 +235,7 @@ macro_rules! wrap_functions { } pub(crate) use { - derive_clone, derive_free, nonnull_as_mut, nonnull_as_ref, wrap_fields, - wrap_functions, wrap_methods, wrap_fields_accessor, wrap_method + derive_clone, derive_free, nonnull_as_move, nonnull_as_mut, nonnull_as_ref, + wrap_fields, wrap_fields_accessor, wrap_functions, wrap_method, + wrap_methods, }; diff --git a/src/udp.rs b/src/udp.rs index 321c4d1..7889937 100644 --- a/src/udp.rs +++ b/src/udp.rs @@ -1,6 +1,6 @@ use crate::{ - commands::{CommandTag, SPCommand}, - macros::{derive_free, wrap_functions}, + commands::{CommandTag, GenericCommand}, + macros::{derive_free, wrap_functions, wrap_methods}, mem::{heap_move_ok, heap_remove}, }; use servicepoint::{Header, Packet, UdpSocketExt}; @@ -49,17 +49,20 @@ wrap_functions!(associate UdpSocket; heap_move_ok(UdpSocket::bind_connect(addr)) } +); + +wrap_methods! {UdpSocket; /// Sends a [Packet] to the display using the [UdpSocket]. /// /// The passed `packet` gets consumed. /// /// returns: true in case of success - fn send_packet(connection: NonNull, packet: NonNull) -> bool { + ref fn send_packet(connection, packet: NonNull) -> bool { let packet = unsafe { heap_remove(packet) }; - unsafe { connection.as_ref().send(&Vec::from(packet)) }.is_ok() - } + connection.send(&Vec::from(packet)).is_ok() + }; - /// Sends a [SPCommand] to the display using the [UdpSocket]. + /// Sends a [GenericCommand] to the display using the [UdpSocket]. /// /// The passed `command` gets consumed. /// @@ -70,44 +73,26 @@ wrap_functions!(associate UdpSocket; /// ```C /// sp_udp_send_command(connection, sp_command_brightness(5)); /// ``` - fn send_command(connection: NonNull, command: SPCommand) -> bool { + ref fn send_command(connection, command: NonNull) -> bool { unsafe { - match command.tag { + let command = crate::macros::nonnull_as_mut!(command); + let result = match command.tag { CommandTag::Invalid => return false, - CommandTag::Bitmap => connection - .as_ref() - .send_command(heap_remove(command.data.bitmap)), - CommandTag::BitVec => connection - .as_ref() - .send_command(heap_remove(command.data.bit_vec)), - CommandTag::BrightnessGrid => connection - .as_ref() - .send_command(heap_remove(command.data.brightness_grid)), - CommandTag::CharGrid => connection - .as_ref() - .send_command(heap_remove(command.data.char_grid)), - CommandTag::Cp437Grid => connection - .as_ref() - .send_command(heap_remove(command.data.cp437_grid)), - CommandTag::GlobalBrightness => connection - .as_ref() - .send_command(heap_remove(command.data.global_brightness)), - CommandTag::Clear => connection - .as_ref() - .send_command(heap_remove(command.data.clear)), - CommandTag::HardReset => connection - .as_ref() - .send_command(heap_remove(command.data.hard_reset)), - CommandTag::FadeOut => connection - .as_ref() - .send_command(heap_remove(command.data.fade_out)), - CommandTag::BitmapLegacy => connection - .as_ref() - .send_command(heap_remove(command.data.bitmap_legacy)), - } + CommandTag::Bitmap => connection.send_command(heap_remove(command.data.bitmap)), + CommandTag::BitVec => connection.send_command(heap_remove(command.data.bit_vec)), + CommandTag::BrightnessGrid => connection.send_command(heap_remove(command.data.brightness_grid)), + CommandTag::CharGrid => connection.send_command(heap_remove(command.data.char_grid)), + CommandTag::Cp437Grid => connection.send_command(heap_remove(command.data.cp437_grid)), + CommandTag::GlobalBrightness => connection.send_command(heap_remove(command.data.global_brightness)), + CommandTag::Clear => connection.send_command(heap_remove(command.data.clear)), + CommandTag::HardReset => connection.send_command(heap_remove(command.data.hard_reset)), + CommandTag::FadeOut => connection.send_command(heap_remove(command.data.fade_out)), + CommandTag::BitmapLegacy => connection.send_command(heap_remove(command.data.bitmap_legacy)), + }.is_some(); + *command = GenericCommand::INVALID; + result } - .is_some() - } + }; /// Sends a [Header] to the display using the [UdpSocket]. /// @@ -118,17 +103,14 @@ wrap_functions!(associate UdpSocket; /// ```C /// sp_udp_send_header(connection, sp_command_brightness(5)); /// ``` - fn send_header(udp_connection: NonNull, header: Header) -> bool { + ref fn send_header(udp_connection, header: Header) -> bool { let packet = Packet { header, payload: None, }; - unsafe { udp_connection.as_ref() } - .send(&Vec::from(packet)) - .is_ok() - } - -); + udp_connection.send(&Vec::from(packet)).is_ok() + }; +} mod _hidden { /// This is a type only used by cbindgen to have a type for pointers.