From 85ccf4123c36918c93aa7d4bffb85826027c858e Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Tue, 6 May 2025 22:54:54 +0200 Subject: [PATCH] expose tagged union instead of TypedCommand to C --- cbindgen.toml | 1 + include/servicepoint.h | 280 +++++++++++++-------- src/bitmap.rs | 6 +- src/bitvec.rs | 5 +- src/brightness_grid.rs | 8 +- src/char_grid.rs | 7 +- src/commands/bitmap_command.rs | 15 +- src/commands/bitvec_command.rs | 15 +- src/commands/brightness_grid_command.rs | 14 +- src/commands/cc_only_commands.rs | 54 +++++ src/commands/char_grid_command.rs | 15 +- src/commands/cp437_grid_command.rs | 15 +- src/commands/generic_command.rs | 281 ++++++++++++++++++++++ src/commands/global_brightness_command.rs | 53 ++++ src/commands/mod.rs | 4 + src/cp437_grid.rs | 8 +- src/lib.rs | 5 +- src/packet.rs | 19 +- src/typed_command.rs | 86 ------- src/udp.rs | 43 +++- 20 files changed, 657 insertions(+), 277 deletions(-) create mode 100644 src/commands/cc_only_commands.rs create mode 100644 src/commands/generic_command.rs create mode 100644 src/commands/global_brightness_command.rs delete mode 100644 src/typed_command.rs diff --git a/cbindgen.toml b/cbindgen.toml index 68723da..eca3164 100644 --- a/cbindgen.toml +++ b/cbindgen.toml @@ -37,6 +37,7 @@ exclude = ["BitVec"] [export.rename] "SpBitVec" = "BitVec" "SpByteSlice" = "ByteSlice" +"SpCommand" = "Command" [enum] rename_variants = "QualifiedScreamingSnakeCase" diff --git a/include/servicepoint.h b/include/servicepoint.h index 02f4676..404e291 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -125,6 +125,27 @@ enum CommandCode typedef uint16_t CommandCode; #endif // __cplusplus +enum CommandTag +#ifdef __cplusplus + : uint8_t +#endif // __cplusplus + { + COMMAND_TAG_INVALID = 0, + COMMAND_TAG_BITMAP, + COMMAND_TAG_BIT_VEC, + COMMAND_TAG_BRIGHTNESS_GRID, + COMMAND_TAG_CHAR_GRID, + COMMAND_TAG_CP437_GRID, + COMMAND_TAG_GLOBAL_BRIGHTNESS, + COMMAND_TAG_CLEAR, + COMMAND_TAG_HARD_RESET, + COMMAND_TAG_FADE_OUT, + COMMAND_TAG_BITMAP_LEGACY, +}; +#ifndef __cplusplus +typedef uint8_t CommandTag; +#endif // __cplusplus + /** * Specifies the kind of compression to use. Availability depends on features. * @@ -239,6 +260,23 @@ typedef struct Bitmap Bitmap; */ typedef struct BitmapCommand BitmapCommand; +/** + * Legacy command code, gets ignored by the real display. + * + * Might be useful as a noop package. + * + * # Examples + * + * ```rust + * # use servicepoint::*; + * # let connection = FakeConnection; + * // this sends a packet that does nothing + * # #[allow(deprecated)] + * connection.send_command(BitmapLegacyCommand).unwrap(); + * ``` + */ +typedef struct BitmapLegacyCommand BitmapLegacyCommand; + /** * Set the brightness of individual tiles in a rectangular area of the display. */ @@ -260,6 +298,19 @@ typedef struct BrightnessGridCommand BrightnessGridCommand; */ typedef struct CharGridCommand CharGridCommand; +/** + * Set all pixels to the off state. Does not affect brightness. + * + * # Examples + * + * ```rust + * # use servicepoint::*; + * # let connection = FakeConnection; + * connection.send_command(ClearCommand).unwrap(); + * ``` + */ +typedef struct ClearCommand ClearCommand; + /** * Show text on the screen. * @@ -292,6 +343,50 @@ typedef struct Cp437GridCommand Cp437GridCommand; */ typedef struct DisplayBitVec DisplayBitVec; +/** + *
Untested
+ * + * Slowly decrease brightness until off or something like that? + * + * # Examples + * + * ```rust + * # use servicepoint::*; + * # let connection = FakeConnection; + * connection.send_command(FadeOutCommand).unwrap(); + * ``` + */ +typedef struct FadeOutCommand FadeOutCommand; + +/** + * Set the brightness of all tiles to the same value. + * + * # Examples + * + * ```rust + * # use servicepoint::*; + * # let connection = FakeConnection; + * let command = GlobalBrightnessCommand { brightness: Brightness::MAX }; + * connection.send_command(command).unwrap(); + * ``` + */ +typedef struct GlobalBrightnessCommand GlobalBrightnessCommand; + +/** + * Kills the udp daemon on the display, which usually results in a restart. + * + * Please do not send this in your normal program flow. + * + * # Examples + * + * ```rust + * # use servicepoint::*; + * # let connection = FakeConnection; + * connection.send_command(HardResetCommand).unwrap(); + * ``` + */ +typedef struct HardResetCommand HardResetCommand; + /** * The raw packet. * @@ -313,14 +408,6 @@ typedef struct Packet Packet; */ typedef struct SPBitVec SPBitVec; -/** - * This enum contains all commands provided by the library. - * This is useful in case you want one data type for all kinds of commands without using `dyn`. - * - * Please look at the contained structs for documentation per command. - */ -typedef struct TypedCommand TypedCommand; - /** * This is a type only used by cbindgen to have a type for pointers. */ @@ -456,6 +543,31 @@ typedef size_t Offset; */ typedef ValueGrid_u8 Cp437Grid; +typedef union { + uint8_t *null; + BitmapCommand */*notnull*/ bitmap; + BitVecCommand */*notnull*/ bitvec; + BrightnessGridCommand */*notnull*/ brightness_grid; + CharGridCommand */*notnull*/ char_grid; + Cp437GridCommand */*notnull*/ cp437_grid; + GlobalBrightnessCommand */*notnull*/ global_brightness; + ClearCommand */*notnull*/ clear; + BitmapLegacyCommand */*notnull*/ bitmap_legacy; + HardResetCommand */*notnull*/ hard_reset; + FadeOutCommand */*notnull*/ fade_out; +} CommandUnion; + +typedef struct { + /** + * Specifies which kind of command struct is contained in `data` + */ + CommandTag tag; + /** + * The pointer to the command struct + */ + CommandUnion data; +} SPCommand; + /** * A raw header. * @@ -770,7 +882,7 @@ ByteSlice sp_bitvec_unsafe_data_ref(SPBitVec */*notnull*/ bit_vec); /** * Clones a [BrightnessGrid]. */ -BrightnessGrid */*notnull*/ sp_brightness_grid_clone(BrightnessGrid */*notnull*/ brightness_grid); +BrightnessGrid */*notnull*/ sp_brightness_grid_clone(BrightnessGrid */*notnull*/ grid); /** * Sets the value of all cells in the [BrightnessGrid]. @@ -906,7 +1018,7 @@ size_t sp_brightness_grid_width(BrightnessGrid */*notnull*/ brightness_grid); /** * Clones a [CharGrid]. */ -CharGrid */*notnull*/ sp_char_grid_clone(CharGrid */*notnull*/ char_grid); +CharGrid */*notnull*/ sp_char_grid_clone(CharGrid */*notnull*/ grid); /** * Sets the value of all cells in the [CharGrid]. @@ -1039,8 +1151,6 @@ void sp_cmd_bitmap_get_origin(BitmapCommand */*notnull*/ command, Packet *sp_cmd_bitmap_into_packet(BitmapCommand */*notnull*/ command); -TypedCommand */*notnull*/ sp_cmd_bitmap_into_typed(BitmapCommand */*notnull*/ command); - /** * Sets a window of pixels to the specified values. * @@ -1080,8 +1190,6 @@ BinaryOperation sp_cmd_bitvec_get_operation(BitVecCommand */*notnull*/ command); Packet *sp_cmd_bitvec_into_packet(BitVecCommand */*notnull*/ command); -TypedCommand */*notnull*/ sp_cmd_bitvec_into_typed(BitVecCommand */*notnull*/ command); - /** * Set pixel data starting at the pixel offset on screen. * @@ -1116,6 +1224,22 @@ void sp_cmd_bitvec_set_offset(BitVecCommand */*notnull*/ command, void sp_cmd_bitvec_set_operation(BitVecCommand */*notnull*/ command, BinaryOperation operation); +GlobalBrightnessCommand */*notnull*/ sp_cmd_brightness_global_clone(GlobalBrightnessCommand */*notnull*/ command); + +void sp_cmd_brightness_global_free(BitmapCommand */*notnull*/ command); + +Brightness *sp_cmd_brightness_global_get(GlobalBrightnessCommand */*notnull*/ command); + +Packet *sp_cmd_brightness_global_into_packet(GlobalBrightnessCommand */*notnull*/ command); + +GlobalBrightnessCommand */*notnull*/ sp_cmd_brightness_global_new(Brightness brightness); + +/** + * Moves the provided bitmap to be contained in the command. + */ +void sp_cmd_brightness_global_set(GlobalBrightnessCommand */*notnull*/ command, + Brightness brightness); + BrightnessGridCommand */*notnull*/ sp_cmd_brightness_grid_clone(BrightnessGridCommand */*notnull*/ command); void sp_cmd_brightness_grid_free(BitmapCommand */*notnull*/ command); @@ -1130,8 +1254,6 @@ void sp_cmd_brightness_grid_get_origin(BrightnessGridCommand */*notnull*/ comman Packet *sp_cmd_brightness_grid_into_packet(BrightnessGridCommand */*notnull*/ command); -TypedCommand */*notnull*/ sp_cmd_brightness_grid_into_typed(BrightnessGridCommand */*notnull*/ command); - BrightnessGridCommand */*notnull*/ sp_cmd_brightness_grid_new(BrightnessGrid */*notnull*/ grid, size_t origin_x, size_t origin_y); @@ -1160,8 +1282,6 @@ void sp_cmd_char_grid_get_origin(CharGridCommand */*notnull*/ command, Packet *sp_cmd_char_grid_into_packet(CharGridCommand */*notnull*/ command); -TypedCommand */*notnull*/ sp_cmd_char_grid_into_typed(CharGridCommand */*notnull*/ command); - CharGridCommand */*notnull*/ sp_cmd_char_grid_new(CharGrid */*notnull*/ grid, size_t origin_x, size_t origin_y); @@ -1176,6 +1296,23 @@ void sp_cmd_char_grid_set_origin(CharGridCommand */*notnull*/ command, size_t origin_x, size_t origin_y); +void sp_cmd_clear_free(ClearCommand */*notnull*/ command); + +/** + * Set all pixels to the off state. + * + * Does not affect brightness. + * + * Returns: a new [ClearCommand] instance. + * + * # Examples + * + * ```C + * sp_udp_send_command(connection, sp_cmd_clear()); + * ``` + */ +ClearCommand */*notnull*/ sp_cmd_clear_new(void); + Cp437GridCommand */*notnull*/ sp_cmd_cp437_grid_clone(Cp437GridCommand */*notnull*/ command); void sp_cmd_cp437_grid_free(BitmapCommand */*notnull*/ command); @@ -1190,8 +1327,6 @@ void sp_cmd_cp437_grid_get_origin(Cp437GridCommand */*notnull*/ command, Packet *sp_cmd_cp437_grid_into_packet(Cp437GridCommand */*notnull*/ command); -TypedCommand */*notnull*/ sp_cmd_cp437_grid_into_typed(Cp437GridCommand */*notnull*/ command); - Cp437GridCommand */*notnull*/ sp_cmd_cp437_grid_new(Cp437Grid */*notnull*/ grid, size_t origin_x, size_t origin_y); @@ -1206,70 +1341,24 @@ void sp_cmd_cp437_grid_set_origin(Cp437GridCommand */*notnull*/ command, size_t origin_x, size_t origin_y); -/** - * Set the brightness of individual tiles in a rectangular area of the display. - * - * The passed [BrightnessGrid] gets consumed. - * - * Returns: a new [servicepoint::Command::CharBrightness] instance. - */ -TypedCommand */*notnull*/ sp_command_brightness_grid(size_t x, - size_t y, - BrightnessGrid */*notnull*/ grid); - -/** - * Show UTF-8 encoded text on the screen. - * - * The passed [CharGrid] gets consumed. - * - * Returns: a new [servicepoint::CharGridCommand] instance. - */ -TypedCommand */*notnull*/ sp_command_char_grid(size_t x, - size_t y, - CharGrid */*notnull*/ grid); - -/** - * Set all pixels to the off state. - * - * Does not affect brightness. - * - * Returns: a new [servicepoint::Command::Clear] instance. - * - * # Examples - * - * ```C - * sp_udp_send_command(connection, sp_command_clear()); - * ``` - */ -TypedCommand */*notnull*/ sp_command_clear(void); - -/** - * Clones a [TypedCommand] instance. - * - * returns: new [TypedCommand] instance. - */ -TypedCommand */*notnull*/ sp_command_clone(TypedCommand */*notnull*/ command); - -/** - * Show codepage 437 encoded text on the screen. - * - * The passed [Cp437Grid] gets consumed. - * - * Returns: a new [servicepoint::Cp437GridCommand] instance. - */ -TypedCommand */*notnull*/ sp_command_cp437_grid(size_t x, - size_t y, - Cp437Grid */*notnull*/ grid); +void sp_cmd_fade_out_free(ClearCommand */*notnull*/ command); /** * A yet-to-be-tested command. * - * Returns: a new [servicepoint::Command::FadeOut] instance. + * Returns: a new [FadeOutCommand] instance. */ -TypedCommand */*notnull*/ sp_command_fade_out(void); +FadeOutCommand */*notnull*/ sp_cmd_fade_out_new(void); /** - * Deallocates a [TypedCommand]. + * Clones a [SPCommand] instance. + * + * returns: new [SPCommand] instance. + */ +SPCommand sp_cmd_generic_clone(SPCommand command); + +/** + * Deallocates a [SPCommand]. * * # Examples * @@ -1278,37 +1367,31 @@ TypedCommand */*notnull*/ sp_command_fade_out(void); * sp_command_free(c); * ``` */ -void sp_command_free(TypedCommand */*notnull*/ command); +void sp_cmd_generic_free(SPCommand command); /** - * Set the brightness of all tiles to the same value. + * Turns a [TypedCommand] into a [Packet]. + * The [TypedCommand] gets consumed. * - * Returns: a new [servicepoint::Command::Brightness] instance. + * Returns NULL in case of an error. */ -TypedCommand */*notnull*/ sp_command_global_brightness(Brightness brightness); +Packet *sp_cmd_generic_into_packet(SPCommand command); + +void sp_cmd_hard_reset_free(ClearCommand */*notnull*/ command); /** * Kills the udp daemon on the display, which usually results in a restart. * * Please do not send this in your normal program flow. * - * Returns: a new [servicepoint::Command::HardReset] instance. + * Returns: a new [HardResetCommand] instance. */ -TypedCommand */*notnull*/ sp_command_hard_reset(void); - -/** - * Tries to turn a [Packet] into a [TypedCommand]. - * - * The packet is deallocated in the process. - * - * Returns: pointer to new [TypedCommand] instance or NULL if parsing failed. - */ -TypedCommand *sp_command_try_from_packet(Packet */*notnull*/ packet); +HardResetCommand */*notnull*/ sp_cmd_hard_reset_new(void); /** * Clones a [Cp437Grid]. */ -Cp437Grid */*notnull*/ sp_cp437_grid_clone(Cp437Grid */*notnull*/ cp437_grid); +Cp437Grid */*notnull*/ sp_cp437_grid_clone(Cp437Grid */*notnull*/ grid); /** * Sets the value of all cells in the [Cp437Grid]. @@ -1419,14 +1502,6 @@ Packet */*notnull*/ sp_packet_clone(Packet */*notnull*/ packet); */ void sp_packet_free(Packet */*notnull*/ packet); -/** - * Turns a [TypedCommand] into a [Packet]. - * The [TypedCommand] gets consumed. - * - * Returns NULL in case of an error. - */ -Packet *sp_packet_from_command(TypedCommand */*notnull*/ command); - /** * Creates a raw [Packet] from parts. * @@ -1532,8 +1607,7 @@ UdpSocket *sp_udp_open_ipv4(uint8_t ip1, * sp_udp_send_command(connection, sp_command_brightness(5)); * ``` */ -bool sp_udp_send_command(UdpSocket */*notnull*/ connection, - TypedCommand */*notnull*/ command); +bool sp_udp_send_command(UdpSocket */*notnull*/ connection, SPCommand command); /** * Sends a [Header] to the display using the [UdpSocket]. diff --git a/src/bitmap.rs b/src/bitmap.rs index 9e7f4bd..8341c59 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -1,6 +1,6 @@ use crate::{ - heap_drop, heap_move_nonnull, heap_move_ok, heap_move_some, heap_remove, - byte_slice::ByteSlice, bitvec::SPBitVec, + bitvec::SPBitVec, byte_slice::ByteSlice, heap_clone, heap_drop, + heap_move_nonnull, heap_move_ok, heap_move_some, heap_remove, }; use servicepoint::{ Bitmap, BitmapCommand, CompressionCode, DataRef, Grid, Origin, Packet, @@ -83,7 +83,7 @@ pub unsafe extern "C" fn sp_bitmap_from_bitvec( pub unsafe extern "C" fn sp_bitmap_clone( bitmap: NonNull, ) -> NonNull { - heap_move_nonnull(unsafe { bitmap.as_ref().clone() }) + unsafe { heap_clone(bitmap) } } /// Deallocates a [Bitmap]. diff --git a/src/bitvec.rs b/src/bitvec.rs index b7743aa..3fa7412 100644 --- a/src/bitvec.rs +++ b/src/bitvec.rs @@ -1,5 +1,6 @@ use crate::{ - heap_drop, heap_move_nonnull, heap_move_ok, heap_remove, byte_slice::ByteSlice, + byte_slice::ByteSlice, heap_clone, heap_drop, heap_move_nonnull, + heap_move_ok, heap_remove, }; use servicepoint::{ BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Packet, @@ -52,7 +53,7 @@ pub unsafe extern "C" fn sp_bitvec_load(data: ByteSlice) -> NonNull { pub unsafe extern "C" fn sp_bitvec_clone( bit_vec: NonNull, ) -> NonNull { - heap_move_nonnull(unsafe { bit_vec.as_ref().clone() }) + unsafe { heap_clone(bit_vec) } } /// Deallocates a [SPBitVec]. diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index 496c53f..dc3b2f7 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -1,6 +1,6 @@ use crate::{ - heap_drop, heap_move_nonnull, heap_move_ok, heap_move_some, heap_remove, - byte_slice::ByteSlice, + byte_slice::ByteSlice, heap_clone, heap_drop, heap_move_nonnull, + heap_move_ok, heap_move_some, heap_remove, }; use servicepoint::{ Brightness, BrightnessGrid, BrightnessGridCommand, ByteGrid, DataRef, Grid, @@ -55,9 +55,9 @@ pub unsafe extern "C" fn sp_brightness_grid_load( /// Clones a [BrightnessGrid]. #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_clone( - brightness_grid: NonNull, + grid: NonNull, ) -> NonNull { - heap_move_nonnull(unsafe { brightness_grid.as_ref().clone() }) + unsafe { heap_clone(grid) } } /// Deallocates a [BrightnessGrid]. diff --git a/src/char_grid.rs b/src/char_grid.rs index 42502a7..62aba87 100644 --- a/src/char_grid.rs +++ b/src/char_grid.rs @@ -1,5 +1,6 @@ use crate::{ - heap_drop, heap_move_nonnull, heap_move_ok, heap_remove, byte_slice::ByteSlice, + byte_slice::ByteSlice, heap_clone, heap_drop, heap_move_nonnull, + heap_move_ok, heap_remove, }; use servicepoint::{CharGrid, CharGridCommand, Grid, Origin, Packet}; use std::ptr::NonNull; @@ -40,9 +41,9 @@ pub unsafe extern "C" fn sp_char_grid_load( /// Clones a [CharGrid]. #[no_mangle] pub unsafe extern "C" fn sp_char_grid_clone( - char_grid: NonNull, + grid: NonNull, ) -> NonNull { - heap_move_nonnull(unsafe { char_grid.as_ref().clone() }) + unsafe { heap_clone(grid) } } /// Deallocates a [CharGrid]. diff --git a/src/commands/bitmap_command.rs b/src/commands/bitmap_command.rs index a45a155..b2ff3d8 100644 --- a/src/commands/bitmap_command.rs +++ b/src/commands/bitmap_command.rs @@ -1,7 +1,7 @@ -use crate::{heap_drop, heap_move_nonnull, heap_move_ok, heap_remove}; -use servicepoint::{ - Bitmap, BitmapCommand, CompressionCode, Origin, Packet, TypedCommand, +use crate::{ + heap_clone, heap_drop, heap_move_nonnull, heap_move_ok, heap_remove, }; +use servicepoint::{Bitmap, BitmapCommand, CompressionCode, Origin, Packet}; use std::ptr::NonNull; /// Sets a window of pixels to the specified values. @@ -34,13 +34,6 @@ pub unsafe extern "C" fn sp_cmd_bitmap_from_bitmap( heap_move_nonnull(unsafe { heap_remove(bitmap) }.into()) } -#[no_mangle] -pub unsafe extern "C" fn sp_cmd_bitmap_into_typed( - command: NonNull, -) -> NonNull { - heap_move_nonnull(unsafe { heap_remove(command) }.into()) -} - #[no_mangle] pub unsafe extern "C" fn sp_cmd_bitmap_into_packet( command: NonNull, @@ -52,7 +45,7 @@ pub unsafe extern "C" fn sp_cmd_bitmap_into_packet( pub unsafe extern "C" fn sp_cmd_bitmap_clone( command: NonNull, ) -> NonNull { - heap_move_nonnull(unsafe { command.as_ref().clone() }) + unsafe { heap_clone(command) } } #[no_mangle] diff --git a/src/commands/bitvec_command.rs b/src/commands/bitvec_command.rs index 5795017..bfe2d33 100644 --- a/src/commands/bitvec_command.rs +++ b/src/commands/bitvec_command.rs @@ -1,7 +1,9 @@ -use crate::{heap_drop, heap_move_nonnull, heap_move_ok, heap_remove}; +use crate::{ + heap_clone, heap_drop, heap_move_nonnull, heap_move_ok, heap_remove, +}; use servicepoint::{ BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Offset, - Packet, TypedCommand, + Packet, }; use std::ptr::NonNull; @@ -32,13 +34,6 @@ pub unsafe extern "C" fn sp_cmd_bitvec_new( }) } -#[no_mangle] -pub unsafe extern "C" fn sp_cmd_bitvec_into_typed( - command: NonNull, -) -> NonNull { - heap_move_nonnull(unsafe { heap_remove(command) }.into()) -} - #[no_mangle] pub unsafe extern "C" fn sp_cmd_bitvec_into_packet( command: NonNull, @@ -50,7 +45,7 @@ pub unsafe extern "C" fn sp_cmd_bitvec_into_packet( pub unsafe extern "C" fn sp_cmd_bitvec_clone( command: NonNull, ) -> NonNull { - heap_move_nonnull(unsafe { command.as_ref().clone() }) + unsafe { heap_clone(command) } } #[no_mangle] diff --git a/src/commands/brightness_grid_command.rs b/src/commands/brightness_grid_command.rs index 18a2836..bd975d6 100644 --- a/src/commands/brightness_grid_command.rs +++ b/src/commands/brightness_grid_command.rs @@ -1,7 +1,8 @@ -use crate::{heap_drop, heap_move_nonnull, heap_move_ok, heap_remove}; +use crate::{ + heap_clone, heap_drop, heap_move_nonnull, heap_move_ok, heap_remove, +}; use servicepoint::{ BitmapCommand, BrightnessGrid, BrightnessGridCommand, Origin, Packet, - TypedCommand, }; use std::ptr::NonNull; @@ -24,13 +25,6 @@ pub unsafe extern "C" fn sp_cmd_brightness_grid_from_grid( heap_move_nonnull(unsafe { heap_remove(grid) }.into()) } -#[no_mangle] -pub unsafe extern "C" fn sp_cmd_brightness_grid_into_typed( - command: NonNull, -) -> NonNull { - heap_move_nonnull(unsafe { heap_remove(command) }.into()) -} - #[no_mangle] pub unsafe extern "C" fn sp_cmd_brightness_grid_into_packet( command: NonNull, @@ -42,7 +36,7 @@ pub unsafe extern "C" fn sp_cmd_brightness_grid_into_packet( pub unsafe extern "C" fn sp_cmd_brightness_grid_clone( command: NonNull, ) -> NonNull { - heap_move_nonnull(unsafe { command.as_ref().clone() }) + unsafe { heap_clone(command) } } #[no_mangle] diff --git a/src/commands/cc_only_commands.rs b/src/commands/cc_only_commands.rs new file mode 100644 index 0000000..751a6ab --- /dev/null +++ b/src/commands/cc_only_commands.rs @@ -0,0 +1,54 @@ +use crate::{heap_drop, heap_move_nonnull}; +use servicepoint::{ClearCommand, FadeOutCommand, HardResetCommand}; +use std::ptr::NonNull; + +/// Set all pixels to the off state. +/// +/// Does not affect brightness. +/// +/// Returns: a new [ClearCommand] instance. +/// +/// # Examples +/// +/// ```C +/// sp_udp_send_command(connection, sp_cmd_clear()); +/// ``` +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_clear_new() -> NonNull { + heap_move_nonnull(ClearCommand) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_clear_free(command: NonNull) { + unsafe { heap_drop(command) } +} + +/// Kills the udp daemon on the display, which usually results in a restart. +/// +/// Please do not send this in your normal program flow. +/// +/// Returns: a new [HardResetCommand] instance. +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_hard_reset_new() -> NonNull { + heap_move_nonnull(HardResetCommand) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_hard_reset_free( + command: NonNull, +) { + unsafe { heap_drop(command) } +} + +/// A yet-to-be-tested command. +/// +/// Returns: a new [FadeOutCommand] instance. +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_fade_out_new() -> NonNull { + heap_move_nonnull(FadeOutCommand) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_fade_out_free(command: NonNull) { + unsafe { heap_drop(command) } +} diff --git a/src/commands/char_grid_command.rs b/src/commands/char_grid_command.rs index 933e4cd..bc078cd 100644 --- a/src/commands/char_grid_command.rs +++ b/src/commands/char_grid_command.rs @@ -1,7 +1,7 @@ -use crate::{heap_drop, heap_move_nonnull, heap_move_ok, heap_remove}; -use servicepoint::{ - BitmapCommand, CharGrid, CharGridCommand, Origin, Packet, TypedCommand, +use crate::{ + heap_clone, heap_drop, heap_move_nonnull, heap_move_ok, heap_remove, }; +use servicepoint::{BitmapCommand, CharGrid, CharGridCommand, Origin, Packet}; use std::ptr::NonNull; #[no_mangle] @@ -23,13 +23,6 @@ pub unsafe extern "C" fn sp_cmd_char_grid_from_grid( heap_move_nonnull(unsafe { heap_remove(grid) }.into()) } -#[no_mangle] -pub unsafe extern "C" fn sp_cmd_char_grid_into_typed( - command: NonNull, -) -> NonNull { - heap_move_nonnull(unsafe { heap_remove(command) }.into()) -} - #[no_mangle] pub unsafe extern "C" fn sp_cmd_char_grid_into_packet( command: NonNull, @@ -41,7 +34,7 @@ pub unsafe extern "C" fn sp_cmd_char_grid_into_packet( pub unsafe extern "C" fn sp_cmd_char_grid_clone( command: NonNull, ) -> NonNull { - heap_move_nonnull(unsafe { command.as_ref().clone() }) + unsafe { heap_clone(command) } } #[no_mangle] diff --git a/src/commands/cp437_grid_command.rs b/src/commands/cp437_grid_command.rs index 0f3d9e2..1e1598a 100644 --- a/src/commands/cp437_grid_command.rs +++ b/src/commands/cp437_grid_command.rs @@ -1,6 +1,8 @@ -use crate::{heap_drop, heap_move_nonnull, heap_move_ok, heap_remove}; +use crate::{ + heap_clone, heap_drop, heap_move_nonnull, heap_move_ok, heap_remove, +}; use servicepoint::{ - BitmapCommand, Cp437Grid, Cp437GridCommand, Origin, Packet, TypedCommand, + BitmapCommand, Cp437Grid, Cp437GridCommand, Origin, Packet, }; use std::ptr::NonNull; @@ -23,13 +25,6 @@ pub unsafe extern "C" fn sp_cmd_cp437_grid_from_grid( heap_move_nonnull(unsafe { heap_remove(grid) }.into()) } -#[no_mangle] -pub unsafe extern "C" fn sp_cmd_cp437_grid_into_typed( - command: NonNull, -) -> NonNull { - heap_move_nonnull(unsafe { heap_remove(command) }.into()) -} - #[no_mangle] pub unsafe extern "C" fn sp_cmd_cp437_grid_into_packet( command: NonNull, @@ -41,7 +36,7 @@ pub unsafe extern "C" fn sp_cmd_cp437_grid_into_packet( pub unsafe extern "C" fn sp_cmd_cp437_grid_clone( command: NonNull, ) -> NonNull { - heap_move_nonnull(unsafe { command.as_ref().clone() }) + unsafe { heap_clone(command) } } #[no_mangle] diff --git a/src/commands/generic_command.rs b/src/commands/generic_command.rs new file mode 100644 index 0000000..5066022 --- /dev/null +++ b/src/commands/generic_command.rs @@ -0,0 +1,281 @@ +use crate::{ + heap_clone, heap_drop, heap_move_nonnull, heap_move_ok, heap_remove, +}; +use servicepoint::{ + BitVecCommand, BitmapCommand, BitmapLegacyCommand, BrightnessGridCommand, + CharGridCommand, ClearCommand, Cp437GridCommand, FadeOutCommand, + GlobalBrightnessCommand, HardResetCommand, Packet, TypedCommand, +}; +use std::ptr::{null_mut, NonNull}; + +#[repr(C)] +pub union CommandUnion { + pub null: *mut u8, + pub bitmap: NonNull, + pub bitvec: NonNull, + pub brightness_grid: NonNull, + pub char_grid: NonNull, + pub cp437_grid: NonNull, + pub global_brightness: NonNull, + pub clear: NonNull, + #[allow(deprecated)] + pub bitmap_legacy: NonNull, + pub hard_reset: NonNull, + pub fade_out: NonNull, +} + +#[repr(u8)] +pub enum CommandTag { + Invalid = 0, + Bitmap, + BitVec, + BrightnessGrid, + CharGrid, + Cp437Grid, + GlobalBrightness, + Clear, + HardReset, + FadeOut, + BitmapLegacy, +} + +#[repr(C)] +pub struct SPCommand { + /// 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 { + tag: CommandTag::Invalid, + data: CommandUnion { null: null_mut() }, + }; +} + +/// Tries to turn a [Packet] into a [TypedCommand]. +/// +/// The packet is deallocated in the process. +/// +/// Returns: pointer to new [TypedCommand] instance or NULL if parsing failed. +/// #[no_mangle] +pub unsafe extern "C" fn sp_cmd_generic_try_from_packet( + packet: NonNull, +) -> *mut SPCommand { + let packet = *unsafe { Box::from_raw(packet.as_ptr()) }; + heap_move_ok(servicepoint::TypedCommand::try_from(packet).map(|value| { + match value { + TypedCommand::Clear(clear) => SPCommand { + tag: CommandTag::Clear, + data: CommandUnion { + clear: heap_move_nonnull(clear), + }, + }, + TypedCommand::CharGrid(char_grid) => SPCommand { + tag: CommandTag::CharGrid, + data: CommandUnion { + char_grid: heap_move_nonnull(char_grid), + }, + }, + TypedCommand::Cp437Grid(cp437_grid) => SPCommand { + tag: CommandTag::Cp437Grid, + data: CommandUnion { + cp437_grid: heap_move_nonnull(cp437_grid), + }, + }, + TypedCommand::Bitmap(bitmap) => SPCommand { + tag: CommandTag::Bitmap, + data: CommandUnion { + bitmap: heap_move_nonnull(bitmap), + }, + }, + TypedCommand::Brightness(global_brightness) => SPCommand { + tag: CommandTag::GlobalBrightness, + data: CommandUnion { + global_brightness: heap_move_nonnull(global_brightness), + }, + }, + TypedCommand::BrightnessGrid(brightness_grid) => SPCommand { + tag: CommandTag::BrightnessGrid, + data: CommandUnion { + brightness_grid: heap_move_nonnull(brightness_grid), + }, + }, + TypedCommand::BitVec(bitvec) => SPCommand { + tag: CommandTag::BitVec, + data: CommandUnion { + bitvec: heap_move_nonnull(bitvec), + }, + }, + TypedCommand::HardReset(hard_reset) => SPCommand { + tag: CommandTag::HardReset, + data: CommandUnion { + hard_reset: heap_move_nonnull(hard_reset), + }, + }, + TypedCommand::FadeOut(fade_out) => SPCommand { + tag: CommandTag::FadeOut, + data: CommandUnion { + fade_out: heap_move_nonnull(fade_out), + }, + }, + #[allow(deprecated)] + TypedCommand::BitmapLegacy(bitmap_legacy) => SPCommand { + tag: CommandTag::BitmapLegacy, + data: CommandUnion { + bitmap_legacy: heap_move_nonnull(bitmap_legacy), + }, + }, + } + })) +} + +/// Clones a [SPCommand] instance. +/// +/// returns: new [SPCommand] instance. +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_generic_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 { + bitvec: heap_clone(command.data.bitvec), + }, + }, + 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 a [SPCommand]. +/// +/// # Examples +/// +/// ```C +/// TypedCommand c = sp_command_clear(); +/// sp_command_free(c); +/// ``` +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_generic_free(command: SPCommand) { + unsafe { + match command.tag { + CommandTag::Invalid => return, + CommandTag::Bitmap => heap_drop(command.data.bitmap), + CommandTag::BitVec => heap_drop(command.data.bitvec), + 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), + } + } +} + +/// Turns a [TypedCommand] into a [Packet]. +/// The [TypedCommand] gets consumed. +/// +/// Returns NULL in case of an error. +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_generic_into_packet( + command: SPCommand, +) -> *mut Packet { + match command.tag { + CommandTag::Invalid => null_mut(), + CommandTag::Bitmap => { + heap_move_ok(unsafe { heap_remove(command.data.bitmap).try_into() }) + } + CommandTag::BitVec => { + heap_move_ok(unsafe { heap_remove(command.data.bitvec).try_into() }) + } + CommandTag::BrightnessGrid => heap_move_ok(unsafe { + heap_remove(command.data.brightness_grid).try_into() + }), + CommandTag::CharGrid => heap_move_ok(unsafe { + heap_remove(command.data.char_grid).try_into() + }), + CommandTag::Cp437Grid => heap_move_ok(unsafe { + heap_remove(command.data.cp437_grid).try_into() + }), + CommandTag::GlobalBrightness => heap_move_ok(unsafe { + heap_remove(command.data.global_brightness).try_into() + }), + CommandTag::Clear => { + heap_move_ok(unsafe { heap_remove(command.data.clear).try_into() }) + } + CommandTag::HardReset => heap_move_ok(unsafe { + heap_remove(command.data.hard_reset).try_into() + }), + CommandTag::FadeOut => heap_move_ok(unsafe { + heap_remove(command.data.fade_out).try_into() + }), + CommandTag::BitmapLegacy => heap_move_ok(unsafe { + heap_remove(command.data.bitmap_legacy).try_into() + }), + } +} diff --git a/src/commands/global_brightness_command.rs b/src/commands/global_brightness_command.rs new file mode 100644 index 0000000..29e7c19 --- /dev/null +++ b/src/commands/global_brightness_command.rs @@ -0,0 +1,53 @@ +use crate::{ + heap_clone, heap_drop, heap_move_nonnull, heap_move_ok, heap_remove, +}; +use servicepoint::{ + BitmapCommand, Brightness, GlobalBrightnessCommand, Packet, +}; +use std::ptr::NonNull; + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_brightness_global_new( + brightness: Brightness, +) -> NonNull { + heap_move_nonnull(GlobalBrightnessCommand::from(brightness)) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_brightness_global_into_packet( + command: NonNull, +) -> *mut Packet { + heap_move_ok(unsafe { heap_remove(command) }.try_into()) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_brightness_global_clone( + command: NonNull, +) -> NonNull { + unsafe { heap_clone(command) } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_brightness_global_free( + command: NonNull, +) { + unsafe { heap_drop(command) } +} + +/// Moves the provided bitmap to be contained in the command. +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_brightness_global_set( + mut command: NonNull, + brightness: Brightness, +) { + unsafe { + command.as_mut().brightness = brightness; + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_brightness_global_get( + mut command: NonNull, +) -> *mut Brightness { + &mut unsafe { command.as_mut() }.brightness +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index e4b1d4a..3cbb99a 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,11 +1,15 @@ mod bitmap_command; mod bitvec_command; mod brightness_grid_command; +mod cc_only_commands; mod char_grid_command; mod cp437_grid_command; +mod generic_command; +mod global_brightness_command; pub use bitmap_command::*; pub use bitvec_command::*; pub use brightness_grid_command::*; pub use char_grid_command::*; pub use cp437_grid_command::*; +pub use generic_command::*; diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index c39118e..b4d449e 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -1,6 +1,6 @@ use crate::{ - heap_drop, heap_move_nonnull, heap_move_ok, heap_move_some, heap_remove, - byte_slice::ByteSlice, + byte_slice::ByteSlice, heap_clone, heap_drop, heap_move_nonnull, + heap_move_ok, heap_move_some, heap_remove, }; use servicepoint::{ Cp437Grid, Cp437GridCommand, DataRef, Grid, Origin, Packet, @@ -32,9 +32,9 @@ pub unsafe extern "C" fn sp_cp437_grid_load( /// Clones a [Cp437Grid]. #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_clone( - cp437_grid: NonNull, + grid: NonNull, ) -> NonNull { - heap_move_nonnull(unsafe { cp437_grid.as_ref().clone() }) + unsafe { heap_clone(grid) } } /// Deallocates a [Cp437Grid]. diff --git a/src/lib.rs b/src/lib.rs index c98318a..de22866 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,7 +35,6 @@ pub mod char_grid; pub mod commands; pub mod cp437_grid; pub mod packet; -pub mod typed_command; pub mod udp; use std::time::Duration; @@ -67,6 +66,10 @@ pub(crate) unsafe fn heap_remove(x: NonNull) -> T { unsafe { *Box::from_raw(x.as_ptr()) } } +unsafe fn heap_clone(source: NonNull) -> NonNull { + heap_move_nonnull(unsafe { source.as_ref().clone() }) +} + /// This is a type only used by cbindgen to have a type for pointers. pub struct UdpSocket; diff --git a/src/packet.rs b/src/packet.rs index ea41597..16509be 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,21 +1,10 @@ use crate::{ - heap_drop, heap_move_nonnull, heap_move_ok, heap_remove, byte_slice::ByteSlice, + byte_slice::ByteSlice, heap_clone, heap_drop, heap_move_nonnull, + heap_move_ok, }; -use servicepoint::{CommandCode, Header, Packet, TypedCommand}; +use servicepoint::{CommandCode, Header, Packet}; use std::ptr::NonNull; -/// Turns a [TypedCommand] into a [Packet]. -/// The [TypedCommand] gets consumed. -/// -/// Returns NULL in case of an error. -#[no_mangle] -pub unsafe extern "C" fn sp_packet_from_command( - command: NonNull, -) -> *mut Packet { - let command = unsafe { heap_remove(command) }; - heap_move_ok(command.try_into()) -} - /// 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 @@ -94,7 +83,7 @@ pub unsafe extern "C" fn sp_packet_serialize_to( pub unsafe extern "C" fn sp_packet_clone( packet: NonNull, ) -> NonNull { - heap_move_nonnull(unsafe { packet.as_ref().clone() }) + unsafe { heap_clone(packet) } } /// Deallocates a [Packet]. diff --git a/src/typed_command.rs b/src/typed_command.rs deleted file mode 100644 index 26c33f1..0000000 --- a/src/typed_command.rs +++ /dev/null @@ -1,86 +0,0 @@ -use crate::{heap_drop, heap_move_nonnull, heap_move_ok}; -use servicepoint::{ - Brightness, GlobalBrightnessCommand, - Packet, TypedCommand, -}; -use std::ptr::NonNull; - -/// Tries to turn a [Packet] into a [TypedCommand]. -/// -/// The packet is deallocated in the process. -/// -/// Returns: pointer to new [TypedCommand] instance or NULL if parsing failed. -#[no_mangle] -pub unsafe extern "C" fn sp_command_try_from_packet( - packet: NonNull, -) -> *mut TypedCommand { - let packet = *unsafe { Box::from_raw(packet.as_ptr()) }; - heap_move_ok(servicepoint::TypedCommand::try_from(packet)) -} - -/// Clones a [TypedCommand] instance. -/// -/// returns: new [TypedCommand] instance. -#[no_mangle] -pub unsafe extern "C" fn sp_command_clone( - command: NonNull, -) -> NonNull { - heap_move_nonnull(unsafe { command.as_ref().clone() }) -} - -/// Set all pixels to the off state. -/// -/// Does not affect brightness. -/// -/// Returns: a new [servicepoint::Command::Clear] instance. -/// -/// # Examples -/// -/// ```C -/// sp_udp_send_command(connection, sp_command_clear()); -/// ``` -#[no_mangle] -pub unsafe extern "C" fn sp_command_clear() -> NonNull { - heap_move_nonnull(servicepoint::ClearCommand.into()) -} - -/// Kills the udp daemon on the display, which usually results in a restart. -/// -/// Please do not send this in your normal program flow. -/// -/// Returns: a new [servicepoint::Command::HardReset] instance. -#[no_mangle] -pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull { - heap_move_nonnull(servicepoint::HardResetCommand.into()) -} - -/// A yet-to-be-tested command. -/// -/// Returns: a new [servicepoint::Command::FadeOut] instance. -#[no_mangle] -pub unsafe extern "C" fn sp_command_fade_out() -> NonNull { - heap_move_nonnull(servicepoint::FadeOutCommand.into()) -} - -/// Set the brightness of all tiles to the same value. -/// -/// Returns: a new [servicepoint::Command::Brightness] instance. -#[no_mangle] -pub unsafe extern "C" fn sp_command_global_brightness( - brightness: Brightness, -) -> NonNull { - heap_move_nonnull(GlobalBrightnessCommand::from(brightness).into()) -} - -/// Deallocates a [TypedCommand]. -/// -/// # Examples -/// -/// ```C -/// TypedCommand c = sp_command_clear(); -/// sp_command_free(c); -/// ``` -#[no_mangle] -pub unsafe extern "C" fn sp_command_free(command: NonNull) { - unsafe { heap_drop(command) } -} diff --git a/src/udp.rs b/src/udp.rs index b75f13d..7b659cf 100644 --- a/src/udp.rs +++ b/src/udp.rs @@ -1,5 +1,6 @@ +use crate::commands::{CommandTag, SPCommand}; use crate::{heap_drop, heap_move_ok, heap_remove}; -use servicepoint::{Header, Packet, TypedCommand, UdpSocketExt}; +use servicepoint::{Header, Packet, UdpSocketExt}; use std::ffi::{c_char, CStr}; use std::net::{Ipv4Addr, SocketAddrV4, UdpSocket}; use std::ptr::NonNull; @@ -75,10 +76,44 @@ pub unsafe extern "C" fn sp_udp_send_packet( #[no_mangle] pub unsafe extern "C" fn sp_udp_send_command( connection: NonNull, - command: NonNull, + command: SPCommand, ) -> bool { - let command = unsafe { heap_remove(command) }; - unsafe { connection.as_ref().send_command(command) }.is_some() + unsafe { + 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.bitvec)), + 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)), + } + } + .is_some() } /// Sends a [Header] to the display using the [UdpSocket].