Compare commits

..

No commits in common. "c65b735f5743f31a30e92f062062ec3c9e861c02" and "82696b2d1ae49042dab5944f5fef67a7159fd437" have entirely different histories.

16 changed files with 780 additions and 837 deletions

View file

@ -1,43 +1,43 @@
use crate::{ use crate::{
commands::{wrap_command, wrap_origin_accessors}, commands::{wrap_command, wrap_origin_accessors},
macros::wrap, macros::{wrap_fields, wrap_functions},
}; };
use servicepoint::{Bitmap, BitmapCommand, CompressionCode, Origin}; use servicepoint::{Bitmap, BitmapCommand, CompressionCode, Origin};
use std::ptr::NonNull; use std::ptr::NonNull;
wrap_command!(Bitmap); wrap_command!(Bitmap);
wrap_fields!(BitmapCommand;
prop bitmap: Bitmap { get mut; set move; };
prop compression: CompressionCode { get; set; };
);
wrap_origin_accessors!(BitmapCommand); wrap_origin_accessors!(BitmapCommand);
wrap! { wrap_functions!(associate BitmapCommand;
BitmapCommand { /// Sets a window of pixels to the specified values.
properties: ///
prop bitmap: Bitmap { get mut; set move; }; /// The passed [Bitmap] gets consumed.
prop compression: CompressionCode { get; set; }; ///
functions: /// Returns: a new [BitmapCommand] instance.
/// Sets a window of pixels to the specified values. fn new(
/// bitmap: move NonNull<Bitmap>,
/// The passed [Bitmap] gets consumed. origin_x: val usize,
/// origin_y: val usize,
/// Returns: a new [BitmapCommand] instance. compression: val CompressionCode,
fn new( ) -> move NonNull<BitmapCommand> {
bitmap: move NonNull<Bitmap>, BitmapCommand {
origin_x: val usize, bitmap,
origin_y: val usize, origin: Origin::new(origin_x, origin_y),
compression: val CompressionCode, compression,
) -> move NonNull<BitmapCommand> { }
BitmapCommand { };
bitmap,
origin: Origin::new(origin_x, origin_y),
compression,
}
};
/// Move the provided [Bitmap] into a new [BitmapCommand], /// Move the provided [Bitmap] into a new [BitmapCommand],
/// leaving other fields as their default values. /// leaving other fields as their default values.
/// ///
/// Rust equivalent: `BitmapCommand::from(bitmap)` /// Rust equivalent: `BitmapCommand::from(bitmap)`
fn from_bitmap(bitmap: move NonNull<Bitmap>) -> move NonNull<BitmapCommand> { fn from_bitmap(bitmap: move NonNull<Bitmap>) -> move NonNull<BitmapCommand> {
bitmap.into() bitmap.into()
}; };
} );
}

View file

@ -1,4 +1,7 @@
use crate::{commands::wrap_command, macros::wrap}; use crate::{
commands::wrap_command,
macros::{wrap_fields, wrap_functions},
};
use servicepoint::{ use servicepoint::{
BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Offset, BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Offset,
}; };
@ -6,38 +9,37 @@ use std::ptr::NonNull;
wrap_command!(BitVec); wrap_command!(BitVec);
wrap!( wrap_fields!(BitVecCommand;
BitVecCommand { prop bitvec: DisplayBitVec { get mut; set move; };
properties: prop offset: Offset { get; set; };
prop bitvec: DisplayBitVec { get mut; set move; }; prop operation: BinaryOperation { get; set; };
prop offset: Offset { get; set; }; prop compression: CompressionCode { get; set; };
prop operation: BinaryOperation { get; set; }; );
prop compression: CompressionCode { get; set; };
functions: wrap_functions!(associate BitVecCommand;
/// Set pixel data starting at the pixel offset on screen. /// Set pixel data starting at the pixel offset on screen.
/// ///
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning /// 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. /// 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. /// The [`BinaryOperation`] will be applied on the display comparing old and sent bit.
/// ///
/// `new_bit = old_bit op 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. /// For example, [`BinaryOperation::Or`] can be used to turn on some pixels without affecting other pixels.
/// ///
/// The contained [`DisplayBitVec`] is always uncompressed. /// The contained [`DisplayBitVec`] is always uncompressed.
fn new( fn new(
bitvec: move NonNull<DisplayBitVec>, bitvec: move NonNull<DisplayBitVec>,
offset: val usize, offset: val usize,
operation: val BinaryOperation, operation: val BinaryOperation,
compression: val CompressionCode, compression: val CompressionCode,
) -> move NonNull<BitVecCommand> { ) -> move NonNull<BitVecCommand> {
BitVecCommand { BitVecCommand {
bitvec, bitvec,
offset, offset,
operation, operation,
compression, compression,
} }
}; };
}
); );

View file

@ -1,38 +1,38 @@
use crate::{ use crate::{
commands::{wrap_command, wrap_origin_accessors}, commands::{wrap_command, wrap_origin_accessors},
macros::wrap, macros::{wrap_fields, wrap_functions},
}; };
use servicepoint::{BrightnessGrid, BrightnessGridCommand, Origin}; use servicepoint::{BrightnessGrid, BrightnessGridCommand, Origin};
use std::ptr::NonNull; use std::ptr::NonNull;
wrap_command!(BrightnessGrid); wrap_command!(BrightnessGrid);
wrap_fields!(BrightnessGridCommand;
prop grid: BrightnessGrid { get mut; set move; };
);
wrap_origin_accessors!(BrightnessGridCommand); wrap_origin_accessors!(BrightnessGridCommand);
wrap!( wrap_functions!(associate BrightnessGridCommand;
BrightnessGridCommand { /// Set the brightness of individual tiles in a rectangular area of the display.
properties: ///
prop grid: BrightnessGrid { get mut; set move; }; /// The passed [BrightnessGrid] gets consumed.
functions: ///
/// Set the brightness of individual tiles in a rectangular area of the display. /// Returns: a new [BrightnessGridCommand] instance.
/// fn new(
/// The passed [BrightnessGrid] gets consumed. grid: move NonNull<BrightnessGrid>,
/// origin_x: val usize,
/// Returns: a new [BrightnessGridCommand] instance. origin_y: val usize
fn new( ) -> move NonNull<BrightnessGridCommand> {
grid: move NonNull<BrightnessGrid>, BrightnessGridCommand {
origin_x: val usize, grid,
origin_y: val usize origin: Origin::new(origin_x, origin_y),
) -> move NonNull<BrightnessGridCommand> { }
BrightnessGridCommand { };
grid,
origin: Origin::new(origin_x, origin_y),
}
};
/// Moves the provided [BrightnessGrid] into a new [BrightnessGridCommand], /// Moves the provided [BrightnessGrid] into a new [BrightnessGridCommand],
/// leaving other fields as their default values. /// leaving other fields as their default values.
fn from_grid(grid: move NonNull<BrightnessGrid>) -> move NonNull<BrightnessGridCommand> { fn from_grid(grid: move NonNull<BrightnessGrid>) -> move NonNull<BrightnessGridCommand> {
grid.into() grid.into()
}; };
}
); );

View file

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

View file

@ -1,38 +1,38 @@
use crate::{ use crate::{
commands::{wrap_command, wrap_origin_accessors}, commands::{wrap_command, wrap_origin_accessors},
macros::wrap, macros::{wrap_fields, wrap_functions},
}; };
use servicepoint::{CharGrid, CharGridCommand, Origin}; use servicepoint::{CharGrid, CharGridCommand, Origin};
use std::ptr::NonNull; use std::ptr::NonNull;
wrap_command!(CharGrid); wrap_command!(CharGrid);
wrap_fields!(CharGridCommand;
prop grid: CharGrid { get mut; set move; };
);
wrap_origin_accessors!(CharGridCommand); wrap_origin_accessors!(CharGridCommand);
wrap!( wrap_functions!(associate CharGridCommand;
CharGridCommand { /// Show UTF-8 encoded text on the screen.
properties: ///
prop grid: CharGrid { get mut; set move; }; /// The passed [CharGrid] gets consumed.
functions: ///
/// Show UTF-8 encoded text on the screen. /// Returns: a new [CharGridCommand] instance.
/// fn new(
/// The passed [CharGrid] gets consumed. grid: move NonNull<CharGrid>,
/// origin_x: val usize,
/// Returns: a new [CharGridCommand] instance. origin_y: val usize,
fn new( ) -> move NonNull<CharGridCommand> {
grid: move NonNull<CharGrid>, CharGridCommand {
origin_x: val usize, grid,
origin_y: val usize, origin: Origin::new(origin_x, origin_y),
) -> move NonNull<CharGridCommand> { }
CharGridCommand { };
grid,
origin: Origin::new(origin_x, origin_y),
}
};
/// Moves the provided [CharGrid] into a new [CharGridCommand], /// Moves the provided [CharGrid] into a new [CharGridCommand],
/// leaving other fields as their default values. /// leaving other fields as their default values.
fn from_grid(grid: move NonNull<CharGrid>) -> move NonNull<CharGridCommand> { fn from_grid(grid: move NonNull<CharGrid>) -> move NonNull<CharGridCommand> {
grid.into() grid.into()
}; };
}
); );

View file

@ -1,38 +1,38 @@
use crate::{ use crate::{
commands::{wrap_command, wrap_origin_accessors}, commands::{wrap_command, wrap_origin_accessors},
macros::wrap, macros::{wrap_fields, wrap_functions},
}; };
use servicepoint::{Cp437Grid, Cp437GridCommand, Origin}; use servicepoint::{Cp437Grid, Cp437GridCommand, Origin};
use std::ptr::NonNull; use std::ptr::NonNull;
wrap_command!(Cp437Grid); wrap_command!(Cp437Grid);
wrap_fields!(Cp437GridCommand;
prop grid: Cp437Grid { get mut; set move; };
);
wrap_origin_accessors!(Cp437GridCommand); wrap_origin_accessors!(Cp437GridCommand);
wrap!( wrap_functions!(associate Cp437GridCommand;
Cp437GridCommand { /// Show text on the screen.
properties: ///
prop grid: Cp437Grid { get mut; set move; }; /// The text is sent in the form of a 2D grid of [CP-437] encoded characters.
functions: ///
/// Show text on the screen. /// The origin is relative to the top-left of the display.
/// fn new(
/// The text is sent in the form of a 2D grid of [CP-437] encoded characters. grid: move NonNull<Cp437Grid>,
/// origin_x: val usize,
/// The origin is relative to the top-left of the display. origin_y: val usize,
fn new( ) -> move NonNull<Cp437GridCommand> {
grid: move NonNull<Cp437Grid>, Cp437GridCommand {
origin_x: val usize, grid,
origin_y: val usize, origin: Origin::new(origin_x, origin_y),
) -> move NonNull<Cp437GridCommand> { }
Cp437GridCommand { };
grid,
origin: Origin::new(origin_x, origin_y),
}
};
/// Moves the provided [Cp437Grid] into a new [Cp437GridCommand], /// Moves the provided [Cp437Grid] into a new [Cp437GridCommand],
/// leaving other fields as their default values. /// leaving other fields as their default values.
fn from_grid(grid: move NonNull<Cp437Grid>) -> move NonNull<Cp437GridCommand> { fn from_grid(grid: move NonNull<Cp437Grid>) -> move NonNull<Cp437GridCommand> {
grid.into() grid.into()
}; };
}
); );

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
macros::{derive_clone, derive_free, wrap}, macros::{derive_clone, derive_free, wrap_functions, wrap_methods},
mem::{ mem::{
heap_clone, heap_drop, heap_move, heap_move_nonnull, heap_move_ok, heap_clone, heap_drop, heap_move, heap_move_nonnull, heap_move_ok,
heap_remove, heap_remove,
@ -69,6 +69,8 @@ impl GenericCommand {
}; };
} }
derive_clone!(GenericCommand);
impl Clone for GenericCommand { impl Clone for GenericCommand {
fn clone(&self) -> Self { fn clone(&self) -> Self {
unsafe { unsafe {
@ -142,6 +144,8 @@ impl Clone for GenericCommand {
} }
} }
derive_free!(GenericCommand);
impl Drop for GenericCommand { impl Drop for GenericCommand {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
@ -168,126 +172,122 @@ impl Drop for GenericCommand {
} }
} }
derive_clone!(GenericCommand); wrap_functions!(associate GenericCommand;
derive_free!(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<Packet>) -> move NonNull<GenericCommand> {
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() },
})
};
);
wrap! { wrap_methods! { GenericCommand;
GenericCommand { /// Tries to turn a [GenericCommand] into a [Packet].
functions: /// The [GenericCommand] gets consumed.
/// Tries to turn a [Packet] into a [GenericCommand]. ///
/// /// Returns tag [CommandTag::Invalid] in case of an error.
/// The packet is dropped in the process. fn try_into_packet(move command) -> val *mut Packet {
/// match command.tag {
/// Returns: pointer to new [GenericCommand] instance or NULL if parsing failed. CommandTag::Invalid => null_mut(),
fn try_from_packet(packet: move NonNull<Packet>) -> move NonNull<GenericCommand> { CommandTag::Bitmap => {
servicepoint::TypedCommand::try_from(packet) heap_move_ok(unsafe { heap_remove(command.data.bitmap).try_into() })
.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() })
}
}
};
} }

View file

@ -1,19 +1,21 @@
use crate::{commands::wrap_command, macros::wrap}; use crate::{
commands::wrap_command,
macros::{wrap_fields, wrap_functions},
};
use servicepoint::{Brightness, GlobalBrightnessCommand}; use servicepoint::{Brightness, GlobalBrightnessCommand};
use std::ptr::NonNull; 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> {
GlobalBrightnessCommand::from(brightness)
};
);
wrap_command!(GlobalBrightness); wrap_command!(GlobalBrightness);
wrap!( wrap_fields!(GlobalBrightnessCommand;
GlobalBrightnessCommand { prop brightness: Brightness { get; set; };
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> {
GlobalBrightnessCommand::from(brightness)
};
}
); );

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
containers::{wrap_grid, ByteSlice}, containers::{wrap_grid, ByteSlice},
macros::wrap, macros::{wrap_functions, wrap_methods},
}; };
use servicepoint::{ use servicepoint::{
Bitmap, BitmapCommand, CompressionCode, DataRef, DisplayBitVec, Grid, Bitmap, BitmapCommand, CompressionCode, DataRef, DisplayBitVec, Grid,
@ -10,93 +10,91 @@ use std::ptr::NonNull;
wrap_grid!(Bitmap, bool); wrap_grid!(Bitmap, bool);
wrap! { wrap_functions!(associate Bitmap;
Bitmap { /// Creates a new [Bitmap] with the specified dimensions.
functions: ///
/// Creates a new [Bitmap] with the specified dimensions. /// # Arguments
/// ///
/// # Arguments /// - `width`: size in pixels in x-direction
/// /// - `height`: size in pixels in y-direction
/// - `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.
/// ///
/// returns: [Bitmap] initialized to all pixels off, or NULL in case of an error. /// # Errors
/// ///
/// # Errors /// In the following cases, this function will return NULL:
/// ///
/// In the following cases, this function will return NULL: /// - when the width is not dividable by 8
/// ///
/// - when the width is not dividable by 8 /// # Examples
/// ///
/// # Examples /// ```C
/// /// Cp437Grid grid = sp_bitmap_new(8, 3);
/// ```C /// sp_bitmap_fill(grid, true);
/// Cp437Grid grid = sp_bitmap_new(8, 3); /// sp_bitmap_set(grid, 0, 0, false);
/// sp_bitmap_fill(grid, true); /// sp_bitmap_free(grid);
/// 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)
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. /// Creates a new [Bitmap] with a size matching the screen.
/// ///
/// returns: [Bitmap] initialized to all pixels off. /// returns: [Bitmap] initialized to all pixels off.
fn new_max_sized() -> move NonNull<Bitmap> { fn new_max_sized() -> move NonNull<Bitmap> {
Bitmap::max_sized() Bitmap::max_sized()
}; };
/// Loads a [Bitmap] with the specified dimensions from the provided data. /// Loads a [Bitmap] with the specified dimensions from the provided data.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - `width`: size in pixels in x-direction /// - `width`: size in pixels in x-direction
/// - `height`: size in pixels in y-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. /// returns: [Bitmap] that contains a copy of the provided data, or NULL in case of an error.
fn load( fn load(
width: val usize, width: val usize,
height: val usize, height: val usize,
data: slice ByteSlice, data: slice ByteSlice,
) -> move_ok *mut Bitmap { ) -> move_ok *mut Bitmap {
Bitmap::load(width, height, data) Bitmap::load(width, height, data)
}; };
/// Tries to convert the BitVec to a Bitmap. /// Tries to convert the BitVec to a Bitmap.
/// ///
/// The provided BitVec gets consumed. /// The provided BitVec gets consumed.
/// ///
/// Returns NULL in case of error. /// Returns NULL in case of error.
fn from_bitvec( fn from_bitvec(
width: val usize, width: val usize,
bitvec: move NonNull<DisplayBitVec>, bitvec: move NonNull<DisplayBitVec>,
) -> move_ok *mut Bitmap { ) -> move_ok *mut Bitmap {
Bitmap::from_bitvec(width, bitvec) Bitmap::from_bitvec(width, bitvec)
}; };
);
methods: wrap_methods!(Bitmap;
/// Consumes the Bitmap and returns the contained BitVec. /// Consumes the Bitmap and returns the contained BitVec.
fn into_bitvec(move bitmap) -> move NonNull<DisplayBitVec> { fn into_bitvec(move bitmap) -> move NonNull<DisplayBitVec> {
bitmap.into() bitmap.into()
}; };
/// Creates a [BitmapCommand] and immediately turns that into a [Packet]. /// Creates a [BitmapCommand] and immediately turns that into a [Packet].
/// ///
/// The provided [Bitmap] gets consumed. /// The provided [Bitmap] gets consumed.
/// ///
/// Returns NULL in case of an error. /// Returns NULL in case of an error.
fn try_into_packet(move bitmap, x: val usize, y: val usize, compression: val CompressionCode) -> move_ok *mut Packet { fn try_into_packet(move bitmap, x: val usize, y: val usize, compression: val CompressionCode) -> move_ok *mut Packet {
Packet::try_from(BitmapCommand { Packet::try_from(BitmapCommand {
bitmap, bitmap,
origin: Origin::new(x, y), origin: Origin::new(x, y),
compression, compression,
}) })
}; };
/// Gets an unsafe reference to the data of the [Bitmap] instance. /// Gets an unsafe reference to the data of the [Bitmap] instance.
/// ///
/// The returned memory is valid for the lifetime of the bitmap. /// The returned memory is valid for the lifetime of the bitmap.
fn data_ref_mut(mut instance) -> slice ByteSlice; fn data_ref_mut(mut instance) -> slice ByteSlice;
} );
}

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
containers::{wrap_container, ByteSlice}, containers::{wrap_container, ByteSlice},
macros::wrap, macros::{wrap_functions, wrap_methods},
}; };
use servicepoint::{ use servicepoint::{
BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Packet, BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Packet,
@ -9,95 +9,93 @@ use std::ptr::NonNull;
wrap_container!(DisplayBitVec); wrap_container!(DisplayBitVec);
wrap! { wrap_functions!(associate DisplayBitVec;
DisplayBitVec { /// Creates a new [DisplayBitVec] instance.
functions: ///
/// Creates a new [DisplayBitVec] instance. /// # Arguments
/// ///
/// # Arguments /// - `size`: size in bits.
/// ///
/// - `size`: size in bits. /// returns: [DisplayBitVec] with all bits set to false.
/// ///
/// returns: [DisplayBitVec] with all bits set to false. /// # Panics
/// ///
/// # Panics /// - when `size` is not divisible by 8.
/// fn new(size: val usize) -> move NonNull<DisplayBitVec> {
/// - when `size` is not divisible by 8. DisplayBitVec::repeat(false, size)
fn new(size: val usize) -> move NonNull<DisplayBitVec> { };
DisplayBitVec::repeat(false, size)
};
/// Interpret the data as a series of bits and load then into a new [DisplayBitVec] instance. /// Interpret the data as a series of bits and load then into a new [DisplayBitVec] instance.
/// ///
/// returns: [DisplayBitVec] instance containing data. /// returns: [DisplayBitVec] instance containing data.
fn load(data: slice ByteSlice) -> move NonNull<DisplayBitVec> { fn load(data: slice ByteSlice) -> move NonNull<DisplayBitVec> {
DisplayBitVec::from_slice(data) DisplayBitVec::from_slice(data)
}; };
);
methods: wrap_methods!(DisplayBitVec;
/// Creates a [BitVecCommand] and immediately turns that into a [Packet]. /// Creates a [BitVecCommand] and immediately turns that into a [Packet].
/// ///
/// The provided [DisplayBitVec] gets consumed. /// The provided [DisplayBitVec] gets consumed.
/// ///
/// Returns NULL in case of an error. /// Returns NULL in case of an error.
fn try_into_packet( fn try_into_packet(
move bitvec, move bitvec,
offset: val usize, offset: val usize,
operation: val BinaryOperation, operation: val BinaryOperation,
compression: val CompressionCode compression: val CompressionCode
) -> move_ok *mut Packet { ) -> move_ok *mut Packet {
Packet::try_from(BitVecCommand { Packet::try_from(BitVecCommand {
bitvec, bitvec,
offset, offset,
operation, operation,
compression, compression,
}) })
}; };
/// Gets the value of a bit. /// Gets the value of a bit.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - `bit_vec`: instance to read from /// - `bit_vec`: instance to read from
/// - `index`: the bit index to read /// - `index`: the bit index to read
/// ///
/// returns: value of the bit /// returns: value of the bit
/// ///
/// # Panics /// # Panics
/// ///
/// - when accessing `index` out of bounds /// - when accessing `index` out of bounds
fn get(ref instance, index: val usize) -> val bool { fn get(ref instance, index: val usize) -> val bool {
instance.get(index).map(|x| *x).unwrap_or(false) instance.get(index).map(|x| *x).unwrap_or(false)
}; };
/// Sets the value of a bit. /// Sets the value of a bit.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - `index`: the bit index to edit /// - `index`: the bit index to edit
/// - `value`: the value to set the bit to /// - `value`: the value to set the bit to
/// ///
/// # Panics /// # Panics
/// ///
/// - when accessing `index` out of bounds /// - when accessing `index` out of bounds
fn set(mut instance, index: val usize, value: val bool); fn set(mut instance, index: val usize, value: val bool);
/// Sets the value of all bits. /// Sets the value of all bits.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - `value`: the value to set all bits to /// - `value`: the value to set all bits to
fn fill(mut instance, value: val bool); fn fill(mut instance, value: val bool);
/// Gets the length in bits. /// Gets the length in bits.
fn len(ref instance) -> val usize; fn len(ref instance) -> val usize;
/// Returns true if length is 0. /// Returns true if length is 0.
fn is_empty(ref instance) -> val bool; fn is_empty(ref instance) -> val bool;
/// Gets an unsafe reference to the data of the [DisplayBitVec] instance. /// Gets an unsafe reference to the data of the [DisplayBitVec] instance.
/// ///
/// The returned memory is valid for the lifetime of the bitvec. /// The returned memory is valid for the lifetime of the bitvec.
fn as_raw_mut_slice(mut instance) -> slice ByteSlice; fn as_raw_mut_slice(mut instance) -> slice ByteSlice;
} );
}

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
containers::{wrap_grid, ByteSlice}, containers::{wrap_grid, ByteSlice},
macros::wrap, macros::{wrap_functions, wrap_methods},
}; };
use servicepoint::{ use servicepoint::{
Brightness, BrightnessGrid, BrightnessGridCommand, ByteGrid, DataRef, Grid, Brightness, BrightnessGrid, BrightnessGridCommand, ByteGrid, DataRef, Grid,
@ -10,68 +10,66 @@ use std::{mem::transmute, ptr::NonNull};
wrap_grid!(BrightnessGrid, Brightness); wrap_grid!(BrightnessGrid, Brightness);
wrap! { wrap_functions!(associate BrightnessGrid;
BrightnessGrid { /// Creates a new [BrightnessGrid] with the specified dimensions.
functions: ///
/// Creates a new [BrightnessGrid] with the specified dimensions. /// returns: [BrightnessGrid] initialized to 0.
/// ///
/// returns: [BrightnessGrid] initialized to 0. /// # Examples
/// /// ```C
/// # Examples /// UdpSocket *connection = sp_udp_open("127.0.0.1:2342");
/// ```C /// if (connection == NULL)
/// UdpSocket *connection = sp_udp_open("127.0.0.1:2342"); /// return 1;
/// if (connection == NULL) ///
/// return 1; /// BrightnessGrid *grid = sp_brightness_grid_new(2, 2);
/// /// sp_brightness_grid_set(grid, 0, 0, 0);
/// BrightnessGrid *grid = sp_brightness_grid_new(2, 2); /// sp_brightness_grid_set(grid, 1, 1, 10);
/// 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);
/// TypedCommand *command = sp_command_char_brightness(grid); /// ```
/// sp_udp_free(connection); fn new(width: val usize, height: val usize) -> move NonNull<BrightnessGrid> {
/// ``` BrightnessGrid::new(width, height)
fn new(width: val usize, height: val usize) -> move NonNull<BrightnessGrid> { };
BrightnessGrid::new(width, height)
};
/// Loads a [BrightnessGrid] with the specified dimensions from the provided data. /// Loads a [BrightnessGrid] with the specified dimensions from the provided data.
/// ///
/// Any out of range values will be set to [Brightness::MAX] or [Brightness::MIN]. /// 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. /// returns: new [BrightnessGrid] instance, or NULL in case of an error.
fn load( fn load(
width: val usize, width: val usize,
height: val usize, height: val usize,
data: slice ByteSlice, data: slice ByteSlice,
) -> move_some *mut BrightnessGrid { ) -> move_some *mut BrightnessGrid {
ByteGrid::load(width, height, data) ByteGrid::load(width, height, data)
.map(move |grid| grid.map(Brightness::saturating_from)) .map(move |grid| grid.map(Brightness::saturating_from))
}; };
);
methods: wrap_methods!(BrightnessGrid;
/// Creates a [BrightnessGridCommand] and immediately turns that into a [Packet]. /// Creates a [BrightnessGridCommand] and immediately turns that into a [Packet].
/// ///
/// The provided [BrightnessGrid] gets consumed. /// The provided [BrightnessGrid] gets consumed.
/// ///
/// Returns NULL in case of an error. /// Returns NULL in case of an error.
fn try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet { fn try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet {
Packet::try_from(BrightnessGridCommand { Packet::try_from(BrightnessGridCommand {
grid, grid,
origin: Origin::new(x, y), origin: Origin::new(x, y),
}) })
}; };
/// Gets an unsafe reference to the data of the instance. /// Gets an unsafe reference to the data of the instance.
/// ///
/// The returned memory is valid for the lifetime of the grid. /// The returned memory is valid for the lifetime of the grid.
fn data_ref_mut(mut instance) -> slice ByteSlice { fn data_ref_mut(mut instance) -> slice ByteSlice {
//noinspection RsAssertEqual //noinspection RsAssertEqual
const _: () = assert!(size_of::<Brightness>() == 1); const _: () = assert!(size_of::<Brightness>() == 1);
let br_slice = instance.data_ref_mut(); let br_slice = instance.data_ref_mut();
unsafe { unsafe {
transmute::<&mut [Brightness], &mut [u8]>(br_slice) transmute::<&mut [Brightness], &mut [u8]>(br_slice)
} }
}; };
} );
}

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
containers::{derive_get_width_height, wrap_container, ByteSlice}, containers::{derive_get_width_height, wrap_container, ByteSlice},
macros::wrap, macros::{wrap_functions, wrap_methods},
}; };
use servicepoint::{CharGrid, CharGridCommand, Grid, Origin, Packet}; use servicepoint::{CharGrid, CharGridCommand, Grid, Origin, Packet};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -8,82 +8,82 @@ use std::ptr::NonNull;
wrap_container!(CharGrid); wrap_container!(CharGrid);
derive_get_width_height!(CharGrid); derive_get_width_height!(CharGrid);
wrap! { wrap_functions!(associate CharGrid;
CharGrid { /// Creates a new [CharGrid] with the specified dimensions.
functions: ///
/// Creates a new [CharGrid] with the specified dimensions. /// returns: [CharGrid] initialized to 0.
/// ///
/// returns: [CharGrid] initialized to 0. /// # Examples
/// ///
/// # Examples /// ```C
/// /// CharGrid grid = sp_char_grid_new(4, 3);
/// ```C /// sp_char_grid_fill(grid, '?');
/// CharGrid grid = sp_char_grid_new(4, 3); /// sp_char_grid_set(grid, 0, 0, '!');
/// sp_char_grid_fill(grid, '?'); /// sp_char_grid_free(grid);
/// sp_char_grid_set(grid, 0, 0, '!'); /// ```
/// sp_char_grid_free(grid); fn new(width: val usize, height: val usize) -> move NonNull<CharGrid> {
/// ``` CharGrid::new(width, height)
fn new(width: val usize, height: val usize) -> move NonNull<CharGrid> { };
CharGrid::new(width, height)
};
/// Loads a [CharGrid] with the specified dimensions from the provided data. /// Loads a [CharGrid] with the specified dimensions from the provided data.
/// ///
/// returns: new CharGrid or NULL in case of an error /// returns: new CharGrid or NULL in case of an error
fn load(width: val usize, height: val usize, data: slice ByteSlice) -> move_ok *mut CharGrid { fn load(width: val usize, height: val usize, data: slice ByteSlice) -> move_ok *mut CharGrid {
CharGrid::load_utf8(width, height, data.to_vec()) 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
};
/// Sets the value of the specified position in the grid. wrap_methods!(CharGrid;
///
/// # 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 all cells in the grid. /// Returns the current value at the specified position.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - `value`: the value to set all cells to /// - `x` and `y`: position of the cell to read
/// - when providing values that cannot be converted to Rust's `char`. ///
fn fill(mut instance, value: val u32) { /// # Panics
instance.fill(char::from_u32(value).unwrap()) ///
}; /// - 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
};
/// Creates a [CharGridCommand] and immediately turns that into a [Packet]. /// Sets the value of the specified position in the grid.
/// ///
/// The provided [CharGrid] gets consumed. /// # Arguments
/// ///
/// Returns NULL in case of an error. /// - `x` and `y`: position of the cell
fn try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet { /// - `value`: the value to write to the cell
Packet::try_from(CharGridCommand { ///
grid, /// returns: old value of the cell
origin: Origin::new(x, y), ///
}) /// # 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 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())
};
/// 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),
})
};
);

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
containers::{wrap_grid, ByteSlice}, containers::{wrap_grid, ByteSlice},
macros::wrap, macros::{wrap_functions, wrap_methods},
}; };
use servicepoint::{ use servicepoint::{
Cp437Grid, Cp437GridCommand, DataRef, Grid, Origin, Packet, Cp437Grid, Cp437GridCommand, DataRef, Grid, Origin, Packet,
@ -9,37 +9,35 @@ use std::ptr::NonNull;
wrap_grid!(Cp437Grid, u8); wrap_grid!(Cp437Grid, u8);
wrap! { wrap_functions!(associate Cp437Grid;
Cp437Grid { /// Creates a new [Cp437Grid] with the specified dimensions.
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> {
/// returns: [Cp437Grid] initialized to 0. Cp437Grid::new(width, height)
fn new(width: val usize, height: val usize) -> move NonNull<Cp437Grid> { };
Cp437Grid::new(width, height)
};
/// Loads a [Cp437Grid] with the specified dimensions from the provided data. /// Loads a [Cp437Grid] with the specified dimensions from the provided data.
fn load(width: val usize, height: val usize, data: slice ByteSlice) -> move_some *mut Cp437Grid { fn load(width: val usize, height: val usize, data: slice ByteSlice) -> move_some *mut Cp437Grid {
Cp437Grid::load(width, height, data) Cp437Grid::load(width, height, data)
}; };
);
methods: wrap_methods!(Cp437Grid;
/// Creates a [Cp437GridCommand] and immediately turns that into a [Packet]. /// Creates a [Cp437GridCommand] and immediately turns that into a [Packet].
/// ///
/// The provided [Cp437Grid] gets consumed. /// The provided [Cp437Grid] gets consumed.
/// ///
/// Returns NULL in case of an error. /// Returns NULL in case of an error.
fn try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet { fn try_into_packet(move grid, x: val usize, y: val usize) -> move_ok *mut Packet {
Packet::try_from(Cp437GridCommand { Packet::try_from(Cp437GridCommand {
grid, grid,
origin: Origin::new(x, y), origin: Origin::new(x, y),
}) })
}; };
/// Gets an unsafe reference to the data of the grid. /// Gets an unsafe reference to the data of the grid.
/// ///
/// The returned memory is valid for the lifetime of the instance. /// The returned memory is valid for the lifetime of the instance.
fn data_ref_mut(mut instance) -> slice ByteSlice; fn data_ref_mut(mut instance) -> slice ByteSlice;
} );
}

View file

@ -263,61 +263,8 @@ macro_rules! wrap_functions {
}; };
} }
macro_rules! wrap {
(
$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_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)?;
);
)*)?
};
}
pub(crate) use { pub(crate) use {
apply_param_modifier, apply_return_modifier, derive_clone, derive_free, apply_param_modifier, apply_return_modifier, derive_clone, derive_free,
wrap, wrap_fields, wrap_fields_accessor, wrap_function, wrap_functions, wrap_fields, wrap_fields_accessor, wrap_function, wrap_functions,
wrap_method, wrap_methods, wrap_method, wrap_methods,
}; };

View file

@ -1,75 +1,79 @@
use crate::{ use crate::{
containers::ByteSlice, containers::ByteSlice,
macros::{derive_clone, derive_free, wrap, wrap_functions}, macros::{
derive_clone, derive_free, wrap_fields, wrap_functions, wrap_methods,
},
}; };
use servicepoint::{CommandCode, Header, Packet}; use servicepoint::{CommandCode, Header, Packet};
use std::ptr::NonNull; 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<Packet> {
let payload = if payload == ByteSlice::INVALID {
None
} else {
Some(Vec::from(unsafe { payload.as_slice() }))
};
Packet { header, payload }
};
);
derive_clone!(Packet); derive_clone!(Packet);
derive_free!(Packet); derive_free!(Packet);
wrap! { wrap_fields!(Packet;
Packet { prop header: Header { get; get mut; set; };
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)
};
/// Creates a raw [Packet] from parts. wrap_methods! { Packet;
/// /// Returns a pointer to the current payload of the provided packet.
/// returns: new instance. Will never return null. ///
fn from_parts(header: val Header, payload: val ByteSlice) -> move NonNull<Packet> { /// Returns an [ByteSlice::INVALID] instance in case the packet does not have any payload.
let payload = if payload == ByteSlice::INVALID { ///
None /// The returned memory can be changed and will be valid until a new payload is set.
} else { fn get_payload(mut packet) -> val ByteSlice {
Some(Vec::from(unsafe { payload.as_slice() })) match &mut packet.payload {
}; None => ByteSlice::INVALID,
Some(payload) => unsafe { ByteSlice::from_slice(payload) },
}
};
Packet { header, payload } /// Sets the payload of the provided packet to the provided data.
}; ///
methods: /// This makes previous payload pointers invalid.
/// Returns a pointer to the current payload of the provided packet. fn set_payload(mut packet, data: val ByteSlice) {
/// packet.payload = if data == ByteSlice::INVALID {
/// Returns an [ByteSlice::INVALID] instance in case the packet does not have any payload. None
/// } else {
/// The returned memory can be changed and will be valid until a new payload is set. Some(unsafe { data.as_slice().to_vec() })
fn get_payload(mut packet) -> val ByteSlice { }
match &mut packet.payload { };
None => ByteSlice::INVALID,
Some(payload) => unsafe { ByteSlice::from_slice(payload) },
}
};
/// Sets the payload of the provided packet to the provided data. /// Serialize the packet into the provided buffer.
/// ///
/// This makes previous payload pointers invalid. /// # Panics
fn set_payload(mut packet, data: val ByteSlice) { ///
packet.payload = if data == ByteSlice::INVALID { /// - if the buffer is not big enough to hold header+payload.
None fn serialize_to(mut packet, buffer: val ByteSlice) -> val usize {
} else { unsafe {
Some(unsafe { data.as_slice().to_vec() }) packet.serialize_to(buffer.as_slice_mut()).unwrap_or(0)
} }
}; };
/// 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; wrap_functions!(sp;
/// Converts u16 into [CommandCode]. /// Converts u16 into [CommandCode].
/// ///
/// If the provided value is not valid, false is returned and result is not changed. /// If the provided value is not valid, false is returned and result is not changed.

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
commands::{CommandTag, GenericCommand}, commands::{CommandTag, GenericCommand},
macros::{derive_free, wrap}, macros::{derive_free, wrap_functions, wrap_methods},
mem::heap_remove, mem::heap_remove,
}; };
use servicepoint::{Header, Packet, UdpSocketExt}; use servicepoint::{Header, Packet, UdpSocketExt};
@ -12,100 +12,99 @@ use std::{
derive_free!(UdpSocket); derive_free!(UdpSocket);
wrap! { wrap_functions!(associate UdpSocket;
UdpSocket { /// Creates a new instance of [UdpSocket].
functions: ///
/// Creates a new instance of [UdpSocket]. /// returns: NULL if connection fails, or connected instance
/// ///
/// returns: NULL if connection fails, or connected instance /// # Examples
/// ///
/// # Examples /// ```C
/// /// UdpSocket connection = sp_udp_open("172.23.42.29:2342");
/// ```C /// if (connection != NULL)
/// UdpSocket connection = sp_udp_open("172.23.42.29:2342"); /// sp_udp_send_command(connection, sp_command_clear());
/// if (connection != NULL) /// ```
/// sp_udp_send_command(connection, sp_command_clear()); fn open(host: val NonNull<c_char>) -> move_ok *mut UdpSocket {
/// ``` let host = unsafe { CStr::from_ptr(host.as_ptr()) }
fn open(host: val NonNull<c_char>) -> move_ok *mut UdpSocket { .to_str()
let host = unsafe { CStr::from_ptr(host.as_ptr()) } .expect("Bad encoding");
.to_str() UdpSocket::bind_connect(host)
.expect("Bad encoding"); };
UdpSocket::bind_connect(host)
};
/// Creates a new instance of [UdpSocket]. /// Creates a new instance of [UdpSocket].
/// ///
/// returns: NULL if connection fails, or connected instance /// returns: NULL if connection fails, or connected instance
/// ///
/// # Examples /// # Examples
/// ///
/// ```C /// ```C
/// UdpSocket connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); /// UdpSocket connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342);
/// if (connection != NULL) /// if (connection != NULL)
/// sp_udp_send_command(connection, sp_command_clear()); /// sp_udp_send_command(connection, sp_command_clear());
/// ``` /// ```
fn open_ipv4(ip1: val u8, ip2: val u8, ip3: val u8, ip4: val u8, port: val u16) -> move_ok *mut UdpSocket { fn open_ipv4(ip1: val u8, ip2: val u8, ip3: val u8, ip4: val u8, port: val u16) -> move_ok *mut UdpSocket {
let addr = SocketAddrV4::new(Ipv4Addr::from([ip1, ip2, ip3, ip4]), port); let addr = SocketAddrV4::new(Ipv4Addr::from([ip1, ip2, ip3, ip4]), port);
UdpSocket::bind_connect(addr) 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<Packet>) -> val bool {
connection.send(&Vec::from(packet)).is_ok()
};
/// Sends a [GenericCommand] to the display using the [UdpSocket]. wrap_methods! {UdpSocket;
/// /// Sends a [Packet] to the display using the [UdpSocket].
/// The passed `command` gets consumed. ///
/// /// The passed `packet` gets consumed.
/// returns: true in case of success ///
/// /// returns: true in case of success
/// # Examples fn send_packet(ref connection, packet: move NonNull<Packet>) -> val bool {
/// connection.send(&Vec::from(packet)).is_ok()
/// ```C };
/// sp_udp_send_command(connection, sp_command_brightness(5));
/// ```
fn send_command(ref connection, command: mut NonNull<GenericCommand>) -> 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]. /// Sends a [GenericCommand] to the display using the [UdpSocket].
/// ///
/// returns: true in case of success /// The passed `command` gets consumed.
/// ///
/// # Examples /// returns: true in case of success
/// ///
/// ```C /// # Examples
/// sp_udp_send_header(connection, sp_command_brightness(5)); ///
/// ``` /// ```C
fn send_header(ref udp_connection, header: val Header) -> val bool { /// sp_udp_send_command(connection, sp_command_brightness(5));
let packet = Packet { /// ```
header, fn send_command(ref connection, command: mut NonNull<GenericCommand>) -> val bool {
payload: None, unsafe {
}; let result = match command.tag {
udp_connection.send(&Vec::from(packet)).is_ok() 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 { mod _hidden {