From c65b735f5743f31a30e92f062062ec3c9e861c02 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Thu, 26 Jun 2025 22:23:53 +0200 Subject: [PATCH] generic wrap --- src/commands/bitmap_command.rs | 66 +++--- src/commands/bitvec_command.rs | 72 ++++--- src/commands/brightness_grid_command.rs | 54 ++--- src/commands/cc_only_commands.rs | 21 +- src/commands/char_grid_command.rs | 54 ++--- src/commands/cp437_grid_command.rs | 54 ++--- src/commands/generic_command.rs | 242 +++++++++++----------- src/commands/global_brightness_command.rs | 28 ++- src/containers/bitmap.rs | 168 +++++++-------- src/containers/bitvec.rs | 168 +++++++-------- src/containers/brightness_grid.rs | 122 +++++------ src/containers/char_grid.rs | 151 +++++++------- src/containers/cp437_grid.rs | 62 +++--- src/macros.rs | 62 ++++-- src/packet.rs | 112 +++++----- src/udp.rs | 187 ++++++++--------- 16 files changed, 828 insertions(+), 795 deletions(-) diff --git a/src/commands/bitmap_command.rs b/src/commands/bitmap_command.rs index 5b74924..2cb86f0 100644 --- a/src/commands/bitmap_command.rs +++ b/src/commands/bitmap_command.rs @@ -1,43 +1,43 @@ use crate::{ commands::{wrap_command, wrap_origin_accessors}, - macros::{wrap, wrap_functions}, + macros::wrap, }; use servicepoint::{Bitmap, BitmapCommand, CompressionCode, Origin}; use std::ptr::NonNull; wrap_command!(Bitmap); - -wrap!(BitmapCommand; - prop bitmap: Bitmap { get mut; set move; }; - prop compression: CompressionCode { get; set; }; -); - wrap_origin_accessors!(BitmapCommand); -wrap_functions!(associate BitmapCommand; - /// Sets a window of pixels to the specified values. - /// - /// The passed [Bitmap] gets consumed. - /// - /// Returns: a new [BitmapCommand] instance. - fn new( - bitmap: move NonNull, - origin_x: val usize, - origin_y: val usize, - compression: val CompressionCode, - ) -> move NonNull { - BitmapCommand { - bitmap, - origin: Origin::new(origin_x, origin_y), - compression, - } - }; +wrap! { + BitmapCommand { + properties: + prop bitmap: Bitmap { get mut; set move; }; + prop compression: CompressionCode { get; set; }; + functions: + /// Sets a window of pixels to the specified values. + /// + /// The passed [Bitmap] gets consumed. + /// + /// Returns: a new [BitmapCommand] instance. + fn new( + bitmap: move NonNull, + origin_x: val usize, + origin_y: val usize, + compression: val CompressionCode, + ) -> move NonNull { + BitmapCommand { + bitmap, + origin: Origin::new(origin_x, origin_y), + compression, + } + }; - /// Move the provided [Bitmap] into a new [BitmapCommand], - /// leaving other fields as their default values. - /// - /// Rust equivalent: `BitmapCommand::from(bitmap)` - fn from_bitmap(bitmap: move NonNull) -> move NonNull { - bitmap.into() - }; -); + /// Move the provided [Bitmap] into a new [BitmapCommand], + /// leaving other fields as their default values. + /// + /// Rust equivalent: `BitmapCommand::from(bitmap)` + fn from_bitmap(bitmap: move NonNull) -> move NonNull { + bitmap.into() + }; + } +} diff --git a/src/commands/bitvec_command.rs b/src/commands/bitvec_command.rs index 440850f..3b239aa 100644 --- a/src/commands/bitvec_command.rs +++ b/src/commands/bitvec_command.rs @@ -1,7 +1,4 @@ -use crate::{ - commands::wrap_command, - macros::{wrap, wrap_functions}, -}; +use crate::{commands::wrap_command, macros::wrap}; use servicepoint::{ BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Offset, }; @@ -9,37 +6,38 @@ use std::ptr::NonNull; wrap_command!(BitVec); -wrap!(BitVecCommand; - prop bitvec: DisplayBitVec { get mut; set move; }; - prop offset: Offset { get; set; }; - prop operation: BinaryOperation { get; set; }; - prop compression: CompressionCode { get; set; }; -); - -wrap_functions!(associate BitVecCommand; - /// Set pixel data starting at the pixel offset on screen. - /// - /// The screen will continuously overwrite more pixel data without regarding the offset, meaning - /// once the starting row is full, overwriting will continue on column 0. - /// - /// The [`BinaryOperation`] will be applied on the display comparing old and sent bit. - /// - /// `new_bit = old_bit op sent_bit` - /// - /// For example, [`BinaryOperation::Or`] can be used to turn on some pixels without affecting other pixels. - /// - /// The contained [`DisplayBitVec`] is always uncompressed. - fn new( - bitvec: move NonNull, - offset: val usize, - operation: val BinaryOperation, - compression: val CompressionCode, - ) -> move NonNull { - BitVecCommand { - bitvec, - offset, - operation, - compression, - } - }; +wrap!( + BitVecCommand { + properties: + prop bitvec: DisplayBitVec { get mut; set move; }; + prop offset: Offset { get; set; }; + prop operation: BinaryOperation { get; set; }; + prop compression: CompressionCode { get; set; }; + functions: + /// Set pixel data starting at the pixel offset on screen. + /// + /// The screen will continuously overwrite more pixel data without regarding the offset, meaning + /// once the starting row is full, overwriting will continue on column 0. + /// + /// The [`BinaryOperation`] will be applied on the display comparing old and sent bit. + /// + /// `new_bit = old_bit op sent_bit` + /// + /// For example, [`BinaryOperation::Or`] can be used to turn on some pixels without affecting other pixels. + /// + /// The contained [`DisplayBitVec`] is always uncompressed. + fn new( + bitvec: move NonNull, + offset: val usize, + operation: val BinaryOperation, + compression: val CompressionCode, + ) -> move NonNull { + BitVecCommand { + bitvec, + offset, + operation, + compression, + } + }; + } ); diff --git a/src/commands/brightness_grid_command.rs b/src/commands/brightness_grid_command.rs index 23f5982..cbf22bb 100644 --- a/src/commands/brightness_grid_command.rs +++ b/src/commands/brightness_grid_command.rs @@ -1,38 +1,38 @@ use crate::{ commands::{wrap_command, wrap_origin_accessors}, - macros::{wrap, wrap_functions}, + macros::wrap, }; use servicepoint::{BrightnessGrid, BrightnessGridCommand, Origin}; use std::ptr::NonNull; wrap_command!(BrightnessGrid); - -wrap!(BrightnessGridCommand; - prop grid: BrightnessGrid { get mut; set move; }; -); - wrap_origin_accessors!(BrightnessGridCommand); -wrap_functions!(associate BrightnessGridCommand; - /// Set the brightness of individual tiles in a rectangular area of the display. - /// - /// The passed [BrightnessGrid] gets consumed. - /// - /// Returns: a new [BrightnessGridCommand] instance. - fn new( - grid: move NonNull, - origin_x: val usize, - origin_y: val usize - ) -> move NonNull { - BrightnessGridCommand { - grid, - origin: Origin::new(origin_x, origin_y), - } - }; +wrap!( + BrightnessGridCommand { + properties: + prop grid: BrightnessGrid { get mut; set move; }; + functions: + /// Set the brightness of individual tiles in a rectangular area of the display. + /// + /// The passed [BrightnessGrid] gets consumed. + /// + /// Returns: a new [BrightnessGridCommand] instance. + fn new( + grid: move NonNull, + origin_x: val usize, + origin_y: val usize + ) -> move NonNull { + BrightnessGridCommand { + grid, + origin: Origin::new(origin_x, origin_y), + } + }; - /// Moves the provided [BrightnessGrid] into a new [BrightnessGridCommand], - /// leaving other fields as their default values. - fn from_grid(grid: move NonNull) -> move NonNull { - grid.into() - }; + /// Moves the provided [BrightnessGrid] into a new [BrightnessGridCommand], + /// leaving other fields as their default values. + fn from_grid(grid: move NonNull) -> move NonNull { + grid.into() + }; + } ); diff --git a/src/commands/cc_only_commands.rs b/src/commands/cc_only_commands.rs index ef49fa1..3fa97c7 100644 --- a/src/commands/cc_only_commands.rs +++ b/src/commands/cc_only_commands.rs @@ -1,4 +1,4 @@ -use crate::{commands::wrap_command, macros::wrap_functions}; +use crate::commands::wrap_command; use servicepoint::{ClearCommand, FadeOutCommand, HardResetCommand}; macro_rules! wrap_cc_only { @@ -6,14 +6,17 @@ macro_rules! wrap_cc_only { ::paste::paste!{ wrap_command!($command); - wrap_functions!(associate [< $command Command >]; - $(#[$meta])* - /// - #[doc = " Returns: a new [`" [< $command Command >] "`] instance."] - fn new() -> move ::core::ptr::NonNull<[< $command Command >]> { - [< $command Command >] - }; - ); + $crate::macros::wrap!{ + [< $command Command >] { + functions: + $(#[$meta])* + /// + #[doc = " Returns: a new [`" [< $command Command >] "`] instance."] + fn new() -> move ::core::ptr::NonNull<[< $command Command >]> { + [< $command Command >] + }; + } + } } }; } diff --git a/src/commands/char_grid_command.rs b/src/commands/char_grid_command.rs index dcd5bc7..cbb91e6 100644 --- a/src/commands/char_grid_command.rs +++ b/src/commands/char_grid_command.rs @@ -1,38 +1,38 @@ use crate::{ commands::{wrap_command, wrap_origin_accessors}, - macros::{wrap, wrap_functions}, + macros::wrap, }; use servicepoint::{CharGrid, CharGridCommand, Origin}; use std::ptr::NonNull; wrap_command!(CharGrid); - -wrap!(CharGridCommand; - prop grid: CharGrid { get mut; set move; }; -); - wrap_origin_accessors!(CharGridCommand); -wrap_functions!(associate CharGridCommand; - /// Show UTF-8 encoded text on the screen. - /// - /// The passed [CharGrid] gets consumed. - /// - /// Returns: a new [CharGridCommand] instance. - fn new( - grid: move NonNull, - origin_x: val usize, - origin_y: val usize, - ) -> move NonNull { - CharGridCommand { - grid, - origin: Origin::new(origin_x, origin_y), - } - }; +wrap!( + CharGridCommand { + properties: + prop grid: CharGrid { get mut; set move; }; + functions: + /// Show UTF-8 encoded text on the screen. + /// + /// The passed [CharGrid] gets consumed. + /// + /// Returns: a new [CharGridCommand] instance. + fn new( + grid: move NonNull, + origin_x: val usize, + origin_y: val usize, + ) -> move NonNull { + CharGridCommand { + grid, + origin: Origin::new(origin_x, origin_y), + } + }; - /// Moves the provided [CharGrid] into a new [CharGridCommand], - /// leaving other fields as their default values. - fn from_grid(grid: move NonNull) -> move NonNull { - grid.into() - }; + /// Moves the provided [CharGrid] into a new [CharGridCommand], + /// leaving other fields as their default values. + fn from_grid(grid: move NonNull) -> move NonNull { + grid.into() + }; + } ); diff --git a/src/commands/cp437_grid_command.rs b/src/commands/cp437_grid_command.rs index 90b2d3d..8eeeb8e 100644 --- a/src/commands/cp437_grid_command.rs +++ b/src/commands/cp437_grid_command.rs @@ -1,38 +1,38 @@ use crate::{ commands::{wrap_command, wrap_origin_accessors}, - macros::{wrap, wrap_functions}, + macros::wrap, }; use servicepoint::{Cp437Grid, Cp437GridCommand, Origin}; use std::ptr::NonNull; wrap_command!(Cp437Grid); - -wrap!(Cp437GridCommand; - prop grid: Cp437Grid { get mut; set move; }; -); - wrap_origin_accessors!(Cp437GridCommand); -wrap_functions!(associate Cp437GridCommand; - /// Show text on the screen. - /// - /// The text is sent in the form of a 2D grid of [CP-437] encoded characters. - /// - /// The origin is relative to the top-left of the display. - fn new( - grid: move NonNull, - origin_x: val usize, - origin_y: val usize, - ) -> move NonNull { - Cp437GridCommand { - grid, - origin: Origin::new(origin_x, origin_y), - } - }; +wrap!( + Cp437GridCommand { + properties: + prop grid: Cp437Grid { get mut; set move; }; + functions: + /// Show text on the screen. + /// + /// The text is sent in the form of a 2D grid of [CP-437] encoded characters. + /// + /// The origin is relative to the top-left of the display. + fn new( + grid: move NonNull, + origin_x: val usize, + origin_y: val usize, + ) -> move NonNull { + Cp437GridCommand { + grid, + origin: Origin::new(origin_x, origin_y), + } + }; - /// Moves the provided [Cp437Grid] into a new [Cp437GridCommand], - /// leaving other fields as their default values. - fn from_grid(grid: move NonNull) -> move NonNull { - grid.into() - }; + /// Moves the provided [Cp437Grid] into a new [Cp437GridCommand], + /// leaving other fields as their default values. + fn from_grid(grid: move NonNull) -> move NonNull { + grid.into() + }; + } ); diff --git a/src/commands/generic_command.rs b/src/commands/generic_command.rs index 4f71dc4..2991352 100644 --- a/src/commands/generic_command.rs +++ b/src/commands/generic_command.rs @@ -1,5 +1,5 @@ use crate::{ - macros::{derive_clone, derive_free, wrap, wrap_functions}, + macros::{derive_clone, derive_free, wrap}, mem::{ heap_clone, heap_drop, heap_move, heap_move_nonnull, heap_move_ok, heap_remove, @@ -69,8 +69,6 @@ impl GenericCommand { }; } -derive_clone!(GenericCommand); - impl Clone for GenericCommand { fn clone(&self) -> Self { unsafe { @@ -144,8 +142,6 @@ impl Clone for GenericCommand { } } -derive_free!(GenericCommand); - impl Drop for GenericCommand { fn drop(&mut self) { unsafe { @@ -172,122 +168,126 @@ impl Drop for GenericCommand { } } -wrap_functions!(associate GenericCommand; - /// 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. - fn try_from_packet(packet: move NonNull) -> move NonNull { - servicepoint::TypedCommand::try_from(packet) - .map(|value| match value { - TypedCommand::Clear(clear) => GenericCommand { - tag: CommandTag::Clear, - data: CommandUnion { - clear: heap_move_nonnull(clear), - }, - }, - TypedCommand::CharGrid(char_grid) => GenericCommand { - tag: CommandTag::CharGrid, - data: CommandUnion { - char_grid: heap_move_nonnull(char_grid), - }, - }, - TypedCommand::Cp437Grid(cp437_grid) => GenericCommand { - tag: CommandTag::Cp437Grid, - data: CommandUnion { - cp437_grid: heap_move_nonnull(cp437_grid), - }, - }, - TypedCommand::Bitmap(bitmap) => GenericCommand { - tag: CommandTag::Bitmap, - data: CommandUnion { - bitmap: heap_move_nonnull(bitmap), - }, - }, - TypedCommand::Brightness(global_brightness) => GenericCommand { - tag: CommandTag::GlobalBrightness, - data: CommandUnion { - global_brightness: heap_move_nonnull(global_brightness), - }, - }, - TypedCommand::BrightnessGrid(brightness_grid) => GenericCommand { - tag: CommandTag::BrightnessGrid, - data: CommandUnion { - brightness_grid: heap_move_nonnull(brightness_grid), - }, - }, - TypedCommand::BitVec(bitvec) => GenericCommand { - tag: CommandTag::BitVec, - data: CommandUnion { - bit_vec: heap_move_nonnull(bitvec), - }, - }, - TypedCommand::HardReset(hard_reset) => GenericCommand { - tag: CommandTag::HardReset, - data: CommandUnion { - hard_reset: heap_move_nonnull(hard_reset), - }, - }, - TypedCommand::FadeOut(fade_out) => GenericCommand { - tag: CommandTag::FadeOut, - data: CommandUnion { - fade_out: heap_move_nonnull(fade_out), - }, - }, - #[allow(deprecated)] - TypedCommand::BitmapLegacy(bitmap_legacy) => GenericCommand { - tag: CommandTag::BitmapLegacy, - data: CommandUnion { - bitmap_legacy: heap_move_nonnull(bitmap_legacy), - }, - }, - }) - .unwrap_or_else(move |_| GenericCommand { - tag: CommandTag::Invalid, - data: CommandUnion { null: null_mut() }, - }) - }; -); +derive_clone!(GenericCommand); +derive_free!(GenericCommand); -wrap! { GenericCommand; - /// Tries to turn a [GenericCommand] into a [Packet]. - /// The [GenericCommand] gets consumed. - /// - /// Returns tag [CommandTag::Invalid] in case of an error. - method try_into_packet(move command) -> val *mut Packet { - match command.tag { - CommandTag::Invalid => null_mut(), - CommandTag::Bitmap => { - heap_move_ok(unsafe { heap_remove(command.data.bitmap).try_into() }) +wrap! { + GenericCommand { + functions: + /// 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. + fn try_from_packet(packet: move NonNull) -> move NonNull { + servicepoint::TypedCommand::try_from(packet) + .map(|value| match value { + TypedCommand::Clear(clear) => GenericCommand { + tag: CommandTag::Clear, + data: CommandUnion { + clear: heap_move_nonnull(clear), + }, + }, + TypedCommand::CharGrid(char_grid) => GenericCommand { + tag: CommandTag::CharGrid, + data: CommandUnion { + char_grid: heap_move_nonnull(char_grid), + }, + }, + TypedCommand::Cp437Grid(cp437_grid) => GenericCommand { + tag: CommandTag::Cp437Grid, + data: CommandUnion { + cp437_grid: heap_move_nonnull(cp437_grid), + }, + }, + TypedCommand::Bitmap(bitmap) => GenericCommand { + tag: CommandTag::Bitmap, + data: CommandUnion { + bitmap: heap_move_nonnull(bitmap), + }, + }, + TypedCommand::Brightness(global_brightness) => GenericCommand { + tag: CommandTag::GlobalBrightness, + data: CommandUnion { + global_brightness: heap_move_nonnull(global_brightness), + }, + }, + TypedCommand::BrightnessGrid(brightness_grid) => GenericCommand { + tag: CommandTag::BrightnessGrid, + data: CommandUnion { + brightness_grid: heap_move_nonnull(brightness_grid), + }, + }, + TypedCommand::BitVec(bitvec) => GenericCommand { + tag: CommandTag::BitVec, + data: CommandUnion { + bit_vec: heap_move_nonnull(bitvec), + }, + }, + TypedCommand::HardReset(hard_reset) => GenericCommand { + tag: CommandTag::HardReset, + data: CommandUnion { + hard_reset: heap_move_nonnull(hard_reset), + }, + }, + TypedCommand::FadeOut(fade_out) => GenericCommand { + tag: CommandTag::FadeOut, + data: CommandUnion { + fade_out: heap_move_nonnull(fade_out), + }, + }, + #[allow(deprecated)] + TypedCommand::BitmapLegacy(bitmap_legacy) => GenericCommand { + tag: CommandTag::BitmapLegacy, + data: CommandUnion { + bitmap_legacy: heap_move_nonnull(bitmap_legacy), + }, + }, + }) + .unwrap_or_else(move |_| GenericCommand { + tag: CommandTag::Invalid, + data: CommandUnion { null: null_mut() }, + }) + }; + methods: + /// Tries to turn a [GenericCommand] into a [Packet]. + /// The [GenericCommand] gets consumed. + /// + /// Returns tag [CommandTag::Invalid] in case of an error. + fn try_into_packet(move command) -> val *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.bit_vec).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(unsafe { + heap_remove(command.data.global_brightness).into() + }), + CommandTag::Clear => { + heap_move(unsafe { heap_remove(command.data.clear).into() }) + } + CommandTag::HardReset => { + heap_move(unsafe { heap_remove(command.data.hard_reset).into() }) + } + CommandTag::FadeOut => { + heap_move(unsafe { heap_remove(command.data.fade_out).into() }) + } + CommandTag::BitmapLegacy => { + heap_move(unsafe { heap_remove(command.data.bitmap_legacy).into() }) + } } - CommandTag::BitVec => { - heap_move_ok(unsafe { heap_remove(command.data.bit_vec).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(unsafe { - heap_remove(command.data.global_brightness).into() - }), - CommandTag::Clear => { - heap_move(unsafe { heap_remove(command.data.clear).into() }) - } - CommandTag::HardReset => { - heap_move(unsafe { heap_remove(command.data.hard_reset).into() }) - } - CommandTag::FadeOut => { - heap_move(unsafe { heap_remove(command.data.fade_out).into() }) - } - CommandTag::BitmapLegacy => { - heap_move(unsafe { heap_remove(command.data.bitmap_legacy).into() }) - } - } - }; + }; + } } diff --git a/src/commands/global_brightness_command.rs b/src/commands/global_brightness_command.rs index 06377ae..8e988c1 100644 --- a/src/commands/global_brightness_command.rs +++ b/src/commands/global_brightness_command.rs @@ -1,21 +1,19 @@ -use crate::{ - commands::wrap_command, - macros::{wrap, wrap_functions}, -}; +use crate::{commands::wrap_command, macros::wrap}; use servicepoint::{Brightness, GlobalBrightnessCommand}; use std::ptr::NonNull; -wrap_functions!(associate GlobalBrightnessCommand; - /// Set the brightness of all tiles to the same value. - /// - /// Returns: a new [GlobalBrightnessCommand] instance. - fn new(brightness: val Brightness) -> move NonNull { - GlobalBrightnessCommand::from(brightness) - }; -); - wrap_command!(GlobalBrightness); -wrap!(GlobalBrightnessCommand; - prop brightness: Brightness { get; set; }; +wrap!( + GlobalBrightnessCommand { + properties: + prop brightness: Brightness { get; set; }; + functions: + /// Set the brightness of all tiles to the same value. + /// + /// Returns: a new [GlobalBrightnessCommand] instance. + fn new(brightness: val Brightness) -> move NonNull { + GlobalBrightnessCommand::from(brightness) + }; + } ); diff --git a/src/containers/bitmap.rs b/src/containers/bitmap.rs index acc959a..4de29db 100644 --- a/src/containers/bitmap.rs +++ b/src/containers/bitmap.rs @@ -1,6 +1,6 @@ use crate::{ containers::{wrap_grid, ByteSlice}, - macros::{wrap, wrap_functions}, + macros::wrap, }; use servicepoint::{ Bitmap, BitmapCommand, CompressionCode, DataRef, DisplayBitVec, Grid, @@ -10,91 +10,93 @@ use std::ptr::NonNull; wrap_grid!(Bitmap, bool); -wrap_functions!(associate Bitmap; - /// Creates a new [Bitmap] with the specified dimensions. - /// - /// # Arguments - /// - /// - `width`: size in pixels in x-direction - /// - `height`: size in pixels in y-direction - /// - /// returns: [Bitmap] initialized to all pixels off, or NULL in case of an error. - /// - /// # Errors - /// - /// In the following cases, this function will return NULL: - /// - /// - when the width is not dividable by 8 - /// - /// # Examples - /// - /// ```C - /// Cp437Grid grid = sp_bitmap_new(8, 3); - /// sp_bitmap_fill(grid, true); - /// sp_bitmap_set(grid, 0, 0, false); - /// sp_bitmap_free(grid); - /// ``` - fn new(width: val usize, height: val usize) -> move_some *mut Bitmap { - Bitmap::new(width, height) - }; +wrap! { + Bitmap { + functions: + /// Creates a new [Bitmap] with the specified dimensions. + /// + /// # Arguments + /// + /// - `width`: size in pixels in x-direction + /// - `height`: size in pixels in y-direction + /// + /// returns: [Bitmap] initialized to all pixels off, or NULL in case of an error. + /// + /// # Errors + /// + /// In the following cases, this function will return NULL: + /// + /// - when the width is not dividable by 8 + /// + /// # Examples + /// + /// ```C + /// Cp437Grid grid = sp_bitmap_new(8, 3); + /// sp_bitmap_fill(grid, true); + /// sp_bitmap_set(grid, 0, 0, false); + /// sp_bitmap_free(grid); + /// ``` + fn new(width: val usize, height: val usize) -> move_some *mut Bitmap { + Bitmap::new(width, height) + }; - /// Creates a new [Bitmap] with a size matching the screen. - /// - /// returns: [Bitmap] initialized to all pixels off. - fn new_max_sized() -> move NonNull { - Bitmap::max_sized() - }; + /// Creates a new [Bitmap] with a size matching the screen. + /// + /// returns: [Bitmap] initialized to all pixels off. + fn new_max_sized() -> move NonNull { + Bitmap::max_sized() + }; - /// Loads a [Bitmap] with the specified dimensions from the provided data. - /// - /// # Arguments - /// - /// - `width`: size in pixels in x-direction - /// - `height`: size in pixels in y-direction - /// - /// returns: [Bitmap] that contains a copy of the provided data, or NULL in case of an error. - fn load( - width: val usize, - height: val usize, - data: slice ByteSlice, - ) -> move_ok *mut Bitmap { - Bitmap::load(width, height, data) - }; + /// Loads a [Bitmap] with the specified dimensions from the provided data. + /// + /// # Arguments + /// + /// - `width`: size in pixels in x-direction + /// - `height`: size in pixels in y-direction + /// + /// returns: [Bitmap] that contains a copy of the provided data, or NULL in case of an error. + fn load( + width: val usize, + height: val usize, + data: slice ByteSlice, + ) -> move_ok *mut Bitmap { + Bitmap::load(width, height, data) + }; - /// Tries to convert the BitVec to a Bitmap. - /// - /// The provided BitVec gets consumed. - /// - /// Returns NULL in case of error. - fn from_bitvec( - width: val usize, - bitvec: move NonNull, - ) -> move_ok *mut Bitmap { - Bitmap::from_bitvec(width, bitvec) - }; -); + /// Tries to convert the BitVec to a Bitmap. + /// + /// The provided BitVec gets consumed. + /// + /// Returns NULL in case of error. + fn from_bitvec( + width: val usize, + bitvec: move NonNull, + ) -> move_ok *mut Bitmap { + Bitmap::from_bitvec(width, bitvec) + }; -wrap!(Bitmap; - /// Consumes the Bitmap and returns the contained BitVec. - method into_bitvec(move bitmap) -> move NonNull { - bitmap.into() - }; + methods: + /// Consumes the Bitmap and returns the contained BitVec. + fn into_bitvec(move bitmap) -> 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. - method try_into_packet(move bitmap, x: val usize, y: val usize, compression: val CompressionCode) -> move_ok *mut Packet { - Packet::try_from(BitmapCommand { - bitmap, - origin: Origin::new(x, y), - compression, - }) - }; + /// 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(move bitmap, x: val usize, y: val usize, compression: val CompressionCode) -> move_ok *mut Packet { + Packet::try_from(BitmapCommand { + bitmap, + origin: Origin::new(x, y), + compression, + }) + }; - /// Gets an unsafe reference to the data of the [Bitmap] instance. - /// - /// The returned memory is valid for the lifetime of the bitmap. - method data_ref_mut(mut instance) -> slice ByteSlice; -); + /// Gets an unsafe reference to the data of the [Bitmap] instance. + /// + /// The returned memory is valid for the lifetime of the bitmap. + fn data_ref_mut(mut instance) -> slice ByteSlice; + } +} diff --git a/src/containers/bitvec.rs b/src/containers/bitvec.rs index c0627da..369501b 100644 --- a/src/containers/bitvec.rs +++ b/src/containers/bitvec.rs @@ -1,6 +1,6 @@ use crate::{ containers::{wrap_container, ByteSlice}, - macros::{wrap, wrap_functions}, + macros::wrap, }; use servicepoint::{ BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Packet, @@ -9,93 +9,95 @@ use std::ptr::NonNull; wrap_container!(DisplayBitVec); -wrap_functions!(associate DisplayBitVec; - /// Creates a new [DisplayBitVec] instance. - /// - /// # Arguments - /// - /// - `size`: size in bits. - /// - /// returns: [DisplayBitVec] with all bits set to false. - /// - /// # Panics - /// - /// - when `size` is not divisible by 8. - fn new(size: val usize) -> move NonNull { - DisplayBitVec::repeat(false, size) - }; +wrap! { + DisplayBitVec { + functions: + /// Creates a new [DisplayBitVec] instance. + /// + /// # Arguments + /// + /// - `size`: size in bits. + /// + /// returns: [DisplayBitVec] with all bits set to false. + /// + /// # Panics + /// + /// - when `size` is not divisible by 8. + fn new(size: val usize) -> move NonNull { + DisplayBitVec::repeat(false, size) + }; - /// Interpret the data as a series of bits and load then into a new [DisplayBitVec] instance. - /// - /// returns: [DisplayBitVec] instance containing data. - fn load(data: slice ByteSlice) -> move NonNull { - DisplayBitVec::from_slice(data) - }; -); + /// Interpret the data as a series of bits and load then into a new [DisplayBitVec] instance. + /// + /// returns: [DisplayBitVec] instance containing data. + fn load(data: slice ByteSlice) -> move NonNull { + DisplayBitVec::from_slice(data) + }; -wrap!(DisplayBitVec; - /// Creates a [BitVecCommand] and immediately turns that into a [Packet]. - /// - /// The provided [DisplayBitVec] gets consumed. - /// - /// Returns NULL in case of an error. - method try_into_packet( - move bitvec, - offset: val usize, - operation: val BinaryOperation, - compression: val CompressionCode - ) -> move_ok *mut Packet { - Packet::try_from(BitVecCommand { - bitvec, - offset, - operation, - compression, - }) - }; + methods: + /// 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( + move bitvec, + offset: val usize, + operation: val BinaryOperation, + compression: val CompressionCode + ) -> move_ok *mut Packet { + Packet::try_from(BitVecCommand { + bitvec, + offset, + operation, + compression, + }) + }; - /// Gets the value of a bit. - /// - /// # Arguments - /// - /// - `bit_vec`: instance to read from - /// - `index`: the bit index to read - /// - /// returns: value of the bit - /// - /// # Panics - /// - /// - when accessing `index` out of bounds - method get(ref instance, index: val usize) -> val bool { - instance.get(index).map(|x| *x).unwrap_or(false) - }; + /// Gets the value of a bit. + /// + /// # Arguments + /// + /// - `bit_vec`: instance to read from + /// - `index`: the bit index to read + /// + /// returns: value of the bit + /// + /// # Panics + /// + /// - when accessing `index` out of bounds + fn get(ref instance, index: val usize) -> val bool { + instance.get(index).map(|x| *x).unwrap_or(false) + }; - /// Sets the value of a bit. - /// - /// # Arguments - /// - /// - `index`: the bit index to edit - /// - `value`: the value to set the bit to - /// - /// # Panics - /// - /// - when accessing `index` out of bounds - method set(mut instance, index: val usize, value: val bool); + /// Sets the value of a bit. + /// + /// # Arguments + /// + /// - `index`: the bit index to edit + /// - `value`: the value to set the bit to + /// + /// # Panics + /// + /// - when accessing `index` out of bounds + fn set(mut instance, index: val usize, value: val bool); - /// Sets the value of all bits. - /// - /// # Arguments - /// - /// - `value`: the value to set all bits to - method fill(mut instance, value: val bool); + /// Sets the value of all bits. + /// + /// # Arguments + /// + /// - `value`: the value to set all bits to + fn fill(mut instance, value: val bool); - /// Gets the length in bits. - method len(ref instance) -> val usize; + /// Gets the length in bits. + fn len(ref instance) -> val usize; - /// Returns true if length is 0. - method is_empty(ref instance) -> val bool; + /// Returns true if length is 0. + fn is_empty(ref instance) -> val bool; - /// Gets an unsafe reference to the data of the [DisplayBitVec] instance. - /// - /// The returned memory is valid for the lifetime of the bitvec. - method as_raw_mut_slice(mut instance) -> slice ByteSlice; -); + /// Gets an unsafe reference to the data of the [DisplayBitVec] instance. + /// + /// The returned memory is valid for the lifetime of the bitvec. + fn as_raw_mut_slice(mut instance) -> slice ByteSlice; + } +} diff --git a/src/containers/brightness_grid.rs b/src/containers/brightness_grid.rs index c6b7f13..8c74b25 100644 --- a/src/containers/brightness_grid.rs +++ b/src/containers/brightness_grid.rs @@ -1,6 +1,6 @@ use crate::{ containers::{wrap_grid, ByteSlice}, - macros::{wrap, wrap_functions}, + macros::wrap, }; use servicepoint::{ Brightness, BrightnessGrid, BrightnessGridCommand, ByteGrid, DataRef, Grid, @@ -10,66 +10,68 @@ use std::{mem::transmute, ptr::NonNull}; wrap_grid!(BrightnessGrid, Brightness); -wrap_functions!(associate BrightnessGrid; - /// Creates a new [BrightnessGrid] with the specified dimensions. - /// - /// returns: [BrightnessGrid] initialized to 0. - /// - /// # Examples - /// ```C - /// UdpSocket *connection = sp_udp_open("127.0.0.1:2342"); - /// if (connection == NULL) - /// return 1; - /// - /// BrightnessGrid *grid = sp_brightness_grid_new(2, 2); - /// sp_brightness_grid_set(grid, 0, 0, 0); - /// sp_brightness_grid_set(grid, 1, 1, 10); - /// - /// TypedCommand *command = sp_command_char_brightness(grid); - /// sp_udp_free(connection); - /// ``` - fn new(width: val usize, height: val usize) -> move NonNull { - BrightnessGrid::new(width, height) - }; +wrap! { + BrightnessGrid { + functions: + /// Creates a new [BrightnessGrid] with the specified dimensions. + /// + /// returns: [BrightnessGrid] initialized to 0. + /// + /// # Examples + /// ```C + /// UdpSocket *connection = sp_udp_open("127.0.0.1:2342"); + /// if (connection == NULL) + /// return 1; + /// + /// BrightnessGrid *grid = sp_brightness_grid_new(2, 2); + /// sp_brightness_grid_set(grid, 0, 0, 0); + /// sp_brightness_grid_set(grid, 1, 1, 10); + /// + /// TypedCommand *command = sp_command_char_brightness(grid); + /// sp_udp_free(connection); + /// ``` + fn new(width: val usize, height: val usize) -> move NonNull { + BrightnessGrid::new(width, height) + }; - /// Loads a [BrightnessGrid] with the specified dimensions from the provided data. - /// - /// Any out of range values will be set to [Brightness::MAX] or [Brightness::MIN]. - /// - /// returns: new [BrightnessGrid] instance, or NULL in case of an error. - fn load( - width: val usize, - height: val usize, - data: slice ByteSlice, - ) -> move_some *mut BrightnessGrid { - ByteGrid::load(width, height, data) - .map(move |grid| grid.map(Brightness::saturating_from)) - }; -); + /// Loads a [BrightnessGrid] with the specified dimensions from the provided data. + /// + /// Any out of range values will be set to [Brightness::MAX] or [Brightness::MIN]. + /// + /// returns: new [BrightnessGrid] instance, or NULL in case of an error. + fn load( + width: val usize, + height: val usize, + data: slice ByteSlice, + ) -> move_some *mut BrightnessGrid { + ByteGrid::load(width, height, data) + .map(move |grid| grid.map(Brightness::saturating_from)) + }; -wrap!(BrightnessGrid; - /// Creates a [BrightnessGridCommand] and immediately turns that into a [Packet]. - /// - /// The provided [BrightnessGrid] gets consumed. - /// - /// Returns NULL in case of an error. - method try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet { - Packet::try_from(BrightnessGridCommand { - grid, - origin: Origin::new(x, y), - }) - }; + methods: + /// 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(move grid, x: val usize, y: val usize) -> move_ok *mut Packet { + Packet::try_from(BrightnessGridCommand { + grid, + origin: Origin::new(x, y), + }) + }; - /// Gets an unsafe reference to the data of the instance. - /// - /// The returned memory is valid for the lifetime of the grid. - method data_ref_mut(mut instance) -> slice ByteSlice { - //noinspection RsAssertEqual - const _: () = assert!(size_of::() == 1); + /// Gets an unsafe reference to the data of the instance. + /// + /// The returned memory is valid for the lifetime of the grid. + fn data_ref_mut(mut instance) -> slice ByteSlice { + //noinspection RsAssertEqual + const _: () = assert!(size_of::() == 1); - let br_slice = instance.data_ref_mut(); - unsafe { - transmute::<&mut [Brightness], &mut [u8]>(br_slice) - } - }; -); + let br_slice = instance.data_ref_mut(); + unsafe { + transmute::<&mut [Brightness], &mut [u8]>(br_slice) + } + }; + } +} diff --git a/src/containers/char_grid.rs b/src/containers/char_grid.rs index 4323021..4423071 100644 --- a/src/containers/char_grid.rs +++ b/src/containers/char_grid.rs @@ -1,6 +1,6 @@ use crate::{ containers::{derive_get_width_height, wrap_container, ByteSlice}, - macros::{wrap, wrap_functions}, + macros::wrap, }; use servicepoint::{CharGrid, CharGridCommand, Grid, Origin, Packet}; use std::ptr::NonNull; @@ -8,81 +8,82 @@ use std::ptr::NonNull; wrap_container!(CharGrid); derive_get_width_height!(CharGrid); -wrap_functions!(associate CharGrid; - /// Creates a new [CharGrid] with the specified dimensions. - /// - /// returns: [CharGrid] initialized to 0. - /// - /// # Examples - /// - /// ```C - /// CharGrid grid = sp_char_grid_new(4, 3); - /// sp_char_grid_fill(grid, '?'); - /// sp_char_grid_set(grid, 0, 0, '!'); - /// sp_char_grid_free(grid); - /// ``` - fn new(width: val usize, height: val usize) -> move NonNull { - CharGrid::new(width, height) - }; +wrap! { + CharGrid { + functions: + /// Creates a new [CharGrid] with the specified dimensions. + /// + /// returns: [CharGrid] initialized to 0. + /// + /// # Examples + /// + /// ```C + /// CharGrid grid = sp_char_grid_new(4, 3); + /// sp_char_grid_fill(grid, '?'); + /// sp_char_grid_set(grid, 0, 0, '!'); + /// sp_char_grid_free(grid); + /// ``` + fn new(width: val usize, height: val usize) -> 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: val usize, height: val usize, data: slice ByteSlice) -> move_ok *mut CharGrid { - CharGrid::load_utf8(width, height, data.to_vec()) - }; -); + /// Loads a [CharGrid] with the specified dimensions from the provided data. + /// + /// returns: new CharGrid or NULL in case of an error + fn load(width: val usize, height: val usize, data: slice ByteSlice) -> move_ok *mut CharGrid { + CharGrid::load_utf8(width, height, data.to_vec()) + }; + methods: + /// Returns the current value at the specified position. + /// + /// # Arguments + /// + /// - `x` and `y`: position of the cell to read + /// + /// # Panics + /// + /// - when accessing `x` or `y` out of bounds + fn get(ref instance, x: val usize, y: val usize) -> val u32 { + instance.get(x, y) as u32 + }; -wrap!(CharGrid; - /// Returns the current value at the specified position. - /// - /// # Arguments - /// - /// - `x` and `y`: position of the cell to read - /// - /// # Panics - /// - /// - when accessing `x` or `y` out of bounds - method get(ref instance, x: val usize, y: val usize) -> val u32 { - instance.get(x, y) as u32 - }; + /// Sets the value of the specified position in the grid. + /// + /// # Arguments + /// + /// - `x` and `y`: position of the cell + /// - `value`: the value to write to the cell + /// + /// returns: old value of the cell + /// + /// # Panics + /// + /// - when accessing `x` or `y` out of bounds + /// - when providing values that cannot be converted to Rust's `char`. + fn set(mut instance, x: val usize, y: val usize, value: val u32) { + instance.set(x, y, char::from_u32(value).unwrap()) + }; - /// Sets the value of the specified position in the grid. - /// - /// # Arguments - /// - /// - `x` and `y`: position of the cell - /// - `value`: the value to write to the cell - /// - /// returns: old value of the cell - /// - /// # Panics - /// - /// - when accessing `x` or `y` out of bounds - /// - when providing values that cannot be converted to Rust's `char`. - method set(mut instance, x: val usize, y: val usize, value: val u32) { - instance.set(x, y, char::from_u32(value).unwrap()) - }; + /// Sets the value of all cells in the grid. + /// + /// # Arguments + /// + /// - `value`: the value to set all cells to + /// - when providing values that cannot be converted to Rust's `char`. + fn fill(mut instance, value: val u32) { + instance.fill(char::from_u32(value).unwrap()) + }; - /// Sets the value of all cells in the grid. - /// - /// # Arguments - /// - /// - `value`: the value to set all cells to - /// - when providing values that cannot be converted to Rust's `char`. - method fill(mut instance, value: val 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. - method try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet { - Packet::try_from(CharGridCommand { - grid, - origin: Origin::new(x, y), - }) - }; -); + /// 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(move grid, x: val usize, y: val usize) -> move_ok *mut Packet { + 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 2a157c2..a6dbeea 100644 --- a/src/containers/cp437_grid.rs +++ b/src/containers/cp437_grid.rs @@ -1,6 +1,6 @@ use crate::{ containers::{wrap_grid, ByteSlice}, - macros::{wrap, wrap_functions}, + macros::wrap, }; use servicepoint::{ Cp437Grid, Cp437GridCommand, DataRef, Grid, Origin, Packet, @@ -9,35 +9,37 @@ use std::ptr::NonNull; wrap_grid!(Cp437Grid, u8); -wrap_functions!(associate Cp437Grid; - /// Creates a new [Cp437Grid] with the specified dimensions. - /// - /// returns: [Cp437Grid] initialized to 0. - fn new(width: val usize, height: val usize) -> move NonNull { - Cp437Grid::new(width, height) - }; +wrap! { + Cp437Grid { + functions: + /// Creates a new [Cp437Grid] with the specified dimensions. + /// + /// returns: [Cp437Grid] initialized to 0. + fn new(width: val usize, height: val usize) -> move NonNull { + Cp437Grid::new(width, height) + }; - /// Loads a [Cp437Grid] with the specified dimensions from the provided data. - fn load(width: val usize, height: val usize, data: slice ByteSlice) -> move_some *mut Cp437Grid { - Cp437Grid::load(width, height, data) - }; -); + /// Loads a [Cp437Grid] with the specified dimensions from the provided data. + fn load(width: val usize, height: val usize, data: slice ByteSlice) -> move_some *mut Cp437Grid { + Cp437Grid::load(width, height, data) + }; -wrap!(Cp437Grid; - /// Creates a [Cp437GridCommand] and immediately turns that into a [Packet]. - /// - /// The provided [Cp437Grid] gets consumed. - /// - /// Returns NULL in case of an error. - method try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet { - Packet::try_from(Cp437GridCommand { - grid, - origin: Origin::new(x, y), - }) - }; + methods: + /// 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(move grid, x: val usize, y: val usize) -> move_ok *mut Packet { + Packet::try_from(Cp437GridCommand { + grid, + origin: Origin::new(x, y), + }) + }; - /// Gets an unsafe reference to the data of the grid. - /// - /// The returned memory is valid for the lifetime of the instance. - method data_ref_mut(mut instance) -> slice ByteSlice; -); + /// Gets an unsafe reference to the data of the grid. + /// + /// The returned memory is valid for the lifetime of the instance. + fn data_ref_mut(mut instance) -> slice ByteSlice; + } +} diff --git a/src/macros.rs b/src/macros.rs index ebcad75..4149873 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -265,30 +265,54 @@ macro_rules! wrap_functions { macro_rules! wrap { ( - $object_type:ident; - $( - prop $prop_name:ident : $prop_type:ty { $($accessor:ident $($modifier:ident)?;)+ }; - )* - $( - $(#[$meta:meta])+ - method $function:ident($ref_or_mut:ident $instance:ident $(, $($param_name:ident: $param_modifier:ident $param_type:ty),*)?) - $(-> $return_modifier:ident $return_type:ty)? - $($impl:block)?; - )* + $object_type:ident { + $( + properties: + $( + prop $prop_name:ident : $prop_type:ty { $($accessor:ident $($modifier:ident)?;)+ }; + )* + )? + $( + functions: + $( + $(#[$fn_meta:meta])+ + fn $fn_name:ident($($fn_param_name:ident: $fn_param_modifier:ident $fn_param_type:ty),*$(,)?) + $(-> $fn_return_modifier:ident $fn_return_type:ty)? + $fn_block:block; + )* + )? + $( + methods: + $( + $(#[$method_meta:meta])+ + fn $method_name:ident($method_instance_modifier:ident $method_instance:ident $(, $($method_param_name:ident: $method_param_modifier:ident $method_param_type:ty),*)?) + $(-> $method_return_modifier:ident $method_return_type:ty)? + $($method_impl:block)?; + )* + )? + } ) => { - $( + $($( $crate::macros::wrap_fields!($object_type; prop $prop_name : $prop_type { $($accessor $($modifier)?;)+ }; ); - )* - $( - $crate::macros::wrap_method!($object_type; - $(#[$meta])+ - fn $function($ref_or_mut $instance $(, $($param_name: $param_modifier $param_type),*)?) - $(-> $return_modifier $return_type)? - $($impl)?; + )*)? + $($( + $crate::macros::wrap_functions!(associate $object_type; + $(#[$fn_meta])+ + fn $fn_name($($fn_param_name: $fn_param_modifier $fn_param_type),*) + $(-> $fn_return_modifier $fn_return_type)? + $fn_block; ); - )* + )*)? + $($( + $crate::macros::wrap_method!($object_type; + $(#[$method_meta])+ + fn $method_name($method_instance_modifier $method_instance $(, $($method_param_name: $method_param_modifier $method_param_type),*)?) + $(-> $method_return_modifier $method_return_type)? + $($method_impl)?; + ); + )*)? }; } diff --git a/src/packet.rs b/src/packet.rs index 71c746d..00a34a9 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -5,71 +5,71 @@ use crate::{ use servicepoint::{CommandCode, Header, Packet}; use std::ptr::NonNull; -wrap_functions!(associate Packet; - /// 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 - fn try_load(data: slice ByteSlice) -> move_ok *mut Packet { - servicepoint::Packet::try_from(data) - }; - - /// Creates a raw [Packet] from parts. - /// - /// returns: new instance. Will never return null. - fn from_parts(header: val Header, payload: val ByteSlice) -> move NonNull { - let payload = if payload == ByteSlice::INVALID { - None - } else { - Some(Vec::from(unsafe { payload.as_slice() })) - }; - - Packet { header, payload } - }; -); - derive_clone!(Packet); derive_free!(Packet); -wrap! {Packet; - prop header: Header { get; get mut; set; }; +wrap! { + Packet { + properties: + prop header: Header { get; get mut; set; }; + functions: + /// 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 + fn try_load(data: slice ByteSlice) -> move_ok *mut Packet { + servicepoint::Packet::try_from(data) + }; - /// Returns a pointer to the current payload of the provided packet. - /// - /// Returns an [ByteSlice::INVALID] instance in case the packet does not have any payload. - /// - /// The returned memory can be changed and will be valid until a new payload is set. - method get_payload(mut packet) -> val ByteSlice { - match &mut packet.payload { - None => ByteSlice::INVALID, - Some(payload) => unsafe { ByteSlice::from_slice(payload) }, - } - }; + /// Creates a raw [Packet] from parts. + /// + /// returns: new instance. Will never return null. + fn from_parts(header: val Header, payload: val ByteSlice) -> move NonNull { + let payload = if payload == ByteSlice::INVALID { + None + } else { + Some(Vec::from(unsafe { payload.as_slice() })) + }; - /// Sets the payload of the provided packet to the provided data. - /// - /// This makes previous payload pointers invalid. - method set_payload(mut packet, data: val ByteSlice) { - packet.payload = if data == ByteSlice::INVALID { - None - } else { - Some(unsafe { data.as_slice().to_vec() }) - } - }; + Packet { header, payload } + }; + methods: + /// Returns a pointer to the current payload of the provided packet. + /// + /// Returns an [ByteSlice::INVALID] instance in case the packet does not have any payload. + /// + /// The returned memory can be changed and will be valid until a new payload is set. + fn get_payload(mut packet) -> val ByteSlice { + match &mut packet.payload { + None => ByteSlice::INVALID, + Some(payload) => unsafe { ByteSlice::from_slice(payload) }, + } + }; - /// Serialize the packet into the provided buffer. - /// - /// # Panics - /// - /// - if the buffer is not big enough to hold header+payload. - method serialize_to(mut packet, buffer: val ByteSlice) -> val usize { - unsafe { - packet.serialize_to(buffer.as_slice_mut()).unwrap_or(0) - } - }; + /// Sets the payload of the provided packet to the provided data. + /// + /// This makes previous payload pointers invalid. + fn set_payload(mut packet, data: val ByteSlice) { + packet.payload = if data == ByteSlice::INVALID { + None + } else { + Some(unsafe { data.as_slice().to_vec() }) + } + }; + + /// Serialize the packet into the provided buffer. + /// + /// # Panics + /// + /// - if the buffer is not big enough to hold header+payload. + fn serialize_to(mut packet, buffer: val ByteSlice) -> val usize { + unsafe { + packet.serialize_to(buffer.as_slice_mut()).unwrap_or(0) + } + }; + } } wrap_functions!(sp; - /// Converts u16 into [CommandCode]. /// /// If the provided value is not valid, false is returned and result is not changed. diff --git a/src/udp.rs b/src/udp.rs index 4fce7c0..22a7f7c 100644 --- a/src/udp.rs +++ b/src/udp.rs @@ -1,6 +1,6 @@ use crate::{ commands::{CommandTag, GenericCommand}, - macros::{derive_free, wrap, wrap_functions}, + macros::{derive_free, wrap}, mem::heap_remove, }; use servicepoint::{Header, Packet, UdpSocketExt}; @@ -12,99 +12,100 @@ use std::{ derive_free!(UdpSocket); -wrap_functions!(associate UdpSocket; - /// Creates a new instance of [UdpSocket]. - /// - /// returns: NULL if connection fails, or connected instance - /// - /// # Examples - /// - /// ```C - /// UdpSocket connection = sp_udp_open("172.23.42.29:2342"); - /// if (connection != NULL) - /// sp_udp_send_command(connection, sp_command_clear()); - /// ``` - fn open(host: val NonNull) -> move_ok *mut UdpSocket { - let host = unsafe { CStr::from_ptr(host.as_ptr()) } - .to_str() - .expect("Bad encoding"); - UdpSocket::bind_connect(host) - }; - - /// Creates a new instance of [UdpSocket]. - /// - /// returns: NULL if connection fails, or connected instance - /// - /// # Examples - /// - /// ```C - /// UdpSocket connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); - /// if (connection != NULL) - /// sp_udp_send_command(connection, sp_command_clear()); - /// ``` - fn open_ipv4(ip1: val u8, ip2: val u8, ip3: val u8, ip4: val u8, port: val u16) -> move_ok *mut UdpSocket { - let addr = SocketAddrV4::new(Ipv4Addr::from([ip1, ip2, ip3, ip4]), port); - UdpSocket::bind_connect(addr) - }; -); - -wrap! {UdpSocket; - /// Sends a [Packet] to the display using the [UdpSocket]. - /// - /// The passed `packet` gets consumed. - /// - /// returns: true in case of success - method send_packet(ref connection, packet: move NonNull) -> val bool { - connection.send(&Vec::from(packet)).is_ok() - }; - - /// Sends a [GenericCommand] to the display using the [UdpSocket]. - /// - /// The passed `command` gets consumed. - /// - /// returns: true in case of success - /// - /// # Examples - /// - /// ```C - /// sp_udp_send_command(connection, sp_command_brightness(5)); - /// ``` - method send_command(ref connection, command: mut NonNull) -> val bool { - unsafe { - let result = match command.tag { - CommandTag::Invalid => return false, - 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 - } - }; - - /// Sends a [Header] to the display using the [UdpSocket]. - /// - /// returns: true in case of success - /// - /// # Examples - /// - /// ```C - /// sp_udp_send_header(connection, sp_command_brightness(5)); - /// ``` - method send_header(ref udp_connection, header: val Header) -> val bool { - let packet = Packet { - header, - payload: None, +wrap! { + UdpSocket { + functions: + /// Creates a new instance of [UdpSocket]. + /// + /// returns: NULL if connection fails, or connected instance + /// + /// # Examples + /// + /// ```C + /// UdpSocket connection = sp_udp_open("172.23.42.29:2342"); + /// if (connection != NULL) + /// sp_udp_send_command(connection, sp_command_clear()); + /// ``` + fn open(host: val NonNull) -> move_ok *mut UdpSocket { + let host = unsafe { CStr::from_ptr(host.as_ptr()) } + .to_str() + .expect("Bad encoding"); + UdpSocket::bind_connect(host) }; - udp_connection.send(&Vec::from(packet)).is_ok() - }; + + /// Creates a new instance of [UdpSocket]. + /// + /// returns: NULL if connection fails, or connected instance + /// + /// # Examples + /// + /// ```C + /// UdpSocket connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); + /// if (connection != NULL) + /// sp_udp_send_command(connection, sp_command_clear()); + /// ``` + fn open_ipv4(ip1: val u8, ip2: val u8, ip3: val u8, ip4: val u8, port: val u16) -> move_ok *mut UdpSocket { + let addr = SocketAddrV4::new(Ipv4Addr::from([ip1, ip2, ip3, ip4]), port); + UdpSocket::bind_connect(addr) + }; + methods: + /// Sends a [Packet] to the display using the [UdpSocket]. + /// + /// The passed `packet` gets consumed. + /// + /// returns: true in case of success + fn send_packet(ref connection, packet: move NonNull) -> val bool { + connection.send(&Vec::from(packet)).is_ok() + }; + + /// Sends a [GenericCommand] to the display using the [UdpSocket]. + /// + /// The passed `command` gets consumed. + /// + /// returns: true in case of success + /// + /// # Examples + /// + /// ```C + /// sp_udp_send_command(connection, sp_command_brightness(5)); + /// ``` + fn send_command(ref connection, command: mut NonNull) -> val bool { + unsafe { + let result = match command.tag { + CommandTag::Invalid => return false, + 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 + } + }; + + /// Sends a [Header] to the display using the [UdpSocket]. + /// + /// returns: true in case of success + /// + /// # Examples + /// + /// ```C + /// sp_udp_send_header(connection, sp_command_brightness(5)); + /// ``` + fn send_header(ref udp_connection, header: val Header) -> val bool { + let packet = Packet { + header, + payload: None, + }; + udp_connection.send(&Vec::from(packet)).is_ok() + }; + } } mod _hidden {