wip update to next servicepoint version

This commit is contained in:
Vinzenz Schroeter 2025-04-11 21:40:49 +02:00
parent ac3c470b44
commit da1c5ebb03
13 changed files with 242 additions and 235 deletions

9
Cargo.lock generated
View file

@ -98,9 +98,9 @@ dependencies = [
[[package]] [[package]]
name = "cbindgen" name = "cbindgen"
version = "0.27.0" version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fce8dd7fcfcbf3a0a87d8f515194b49d6135acab73e18bd380d1d93bb1a15eb" checksum = "eadd868a2ce9ca38de7eeafdcec9c7065ef89b42b32f0839278d55f35c54d1ff"
dependencies = [ dependencies = [
"clap", "clap",
"heck", "heck",
@ -407,9 +407,8 @@ dependencies = [
[[package]] [[package]]
name = "servicepoint" name = "servicepoint"
version = "0.13.1" version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#fe67160974d9fed542eb37e5e9a202eaf6fe00dc"
checksum = "93b52049be55a15fe37c13249d7f96aa8a5de56e1a41838e74a822ee8316a0c4"
dependencies = [ dependencies = [
"bitvec", "bitvec",
"bzip2", "bzip2",

View file

@ -15,14 +15,14 @@ keywords = ["cccb", "cccb-servicepoint", "cbindgen"]
crate-type = ["staticlib", "cdylib", "rlib"] crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies] [build-dependencies]
cbindgen = "0.27.0" cbindgen = "0.28.0"
[dependencies.servicepoint] [dependencies]
version = "0.13.1" servicepoint = { features = ["all_compressions"], git = "https://git.berlin.ccc.de/servicepoint/servicepoint/", branch = "next" }
features = ["all_compressions"]
[lints.rust] [lints.rust]
missing-docs = "warn" missing-docs = "warn"
unsafe_op_in_unsafe_fn = "warn"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View file

@ -1,4 +1,4 @@
/* Generated with cbindgen:0.27.0 */ /* Generated with cbindgen:0.28.0 */
/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */ /* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */
@ -168,19 +168,6 @@ typedef struct SPCharGrid SPCharGrid;
*/ */
typedef struct SPCommand SPCommand; typedef struct SPCommand SPCommand;
/**
* A connection to the display.
*
* # Examples
*
* ```C
* CConnection connection = sp_connection_open("172.23.42.29:2342");
* if (connection != NULL)
* sp_connection_send_command(connection, sp_command_clear());
* ```
*/
typedef struct SPConnection SPConnection;
/** /**
* A C-wrapper for grid containing codepage 437 characters. * A C-wrapper for grid containing codepage 437 characters.
* *
@ -202,6 +189,19 @@ typedef struct SPCp437Grid SPCp437Grid;
*/ */
typedef struct SPPacket SPPacket; typedef struct SPPacket SPPacket;
/**
* A connection to the display.
*
* # Examples
*
* ```C
* CConnection connection = sp_connection_open("172.23.42.29:2342");
* if (connection != NULL)
* sp_connection_send_command(connection, sp_command_clear());
* ```
*/
typedef struct SPUdpConnection SPUdpConnection;
/** /**
* Represents a span of memory (`&mut [u8]` ) as a struct usable by C code. * Represents a span of memory (`&mut [u8]` ) as a struct usable by C code.
* *
@ -290,7 +290,7 @@ void sp_bitmap_fill(SPBitmap *bitmap, bool value);
* *
* [SPCommand]: [crate::SPCommand] * [SPCommand]: [crate::SPCommand]
*/ */
void sp_bitmap_free(SPBitmap *bitmap); void sp_bitmap_free(SPBitmap **bitmap);
/** /**
* Gets the current value at the specified position in the [SPBitmap]. * Gets the current value at the specified position in the [SPBitmap].
@ -341,13 +341,18 @@ size_t sp_bitmap_height(const SPBitmap *bitmap);
* - `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: [SPBitmap] that contains a copy of the provided data. Will never return NULL. * returns: [SPBitmap] that contains a copy of the provided data, or NULL in case of an error.
*
* # Errors
*
* In the following cases, this function will return NULL:
*
* - when the dimensions and data size do not match exactly.
* - when the width is not dividable by 8
* *
* # Panics * # Panics
* *
* - when `data` is NULL * - when `data` is NULL
* - when the dimensions and data size do not match exactly.
* - when the width is not dividable by 8
* *
* # Safety * # Safety
* *
@ -370,9 +375,11 @@ SPBitmap *sp_bitmap_load(size_t width,
* - `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: [SPBitmap] initialized to all pixels off. Will never return NULL. * returns: [SPBitmap] initialized to all pixels off, or NULL in case of an error.
* *
* # Panics * # Errors
*
* 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
* *
@ -1206,7 +1213,7 @@ SPCommand *sp_command_bitmap_linear_or(size_t offset,
SPCommand *sp_command_bitmap_linear_win(size_t x, SPCommand *sp_command_bitmap_linear_win(size_t x,
size_t y, size_t y,
SPBitmap *bitmap, SPBitmap *bitmap,
SPCompressionCode compression_code); SPCompressionCode compression);
/** /**
* Set pixel data according to a xor-mask starting at the offset. * Set pixel data according to a xor-mask starting at the offset.
@ -1449,21 +1456,7 @@ SPCommand *sp_command_utf8_data(size_t x,
SPCharGrid *grid); SPCharGrid *grid);
/** /**
* Creates a new instance of [SPConnection] for testing that does not actually send anything. * Closes and deallocates a [SPUdpConnection].
*
* returns: a new instance. Will never return NULL.
*
* # Safety
*
* The caller has to make sure that:
*
* - the returned instance is freed in some way, either by using a consuming function or
* by explicitly calling `sp_connection_free`.
*/
SPConnection *sp_connection_fake(void);
/**
* Closes and deallocates a [SPConnection].
* *
* # Panics * # Panics
* *
@ -1473,13 +1466,13 @@ SPConnection *sp_connection_fake(void);
* *
* The caller has to make sure that: * The caller has to make sure that:
* *
* - `connection` points to a valid [SPConnection] * - `connection` points to a valid [SPUdpConnection]
* - `connection` is not used concurrently or after this call * - `connection` is not used concurrently or after this call
*/ */
void sp_connection_free(SPConnection *connection); void sp_connection_free(SPUdpConnection *connection);
/** /**
* Creates a new instance of [SPConnection]. * Creates a new instance of [SPUdpConnection].
* *
* returns: NULL if connection fails, or connected instance * returns: NULL if connection fails, or connected instance
* *
@ -1494,10 +1487,10 @@ void sp_connection_free(SPConnection *connection);
* - the returned instance is freed in some way, either by using a consuming function or * - the returned instance is freed in some way, either by using a consuming function or
* by explicitly calling `sp_connection_free`. * by explicitly calling `sp_connection_free`.
*/ */
SPConnection *sp_connection_open(const char *host); SPUdpConnection *sp_connection_open(const char *host);
/** /**
* Sends a [SPCommand] to the display using the [SPConnection]. * Sends a [SPCommand] to the display using the [SPUdpConnection].
* *
* The passed `command` gets consumed. * The passed `command` gets consumed.
* *
@ -1512,15 +1505,15 @@ SPConnection *sp_connection_open(const char *host);
* *
* The caller has to make sure that: * The caller has to make sure that:
* *
* - `connection` points to a valid instance of [SPConnection] * - `connection` points to a valid instance of [SPUdpConnection]
* - `command` points to a valid instance of [SPPacket] * - `command` points to a valid instance of [SPPacket]
* - `command` is not used concurrently or after this call * - `command` is not used concurrently or after this call
*/ */
bool sp_connection_send_command(const SPConnection *connection, bool sp_connection_send_command(const SPUdpConnection *connection,
SPCommand *command); SPCommand *command);
/** /**
* Sends a [SPPacket] to the display using the [SPConnection]. * Sends a [SPPacket] to the display using the [SPUdpConnection].
* *
* The passed `packet` gets consumed. * The passed `packet` gets consumed.
* *
@ -1535,11 +1528,11 @@ bool sp_connection_send_command(const SPConnection *connection,
* *
* The caller has to make sure that: * The caller has to make sure that:
* *
* - `connection` points to a valid instance of [SPConnection] * - `connection` points to a valid instance of [SPUdpConnection]
* - `packet` points to a valid instance of [SPPacket] * - `packet` points to a valid instance of [SPPacket]
* - `packet` is not used concurrently or after this call * - `packet` is not used concurrently or after this call
*/ */
bool sp_connection_send_packet(const SPConnection *connection, bool sp_connection_send_packet(const SPUdpConnection *connection,
SPPacket *packet); SPPacket *packet);
/** /**

View file

@ -2,7 +2,7 @@
#include "servicepoint.h" #include "servicepoint.h"
int main(void) { int main(void) {
SPConnection *connection = sp_connection_open("localhost:2342"); SPUdpConnection *connection = sp_connection_open("localhost:2342");
if (connection == NULL) if (connection == NULL)
return 1; return 1;

View file

@ -3,7 +3,7 @@
//! prefix `sp_bitmap_` //! prefix `sp_bitmap_`
use servicepoint::{DataRef, Grid}; use servicepoint::{DataRef, Grid};
use std::ptr::NonNull; use std::ptr::{null_mut, NonNull};
use crate::byte_slice::SPByteSlice; use crate::byte_slice::SPByteSlice;
@ -26,9 +26,11 @@ pub struct SPBitmap(pub(crate) servicepoint::Bitmap);
/// - `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: [SPBitmap] initialized to all pixels off. Will never return NULL. /// returns: [SPBitmap] initialized to all pixels off, or NULL in case of an error.
/// ///
/// # Panics /// # Errors
///
/// 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
/// ///
@ -42,9 +44,12 @@ pub struct SPBitmap(pub(crate) servicepoint::Bitmap);
pub unsafe extern "C" fn sp_bitmap_new( pub unsafe extern "C" fn sp_bitmap_new(
width: usize, width: usize,
height: usize, height: usize,
) -> NonNull<SPBitmap> { ) -> *mut SPBitmap {
let result = Box::new(SPBitmap(servicepoint::Bitmap::new(width, height))); if let Some(bitmap) = servicepoint::Bitmap::new(width, height) {
NonNull::from(Box::leak(result)) Box::leak(Box::new(SPBitmap(bitmap)))
}else {
std::ptr::null_mut()
}
} }
/// Creates a new [SPBitmap] with a size matching the screen. /// Creates a new [SPBitmap] with a size matching the screen.
@ -70,13 +75,18 @@ pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull<SPBitmap> {
/// - `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: [SPBitmap] that contains a copy of the provided data. Will never return NULL. /// returns: [SPBitmap] that contains a copy of the provided data, or NULL in case of an error.
///
/// # Errors
///
/// In the following cases, this function will return NULL:
///
/// - when the dimensions and data size do not match exactly.
/// - when the width is not dividable by 8
/// ///
/// # Panics /// # Panics
/// ///
/// - when `data` is NULL /// - when `data` is NULL
/// - when the dimensions and data size do not match exactly.
/// - when the width is not dividable by 8
/// ///
/// # Safety /// # Safety
/// ///
@ -91,12 +101,14 @@ pub unsafe extern "C" fn sp_bitmap_load(
height: usize, height: usize,
data: *const u8, data: *const u8,
data_length: usize, data_length: usize,
) -> NonNull<SPBitmap> { ) -> *mut SPBitmap {
assert!(!data.is_null()); assert!(!data.is_null());
let data = std::slice::from_raw_parts(data, data_length); let data = unsafe {std::slice::from_raw_parts(data, data_length)};
let result = if let Ok(bitmap) = servicepoint::Bitmap::load(width, height, data) {
Box::new(SPBitmap(servicepoint::Bitmap::load(width, height, data))); Box::leak(Box::new(SPBitmap(bitmap)))
NonNull::from(Box::leak(result)) }else {
std::ptr::null_mut()
}
} }
/// Clones a [SPBitmap]. /// Clones a [SPBitmap].
@ -120,7 +132,7 @@ pub unsafe extern "C" fn sp_bitmap_clone(
bitmap: *const SPBitmap, bitmap: *const SPBitmap,
) -> NonNull<SPBitmap> { ) -> NonNull<SPBitmap> {
assert!(!bitmap.is_null()); assert!(!bitmap.is_null());
let result = Box::new(SPBitmap((*bitmap).0.clone())); let result = Box::new(SPBitmap(unsafe {(*bitmap).0.clone()}));
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -142,7 +154,7 @@ pub unsafe extern "C" fn sp_bitmap_clone(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_free(bitmap: *mut SPBitmap) { pub unsafe extern "C" fn sp_bitmap_free(bitmap: *mut SPBitmap) {
assert!(!bitmap.is_null()); assert!(!bitmap.is_null());
_ = Box::from_raw(bitmap); _ = unsafe {Box::from_raw(bitmap)};
} }
/// Gets the current value at the specified position in the [SPBitmap]. /// Gets the current value at the specified position in the [SPBitmap].
@ -170,7 +182,7 @@ pub unsafe extern "C" fn sp_bitmap_get(
y: usize, y: usize,
) -> bool { ) -> bool {
assert!(!bitmap.is_null()); assert!(!bitmap.is_null());
(*bitmap).0.get(x, y) unsafe {(*bitmap).0.get(x, y)}
} }
/// Sets the value of the specified position in the [SPBitmap]. /// Sets the value of the specified position in the [SPBitmap].
@ -202,7 +214,7 @@ pub unsafe extern "C" fn sp_bitmap_set(
value: bool, value: bool,
) { ) {
assert!(!bitmap.is_null()); assert!(!bitmap.is_null());
(*bitmap).0.set(x, y, value); unsafe {(*bitmap).0.set(x, y, value)};
} }
/// Sets the state of all pixels in the [SPBitmap]. /// Sets the state of all pixels in the [SPBitmap].
@ -225,7 +237,7 @@ pub unsafe extern "C" fn sp_bitmap_set(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_fill(bitmap: *mut SPBitmap, value: bool) { pub unsafe extern "C" fn sp_bitmap_fill(bitmap: *mut SPBitmap, value: bool) {
assert!(!bitmap.is_null()); assert!(!bitmap.is_null());
(*bitmap).0.fill(value); unsafe {(*bitmap).0.fill(value)};
} }
/// Gets the width in pixels of the [SPBitmap] instance. /// Gets the width in pixels of the [SPBitmap] instance.
@ -246,7 +258,7 @@ pub unsafe extern "C" fn sp_bitmap_fill(bitmap: *mut SPBitmap, value: bool) {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_width(bitmap: *const SPBitmap) -> usize { pub unsafe extern "C" fn sp_bitmap_width(bitmap: *const SPBitmap) -> usize {
assert!(!bitmap.is_null()); assert!(!bitmap.is_null());
(*bitmap).0.width() unsafe {(*bitmap).0.width()}
} }
/// Gets the height in pixels of the [SPBitmap] instance. /// Gets the height in pixels of the [SPBitmap] instance.
@ -267,7 +279,7 @@ pub unsafe extern "C" fn sp_bitmap_width(bitmap: *const SPBitmap) -> usize {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_height(bitmap: *const SPBitmap) -> usize { pub unsafe extern "C" fn sp_bitmap_height(bitmap: *const SPBitmap) -> usize {
assert!(!bitmap.is_null()); assert!(!bitmap.is_null());
(*bitmap).0.height() unsafe {(*bitmap).0.height()}
} }
/// Gets an unsafe reference to the data of the [SPBitmap] instance. /// Gets an unsafe reference to the data of the [SPBitmap] instance.
@ -288,7 +300,7 @@ pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref(
bitmap: *mut SPBitmap, bitmap: *mut SPBitmap,
) -> SPByteSlice { ) -> SPByteSlice {
assert!(!bitmap.is_null()); assert!(!bitmap.is_null());
let data = (*bitmap).0.data_ref_mut(); let data = unsafe {(*bitmap).0.data_ref_mut()};
SPByteSlice { SPByteSlice {
start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), start: NonNull::new(data.as_mut_ptr_range().start).unwrap(),
length: data.len(), length: data.len(),

View file

@ -79,7 +79,7 @@ pub unsafe extern "C" fn sp_bitvec_load(
data_length: usize, data_length: usize,
) -> NonNull<SPBitVec> { ) -> NonNull<SPBitVec> {
assert!(!data.is_null()); assert!(!data.is_null());
let data = std::slice::from_raw_parts(data, data_length); let data = unsafe {std::slice::from_raw_parts(data, data_length)};
let result = Box::new(SPBitVec(servicepoint::BitVec::from_slice(data))); let result = Box::new(SPBitVec(servicepoint::BitVec::from_slice(data)));
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -105,7 +105,7 @@ pub unsafe extern "C" fn sp_bitvec_clone(
bit_vec: *const SPBitVec, bit_vec: *const SPBitVec,
) -> NonNull<SPBitVec> { ) -> NonNull<SPBitVec> {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
let result = Box::new((*bit_vec).clone()); let result = Box::new(unsafe {(*bit_vec).clone()});
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -127,7 +127,7 @@ pub unsafe extern "C" fn sp_bitvec_clone(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_free(bit_vec: *mut SPBitVec) { pub unsafe extern "C" fn sp_bitvec_free(bit_vec: *mut SPBitVec) {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
_ = Box::from_raw(bit_vec); _ = unsafe {Box::from_raw(bit_vec)};
} }
/// Gets the value of a bit from the [SPBitVec]. /// Gets the value of a bit from the [SPBitVec].
@ -156,7 +156,7 @@ pub unsafe extern "C" fn sp_bitvec_get(
index: usize, index: usize,
) -> bool { ) -> bool {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
*(*bit_vec).0.get(index).unwrap() unsafe {*(*bit_vec).0.get(index).unwrap()}
} }
/// Sets the value of a bit in the [SPBitVec]. /// Sets the value of a bit in the [SPBitVec].
@ -185,7 +185,7 @@ pub unsafe extern "C" fn sp_bitvec_set(
value: bool, value: bool,
) { ) {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
(*bit_vec).0.set(index, value) unsafe {(*bit_vec).0.set(index, value)}
} }
/// Sets the value of all bits in the [SPBitVec]. /// Sets the value of all bits in the [SPBitVec].
@ -208,7 +208,7 @@ pub unsafe extern "C" fn sp_bitvec_set(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_fill(bit_vec: *mut SPBitVec, value: bool) { pub unsafe extern "C" fn sp_bitvec_fill(bit_vec: *mut SPBitVec, value: bool) {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
(*bit_vec).0.fill(value) unsafe {(*bit_vec).0.fill(value)}
} }
/// Gets the length of the [SPBitVec] in bits. /// Gets the length of the [SPBitVec] in bits.
@ -229,7 +229,7 @@ pub unsafe extern "C" fn sp_bitvec_fill(bit_vec: *mut SPBitVec, value: bool) {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_len(bit_vec: *const SPBitVec) -> usize { pub unsafe extern "C" fn sp_bitvec_len(bit_vec: *const SPBitVec) -> usize {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
(*bit_vec).0.len() unsafe {(*bit_vec).0.len()}
} }
/// Returns true if length is 0. /// Returns true if length is 0.
@ -250,7 +250,7 @@ pub unsafe extern "C" fn sp_bitvec_len(bit_vec: *const SPBitVec) -> usize {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_is_empty(bit_vec: *const SPBitVec) -> bool { pub unsafe extern "C" fn sp_bitvec_is_empty(bit_vec: *const SPBitVec) -> bool {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
(*bit_vec).0.is_empty() unsafe {(*bit_vec).0.is_empty()}
} }
/// Gets an unsafe reference to the data of the [SPBitVec] instance. /// Gets an unsafe reference to the data of the [SPBitVec] instance.
@ -275,7 +275,7 @@ pub unsafe extern "C" fn sp_bitvec_unsafe_data_ref(
bit_vec: *mut SPBitVec, bit_vec: *mut SPBitVec,
) -> SPByteSlice { ) -> SPByteSlice {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
let data = (*bit_vec).0.as_raw_mut_slice(); let data = unsafe {(*bit_vec).0.as_raw_mut_slice()};
SPByteSlice { SPByteSlice {
start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), start: NonNull::new(data.as_mut_ptr_range().start).unwrap(),
length: data.len(), length: data.len(),

View file

@ -77,14 +77,18 @@ pub unsafe extern "C" fn sp_brightness_grid_load(
height: usize, height: usize,
data: *const u8, data: *const u8,
data_length: usize, data_length: usize,
) -> NonNull<SPBrightnessGrid> { ) -> *mut SPBrightnessGrid {
assert!(!data.is_null()); assert!(!data.is_null());
let data = std::slice::from_raw_parts(data, data_length); let data =unsafe { std::slice::from_raw_parts(data, data_length)};
let grid = servicepoint::ByteGrid::load(width, height, data); let grid = match servicepoint::ByteGrid::load(width, height, data) {
let grid = servicepoint::BrightnessGrid::try_from(grid) None => return std::ptr::null_mut(),
.expect("invalid brightness value"); Some(grid) => grid
let result = Box::new(SPBrightnessGrid(grid)); };
NonNull::from(Box::leak(result)) if let Ok(grid )= servicepoint::BrightnessGrid::try_from(grid) {
Box::leak(Box::new(SPBrightnessGrid(grid)))
}else {
std::ptr::null_mut()
}
} }
/// Clones a [SPBrightnessGrid]. /// Clones a [SPBrightnessGrid].
@ -112,7 +116,7 @@ pub unsafe extern "C" fn sp_brightness_grid_clone(
brightness_grid: *const SPBrightnessGrid, brightness_grid: *const SPBrightnessGrid,
) -> NonNull<SPBrightnessGrid> { ) -> NonNull<SPBrightnessGrid> {
assert!(!brightness_grid.is_null()); assert!(!brightness_grid.is_null());
let result = Box::new((*brightness_grid).clone()); let result = Box::new(unsafe {(*brightness_grid).clone()});
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -140,7 +144,7 @@ pub unsafe extern "C" fn sp_brightness_grid_free(
brightness_grid: *mut SPBrightnessGrid, brightness_grid: *mut SPBrightnessGrid,
) { ) {
assert!(!brightness_grid.is_null()); assert!(!brightness_grid.is_null());
_ = Box::from_raw(brightness_grid); _ = unsafe {Box::from_raw(brightness_grid)};
} }
/// Gets the current value at the specified position. /// Gets the current value at the specified position.
@ -170,7 +174,7 @@ pub unsafe extern "C" fn sp_brightness_grid_get(
y: usize, y: usize,
) -> u8 { ) -> u8 {
assert!(!brightness_grid.is_null()); assert!(!brightness_grid.is_null());
(*brightness_grid).0.get(x, y).into() unsafe {(*brightness_grid).0.get(x, y)}.into()
} }
/// Sets the value of the specified position in the [SPBrightnessGrid]. /// Sets the value of the specified position in the [SPBrightnessGrid].
@ -205,7 +209,7 @@ pub unsafe extern "C" fn sp_brightness_grid_set(
assert!(!brightness_grid.is_null()); assert!(!brightness_grid.is_null());
let brightness = servicepoint::Brightness::try_from(value) let brightness = servicepoint::Brightness::try_from(value)
.expect("invalid brightness value"); .expect("invalid brightness value");
(*brightness_grid).0.set(x, y, brightness); unsafe {(*brightness_grid).0.set(x, y, brightness)};
} }
/// Sets the value of all cells in the [SPBrightnessGrid]. /// Sets the value of all cells in the [SPBrightnessGrid].
@ -234,7 +238,7 @@ pub unsafe extern "C" fn sp_brightness_grid_fill(
assert!(!brightness_grid.is_null()); assert!(!brightness_grid.is_null());
let brightness = servicepoint::Brightness::try_from(value) let brightness = servicepoint::Brightness::try_from(value)
.expect("invalid brightness value"); .expect("invalid brightness value");
(*brightness_grid).0.fill(brightness); unsafe {(*brightness_grid).0.fill(brightness)};
} }
/// Gets the width of the [SPBrightnessGrid] instance. /// Gets the width of the [SPBrightnessGrid] instance.
@ -259,7 +263,7 @@ pub unsafe extern "C" fn sp_brightness_grid_width(
brightness_grid: *const SPBrightnessGrid, brightness_grid: *const SPBrightnessGrid,
) -> usize { ) -> usize {
assert!(!brightness_grid.is_null()); assert!(!brightness_grid.is_null());
(*brightness_grid).0.width() unsafe {(*brightness_grid).0.width()}
} }
/// Gets the height of the [SPBrightnessGrid] instance. /// Gets the height of the [SPBrightnessGrid] instance.
@ -284,7 +288,7 @@ pub unsafe extern "C" fn sp_brightness_grid_height(
brightness_grid: *const SPBrightnessGrid, brightness_grid: *const SPBrightnessGrid,
) -> usize { ) -> usize {
assert!(!brightness_grid.is_null()); assert!(!brightness_grid.is_null());
(*brightness_grid).0.height() unsafe {(*brightness_grid).0.height()}
} }
/// Gets an unsafe reference to the data of the [SPBrightnessGrid] instance. /// Gets an unsafe reference to the data of the [SPBrightnessGrid] instance.
@ -312,9 +316,9 @@ pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref(
) -> SPByteSlice { ) -> SPByteSlice {
assert!(!brightness_grid.is_null()); assert!(!brightness_grid.is_null());
assert_eq!(core::mem::size_of::<servicepoint::Brightness>(), 1); assert_eq!(core::mem::size_of::<servicepoint::Brightness>(), 1);
let data = (*brightness_grid).0.data_ref_mut(); let data = unsafe {(*brightness_grid).0.data_ref_mut()};
// this assumes more about the memory layout than rust guarantees. yikes! // this assumes more about the memory layout than rust guarantees. yikes!
let data: &mut [u8] = transmute(data); let data: &mut [u8] = unsafe {transmute(data)};
SPByteSlice { SPByteSlice {
start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), start: NonNull::new(data.as_mut_ptr_range().start).unwrap(),
length: data.len(), length: data.len(),

View file

@ -74,7 +74,7 @@ pub unsafe extern "C" fn sp_char_grid_load(
data_length: usize, data_length: usize,
) -> NonNull<SPCharGrid> { ) -> NonNull<SPCharGrid> {
assert!(data.is_null()); assert!(data.is_null());
let data = std::slice::from_raw_parts(data, data_length); let data = unsafe {std::slice::from_raw_parts(data, data_length)};
let result = Box::new(SPCharGrid( let result = Box::new(SPCharGrid(
servicepoint::CharGrid::load_utf8(width, height, data.to_vec()) servicepoint::CharGrid::load_utf8(width, height, data.to_vec())
.unwrap(), .unwrap(),
@ -103,7 +103,7 @@ pub unsafe extern "C" fn sp_char_grid_clone(
char_grid: *const SPCharGrid, char_grid: *const SPCharGrid,
) -> NonNull<SPCharGrid> { ) -> NonNull<SPCharGrid> {
assert!(!char_grid.is_null()); assert!(!char_grid.is_null());
let result = Box::new((*char_grid).clone()); let result = Box::new(unsafe{(*char_grid).clone()});
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -125,7 +125,7 @@ pub unsafe extern "C" fn sp_char_grid_clone(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_char_grid_free(char_grid: *mut SPCharGrid) { pub unsafe extern "C" fn sp_char_grid_free(char_grid: *mut SPCharGrid) {
assert!(!char_grid.is_null()); assert!(!char_grid.is_null());
_ = Box::from_raw(char_grid); _ = unsafe {Box::from_raw(char_grid)};
} }
/// Gets the current value at the specified position. /// Gets the current value at the specified position.
@ -153,7 +153,7 @@ pub unsafe extern "C" fn sp_char_grid_get(
y: usize, y: usize,
) -> u32 { ) -> u32 {
assert!(!char_grid.is_null()); assert!(!char_grid.is_null());
(*char_grid).0.get(x, y) as u32 unsafe {(*char_grid).0.get(x, y) as u32}
} }
/// Sets the value of the specified position in the [SPCharGrid]. /// Sets the value of the specified position in the [SPCharGrid].
@ -187,7 +187,7 @@ pub unsafe extern "C" fn sp_char_grid_set(
value: u32, value: u32,
) { ) {
assert!(!char_grid.is_null()); assert!(!char_grid.is_null());
(*char_grid).0.set(x, y, char::from_u32(value).unwrap()); unsafe {(*char_grid).0.set(x, y, char::from_u32(value).unwrap())};
} }
/// Sets the value of all cells in the [SPCharGrid]. /// Sets the value of all cells in the [SPCharGrid].
@ -213,7 +213,7 @@ pub unsafe extern "C" fn sp_char_grid_fill(
value: u32, value: u32,
) { ) {
assert!(!char_grid.is_null()); assert!(!char_grid.is_null());
(*char_grid).0.fill(char::from_u32(value).unwrap()); unsafe {(*char_grid).0.fill(char::from_u32(value).unwrap())};
} }
/// Gets the width of the [SPCharGrid] instance. /// Gets the width of the [SPCharGrid] instance.
@ -236,7 +236,7 @@ pub unsafe extern "C" fn sp_char_grid_width(
char_grid: *const SPCharGrid, char_grid: *const SPCharGrid,
) -> usize { ) -> usize {
assert!(!char_grid.is_null()); assert!(!char_grid.is_null());
(*char_grid).0.width() unsafe {(*char_grid).0.width()}
} }
/// Gets the height of the [SPCharGrid] instance. /// Gets the height of the [SPCharGrid] instance.
@ -259,5 +259,5 @@ pub unsafe extern "C" fn sp_char_grid_height(
char_grid: *const SPCharGrid, char_grid: *const SPCharGrid,
) -> usize { ) -> usize {
assert!(!char_grid.is_null()); assert!(!char_grid.is_null());
(*char_grid).0.height() unsafe {(*char_grid).0.height()}
} }

View file

@ -2,12 +2,12 @@
//! //!
//! prefix `sp_command_` //! prefix `sp_command_`
use std::ptr::{null_mut, NonNull};
use crate::{ use crate::{
SPBitVec, SPBitmap, SPBrightnessGrid, SPCharGrid, SPCompressionCode, SPBitVec, SPBitmap, SPBrightnessGrid, SPCharGrid, SPCompressionCode,
SPCp437Grid, SPPacket, SPCp437Grid, SPPacket,
}; };
use servicepoint::{BinaryOperation, GlobalBrightnessCommand};
use std::ptr::NonNull;
/// A low-level display command. /// A low-level display command.
/// ///
@ -23,7 +23,7 @@ use crate::{
/// ``` /// ```
/// ///
/// [SPConnection]: [crate::SPConnection] /// [SPConnection]: [crate::SPConnection]
pub struct SPCommand(pub(crate) servicepoint::Command); pub struct SPCommand(pub(crate) servicepoint::TypedCommand);
impl Clone for SPCommand { impl Clone for SPCommand {
fn clone(&self) -> Self { fn clone(&self) -> Self {
@ -54,9 +54,9 @@ impl Clone for SPCommand {
pub unsafe extern "C" fn sp_command_try_from_packet( pub unsafe extern "C" fn sp_command_try_from_packet(
packet: *mut SPPacket, packet: *mut SPPacket,
) -> *mut SPCommand { ) -> *mut SPCommand {
let packet = *Box::from_raw(packet); let packet = *unsafe{Box::from_raw(packet)};
match servicepoint::Command::try_from(packet.0) { match servicepoint::TypedCommand::try_from(packet.0) {
Err(_) => null_mut(), Err(_) => std::ptr::null_mut(),
Ok(command) => Box::into_raw(Box::new(SPCommand(command))), Ok(command) => Box::into_raw(Box::new(SPCommand(command))),
} }
} }
@ -82,7 +82,7 @@ pub unsafe extern "C" fn sp_command_clone(
command: *const SPCommand, command: *const SPCommand,
) -> NonNull<SPCommand> { ) -> NonNull<SPCommand> {
assert!(!command.is_null()); assert!(!command.is_null());
let result = Box::new((*command).clone()); let result = Box::new(unsafe { (*command).clone() });
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -106,7 +106,7 @@ pub unsafe extern "C" fn sp_command_clone(
/// by explicitly calling `sp_command_free`. /// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_clear() -> NonNull<SPCommand> { pub unsafe extern "C" fn sp_command_clear() -> NonNull<SPCommand> {
let result = Box::new(SPCommand(servicepoint::Command::Clear)); let result = Box::new(SPCommand(servicepoint::ClearCommand.into()));
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -124,7 +124,7 @@ pub unsafe extern "C" fn sp_command_clear() -> NonNull<SPCommand> {
/// by explicitly calling `sp_command_free`. /// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull<SPCommand> { pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull<SPCommand> {
let result = Box::new(SPCommand(servicepoint::Command::HardReset)); let result = Box::new(SPCommand(servicepoint::HardResetCommand.into()));
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -140,7 +140,7 @@ pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull<SPCommand> {
/// by explicitly calling `sp_command_free`. /// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_fade_out() -> NonNull<SPCommand> { pub unsafe extern "C" fn sp_command_fade_out() -> NonNull<SPCommand> {
let result = Box::new(SPCommand(servicepoint::Command::FadeOut)); let result = Box::new(SPCommand(servicepoint::FadeOutCommand.into()));
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -164,8 +164,7 @@ pub unsafe extern "C" fn sp_command_brightness(
) -> NonNull<SPCommand> { ) -> NonNull<SPCommand> {
let brightness = servicepoint::Brightness::try_from(brightness) let brightness = servicepoint::Brightness::try_from(brightness)
.expect("invalid brightness"); .expect("invalid brightness");
let result = let result = Box::new(SPCommand(GlobalBrightnessCommand::from(brightness).into()));
Box::new(SPCommand(servicepoint::Command::Brightness(brightness)));
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -194,11 +193,11 @@ pub unsafe extern "C" fn sp_command_char_brightness(
grid: *mut SPBrightnessGrid, grid: *mut SPBrightnessGrid,
) -> NonNull<SPCommand> { ) -> NonNull<SPCommand> {
assert!(!grid.is_null()); assert!(!grid.is_null());
let byte_grid = *Box::from_raw(grid); let byte_grid = unsafe { *Box::from_raw(grid) };
let result = Box::new(SPCommand(servicepoint::Command::CharBrightness( let result = Box::new(SPCommand(servicepoint::BrightnessGridCommand {
servicepoint::Origin::new(x, y), origin: servicepoint::Origin::new(x, y),
byte_grid.0, grid: byte_grid.0,
))); }.into()));
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -232,15 +231,8 @@ pub unsafe extern "C" fn sp_command_bitmap_linear(
offset: usize, offset: usize,
bit_vec: *mut SPBitVec, bit_vec: *mut SPBitVec,
compression: SPCompressionCode, compression: SPCompressionCode,
) -> NonNull<SPCommand> { ) -> *mut SPCommand {
assert!(!bit_vec.is_null()); unsafe {sp_command_bitmap_linear_internal(offset, bit_vec, compression, BinaryOperation::Overwrite)}
let bit_vec = *Box::from_raw(bit_vec);
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinear(
offset,
bit_vec.into(),
compression.try_into().expect("invalid compression code"),
)));
NonNull::from(Box::leak(result))
} }
/// Set pixel data according to an and-mask starting at the offset. /// Set pixel data according to an and-mask starting at the offset.
@ -273,15 +265,8 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and(
offset: usize, offset: usize,
bit_vec: *mut SPBitVec, bit_vec: *mut SPBitVec,
compression: SPCompressionCode, compression: SPCompressionCode,
) -> NonNull<SPCommand> { ) -> *mut SPCommand {
assert!(!bit_vec.is_null()); unsafe {sp_command_bitmap_linear_internal(offset, bit_vec, compression, BinaryOperation::Xor)}
let bit_vec = *Box::from_raw(bit_vec);
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearAnd(
offset,
bit_vec.into(),
compression.try_into().expect("invalid compression code"),
)));
NonNull::from(Box::leak(result))
} }
/// Set pixel data according to an or-mask starting at the offset. /// Set pixel data according to an or-mask starting at the offset.
@ -314,15 +299,8 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or(
offset: usize, offset: usize,
bit_vec: *mut SPBitVec, bit_vec: *mut SPBitVec,
compression: SPCompressionCode, compression: SPCompressionCode,
) -> NonNull<SPCommand> { ) -> *mut SPCommand {
assert!(!bit_vec.is_null()); unsafe {sp_command_bitmap_linear_internal(offset, bit_vec, compression, BinaryOperation::Or)}
let bit_vec = *Box::from_raw(bit_vec);
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearOr(
offset,
bit_vec.into(),
compression.try_into().expect("invalid compression code"),
)));
NonNull::from(Box::leak(result))
} }
/// Set pixel data according to a xor-mask starting at the offset. /// Set pixel data according to a xor-mask starting at the offset.
@ -355,15 +333,30 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
offset: usize, offset: usize,
bit_vec: *mut SPBitVec, bit_vec: *mut SPBitVec,
compression: SPCompressionCode, compression: SPCompressionCode,
) -> NonNull<SPCommand> { ) -> *mut SPCommand {
unsafe {sp_command_bitmap_linear_internal(offset, bit_vec, compression, BinaryOperation::Xor)}
}
#[inline]
unsafe fn sp_command_bitmap_linear_internal(
offset: usize,
bit_vec: *mut SPBitVec,
compression: SPCompressionCode,
operation: BinaryOperation
) -> *mut SPCommand {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
let bit_vec = *Box::from_raw(bit_vec); let bit_vec = unsafe { *Box::from_raw(bit_vec) };
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearXor( let compression = match compression.try_into() {
Ok(compression) => compression,
Err(_) => return std::ptr::null_mut(),
};
let command = SPCommand(servicepoint::BitVecCommand {
offset, offset,
bit_vec.into(), operation,
compression.try_into().expect("invalid compression code"), bitvec: bit_vec.into(),
))); compression,
NonNull::from(Box::leak(result)) }.into());
Box::leak(Box::new(command))
} }
/// Show codepage 437 encoded text on the screen. /// Show codepage 437 encoded text on the screen.
@ -391,11 +384,12 @@ pub unsafe extern "C" fn sp_command_cp437_data(
grid: *mut SPCp437Grid, grid: *mut SPCp437Grid,
) -> NonNull<SPCommand> { ) -> NonNull<SPCommand> {
assert!(!grid.is_null()); assert!(!grid.is_null());
let grid = *Box::from_raw(grid); let grid = *unsafe{Box::from_raw(grid)};
let result = Box::new(SPCommand(servicepoint::Command::Cp437Data( let result = Box::new(SPCommand(servicepoint::Cp437GridCommand {
servicepoint::Origin::new(x, y), origin: servicepoint::Origin::new(x,
grid.0, y),
))); grid: grid.0,
}.into()));
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -424,11 +418,12 @@ pub unsafe extern "C" fn sp_command_utf8_data(
grid: *mut SPCharGrid, grid: *mut SPCharGrid,
) -> NonNull<SPCommand> { ) -> NonNull<SPCommand> {
assert!(!grid.is_null()); assert!(!grid.is_null());
let grid = *Box::from_raw(grid); let grid = unsafe { *Box::from_raw(grid) };
let result = Box::new(SPCommand(servicepoint::Command::Utf8Data( let result = Box::new(SPCommand(servicepoint::CharGridCommand {
servicepoint::Origin::new(x, y), origin: servicepoint::Origin::new(x,
grid.0, y),
))); grid: grid.0,
}.into()));
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -457,18 +452,20 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win(
x: usize, x: usize,
y: usize, y: usize,
bitmap: *mut SPBitmap, bitmap: *mut SPBitmap,
compression_code: SPCompressionCode, compression: SPCompressionCode,
) -> NonNull<SPCommand> { ) -> *mut SPCommand {
assert!(!bitmap.is_null()); assert!(!bitmap.is_null());
let byte_grid = (*Box::from_raw(bitmap)).0; let bitmap = unsafe { *Box::from_raw(bitmap) }.0;
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearWin( let compression = match compression.try_into() {
servicepoint::Origin::new(x, y), Ok(compression) => compression,
byte_grid, Err(_) => return std::ptr::null_mut(),
compression_code };
.try_into() let command = SPCommand(servicepoint::BitmapCommand {
.expect("invalid compression code"), origin: servicepoint::Origin::new(x, y),
))); bitmap,
NonNull::from(Box::leak(result)) compression,
}.into());
Box::leak(Box::new(command))
} }
/// Deallocates a [SPCommand]. /// Deallocates a [SPCommand].
@ -494,5 +491,5 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_free(command: *mut SPCommand) { pub unsafe extern "C" fn sp_command_free(command: *mut SPCommand) {
assert!(!command.is_null()); assert!(!command.is_null());
_ = Box::from_raw(command); _ = unsafe { Box::from_raw(command) };
} }

View file

@ -3,8 +3,7 @@
//! prefix `sp_connection_` //! prefix `sp_connection_`
use std::ffi::{c_char, CStr}; use std::ffi::{c_char, CStr};
use std::ptr::{null_mut, NonNull}; use servicepoint::Connection;
use crate::{SPCommand, SPPacket}; use crate::{SPCommand, SPPacket};
/// A connection to the display. /// A connection to the display.
@ -16,7 +15,7 @@ use crate::{SPCommand, SPPacket};
/// if (connection != NULL) /// if (connection != NULL)
/// sp_connection_send_command(connection, sp_command_clear()); /// sp_connection_send_command(connection, sp_command_clear());
/// ``` /// ```
pub struct SPConnection(pub(crate) servicepoint::Connection); pub struct SPConnection(pub(crate) servicepoint::UdpConnection);
/// Creates a new instance of [SPConnection]. /// Creates a new instance of [SPConnection].
/// ///
@ -37,30 +36,30 @@ pub unsafe extern "C" fn sp_connection_open(
host: *const c_char, host: *const c_char,
) -> *mut SPConnection { ) -> *mut SPConnection {
assert!(!host.is_null()); assert!(!host.is_null());
let host = CStr::from_ptr(host).to_str().expect("Bad encoding"); let host = unsafe {CStr::from_ptr(host)}.to_str().expect("Bad encoding");
let connection = match servicepoint::Connection::open(host) { let connection = match servicepoint::UdpConnection::open(host) {
Err(_) => return null_mut(), Err(_) => return std::ptr::null_mut(),
Ok(value) => value, Ok(value) => value,
}; };
Box::into_raw(Box::new(SPConnection(connection))) Box::into_raw(Box::new(SPConnection(connection)))
} }
/// Creates a new instance of [SPConnection] for testing that does not actually send anything. // /// Creates a new instance of [SPUdpConnection] for testing that does not actually send anything.
/// // ///
/// returns: a new instance. Will never return NULL. // /// returns: a new instance. Will never return NULL.
/// // ///
/// # Safety // /// # Safety
/// // ///
/// The caller has to make sure that: // /// The caller has to make sure that:
/// // ///
/// - the returned instance is freed in some way, either by using a consuming function or // /// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_connection_free`. // /// by explicitly calling `sp_connection_free`.
#[no_mangle] // #[no_mangle]
pub unsafe extern "C" fn sp_connection_fake() -> NonNull<SPConnection> { // pub unsafe extern "C" fn sp_connection_fake() -> NonNull<SPUdpConnection> {
let result = Box::new(SPConnection(servicepoint::Connection::Fake)); // let result = Box::new(SPUdpConnection(servicepoint::Connection::Fake));
NonNull::from(Box::leak(result)) // NonNull::from(Box::leak(result))
} // }
/// Sends a [SPPacket] to the display using the [SPConnection]. /// Sends a [SPPacket] to the display using the [SPConnection].
/// ///
@ -87,8 +86,8 @@ pub unsafe extern "C" fn sp_connection_send_packet(
) -> bool { ) -> bool {
assert!(!connection.is_null()); assert!(!connection.is_null());
assert!(!packet.is_null()); assert!(!packet.is_null());
let packet = Box::from_raw(packet); let packet = unsafe {Box::from_raw(packet)};
(*connection).0.send((*packet).0).is_ok() unsafe {(*connection).0.send((*packet).0)}.is_ok()
} }
/// Sends a [SPCommand] to the display using the [SPConnection]. /// Sends a [SPCommand] to the display using the [SPConnection].
@ -116,8 +115,8 @@ pub unsafe extern "C" fn sp_connection_send_command(
) -> bool { ) -> bool {
assert!(!connection.is_null()); assert!(!connection.is_null());
assert!(!command.is_null()); assert!(!command.is_null());
let command = (*Box::from_raw(command)).0; let command = (*unsafe {Box::from_raw(command)}).0;
(*connection).0.send(command).is_ok() unsafe{(*connection).0.send(command)}.is_ok()
} }
/// Closes and deallocates a [SPConnection]. /// Closes and deallocates a [SPConnection].
@ -135,5 +134,5 @@ pub unsafe extern "C" fn sp_connection_send_command(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_connection_free(connection: *mut SPConnection) { pub unsafe extern "C" fn sp_connection_free(connection: *mut SPConnection) {
assert!(!connection.is_null()); assert!(!connection.is_null());
_ = Box::from_raw(connection); _ = unsafe {Box::from_raw(connection)};
} }

View file

@ -43,6 +43,6 @@ impl TryFrom<SPCompressionCode> for CompressionCode {
type Error = (); type Error = ();
fn try_from(value: SPCompressionCode) -> Result<Self, Self::Error> { fn try_from(value: SPCompressionCode) -> Result<Self, Self::Error> {
CompressionCode::try_from(value as u16) CompressionCode::try_from(value as u16).map_err(|_|())
} }
} }

View file

@ -69,13 +69,15 @@ pub unsafe extern "C" fn sp_cp437_grid_load(
height: usize, height: usize,
data: *const u8, data: *const u8,
data_length: usize, data_length: usize,
) -> NonNull<SPCp437Grid> { ) -> *mut SPCp437Grid {
assert!(data.is_null()); assert!(data.is_null());
let data = std::slice::from_raw_parts(data, data_length); let data = unsafe{std::slice::from_raw_parts(data, data_length)};
let result = Box::new(SPCp437Grid(servicepoint::Cp437Grid::load( let grid = servicepoint::Cp437Grid::load( width, height, data, );
width, height, data, if let Some(grid ) = grid {
))); Box::leak(Box::new(SPCp437Grid(grid)))
NonNull::from(Box::leak(result)) } else {
std::ptr::null_mut()
}
} }
/// Clones a [SPCp437Grid]. /// Clones a [SPCp437Grid].
@ -99,7 +101,7 @@ pub unsafe extern "C" fn sp_cp437_grid_clone(
cp437_grid: *const SPCp437Grid, cp437_grid: *const SPCp437Grid,
) -> NonNull<SPCp437Grid> { ) -> NonNull<SPCp437Grid> {
assert!(!cp437_grid.is_null()); assert!(!cp437_grid.is_null());
let result = Box::new((*cp437_grid).clone()); let result = Box::new(unsafe {(*cp437_grid).clone()});
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -121,7 +123,7 @@ pub unsafe extern "C" fn sp_cp437_grid_clone(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: *mut SPCp437Grid) { pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: *mut SPCp437Grid) {
assert!(!cp437_grid.is_null()); assert!(!cp437_grid.is_null());
_ = Box::from_raw(cp437_grid); _ = unsafe {Box::from_raw(cp437_grid)};
} }
/// Gets the current value at the specified position. /// Gets the current value at the specified position.
@ -149,7 +151,7 @@ pub unsafe extern "C" fn sp_cp437_grid_get(
y: usize, y: usize,
) -> u8 { ) -> u8 {
assert!(!cp437_grid.is_null()); assert!(!cp437_grid.is_null());
(*cp437_grid).0.get(x, y) unsafe{(*cp437_grid).0.get(x, y)}
} }
/// Sets the value of the specified position in the [SPCp437Grid]. /// Sets the value of the specified position in the [SPCp437Grid].
@ -183,7 +185,7 @@ pub unsafe extern "C" fn sp_cp437_grid_set(
value: u8, value: u8,
) { ) {
assert!(!cp437_grid.is_null()); assert!(!cp437_grid.is_null());
(*cp437_grid).0.set(x, y, value); unsafe {(*cp437_grid).0.set(x, y, value)};
} }
/// Sets the value of all cells in the [SPCp437Grid]. /// Sets the value of all cells in the [SPCp437Grid].
@ -209,7 +211,7 @@ pub unsafe extern "C" fn sp_cp437_grid_fill(
value: u8, value: u8,
) { ) {
assert!(!cp437_grid.is_null()); assert!(!cp437_grid.is_null());
(*cp437_grid).0.fill(value); unsafe {(*cp437_grid).0.fill(value)};
} }
/// Gets the width of the [SPCp437Grid] instance. /// Gets the width of the [SPCp437Grid] instance.
@ -232,7 +234,7 @@ pub unsafe extern "C" fn sp_cp437_grid_width(
cp437_grid: *const SPCp437Grid, cp437_grid: *const SPCp437Grid,
) -> usize { ) -> usize {
assert!(!cp437_grid.is_null()); assert!(!cp437_grid.is_null());
(*cp437_grid).0.width() unsafe {(*cp437_grid).0.width()}
} }
/// Gets the height of the [SPCp437Grid] instance. /// Gets the height of the [SPCp437Grid] instance.
@ -255,7 +257,7 @@ pub unsafe extern "C" fn sp_cp437_grid_height(
cp437_grid: *const SPCp437Grid, cp437_grid: *const SPCp437Grid,
) -> usize { ) -> usize {
assert!(!cp437_grid.is_null()); assert!(!cp437_grid.is_null());
(*cp437_grid).0.height() unsafe {(*cp437_grid).0.height()}
} }
/// Gets an unsafe reference to the data of the [SPCp437Grid] instance. /// Gets an unsafe reference to the data of the [SPCp437Grid] instance.
@ -277,7 +279,7 @@ pub unsafe extern "C" fn sp_cp437_grid_height(
pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref( pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref(
cp437_grid: *mut SPCp437Grid, cp437_grid: *mut SPCp437Grid,
) -> SPByteSlice { ) -> SPByteSlice {
let data = (*cp437_grid).0.data_ref_mut(); let data = unsafe {(*cp437_grid).0.data_ref_mut()};
SPByteSlice { SPByteSlice {
start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), start: NonNull::new(data.as_mut_ptr_range().start).unwrap(),
length: data.len(), length: data.len(),

View file

@ -2,7 +2,7 @@
//! //!
//! prefix `sp_packet_` //! prefix `sp_packet_`
use std::ptr::{null_mut, NonNull}; use std::ptr::{NonNull};
use crate::SPCommand; use crate::SPCommand;
@ -29,11 +29,12 @@ pub struct SPPacket(pub(crate) servicepoint::Packet);
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_packet_from_command( pub unsafe extern "C" fn sp_packet_from_command(
command: *mut SPCommand, command: *mut SPCommand,
) -> NonNull<SPPacket> { ) -> *mut SPPacket {
assert!(!command.is_null()); assert!(!command.is_null());
let command = *Box::from_raw(command); let command = unsafe {*Box::from_raw(command)};
let result = Box::new(SPPacket(command.0.into())); if let Ok(packet) = command.0.try_into() {
NonNull::from(Box::leak(result)) Box::leak(Box::new(SPPacket(packet)))
} else { std::ptr::null_mut() }
} }
/// Tries to load a [SPPacket] from the passed array with the specified length. /// Tries to load a [SPPacket] from the passed array with the specified length.
@ -58,9 +59,9 @@ pub unsafe extern "C" fn sp_packet_try_load(
length: usize, length: usize,
) -> *mut SPPacket { ) -> *mut SPPacket {
assert!(!data.is_null()); assert!(!data.is_null());
let data = std::slice::from_raw_parts(data, length); let data = unsafe {std::slice::from_raw_parts(data, length)};
match servicepoint::Packet::try_from(data) { match servicepoint::Packet::try_from(data) {
Err(_) => null_mut(), Err(_) => std::ptr::null_mut(),
Ok(packet) => Box::into_raw(Box::new(SPPacket(packet))), Ok(packet) => Box::into_raw(Box::new(SPPacket(packet))),
} }
} }
@ -104,7 +105,7 @@ pub unsafe extern "C" fn sp_packet_from_parts(
let payload = if payload.is_null() { let payload = if payload.is_null() {
vec![] vec![]
} else { } else {
let payload = std::slice::from_raw_parts(payload, payload_len); let payload = unsafe {std::slice::from_raw_parts(payload, payload_len) };
Vec::from(payload) Vec::from(payload)
}; };
@ -143,7 +144,7 @@ pub unsafe extern "C" fn sp_packet_clone(
packet: *const SPPacket, packet: *const SPPacket,
) -> NonNull<SPPacket> { ) -> NonNull<SPPacket> {
assert!(!packet.is_null()); assert!(!packet.is_null());
let result = Box::new(SPPacket((*packet).0.clone())); let result = Box::new(SPPacket(unsafe {(*packet).0.clone()}));
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
@ -162,5 +163,5 @@ pub unsafe extern "C" fn sp_packet_clone(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_packet_free(packet: *mut SPPacket) { pub unsafe extern "C" fn sp_packet_free(packet: *mut SPPacket) {
assert!(!packet.is_null()); assert!(!packet.is_null());
_ = Box::from_raw(packet) _ = unsafe {Box::from_raw(packet)}
} }