From 4f0eca3ea0ee4caed7ea907033450b68b37db42b Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Tue, 6 May 2025 21:12:37 +0200 Subject: [PATCH] more commands --- example/src/brightness_tester.c | 44 ++++--- include/servicepoint.h | 146 ++++++++++++++++++++++++ src/commands/bitmap_command.rs | 14 ++- src/commands/bitvec_command.rs | 15 ++- src/commands/brightness_grid_command.rs | 95 +++++++++++++++ src/commands/char_grid_command.rs | 94 +++++++++++++++ src/commands/cp437_grid_command.rs | 94 +++++++++++++++ src/commands/mod.rs | 3 + src/typed_command.rs | 62 +--------- 9 files changed, 489 insertions(+), 78 deletions(-) create mode 100644 src/commands/brightness_grid_command.rs create mode 100644 src/commands/char_grid_command.rs create mode 100644 src/commands/cp437_grid_command.rs diff --git a/example/src/brightness_tester.c b/example/src/brightness_tester.c index c3e42ba..9476422 100644 --- a/example/src/brightness_tester.c +++ b/example/src/brightness_tester.c @@ -1,30 +1,44 @@ #include "servicepoint.h" -int main(void) { - UdpSocket *connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); - //UdpSocket *connection = sp_udp_open_ipv4(127, 0, 0, 1, 2342); - if (connection == NULL) - return -1; +static UdpSocket *connection = NULL; +void enable_all_pixels(void) { Bitmap *all_on = sp_bitmap_new_max_sized(); sp_bitmap_fill(all_on, true); - Packet *packet = sp_bitmap_into_packet(all_on, 0, 0, COMPRESSION_CODE_UNCOMPRESSED); - if (packet == NULL) - return -1; - - sp_udp_send_packet(connection, packet); - - BrightnessGrid *grid = sp_brightness_grid_new(TILE_WIDTH, TILE_HEIGHT); + BitmapCommand *bitmapCommand = sp_cmd_bitmap_from_bitmap(all_on); + Packet *packet = sp_cmd_bitmap_into_packet(bitmapCommand); + if (packet != NULL) + sp_udp_send_packet(connection, packet); +} +void make_brightness_pattern(BrightnessGrid *grid) { ByteSlice slice = sp_brightness_grid_unsafe_data_ref(grid); for (size_t index = 0; index < slice.length; index++) { slice.start[index] = (uint8_t) (index % ((size_t) Brightness_MAX)); } +} - packet = sp_brightness_grid_into_packet(grid, 0, 0); - sp_udp_send_packet(connection, packet); - +void run_at_exit() { sp_udp_free(connection); +} + +int main(void) { + //UdpSocket *connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); + connection = sp_udp_open_ipv4(127, 0, 0, 1, 2342); + if (connection == NULL) + return -1; + atexit(run_at_exit); + + enable_all_pixels(); + + BrightnessGrid *grid = sp_brightness_grid_new(TILE_WIDTH, TILE_HEIGHT); + make_brightness_pattern(grid); + + Packet *packet = sp_cmd_brightness_grid_into_packet(sp_cmd_brightness_grid_from_grid(grid)); + if (packet == NULL) + return -2; + + sp_udp_send_packet(connection, packet); return 0; } diff --git a/include/servicepoint.h b/include/servicepoint.h index 8923756..805d84b 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -239,6 +239,54 @@ typedef struct Bitmap Bitmap; */ typedef struct BitmapCommand BitmapCommand; +/** + * Set the brightness of individual tiles in a rectangular area of the display. + */ +typedef struct BrightnessGridCommand BrightnessGridCommand; + +/** + * Show text on the screen. + * + * The text is sent in the form of a 2D grid of UTF-8 encoded characters (the default encoding in rust). + * + * # Examples + * + * ```rust + * # use servicepoint::*; + * # let connection = FakeConnection; + * let grid = CharGrid::from("Hello,\nWorld!"); + * connection.send_command(CharGridCommand { origin: Origin::ZERO, grid }).expect("send failed"); + * ``` + */ +typedef struct CharGridCommand CharGridCommand; + +/** + * Show text on the screen. + * + * The text is sent in the form of a 2D grid of [CP-437] encoded characters. + * + *
You probably want to use [Command::Utf8Data] instead
+ * + * # Examples + * + * ```rust + * # use servicepoint::*; + * # let connection = FakeConnection; + * let grid = CharGrid::from("Hello,\nWorld!"); + * let grid = Cp437Grid::from(&grid); + * connection.send_command(Cp437GridCommand{ origin: Origin::ZERO, grid }).expect("send failed"); + * ``` + * + * ```rust + * # use servicepoint::*; + * # let connection = FakeConnection; + * let grid = Cp437Grid::load_ascii("Hello\nWorld", 5, false).unwrap(); + * connection.send_command(Cp437GridCommand{ origin: Origin::new(2, 2), grid }).unwrap(); + * ``` + * [CP-437]: https://en.wikipedia.org/wiki/Code_page_437 + */ +typedef struct Cp437GridCommand Cp437GridCommand; + /** * This is a type only used by cbindgen to have a type for pointers. */ @@ -961,6 +1009,10 @@ void sp_char_grid_set(CharGrid */*notnull*/ char_grid, */ size_t sp_char_grid_width(CharGrid */*notnull*/ char_grid); +BitmapCommand */*notnull*/ sp_cmd_bitmap_clone(BitmapCommand */*notnull*/ command); + +void sp_cmd_bitmap_free(BitmapCommand */*notnull*/ command); + BitmapCommand */*notnull*/ sp_cmd_bitmap_from_bitmap(Bitmap */*notnull*/ bitmap); /** @@ -1008,6 +1060,10 @@ void sp_cmd_bitmap_set_origin(BitmapCommand */*notnull*/ command, size_t origin_x, size_t origin_y); +BitVecCommand */*notnull*/ sp_cmd_bitvec_clone(BitVecCommand */*notnull*/ command); + +void sp_cmd_bitvec_free(BitVecCommand */*notnull*/ command); + DisplayBitVec *sp_cmd_bitvec_get(BitVecCommand */*notnull*/ command); CompressionCode sp_cmd_bitvec_get_compression(BitVecCommand */*notnull*/ command); @@ -1054,6 +1110,96 @@ void sp_cmd_bitvec_set_offset(BitVecCommand */*notnull*/ command, void sp_cmd_bitvec_set_operation(BitVecCommand */*notnull*/ command, BinaryOperation operation); +BrightnessGridCommand */*notnull*/ sp_cmd_brightness_grid_clone(BrightnessGridCommand */*notnull*/ command); + +void sp_cmd_brightness_grid_free(BitmapCommand */*notnull*/ command); + +BrightnessGridCommand */*notnull*/ sp_cmd_brightness_grid_from_grid(BrightnessGrid */*notnull*/ grid); + +BrightnessGrid *sp_cmd_brightness_grid_get(BrightnessGridCommand */*notnull*/ command); + +void sp_cmd_brightness_grid_get_origin(BrightnessGridCommand */*notnull*/ command, + size_t */*notnull*/ origin_x, + size_t */*notnull*/ origin_y); + +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); + +/** + * Moves the provided bitmap to be contained in the command. + */ +void sp_cmd_brightness_grid_set(BrightnessGridCommand */*notnull*/ command, + BrightnessGrid */*notnull*/ grid); + +void sp_cmd_brightness_grid_set_origin(BrightnessGridCommand */*notnull*/ command, + size_t origin_x, + size_t origin_y); + +CharGridCommand */*notnull*/ sp_cmd_char_grid_clone(CharGridCommand */*notnull*/ command); + +void sp_cmd_char_grid_free(BitmapCommand */*notnull*/ command); + +CharGridCommand */*notnull*/ sp_cmd_char_grid_from_grid(CharGrid */*notnull*/ grid); + +CharGrid *sp_cmd_char_grid_get(CharGridCommand */*notnull*/ command); + +void sp_cmd_char_grid_get_origin(CharGridCommand */*notnull*/ command, + size_t */*notnull*/ origin_x, + size_t */*notnull*/ origin_y); + +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); + +/** + * Moves the provided bitmap to be contained in the command. + */ +void sp_cmd_char_grid_set(CharGridCommand */*notnull*/ command, + CharGrid */*notnull*/ grid); + +void sp_cmd_char_grid_set_origin(CharGridCommand */*notnull*/ command, + size_t origin_x, + size_t origin_y); + +Cp437GridCommand */*notnull*/ sp_cmd_cp437_grid_clone(Cp437GridCommand */*notnull*/ command); + +void sp_cmd_cp437_grid_free(BitmapCommand */*notnull*/ command); + +Cp437GridCommand */*notnull*/ sp_cmd_cp437_grid_from_grid(Cp437Grid */*notnull*/ grid); + +Cp437Grid *sp_cmd_cp437_grid_get(Cp437GridCommand */*notnull*/ command); + +void sp_cmd_cp437_grid_get_origin(Cp437GridCommand */*notnull*/ command, + size_t */*notnull*/ origin_x, + size_t */*notnull*/ origin_y); + +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); + +/** + * Moves the provided bitmap to be contained in the command. + */ +void sp_cmd_cp437_grid_set(Cp437GridCommand */*notnull*/ command, + Cp437Grid */*notnull*/ grid); + +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. * diff --git a/src/commands/bitmap_command.rs b/src/commands/bitmap_command.rs index b1ab343..4413a3c 100644 --- a/src/commands/bitmap_command.rs +++ b/src/commands/bitmap_command.rs @@ -1,4 +1,4 @@ -use crate::{heap_move_nonnull, heap_move_ok, heap_remove}; +use crate::{heap_drop, heap_move_nonnull, heap_move_ok, heap_remove}; use servicepoint::{ Bitmap, BitmapCommand, CompressionCode, Origin, Packet, TypedCommand, }; @@ -44,6 +44,18 @@ pub unsafe extern "C" fn sp_cmd_bitmap_into_packet( heap_move_ok(unsafe { heap_remove(command) }.try_into()) } +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitmap_clone( + command: NonNull, +) -> NonNull { + heap_move_nonnull(unsafe { command.as_ref().clone() }) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitmap_free(command: NonNull) { + unsafe { heap_drop(command) } +} + /// Returns a pointer to the provided `BitmapCommand`. /// /// # Safety diff --git a/src/commands/bitvec_command.rs b/src/commands/bitvec_command.rs index 39d5253..5795017 100644 --- a/src/commands/bitvec_command.rs +++ b/src/commands/bitvec_command.rs @@ -1,4 +1,4 @@ -use crate::{heap_move_nonnull, heap_move_ok, heap_remove}; +use crate::{heap_drop, heap_move_nonnull, heap_move_ok, heap_remove}; use servicepoint::{ BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Offset, Packet, TypedCommand, @@ -46,6 +46,18 @@ pub unsafe extern "C" fn sp_cmd_bitvec_into_packet( heap_move_ok(unsafe { heap_remove(command) }.try_into()) } +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitvec_clone( + command: NonNull, +) -> NonNull { + heap_move_nonnull(unsafe { command.as_ref().clone() }) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_bitvec_free(command: NonNull) { + unsafe { heap_drop(command) } +} + #[no_mangle] pub unsafe extern "C" fn sp_cmd_bitvec_get( mut command: NonNull, @@ -63,6 +75,7 @@ pub unsafe extern "C" fn sp_cmd_bitvec_set( command.as_mut().bitvec = heap_remove(bitvec); } } + #[no_mangle] pub unsafe extern "C" fn sp_cmd_bitvec_get_offset( command: NonNull, diff --git a/src/commands/brightness_grid_command.rs b/src/commands/brightness_grid_command.rs new file mode 100644 index 0000000..18a2836 --- /dev/null +++ b/src/commands/brightness_grid_command.rs @@ -0,0 +1,95 @@ +use crate::{heap_drop, heap_move_nonnull, heap_move_ok, heap_remove}; +use servicepoint::{ + BitmapCommand, BrightnessGrid, BrightnessGridCommand, Origin, Packet, + TypedCommand, +}; +use std::ptr::NonNull; + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_brightness_grid_new( + grid: NonNull, + origin_x: usize, + origin_y: usize, +) -> NonNull { + heap_move_nonnull(BrightnessGridCommand { + grid: unsafe { heap_remove(grid) }, + origin: Origin::new(origin_x, origin_y), + }) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_brightness_grid_from_grid( + grid: NonNull, +) -> NonNull { + 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, +) -> *mut Packet { + heap_move_ok(unsafe { heap_remove(command) }.try_into()) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_brightness_grid_clone( + command: NonNull, +) -> NonNull { + heap_move_nonnull(unsafe { command.as_ref().clone() }) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_brightness_grid_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_grid_set( + mut command: NonNull, + grid: NonNull, +) { + unsafe { + command.as_mut().grid = heap_remove(grid); + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_brightness_grid_get( + mut command: NonNull, +) -> *mut BrightnessGrid { + &mut unsafe { command.as_mut() }.grid +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_brightness_grid_get_origin( + command: NonNull, + origin_x: NonNull, + origin_y: NonNull, +) { + unsafe { + let origin = &command.as_ref().origin; + *origin_x.as_ptr() = origin.x; + *origin_y.as_ptr() = origin.y; + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_brightness_grid_set_origin( + mut command: NonNull, + origin_x: usize, + origin_y: usize, +) { + unsafe { + command.as_mut().origin = Origin::new(origin_x, origin_y); + } +} diff --git a/src/commands/char_grid_command.rs b/src/commands/char_grid_command.rs new file mode 100644 index 0000000..933e4cd --- /dev/null +++ b/src/commands/char_grid_command.rs @@ -0,0 +1,94 @@ +use crate::{heap_drop, heap_move_nonnull, heap_move_ok, heap_remove}; +use servicepoint::{ + BitmapCommand, CharGrid, CharGridCommand, Origin, Packet, TypedCommand, +}; +use std::ptr::NonNull; + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_char_grid_new( + grid: NonNull, + origin_x: usize, + origin_y: usize, +) -> NonNull { + heap_move_nonnull(CharGridCommand { + grid: unsafe { heap_remove(grid) }, + origin: Origin::new(origin_x, origin_y), + }) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_char_grid_from_grid( + grid: NonNull, +) -> NonNull { + 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, +) -> *mut Packet { + heap_move_ok(unsafe { heap_remove(command) }.try_into()) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_char_grid_clone( + command: NonNull, +) -> NonNull { + heap_move_nonnull(unsafe { command.as_ref().clone() }) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_char_grid_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_char_grid_set( + mut command: NonNull, + grid: NonNull, +) { + unsafe { + command.as_mut().grid = heap_remove(grid); + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_char_grid_get( + mut command: NonNull, +) -> *mut CharGrid { + &mut unsafe { command.as_mut() }.grid +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_char_grid_get_origin( + command: NonNull, + origin_x: NonNull, + origin_y: NonNull, +) { + unsafe { + let origin = &command.as_ref().origin; + *origin_x.as_ptr() = origin.x; + *origin_y.as_ptr() = origin.y; + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_char_grid_set_origin( + mut command: NonNull, + origin_x: usize, + origin_y: usize, +) { + unsafe { + command.as_mut().origin = Origin::new(origin_x, origin_y); + } +} diff --git a/src/commands/cp437_grid_command.rs b/src/commands/cp437_grid_command.rs new file mode 100644 index 0000000..0f3d9e2 --- /dev/null +++ b/src/commands/cp437_grid_command.rs @@ -0,0 +1,94 @@ +use crate::{heap_drop, heap_move_nonnull, heap_move_ok, heap_remove}; +use servicepoint::{ + BitmapCommand, Cp437Grid, Cp437GridCommand, Origin, Packet, TypedCommand, +}; +use std::ptr::NonNull; + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_cp437_grid_new( + grid: NonNull, + origin_x: usize, + origin_y: usize, +) -> NonNull { + heap_move_nonnull(Cp437GridCommand { + grid: unsafe { heap_remove(grid) }, + origin: Origin::new(origin_x, origin_y), + }) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_cp437_grid_from_grid( + grid: NonNull, +) -> NonNull { + 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, +) -> *mut Packet { + heap_move_ok(unsafe { heap_remove(command) }.try_into()) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_cp437_grid_clone( + command: NonNull, +) -> NonNull { + heap_move_nonnull(unsafe { command.as_ref().clone() }) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_cp437_grid_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_cp437_grid_set( + mut command: NonNull, + grid: NonNull, +) { + unsafe { + command.as_mut().grid = heap_remove(grid); + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_cp437_grid_get( + mut command: NonNull, +) -> *mut Cp437Grid { + &mut unsafe { command.as_mut() }.grid +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_cp437_grid_get_origin( + command: NonNull, + origin_x: NonNull, + origin_y: NonNull, +) { + unsafe { + let origin = &command.as_ref().origin; + *origin_x.as_ptr() = origin.x; + *origin_y.as_ptr() = origin.y; + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_cmd_cp437_grid_set_origin( + mut command: NonNull, + origin_x: usize, + origin_y: usize, +) { + unsafe { + command.as_mut().origin = Origin::new(origin_x, origin_y); + } +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 45489df..90422ff 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,2 +1,5 @@ mod bitmap_command; mod bitvec_command; +mod brightness_grid_command; +mod char_grid_command; +mod cp437_grid_command; diff --git a/src/typed_command.rs b/src/typed_command.rs index 451c0b7..26c33f1 100644 --- a/src/typed_command.rs +++ b/src/typed_command.rs @@ -1,6 +1,6 @@ use crate::{heap_drop, heap_move_nonnull, heap_move_ok}; use servicepoint::{ - Brightness, BrightnessGrid, CharGrid, Cp437Grid, GlobalBrightnessCommand, + Brightness, GlobalBrightnessCommand, Packet, TypedCommand, }; use std::ptr::NonNull; @@ -72,66 +72,6 @@ pub unsafe extern "C" fn sp_command_global_brightness( heap_move_nonnull(GlobalBrightnessCommand::from(brightness).into()) } -/// 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. -#[no_mangle] -pub unsafe extern "C" fn sp_command_brightness_grid( - x: usize, - y: usize, - grid: NonNull, -) -> NonNull { - let grid = unsafe { *Box::from_raw(grid.as_ptr()) }; - let result = servicepoint::BrightnessGridCommand { - origin: servicepoint::Origin::new(x, y), - grid, - } - .into(); - heap_move_nonnull(result) -} - -/// Show codepage 437 encoded text on the screen. -/// -/// The passed [Cp437Grid] gets consumed. -/// -/// Returns: a new [servicepoint::Cp437GridCommand] instance. -#[no_mangle] -pub unsafe extern "C" fn sp_command_cp437_grid( - x: usize, - y: usize, - grid: NonNull, -) -> NonNull { - let grid = *unsafe { Box::from_raw(grid.as_ptr()) }; - let result = servicepoint::Cp437GridCommand { - origin: servicepoint::Origin::new(x, y), - grid, - } - .into(); - heap_move_nonnull(result) -} - -/// Show UTF-8 encoded text on the screen. -/// -/// The passed [CharGrid] gets consumed. -/// -/// Returns: a new [servicepoint::CharGridCommand] instance. -#[no_mangle] -pub unsafe extern "C" fn sp_command_char_grid( - x: usize, - y: usize, - grid: NonNull, -) -> NonNull { - let grid = unsafe { *Box::from_raw(grid.as_ptr()) }; - let result = servicepoint::CharGridCommand { - origin: servicepoint::Origin::new(x, y), - grid, - } - .into(); - heap_move_nonnull(result) -} - /// Deallocates a [TypedCommand]. /// /// # Examples