From 3c8eafecfb5bf130cea06129ef70430fe6b5f8f3 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 15 Feb 2025 13:04:07 +0100 Subject: [PATCH 01/25] fix example path --- examples/lang_c/Makefile | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 examples/lang_c/Makefile diff --git a/examples/lang_c/Makefile b/examples/lang_c/Makefile new file mode 100644 index 0000000..b28b9d3 --- /dev/null +++ b/examples/lang_c/Makefile @@ -0,0 +1,34 @@ +CC := gcc + +THIS_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) +REPO_ROOT := $(THIS_DIR)/../../ + +build: out/lang_c + +clean: + rm -r out || true + rm include/servicepoint.h || true + cargo clean + +run: out/lang_c + out/lang_c + +PHONY: build clean dependencies run + +out/lang_c: dependencies src/main.c + mkdir -p out || true + ${CC} src/main.c \ + -I include \ + -L $(REPO_ROOT)/target/release \ + -Wl,-Bstatic -lservicepoint_binding_c \ + -Wl,-Bdynamic -llzma \ + -o out/lang_c + +dependencies: FORCE + mkdir -p include || true + # generate servicepoint header and binary to link against + SERVICEPOINT_HEADER_OUT=$(THIS_DIR)/include cargo build \ + --manifest-path=$(REPO_ROOT)/Cargo.toml \ + --release + +FORCE: ; -- 2.47.0 From 57d9e90b0f1c26652f944173ae800a9b8e43ecf3 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Fri, 11 Apr 2025 21:40:49 +0200 Subject: [PATCH 02/25] wip update to next servicepoint version --- Cargo.lock | 9 ++- Cargo.toml | 8 +-- example/main.c | 2 +- include/servicepoint.h | 85 +++++++++++------------- src/bitmap.rs | 56 +++++++++------- src/bitvec.rs | 18 +++--- src/brightness_grid.rs | 36 ++++++----- src/char_grid.rs | 16 ++--- src/command.rs | 143 ++++++++++++++++++++--------------------- src/connection.rs | 51 +++++++-------- src/constants.rs | 2 +- src/cp437_grid.rs | 30 +++++---- src/packet.rs | 21 +++--- 13 files changed, 242 insertions(+), 235 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9fcfa8f..40ece4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "cbindgen" -version = "0.27.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fce8dd7fcfcbf3a0a87d8f515194b49d6135acab73e18bd380d1d93bb1a15eb" +checksum = "eadd868a2ce9ca38de7eeafdcec9c7065ef89b42b32f0839278d55f35c54d1ff" dependencies = [ "clap", "heck", @@ -407,9 +407,8 @@ dependencies = [ [[package]] name = "servicepoint" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93b52049be55a15fe37c13249d7f96aa8a5de56e1a41838e74a822ee8316a0c4" +version = "0.13.2" +source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#fe67160974d9fed542eb37e5e9a202eaf6fe00dc" dependencies = [ "bitvec", "bzip2", diff --git a/Cargo.toml b/Cargo.toml index 7750abc..9e52832 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,14 +15,14 @@ keywords = ["cccb", "cccb-servicepoint", "cbindgen"] crate-type = ["staticlib", "cdylib", "rlib"] [build-dependencies] -cbindgen = "0.27.0" +cbindgen = "0.28.0" -[dependencies.servicepoint] -version = "0.13.1" -features = ["all_compressions"] +[dependencies] +servicepoint = { features = ["all_compressions"], git = "https://git.berlin.ccc.de/servicepoint/servicepoint/", branch = "next" } [lints.rust] missing-docs = "warn" +unsafe_op_in_unsafe_fn = "warn" [package.metadata.docs.rs] all-features = true diff --git a/example/main.c b/example/main.c index 1454804..aeb811b 100644 --- a/example/main.c +++ b/example/main.c @@ -2,7 +2,7 @@ #include "servicepoint.h" int main(void) { - SPConnection *connection = sp_connection_open("localhost:2342"); + SPUdpConnection *connection = sp_connection_open("localhost:2342"); if (connection == NULL) return 1; diff --git a/include/servicepoint.h b/include/servicepoint.h index d9cbe57..e631bc0 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -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. */ @@ -168,19 +168,6 @@ typedef struct SPCharGrid SPCharGrid; */ 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. * @@ -202,6 +189,19 @@ typedef struct SPCp437Grid SPCp437Grid; */ 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. * @@ -290,7 +290,7 @@ void sp_bitmap_fill(SPBitmap *bitmap, bool value); * * [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]. @@ -341,13 +341,18 @@ size_t sp_bitmap_height(const SPBitmap *bitmap); * - `width`: size in pixels in x-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 * * - when `data` is NULL - * - when the dimensions and data size do not match exactly. - * - when the width is not dividable by 8 * * # Safety * @@ -370,9 +375,11 @@ SPBitmap *sp_bitmap_load(size_t width, * - `width`: size in pixels in x-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 * @@ -1206,7 +1213,7 @@ SPCommand *sp_command_bitmap_linear_or(size_t offset, SPCommand *sp_command_bitmap_linear_win(size_t x, size_t y, SPBitmap *bitmap, - SPCompressionCode compression_code); + SPCompressionCode compression); /** * 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); /** - * Creates a new instance of [SPConnection] for testing that does not actually send anything. - * - * 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]. + * Closes and deallocates a [SPUdpConnection]. * * # Panics * @@ -1473,13 +1466,13 @@ SPConnection *sp_connection_fake(void); * * 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 */ -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 * @@ -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 * 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. * @@ -1512,15 +1505,15 @@ SPConnection *sp_connection_open(const char *host); * * 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` 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); /** - * Sends a [SPPacket] to the display using the [SPConnection]. + * Sends a [SPPacket] to the display using the [SPUdpConnection]. * * The passed `packet` gets consumed. * @@ -1535,11 +1528,11 @@ bool sp_connection_send_command(const SPConnection *connection, * * 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` 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); /** diff --git a/src/bitmap.rs b/src/bitmap.rs index 3313385..45993d8 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -3,7 +3,7 @@ //! prefix `sp_bitmap_` use servicepoint::{DataRef, Grid}; -use std::ptr::NonNull; +use std::ptr::{null_mut, NonNull}; use crate::byte_slice::SPByteSlice; @@ -26,9 +26,11 @@ pub struct SPBitmap(pub(crate) servicepoint::Bitmap); /// - `width`: size in pixels in x-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 /// @@ -42,9 +44,12 @@ pub struct SPBitmap(pub(crate) servicepoint::Bitmap); pub unsafe extern "C" fn sp_bitmap_new( width: usize, height: usize, -) -> NonNull { - let result = Box::new(SPBitmap(servicepoint::Bitmap::new(width, height))); - NonNull::from(Box::leak(result)) +) -> *mut SPBitmap { + if let Some(bitmap) = servicepoint::Bitmap::new(width, height) { + Box::leak(Box::new(SPBitmap(bitmap))) + }else { + std::ptr::null_mut() + } } /// 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 { /// - `width`: size in pixels in x-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 /// /// - when `data` is NULL -/// - when the dimensions and data size do not match exactly. -/// - when the width is not dividable by 8 /// /// # Safety /// @@ -91,12 +101,14 @@ pub unsafe extern "C" fn sp_bitmap_load( height: usize, data: *const u8, data_length: usize, -) -> NonNull { +) -> *mut SPBitmap { assert!(!data.is_null()); - let data = std::slice::from_raw_parts(data, data_length); - let result = - Box::new(SPBitmap(servicepoint::Bitmap::load(width, height, data))); - NonNull::from(Box::leak(result)) + let data = unsafe {std::slice::from_raw_parts(data, data_length)}; + if let Ok(bitmap) = servicepoint::Bitmap::load(width, height, data) { + Box::leak(Box::new(SPBitmap(bitmap))) + }else { + std::ptr::null_mut() + } } /// Clones a [SPBitmap]. @@ -120,7 +132,7 @@ pub unsafe extern "C" fn sp_bitmap_clone( bitmap: *const SPBitmap, ) -> NonNull { 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)) } @@ -142,7 +154,7 @@ pub unsafe extern "C" fn sp_bitmap_clone( #[no_mangle] pub unsafe extern "C" fn sp_bitmap_free(bitmap: *mut SPBitmap) { assert!(!bitmap.is_null()); - _ = Box::from_raw(bitmap); + _ = unsafe {Box::from_raw(bitmap)}; } /// 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, ) -> bool { 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]. @@ -202,7 +214,7 @@ pub unsafe extern "C" fn sp_bitmap_set( value: bool, ) { 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]. @@ -225,7 +237,7 @@ pub unsafe extern "C" fn sp_bitmap_set( #[no_mangle] pub unsafe extern "C" fn sp_bitmap_fill(bitmap: *mut SPBitmap, value: bool) { assert!(!bitmap.is_null()); - (*bitmap).0.fill(value); + unsafe {(*bitmap).0.fill(value)}; } /// 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] pub unsafe extern "C" fn sp_bitmap_width(bitmap: *const SPBitmap) -> usize { assert!(!bitmap.is_null()); - (*bitmap).0.width() + unsafe {(*bitmap).0.width()} } /// 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] pub unsafe extern "C" fn sp_bitmap_height(bitmap: *const SPBitmap) -> usize { assert!(!bitmap.is_null()); - (*bitmap).0.height() + unsafe {(*bitmap).0.height()} } /// 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, ) -> SPByteSlice { assert!(!bitmap.is_null()); - let data = (*bitmap).0.data_ref_mut(); + let data = unsafe {(*bitmap).0.data_ref_mut()}; SPByteSlice { start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), length: data.len(), diff --git a/src/bitvec.rs b/src/bitvec.rs index 484e849..ed96be5 100644 --- a/src/bitvec.rs +++ b/src/bitvec.rs @@ -79,7 +79,7 @@ pub unsafe extern "C" fn sp_bitvec_load( data_length: usize, ) -> NonNull { 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))); NonNull::from(Box::leak(result)) } @@ -105,7 +105,7 @@ pub unsafe extern "C" fn sp_bitvec_clone( bit_vec: *const SPBitVec, ) -> NonNull { 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)) } @@ -127,7 +127,7 @@ pub unsafe extern "C" fn sp_bitvec_clone( #[no_mangle] pub unsafe extern "C" fn sp_bitvec_free(bit_vec: *mut SPBitVec) { 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]. @@ -156,7 +156,7 @@ pub unsafe extern "C" fn sp_bitvec_get( index: usize, ) -> bool { 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]. @@ -185,7 +185,7 @@ pub unsafe extern "C" fn sp_bitvec_set( value: bool, ) { 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]. @@ -208,7 +208,7 @@ pub unsafe extern "C" fn sp_bitvec_set( #[no_mangle] pub unsafe extern "C" fn sp_bitvec_fill(bit_vec: *mut SPBitVec, value: bool) { assert!(!bit_vec.is_null()); - (*bit_vec).0.fill(value) + unsafe {(*bit_vec).0.fill(value)} } /// 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] pub unsafe extern "C" fn sp_bitvec_len(bit_vec: *const SPBitVec) -> usize { assert!(!bit_vec.is_null()); - (*bit_vec).0.len() + unsafe {(*bit_vec).0.len()} } /// 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] pub unsafe extern "C" fn sp_bitvec_is_empty(bit_vec: *const SPBitVec) -> bool { 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. @@ -275,7 +275,7 @@ pub unsafe extern "C" fn sp_bitvec_unsafe_data_ref( bit_vec: *mut SPBitVec, ) -> SPByteSlice { 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 { start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), length: data.len(), diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index 83af008..cfd2589 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -77,14 +77,18 @@ pub unsafe extern "C" fn sp_brightness_grid_load( height: usize, data: *const u8, data_length: usize, -) -> NonNull { +) -> *mut SPBrightnessGrid { assert!(!data.is_null()); - let data = std::slice::from_raw_parts(data, data_length); - let grid = servicepoint::ByteGrid::load(width, height, data); - let grid = servicepoint::BrightnessGrid::try_from(grid) - .expect("invalid brightness value"); - let result = Box::new(SPBrightnessGrid(grid)); - NonNull::from(Box::leak(result)) + let data =unsafe { std::slice::from_raw_parts(data, data_length)}; + let grid = match servicepoint::ByteGrid::load(width, height, data) { + None => return std::ptr::null_mut(), + Some(grid) => grid + }; + if let Ok(grid )= servicepoint::BrightnessGrid::try_from(grid) { + Box::leak(Box::new(SPBrightnessGrid(grid))) + }else { + std::ptr::null_mut() + } } /// Clones a [SPBrightnessGrid]. @@ -112,7 +116,7 @@ pub unsafe extern "C" fn sp_brightness_grid_clone( brightness_grid: *const SPBrightnessGrid, ) -> NonNull { 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)) } @@ -140,7 +144,7 @@ pub unsafe extern "C" fn sp_brightness_grid_free( brightness_grid: *mut SPBrightnessGrid, ) { assert!(!brightness_grid.is_null()); - _ = Box::from_raw(brightness_grid); + _ = unsafe {Box::from_raw(brightness_grid)}; } /// Gets the current value at the specified position. @@ -170,7 +174,7 @@ pub unsafe extern "C" fn sp_brightness_grid_get( y: usize, ) -> u8 { 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]. @@ -205,7 +209,7 @@ pub unsafe extern "C" fn sp_brightness_grid_set( assert!(!brightness_grid.is_null()); let brightness = servicepoint::Brightness::try_from(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]. @@ -234,7 +238,7 @@ pub unsafe extern "C" fn sp_brightness_grid_fill( assert!(!brightness_grid.is_null()); let brightness = servicepoint::Brightness::try_from(value) .expect("invalid brightness value"); - (*brightness_grid).0.fill(brightness); + unsafe {(*brightness_grid).0.fill(brightness)}; } /// Gets the width of the [SPBrightnessGrid] instance. @@ -259,7 +263,7 @@ pub unsafe extern "C" fn sp_brightness_grid_width( brightness_grid: *const SPBrightnessGrid, ) -> usize { assert!(!brightness_grid.is_null()); - (*brightness_grid).0.width() + unsafe {(*brightness_grid).0.width()} } /// Gets the height of the [SPBrightnessGrid] instance. @@ -284,7 +288,7 @@ pub unsafe extern "C" fn sp_brightness_grid_height( brightness_grid: *const SPBrightnessGrid, ) -> usize { 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. @@ -312,9 +316,9 @@ pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( ) -> SPByteSlice { assert!(!brightness_grid.is_null()); assert_eq!(core::mem::size_of::(), 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! - let data: &mut [u8] = transmute(data); + let data: &mut [u8] = unsafe {transmute(data)}; SPByteSlice { start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), length: data.len(), diff --git a/src/char_grid.rs b/src/char_grid.rs index dfaf225..3c51e89 100644 --- a/src/char_grid.rs +++ b/src/char_grid.rs @@ -74,7 +74,7 @@ pub unsafe extern "C" fn sp_char_grid_load( data_length: usize, ) -> NonNull { 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( servicepoint::CharGrid::load_utf8(width, height, data.to_vec()) .unwrap(), @@ -103,7 +103,7 @@ pub unsafe extern "C" fn sp_char_grid_clone( char_grid: *const SPCharGrid, ) -> NonNull { 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)) } @@ -125,7 +125,7 @@ pub unsafe extern "C" fn sp_char_grid_clone( #[no_mangle] pub unsafe extern "C" fn sp_char_grid_free(char_grid: *mut SPCharGrid) { assert!(!char_grid.is_null()); - _ = Box::from_raw(char_grid); + _ = unsafe {Box::from_raw(char_grid)}; } /// Gets the current value at the specified position. @@ -153,7 +153,7 @@ pub unsafe extern "C" fn sp_char_grid_get( y: usize, ) -> u32 { 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]. @@ -187,7 +187,7 @@ pub unsafe extern "C" fn sp_char_grid_set( value: u32, ) { 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]. @@ -213,7 +213,7 @@ pub unsafe extern "C" fn sp_char_grid_fill( value: u32, ) { 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. @@ -236,7 +236,7 @@ pub unsafe extern "C" fn sp_char_grid_width( char_grid: *const SPCharGrid, ) -> usize { assert!(!char_grid.is_null()); - (*char_grid).0.width() + unsafe {(*char_grid).0.width()} } /// Gets the height of the [SPCharGrid] instance. @@ -259,5 +259,5 @@ pub unsafe extern "C" fn sp_char_grid_height( char_grid: *const SPCharGrid, ) -> usize { assert!(!char_grid.is_null()); - (*char_grid).0.height() + unsafe {(*char_grid).0.height()} } diff --git a/src/command.rs b/src/command.rs index f7e50ea..0720db6 100644 --- a/src/command.rs +++ b/src/command.rs @@ -2,12 +2,12 @@ //! //! prefix `sp_command_` -use std::ptr::{null_mut, NonNull}; - use crate::{ SPBitVec, SPBitmap, SPBrightnessGrid, SPCharGrid, SPCompressionCode, SPCp437Grid, SPPacket, }; +use servicepoint::{BinaryOperation, GlobalBrightnessCommand}; +use std::ptr::NonNull; /// A low-level display command. /// @@ -23,7 +23,7 @@ use crate::{ /// ``` /// /// [SPConnection]: [crate::SPConnection] -pub struct SPCommand(pub(crate) servicepoint::Command); +pub struct SPCommand(pub(crate) servicepoint::TypedCommand); impl Clone for SPCommand { fn clone(&self) -> Self { @@ -54,9 +54,9 @@ impl Clone for SPCommand { pub unsafe extern "C" fn sp_command_try_from_packet( packet: *mut SPPacket, ) -> *mut SPCommand { - let packet = *Box::from_raw(packet); - match servicepoint::Command::try_from(packet.0) { - Err(_) => null_mut(), + let packet = *unsafe{Box::from_raw(packet)}; + match servicepoint::TypedCommand::try_from(packet.0) { + Err(_) => std::ptr::null_mut(), Ok(command) => Box::into_raw(Box::new(SPCommand(command))), } } @@ -82,7 +82,7 @@ pub unsafe extern "C" fn sp_command_clone( command: *const SPCommand, ) -> NonNull { assert!(!command.is_null()); - let result = Box::new((*command).clone()); + let result = Box::new(unsafe { (*command).clone() }); NonNull::from(Box::leak(result)) } @@ -106,7 +106,7 @@ pub unsafe extern "C" fn sp_command_clone( /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_clear() -> NonNull { - let result = Box::new(SPCommand(servicepoint::Command::Clear)); + let result = Box::new(SPCommand(servicepoint::ClearCommand.into())); NonNull::from(Box::leak(result)) } @@ -124,7 +124,7 @@ pub unsafe extern "C" fn sp_command_clear() -> NonNull { /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull { - let result = Box::new(SPCommand(servicepoint::Command::HardReset)); + let result = Box::new(SPCommand(servicepoint::HardResetCommand.into())); NonNull::from(Box::leak(result)) } @@ -140,7 +140,7 @@ pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull { /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_fade_out() -> NonNull { - let result = Box::new(SPCommand(servicepoint::Command::FadeOut)); + let result = Box::new(SPCommand(servicepoint::FadeOutCommand.into())); NonNull::from(Box::leak(result)) } @@ -164,8 +164,7 @@ pub unsafe extern "C" fn sp_command_brightness( ) -> NonNull { let brightness = servicepoint::Brightness::try_from(brightness) .expect("invalid brightness"); - let result = - Box::new(SPCommand(servicepoint::Command::Brightness(brightness))); + let result = Box::new(SPCommand(GlobalBrightnessCommand::from(brightness).into())); NonNull::from(Box::leak(result)) } @@ -194,11 +193,11 @@ pub unsafe extern "C" fn sp_command_char_brightness( grid: *mut SPBrightnessGrid, ) -> NonNull { assert!(!grid.is_null()); - let byte_grid = *Box::from_raw(grid); - let result = Box::new(SPCommand(servicepoint::Command::CharBrightness( - servicepoint::Origin::new(x, y), - byte_grid.0, - ))); + let byte_grid = unsafe { *Box::from_raw(grid) }; + let result = Box::new(SPCommand(servicepoint::BrightnessGridCommand { + origin: servicepoint::Origin::new(x, y), + grid: byte_grid.0, + }.into())); NonNull::from(Box::leak(result)) } @@ -232,15 +231,8 @@ pub unsafe extern "C" fn sp_command_bitmap_linear( offset: usize, bit_vec: *mut SPBitVec, compression: SPCompressionCode, -) -> NonNull { - assert!(!bit_vec.is_null()); - 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)) +) -> *mut SPCommand { + unsafe {sp_command_bitmap_linear_internal(offset, bit_vec, compression, BinaryOperation::Overwrite)} } /// 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, bit_vec: *mut SPBitVec, compression: SPCompressionCode, -) -> NonNull { - assert!(!bit_vec.is_null()); - 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)) +) -> *mut SPCommand { + unsafe {sp_command_bitmap_linear_internal(offset, bit_vec, compression, BinaryOperation::Xor)} } /// 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, bit_vec: *mut SPBitVec, compression: SPCompressionCode, -) -> NonNull { - assert!(!bit_vec.is_null()); - 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)) +) -> *mut SPCommand { + unsafe {sp_command_bitmap_linear_internal(offset, bit_vec, compression, BinaryOperation::Or)} } /// 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, bit_vec: *mut SPBitVec, compression: SPCompressionCode, -) -> NonNull { +) -> *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()); - let bit_vec = *Box::from_raw(bit_vec); - let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearXor( + let bit_vec = unsafe { *Box::from_raw(bit_vec) }; + let compression = match compression.try_into() { + Ok(compression) => compression, + Err(_) => return std::ptr::null_mut(), + }; + let command = SPCommand(servicepoint::BitVecCommand { offset, - bit_vec.into(), - compression.try_into().expect("invalid compression code"), - ))); - NonNull::from(Box::leak(result)) + operation, + bitvec: bit_vec.into(), + compression, + }.into()); + Box::leak(Box::new(command)) } /// Show codepage 437 encoded text on the screen. @@ -391,11 +384,12 @@ pub unsafe extern "C" fn sp_command_cp437_data( grid: *mut SPCp437Grid, ) -> NonNull { assert!(!grid.is_null()); - let grid = *Box::from_raw(grid); - let result = Box::new(SPCommand(servicepoint::Command::Cp437Data( - servicepoint::Origin::new(x, y), - grid.0, - ))); + let grid = *unsafe{Box::from_raw(grid)}; + let result = Box::new(SPCommand(servicepoint::Cp437GridCommand { + origin: servicepoint::Origin::new(x, + y), + grid: grid.0, + }.into())); NonNull::from(Box::leak(result)) } @@ -424,11 +418,12 @@ pub unsafe extern "C" fn sp_command_utf8_data( grid: *mut SPCharGrid, ) -> NonNull { assert!(!grid.is_null()); - let grid = *Box::from_raw(grid); - let result = Box::new(SPCommand(servicepoint::Command::Utf8Data( - servicepoint::Origin::new(x, y), - grid.0, - ))); + let grid = unsafe { *Box::from_raw(grid) }; + let result = Box::new(SPCommand(servicepoint::CharGridCommand { + origin: servicepoint::Origin::new(x, + y), + grid: grid.0, + }.into())); NonNull::from(Box::leak(result)) } @@ -457,18 +452,20 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win( x: usize, y: usize, bitmap: *mut SPBitmap, - compression_code: SPCompressionCode, -) -> NonNull { + compression: SPCompressionCode, +) -> *mut SPCommand { assert!(!bitmap.is_null()); - let byte_grid = (*Box::from_raw(bitmap)).0; - let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearWin( - servicepoint::Origin::new(x, y), - byte_grid, - compression_code - .try_into() - .expect("invalid compression code"), - ))); - NonNull::from(Box::leak(result)) + let bitmap = unsafe { *Box::from_raw(bitmap) }.0; + let compression = match compression.try_into() { + Ok(compression) => compression, + Err(_) => return std::ptr::null_mut(), + }; + let command = SPCommand(servicepoint::BitmapCommand { + origin: servicepoint::Origin::new(x, y), + bitmap, + compression, + }.into()); + Box::leak(Box::new(command)) } /// Deallocates a [SPCommand]. @@ -494,5 +491,5 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win( #[no_mangle] pub unsafe extern "C" fn sp_command_free(command: *mut SPCommand) { assert!(!command.is_null()); - _ = Box::from_raw(command); + _ = unsafe { Box::from_raw(command) }; } diff --git a/src/connection.rs b/src/connection.rs index 8b31243..6bbdbe2 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -3,8 +3,7 @@ //! prefix `sp_connection_` use std::ffi::{c_char, CStr}; -use std::ptr::{null_mut, NonNull}; - +use servicepoint::Connection; use crate::{SPCommand, SPPacket}; /// A connection to the display. @@ -16,7 +15,7 @@ use crate::{SPCommand, SPPacket}; /// if (connection != NULL) /// 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]. /// @@ -37,30 +36,30 @@ pub unsafe extern "C" fn sp_connection_open( host: *const c_char, ) -> *mut SPConnection { assert!(!host.is_null()); - let host = CStr::from_ptr(host).to_str().expect("Bad encoding"); - let connection = match servicepoint::Connection::open(host) { - Err(_) => return null_mut(), + let host = unsafe {CStr::from_ptr(host)}.to_str().expect("Bad encoding"); + let connection = match servicepoint::UdpConnection::open(host) { + Err(_) => return std::ptr::null_mut(), Ok(value) => value, }; Box::into_raw(Box::new(SPConnection(connection))) } -/// Creates a new instance of [SPConnection] for testing that does not actually send anything. -/// -/// 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`. -#[no_mangle] -pub unsafe extern "C" fn sp_connection_fake() -> NonNull { - let result = Box::new(SPConnection(servicepoint::Connection::Fake)); - NonNull::from(Box::leak(result)) -} +// /// Creates a new instance of [SPUdpConnection] for testing that does not actually send anything. +// /// +// /// 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`. +// #[no_mangle] +// pub unsafe extern "C" fn sp_connection_fake() -> NonNull { +// let result = Box::new(SPUdpConnection(servicepoint::Connection::Fake)); +// NonNull::from(Box::leak(result)) +// } /// Sends a [SPPacket] to the display using the [SPConnection]. /// @@ -87,8 +86,8 @@ pub unsafe extern "C" fn sp_connection_send_packet( ) -> bool { assert!(!connection.is_null()); assert!(!packet.is_null()); - let packet = Box::from_raw(packet); - (*connection).0.send((*packet).0).is_ok() + let packet = unsafe {Box::from_raw(packet)}; + unsafe {(*connection).0.send((*packet).0)}.is_ok() } /// Sends a [SPCommand] to the display using the [SPConnection]. @@ -116,8 +115,8 @@ pub unsafe extern "C" fn sp_connection_send_command( ) -> bool { assert!(!connection.is_null()); assert!(!command.is_null()); - let command = (*Box::from_raw(command)).0; - (*connection).0.send(command).is_ok() + let command = (*unsafe {Box::from_raw(command)}).0; + unsafe{(*connection).0.send(command)}.is_ok() } /// Closes and deallocates a [SPConnection]. @@ -135,5 +134,5 @@ pub unsafe extern "C" fn sp_connection_send_command( #[no_mangle] pub unsafe extern "C" fn sp_connection_free(connection: *mut SPConnection) { assert!(!connection.is_null()); - _ = Box::from_raw(connection); + _ = unsafe {Box::from_raw(connection)}; } diff --git a/src/constants.rs b/src/constants.rs index 1a268f4..ed4e52d 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -43,6 +43,6 @@ impl TryFrom for CompressionCode { type Error = (); fn try_from(value: SPCompressionCode) -> Result { - CompressionCode::try_from(value as u16) + CompressionCode::try_from(value as u16).map_err(|_|()) } } diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index 9b366c8..712034c 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -69,13 +69,15 @@ pub unsafe extern "C" fn sp_cp437_grid_load( height: usize, data: *const u8, data_length: usize, -) -> NonNull { +) -> *mut SPCp437Grid { assert!(data.is_null()); - let data = std::slice::from_raw_parts(data, data_length); - let result = Box::new(SPCp437Grid(servicepoint::Cp437Grid::load( - width, height, data, - ))); - NonNull::from(Box::leak(result)) + let data = unsafe{std::slice::from_raw_parts(data, data_length)}; + let grid = servicepoint::Cp437Grid::load( width, height, data, ); + if let Some(grid ) = grid { + Box::leak(Box::new(SPCp437Grid(grid))) + } else { + std::ptr::null_mut() + } } /// Clones a [SPCp437Grid]. @@ -99,7 +101,7 @@ pub unsafe extern "C" fn sp_cp437_grid_clone( cp437_grid: *const SPCp437Grid, ) -> NonNull { 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)) } @@ -121,7 +123,7 @@ pub unsafe extern "C" fn sp_cp437_grid_clone( #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: *mut SPCp437Grid) { assert!(!cp437_grid.is_null()); - _ = Box::from_raw(cp437_grid); + _ = unsafe {Box::from_raw(cp437_grid)}; } /// Gets the current value at the specified position. @@ -149,7 +151,7 @@ pub unsafe extern "C" fn sp_cp437_grid_get( y: usize, ) -> u8 { 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]. @@ -183,7 +185,7 @@ pub unsafe extern "C" fn sp_cp437_grid_set( value: u8, ) { 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]. @@ -209,7 +211,7 @@ pub unsafe extern "C" fn sp_cp437_grid_fill( value: u8, ) { assert!(!cp437_grid.is_null()); - (*cp437_grid).0.fill(value); + unsafe {(*cp437_grid).0.fill(value)}; } /// Gets the width of the [SPCp437Grid] instance. @@ -232,7 +234,7 @@ pub unsafe extern "C" fn sp_cp437_grid_width( cp437_grid: *const SPCp437Grid, ) -> usize { assert!(!cp437_grid.is_null()); - (*cp437_grid).0.width() + unsafe {(*cp437_grid).0.width()} } /// Gets the height of the [SPCp437Grid] instance. @@ -255,7 +257,7 @@ pub unsafe extern "C" fn sp_cp437_grid_height( cp437_grid: *const SPCp437Grid, ) -> usize { 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. @@ -277,7 +279,7 @@ pub unsafe extern "C" fn sp_cp437_grid_height( pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref( cp437_grid: *mut SPCp437Grid, ) -> SPByteSlice { - let data = (*cp437_grid).0.data_ref_mut(); + let data = unsafe {(*cp437_grid).0.data_ref_mut()}; SPByteSlice { start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), length: data.len(), diff --git a/src/packet.rs b/src/packet.rs index 9293a8a..12afb34 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -2,7 +2,7 @@ //! //! prefix `sp_packet_` -use std::ptr::{null_mut, NonNull}; +use std::ptr::{NonNull}; use crate::SPCommand; @@ -29,11 +29,12 @@ pub struct SPPacket(pub(crate) servicepoint::Packet); #[no_mangle] pub unsafe extern "C" fn sp_packet_from_command( command: *mut SPCommand, -) -> NonNull { +) -> *mut SPPacket { assert!(!command.is_null()); - let command = *Box::from_raw(command); - let result = Box::new(SPPacket(command.0.into())); - NonNull::from(Box::leak(result)) + let command = unsafe {*Box::from_raw(command)}; + if let Ok(packet) = command.0.try_into() { + Box::leak(Box::new(SPPacket(packet))) + } else { std::ptr::null_mut() } } /// 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, ) -> *mut SPPacket { 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) { - Err(_) => null_mut(), + Err(_) => std::ptr::null_mut(), 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() { vec![] } 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) }; @@ -143,7 +144,7 @@ pub unsafe extern "C" fn sp_packet_clone( packet: *const SPPacket, ) -> NonNull { 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)) } @@ -162,5 +163,5 @@ pub unsafe extern "C" fn sp_packet_clone( #[no_mangle] pub unsafe extern "C" fn sp_packet_free(packet: *mut SPPacket) { assert!(!packet.is_null()); - _ = Box::from_raw(packet) + _ = unsafe {Box::from_raw(packet)} } -- 2.47.0 From 69bed7c66504a242e9b4d5b1562681e619d4e91b Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Fri, 11 Apr 2025 20:43:13 +0200 Subject: [PATCH 03/25] wip 80k example --- Cargo.toml | 21 ++++++++++++-- cbindgen.toml | 2 +- example/main.c | 8 +++++- examples/lang_c/Makefile | 59 +++++++++++++++++++++++++++++++++------- flake.nix | 26 ++++++++++++------ include/servicepoint.h | 50 +++++++++++++++++----------------- src/bitmap.rs | 2 +- src/brightness_grid.rs | 2 +- 8 files changed, 121 insertions(+), 49 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9e52832..7e5ed5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,8 +17,17 @@ crate-type = ["staticlib", "cdylib", "rlib"] [build-dependencies] cbindgen = "0.28.0" -[dependencies] -servicepoint = { features = ["all_compressions"], git = "https://git.berlin.ccc.de/servicepoint/servicepoint/", branch = "next" } +[dependencies.servicepoint] +package = "servicepoint" +version = "0.13.2" +default-features = false +features = ["protocol_udp"] +git = "https://git.berlin.ccc.de/servicepoint/servicepoint/" +branch = "next" + +[features] +full = ["servicepoint/all_compressions", "servicepoint/default"] +default = ["full"] [lints.rust] missing-docs = "warn" @@ -26,3 +35,11 @@ unsafe_op_in_unsafe_fn = "warn" [package.metadata.docs.rs] all-features = true + +[profile.size-optimized] +inherits = "release" +opt-level = 'z' # Optimize for size +lto = true # Enable link-time optimization +codegen-units = 1 # Reduce number of codegen units to increase optimizations +panic = 'abort' # Abort on panic +strip = true # Strip symbols from binary diff --git a/cbindgen.toml b/cbindgen.toml index 7fc0fdf..bf2377c 100644 --- a/cbindgen.toml +++ b/cbindgen.toml @@ -26,7 +26,7 @@ sort_by = "Name" parse_deps = false [parse.expand] -all_features = true +features = ["full"] [export] include = [] diff --git a/example/main.c b/example/main.c index aeb811b..6a4b30e 100644 --- a/example/main.c +++ b/example/main.c @@ -2,14 +2,20 @@ #include "servicepoint.h" int main(void) { - SPUdpConnection *connection = sp_connection_open("localhost:2342"); + SPConnection *connection = sp_connection_open("localhost:2342"); if (connection == NULL) return 1; SPBitmap *pixels = sp_bitmap_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT); + if (pixels == NULL) + return 1; + sp_bitmap_fill(pixels, true); SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, SP_COMPRESSION_CODE_UNCOMPRESSED); + if (command == NULL) + return 1; + sp_connection_send_command(connection, command); sp_connection_free(connection); diff --git a/examples/lang_c/Makefile b/examples/lang_c/Makefile index b28b9d3..1be4009 100644 --- a/examples/lang_c/Makefile +++ b/examples/lang_c/Makefile @@ -1,7 +1,47 @@ CC := gcc +CARGO := rustup run nightly cargo THIS_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) REPO_ROOT := $(THIS_DIR)/../../ +RUST_TARGET_DIR := $(REPO_ROOT)/target/x86_64-unknown-linux-musl/size-optimized + +RUSTFLAGS := -Zlocation-detail=none \ + -Zfmt-debug=none \ + -C linker=musl-gcc \ + -C link-arg=-s \ + -C link-arg=--gc-sections \ + -C link-arg=-z,norelro \ + -C link-arg=--hash-style=gnu \ + --crate-type=staticlib \ + -C panic=abort + +CARGOFLAGS := --manifest-path=$(REPO_ROOT)/Cargo.toml \ + --profile=size-optimized \ + --no-default-features \ + --target=x86_64-unknown-linux-musl \ + -Zbuild-std="core,std,alloc,proc_macro,panic_abort" \ + -Zbuild-std-features="panic_immediate_abort" \ + +CCFLAGS := -static -Os \ + -ffunction-sections -fdata-sections \ + -fwrapv -fomit-frame-pointer -fno-stack-protector\ + -fwhole-program \ + -nodefaultlibs -lservicepoint_binding_c -lc \ + -Wl,--gc-sections \ + -fno-unroll-loops \ + -fno-unwind-tables -fno-asynchronous-unwind-tables \ + -fmerge-all-constants \ + -Wl,-z,norelro \ + -Wl,--hash-style=gnu \ + -fvisibility=hidden \ + -Bsymbolic \ + -Wl,--exclude-libs,ALL \ + -fno-ident \ + #-fuse-ld=gold \ + -fno-exceptions + #-Wl,--icf=all \ + +export SERVICEPOINT_HEADER_OUT := $(THIS_DIR)/include build: out/lang_c @@ -15,20 +55,19 @@ run: out/lang_c PHONY: build clean dependencies run -out/lang_c: dependencies src/main.c +out/lang_c_unstripped: dependencies src/main.c mkdir -p out || true ${CC} src/main.c \ - -I include \ - -L $(REPO_ROOT)/target/release \ - -Wl,-Bstatic -lservicepoint_binding_c \ - -Wl,-Bdynamic -llzma \ - -o out/lang_c + -I $(SERVICEPOINT_HEADER_OUT) \ + -L $(RUST_TARGET_DIR)\ + $(CCFLAGS) \ + -o out/lang_c_unstripped +out/lang_c: out/lang_c_unstripped + strip -s -R .comment -R .gnu.version --strip-unneeded out/lang_c_unstripped -o out/lang_c +#strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag dependencies: FORCE mkdir -p include || true # generate servicepoint header and binary to link against - SERVICEPOINT_HEADER_OUT=$(THIS_DIR)/include cargo build \ - --manifest-path=$(REPO_ROOT)/Cargo.toml \ - --release - + ${CARGO} rustc $(CARGOFLAGS) -- $(RUSTFLAGS) FORCE: ; diff --git a/flake.nix b/flake.nix index 9318237..1f0ac97 100644 --- a/flake.nix +++ b/flake.nix @@ -33,25 +33,35 @@ { pkgs, system }: { default = pkgs.mkShell rec { - packages = with pkgs; [ + buildInputs = with pkgs;[ + xe + xz + libgcc + #glibc.static + musl + libunwind + ]; + + nativeBuildInputs = with pkgs;[ (pkgs.symlinkJoin { name = "rust-toolchain"; paths = with pkgs; [ - rustc - cargo - rustPlatform.rustcSrc - rustfmt - clippy + #rustc + #cargo + #rustPlatform.rustcSrc + #rustfmt + #clippy cargo-expand cargo-tarpaulin + rustup ]; }) gcc gnumake - xe - xz pkg-config + ]; + RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}"; }; } diff --git a/include/servicepoint.h b/include/servicepoint.h index e631bc0..ca235ca 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -168,6 +168,19 @@ typedef struct SPCharGrid SPCharGrid; */ 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. * @@ -189,19 +202,6 @@ typedef struct SPCp437Grid SPCp437Grid; */ 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. * @@ -290,7 +290,7 @@ void sp_bitmap_fill(SPBitmap *bitmap, bool value); * * [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]. @@ -1456,7 +1456,7 @@ SPCommand *sp_command_utf8_data(size_t x, SPCharGrid *grid); /** - * Closes and deallocates a [SPUdpConnection]. + * Closes and deallocates a [SPConnection]. * * # Panics * @@ -1466,13 +1466,13 @@ SPCommand *sp_command_utf8_data(size_t x, * * The caller has to make sure that: * - * - `connection` points to a valid [SPUdpConnection] + * - `connection` points to a valid [SPConnection] * - `connection` is not used concurrently or after this call */ -void sp_connection_free(SPUdpConnection *connection); +void sp_connection_free(SPConnection *connection); /** - * Creates a new instance of [SPUdpConnection]. + * Creates a new instance of [SPConnection]. * * returns: NULL if connection fails, or connected instance * @@ -1487,10 +1487,10 @@ void sp_connection_free(SPUdpConnection *connection); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_connection_free`. */ -SPUdpConnection *sp_connection_open(const char *host); +SPConnection *sp_connection_open(const char *host); /** - * Sends a [SPCommand] to the display using the [SPUdpConnection]. + * Sends a [SPCommand] to the display using the [SPConnection]. * * The passed `command` gets consumed. * @@ -1505,15 +1505,15 @@ SPUdpConnection *sp_connection_open(const char *host); * * The caller has to make sure that: * - * - `connection` points to a valid instance of [SPUdpConnection] + * - `connection` points to a valid instance of [SPConnection] * - `command` points to a valid instance of [SPPacket] * - `command` is not used concurrently or after this call */ -bool sp_connection_send_command(const SPUdpConnection *connection, +bool sp_connection_send_command(const SPConnection *connection, SPCommand *command); /** - * Sends a [SPPacket] to the display using the [SPUdpConnection]. + * Sends a [SPPacket] to the display using the [SPConnection]. * * The passed `packet` gets consumed. * @@ -1528,11 +1528,11 @@ bool sp_connection_send_command(const SPUdpConnection *connection, * * The caller has to make sure that: * - * - `connection` points to a valid instance of [SPUdpConnection] + * - `connection` points to a valid instance of [SPConnection] * - `packet` points to a valid instance of [SPPacket] * - `packet` is not used concurrently or after this call */ -bool sp_connection_send_packet(const SPUdpConnection *connection, +bool sp_connection_send_packet(const SPConnection *connection, SPPacket *packet); /** diff --git a/src/bitmap.rs b/src/bitmap.rs index 45993d8..8ac5192 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -3,7 +3,7 @@ //! prefix `sp_bitmap_` use servicepoint::{DataRef, Grid}; -use std::ptr::{null_mut, NonNull}; +use std::ptr::{NonNull}; use crate::byte_slice::SPByteSlice; diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index cfd2589..6087db0 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -5,7 +5,7 @@ use crate::SPByteSlice; use servicepoint::{DataRef, Grid}; use std::convert::Into; -use std::intrinsics::transmute; +use std::mem::transmute; use std::ptr::NonNull; /// see [servicepoint::Brightness::MIN] -- 2.47.0 From 2ab80d395e20f047afca7cba5d2ffe7dc0212aa5 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Fri, 11 Apr 2025 22:00:01 +0200 Subject: [PATCH 04/25] cargo fmt --- src/bitmap.rs | 24 ++++----- src/bitvec.rs | 18 +++---- src/brightness_grid.rs | 26 +++++----- src/char_grid.rs | 16 +++--- src/command.rs | 108 ++++++++++++++++++++++++++++------------- src/connection.rs | 18 ++++--- src/constants.rs | 2 +- src/cp437_grid.rs | 22 ++++----- src/packet.rs | 17 ++++--- 9 files changed, 149 insertions(+), 102 deletions(-) diff --git a/src/bitmap.rs b/src/bitmap.rs index 8ac5192..eee5d24 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -3,7 +3,7 @@ //! prefix `sp_bitmap_` use servicepoint::{DataRef, Grid}; -use std::ptr::{NonNull}; +use std::ptr::NonNull; use crate::byte_slice::SPByteSlice; @@ -47,7 +47,7 @@ pub unsafe extern "C" fn sp_bitmap_new( ) -> *mut SPBitmap { if let Some(bitmap) = servicepoint::Bitmap::new(width, height) { Box::leak(Box::new(SPBitmap(bitmap))) - }else { + } else { std::ptr::null_mut() } } @@ -103,10 +103,10 @@ pub unsafe extern "C" fn sp_bitmap_load( data_length: usize, ) -> *mut SPBitmap { assert!(!data.is_null()); - let data = unsafe {std::slice::from_raw_parts(data, data_length)}; + let data = unsafe { std::slice::from_raw_parts(data, data_length) }; if let Ok(bitmap) = servicepoint::Bitmap::load(width, height, data) { Box::leak(Box::new(SPBitmap(bitmap))) - }else { + } else { std::ptr::null_mut() } } @@ -132,7 +132,7 @@ pub unsafe extern "C" fn sp_bitmap_clone( bitmap: *const SPBitmap, ) -> NonNull { assert!(!bitmap.is_null()); - let result = Box::new(SPBitmap(unsafe {(*bitmap).0.clone()})); + let result = Box::new(SPBitmap(unsafe { (*bitmap).0.clone() })); NonNull::from(Box::leak(result)) } @@ -154,7 +154,7 @@ pub unsafe extern "C" fn sp_bitmap_clone( #[no_mangle] pub unsafe extern "C" fn sp_bitmap_free(bitmap: *mut SPBitmap) { assert!(!bitmap.is_null()); - _ = unsafe {Box::from_raw(bitmap)}; + _ = unsafe { Box::from_raw(bitmap) }; } /// Gets the current value at the specified position in the [SPBitmap]. @@ -182,7 +182,7 @@ pub unsafe extern "C" fn sp_bitmap_get( y: usize, ) -> bool { assert!(!bitmap.is_null()); - unsafe {(*bitmap).0.get(x, y)} + unsafe { (*bitmap).0.get(x, y) } } /// Sets the value of the specified position in the [SPBitmap]. @@ -214,7 +214,7 @@ pub unsafe extern "C" fn sp_bitmap_set( value: bool, ) { assert!(!bitmap.is_null()); - unsafe {(*bitmap).0.set(x, y, value)}; + unsafe { (*bitmap).0.set(x, y, value) }; } /// Sets the state of all pixels in the [SPBitmap]. @@ -237,7 +237,7 @@ pub unsafe extern "C" fn sp_bitmap_set( #[no_mangle] pub unsafe extern "C" fn sp_bitmap_fill(bitmap: *mut SPBitmap, value: bool) { assert!(!bitmap.is_null()); - unsafe {(*bitmap).0.fill(value)}; + unsafe { (*bitmap).0.fill(value) }; } /// Gets the width in pixels of the [SPBitmap] instance. @@ -258,7 +258,7 @@ pub unsafe extern "C" fn sp_bitmap_fill(bitmap: *mut SPBitmap, value: bool) { #[no_mangle] pub unsafe extern "C" fn sp_bitmap_width(bitmap: *const SPBitmap) -> usize { assert!(!bitmap.is_null()); - unsafe {(*bitmap).0.width()} + unsafe { (*bitmap).0.width() } } /// Gets the height in pixels of the [SPBitmap] instance. @@ -279,7 +279,7 @@ pub unsafe extern "C" fn sp_bitmap_width(bitmap: *const SPBitmap) -> usize { #[no_mangle] pub unsafe extern "C" fn sp_bitmap_height(bitmap: *const SPBitmap) -> usize { assert!(!bitmap.is_null()); - unsafe {(*bitmap).0.height()} + unsafe { (*bitmap).0.height() } } /// Gets an unsafe reference to the data of the [SPBitmap] instance. @@ -300,7 +300,7 @@ pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref( bitmap: *mut SPBitmap, ) -> SPByteSlice { assert!(!bitmap.is_null()); - let data = unsafe {(*bitmap).0.data_ref_mut()}; + let data = unsafe { (*bitmap).0.data_ref_mut() }; SPByteSlice { start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), length: data.len(), diff --git a/src/bitvec.rs b/src/bitvec.rs index ed96be5..f17723b 100644 --- a/src/bitvec.rs +++ b/src/bitvec.rs @@ -79,7 +79,7 @@ pub unsafe extern "C" fn sp_bitvec_load( data_length: usize, ) -> NonNull { assert!(!data.is_null()); - let data = unsafe {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))); NonNull::from(Box::leak(result)) } @@ -105,7 +105,7 @@ pub unsafe extern "C" fn sp_bitvec_clone( bit_vec: *const SPBitVec, ) -> NonNull { assert!(!bit_vec.is_null()); - let result = Box::new(unsafe {(*bit_vec).clone()}); + let result = Box::new(unsafe { (*bit_vec).clone() }); NonNull::from(Box::leak(result)) } @@ -127,7 +127,7 @@ pub unsafe extern "C" fn sp_bitvec_clone( #[no_mangle] pub unsafe extern "C" fn sp_bitvec_free(bit_vec: *mut SPBitVec) { assert!(!bit_vec.is_null()); - _ = unsafe {Box::from_raw(bit_vec)}; + _ = unsafe { Box::from_raw(bit_vec) }; } /// Gets the value of a bit from the [SPBitVec]. @@ -156,7 +156,7 @@ pub unsafe extern "C" fn sp_bitvec_get( index: usize, ) -> bool { assert!(!bit_vec.is_null()); - unsafe {*(*bit_vec).0.get(index).unwrap()} + unsafe { *(*bit_vec).0.get(index).unwrap() } } /// Sets the value of a bit in the [SPBitVec]. @@ -185,7 +185,7 @@ pub unsafe extern "C" fn sp_bitvec_set( value: bool, ) { assert!(!bit_vec.is_null()); - unsafe {(*bit_vec).0.set(index, value)} + unsafe { (*bit_vec).0.set(index, value) } } /// Sets the value of all bits in the [SPBitVec]. @@ -208,7 +208,7 @@ pub unsafe extern "C" fn sp_bitvec_set( #[no_mangle] pub unsafe extern "C" fn sp_bitvec_fill(bit_vec: *mut SPBitVec, value: bool) { assert!(!bit_vec.is_null()); - unsafe {(*bit_vec).0.fill(value)} + unsafe { (*bit_vec).0.fill(value) } } /// 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] pub unsafe extern "C" fn sp_bitvec_len(bit_vec: *const SPBitVec) -> usize { assert!(!bit_vec.is_null()); - unsafe {(*bit_vec).0.len()} + unsafe { (*bit_vec).0.len() } } /// 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] pub unsafe extern "C" fn sp_bitvec_is_empty(bit_vec: *const SPBitVec) -> bool { assert!(!bit_vec.is_null()); - unsafe {(*bit_vec).0.is_empty()} + unsafe { (*bit_vec).0.is_empty() } } /// 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, ) -> SPByteSlice { assert!(!bit_vec.is_null()); - let data = unsafe {(*bit_vec).0.as_raw_mut_slice()}; + let data = unsafe { (*bit_vec).0.as_raw_mut_slice() }; SPByteSlice { start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), length: data.len(), diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index 6087db0..97dce2c 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -79,14 +79,14 @@ pub unsafe extern "C" fn sp_brightness_grid_load( data_length: usize, ) -> *mut SPBrightnessGrid { assert!(!data.is_null()); - let data =unsafe { std::slice::from_raw_parts(data, data_length)}; + let data = unsafe { std::slice::from_raw_parts(data, data_length) }; let grid = match servicepoint::ByteGrid::load(width, height, data) { None => return std::ptr::null_mut(), - Some(grid) => grid + Some(grid) => grid, }; - if let Ok(grid )= servicepoint::BrightnessGrid::try_from(grid) { + if let Ok(grid) = servicepoint::BrightnessGrid::try_from(grid) { Box::leak(Box::new(SPBrightnessGrid(grid))) - }else { + } else { std::ptr::null_mut() } } @@ -116,7 +116,7 @@ pub unsafe extern "C" fn sp_brightness_grid_clone( brightness_grid: *const SPBrightnessGrid, ) -> NonNull { assert!(!brightness_grid.is_null()); - let result = Box::new(unsafe {(*brightness_grid).clone()}); + let result = Box::new(unsafe { (*brightness_grid).clone() }); NonNull::from(Box::leak(result)) } @@ -144,7 +144,7 @@ pub unsafe extern "C" fn sp_brightness_grid_free( brightness_grid: *mut SPBrightnessGrid, ) { assert!(!brightness_grid.is_null()); - _ = unsafe {Box::from_raw(brightness_grid)}; + _ = unsafe { Box::from_raw(brightness_grid) }; } /// Gets the current value at the specified position. @@ -174,7 +174,7 @@ pub unsafe extern "C" fn sp_brightness_grid_get( y: usize, ) -> u8 { assert!(!brightness_grid.is_null()); - unsafe {(*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]. @@ -209,7 +209,7 @@ pub unsafe extern "C" fn sp_brightness_grid_set( assert!(!brightness_grid.is_null()); let brightness = servicepoint::Brightness::try_from(value) .expect("invalid brightness value"); - unsafe {(*brightness_grid).0.set(x, y, brightness)}; + unsafe { (*brightness_grid).0.set(x, y, brightness) }; } /// Sets the value of all cells in the [SPBrightnessGrid]. @@ -238,7 +238,7 @@ pub unsafe extern "C" fn sp_brightness_grid_fill( assert!(!brightness_grid.is_null()); let brightness = servicepoint::Brightness::try_from(value) .expect("invalid brightness value"); - unsafe {(*brightness_grid).0.fill(brightness)}; + unsafe { (*brightness_grid).0.fill(brightness) }; } /// Gets the width of the [SPBrightnessGrid] instance. @@ -263,7 +263,7 @@ pub unsafe extern "C" fn sp_brightness_grid_width( brightness_grid: *const SPBrightnessGrid, ) -> usize { assert!(!brightness_grid.is_null()); - unsafe {(*brightness_grid).0.width()} + unsafe { (*brightness_grid).0.width() } } /// Gets the height of the [SPBrightnessGrid] instance. @@ -288,7 +288,7 @@ pub unsafe extern "C" fn sp_brightness_grid_height( brightness_grid: *const SPBrightnessGrid, ) -> usize { assert!(!brightness_grid.is_null()); - unsafe {(*brightness_grid).0.height()} + unsafe { (*brightness_grid).0.height() } } /// Gets an unsafe reference to the data of the [SPBrightnessGrid] instance. @@ -316,9 +316,9 @@ pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( ) -> SPByteSlice { assert!(!brightness_grid.is_null()); assert_eq!(core::mem::size_of::(), 1); - let data = unsafe {(*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! - let data: &mut [u8] = unsafe {transmute(data)}; + let data: &mut [u8] = unsafe { transmute(data) }; SPByteSlice { start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), length: data.len(), diff --git a/src/char_grid.rs b/src/char_grid.rs index 3c51e89..5ed97c2 100644 --- a/src/char_grid.rs +++ b/src/char_grid.rs @@ -74,7 +74,7 @@ pub unsafe extern "C" fn sp_char_grid_load( data_length: usize, ) -> NonNull { assert!(data.is_null()); - let data = unsafe {std::slice::from_raw_parts(data, data_length)}; + let data = unsafe { std::slice::from_raw_parts(data, data_length) }; let result = Box::new(SPCharGrid( servicepoint::CharGrid::load_utf8(width, height, data.to_vec()) .unwrap(), @@ -103,7 +103,7 @@ pub unsafe extern "C" fn sp_char_grid_clone( char_grid: *const SPCharGrid, ) -> NonNull { assert!(!char_grid.is_null()); - let result = Box::new(unsafe{(*char_grid).clone()}); + let result = Box::new(unsafe { (*char_grid).clone() }); NonNull::from(Box::leak(result)) } @@ -125,7 +125,7 @@ pub unsafe extern "C" fn sp_char_grid_clone( #[no_mangle] pub unsafe extern "C" fn sp_char_grid_free(char_grid: *mut SPCharGrid) { assert!(!char_grid.is_null()); - _ = unsafe {Box::from_raw(char_grid)}; + _ = unsafe { Box::from_raw(char_grid) }; } /// Gets the current value at the specified position. @@ -153,7 +153,7 @@ pub unsafe extern "C" fn sp_char_grid_get( y: usize, ) -> u32 { assert!(!char_grid.is_null()); - unsafe {(*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]. @@ -187,7 +187,7 @@ pub unsafe extern "C" fn sp_char_grid_set( value: u32, ) { assert!(!char_grid.is_null()); - unsafe {(*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]. @@ -213,7 +213,7 @@ pub unsafe extern "C" fn sp_char_grid_fill( value: u32, ) { assert!(!char_grid.is_null()); - unsafe {(*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. @@ -236,7 +236,7 @@ pub unsafe extern "C" fn sp_char_grid_width( char_grid: *const SPCharGrid, ) -> usize { assert!(!char_grid.is_null()); - unsafe {(*char_grid).0.width()} + unsafe { (*char_grid).0.width() } } /// Gets the height of the [SPCharGrid] instance. @@ -259,5 +259,5 @@ pub unsafe extern "C" fn sp_char_grid_height( char_grid: *const SPCharGrid, ) -> usize { assert!(!char_grid.is_null()); - unsafe {(*char_grid).0.height()} + unsafe { (*char_grid).0.height() } } diff --git a/src/command.rs b/src/command.rs index 0720db6..8bfaee3 100644 --- a/src/command.rs +++ b/src/command.rs @@ -54,7 +54,7 @@ impl Clone for SPCommand { pub unsafe extern "C" fn sp_command_try_from_packet( packet: *mut SPPacket, ) -> *mut SPCommand { - let packet = *unsafe{Box::from_raw(packet)}; + let packet = *unsafe { Box::from_raw(packet) }; match servicepoint::TypedCommand::try_from(packet.0) { Err(_) => std::ptr::null_mut(), Ok(command) => Box::into_raw(Box::new(SPCommand(command))), @@ -164,7 +164,8 @@ pub unsafe extern "C" fn sp_command_brightness( ) -> NonNull { let brightness = servicepoint::Brightness::try_from(brightness) .expect("invalid brightness"); - let result = Box::new(SPCommand(GlobalBrightnessCommand::from(brightness).into())); + let result = + Box::new(SPCommand(GlobalBrightnessCommand::from(brightness).into())); NonNull::from(Box::leak(result)) } @@ -194,10 +195,13 @@ pub unsafe extern "C" fn sp_command_char_brightness( ) -> NonNull { assert!(!grid.is_null()); let byte_grid = unsafe { *Box::from_raw(grid) }; - let result = Box::new(SPCommand(servicepoint::BrightnessGridCommand { - origin: servicepoint::Origin::new(x, y), - grid: byte_grid.0, - }.into())); + let result = Box::new(SPCommand( + servicepoint::BrightnessGridCommand { + origin: servicepoint::Origin::new(x, y), + grid: byte_grid.0, + } + .into(), + )); NonNull::from(Box::leak(result)) } @@ -232,7 +236,14 @@ pub unsafe extern "C" fn sp_command_bitmap_linear( bit_vec: *mut SPBitVec, compression: SPCompressionCode, ) -> *mut SPCommand { - unsafe {sp_command_bitmap_linear_internal(offset, bit_vec, compression, BinaryOperation::Overwrite)} + unsafe { + sp_command_bitmap_linear_internal( + offset, + bit_vec, + compression, + BinaryOperation::Overwrite, + ) + } } /// Set pixel data according to an and-mask starting at the offset. @@ -266,7 +277,14 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and( bit_vec: *mut SPBitVec, compression: SPCompressionCode, ) -> *mut SPCommand { - unsafe {sp_command_bitmap_linear_internal(offset, bit_vec, compression, BinaryOperation::Xor)} + unsafe { + sp_command_bitmap_linear_internal( + offset, + bit_vec, + compression, + BinaryOperation::Xor, + ) + } } /// Set pixel data according to an or-mask starting at the offset. @@ -300,7 +318,14 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or( bit_vec: *mut SPBitVec, compression: SPCompressionCode, ) -> *mut SPCommand { - unsafe {sp_command_bitmap_linear_internal(offset, bit_vec, compression, BinaryOperation::Or)} + unsafe { + sp_command_bitmap_linear_internal( + offset, + bit_vec, + compression, + BinaryOperation::Or, + ) + } } /// Set pixel data according to a xor-mask starting at the offset. @@ -334,7 +359,14 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor( bit_vec: *mut SPBitVec, compression: SPCompressionCode, ) -> *mut SPCommand { - unsafe {sp_command_bitmap_linear_internal(offset, bit_vec, compression, BinaryOperation::Xor)} + unsafe { + sp_command_bitmap_linear_internal( + offset, + bit_vec, + compression, + BinaryOperation::Xor, + ) + } } #[inline] @@ -342,7 +374,7 @@ unsafe fn sp_command_bitmap_linear_internal( offset: usize, bit_vec: *mut SPBitVec, compression: SPCompressionCode, - operation: BinaryOperation + operation: BinaryOperation, ) -> *mut SPCommand { assert!(!bit_vec.is_null()); let bit_vec = unsafe { *Box::from_raw(bit_vec) }; @@ -350,12 +382,15 @@ unsafe fn sp_command_bitmap_linear_internal( Ok(compression) => compression, Err(_) => return std::ptr::null_mut(), }; - let command = SPCommand(servicepoint::BitVecCommand { - offset, - operation, - bitvec: bit_vec.into(), - compression, - }.into()); + let command = SPCommand( + servicepoint::BitVecCommand { + offset, + operation, + bitvec: bit_vec.into(), + compression, + } + .into(), + ); Box::leak(Box::new(command)) } @@ -384,12 +419,14 @@ pub unsafe extern "C" fn sp_command_cp437_data( grid: *mut SPCp437Grid, ) -> NonNull { assert!(!grid.is_null()); - let grid = *unsafe{Box::from_raw(grid)}; - let result = Box::new(SPCommand(servicepoint::Cp437GridCommand { - origin: servicepoint::Origin::new(x, - y), - grid: grid.0, - }.into())); + let grid = *unsafe { Box::from_raw(grid) }; + let result = Box::new(SPCommand( + servicepoint::Cp437GridCommand { + origin: servicepoint::Origin::new(x, y), + grid: grid.0, + } + .into(), + )); NonNull::from(Box::leak(result)) } @@ -419,11 +456,13 @@ pub unsafe extern "C" fn sp_command_utf8_data( ) -> NonNull { assert!(!grid.is_null()); let grid = unsafe { *Box::from_raw(grid) }; - let result = Box::new(SPCommand(servicepoint::CharGridCommand { - origin: servicepoint::Origin::new(x, - y), - grid: grid.0, - }.into())); + let result = Box::new(SPCommand( + servicepoint::CharGridCommand { + origin: servicepoint::Origin::new(x, y), + grid: grid.0, + } + .into(), + )); NonNull::from(Box::leak(result)) } @@ -460,11 +499,14 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win( Ok(compression) => compression, Err(_) => return std::ptr::null_mut(), }; - let command = SPCommand(servicepoint::BitmapCommand { - origin: servicepoint::Origin::new(x, y), - bitmap, - compression, - }.into()); + let command = SPCommand( + servicepoint::BitmapCommand { + origin: servicepoint::Origin::new(x, y), + bitmap, + compression, + } + .into(), + ); Box::leak(Box::new(command)) } diff --git a/src/connection.rs b/src/connection.rs index 6bbdbe2..9e484ae 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -2,9 +2,9 @@ //! //! prefix `sp_connection_` -use std::ffi::{c_char, CStr}; -use servicepoint::Connection; use crate::{SPCommand, SPPacket}; +use servicepoint::Connection; +use std::ffi::{c_char, CStr}; /// A connection to the display. /// @@ -36,7 +36,9 @@ pub unsafe extern "C" fn sp_connection_open( host: *const c_char, ) -> *mut SPConnection { assert!(!host.is_null()); - let host = unsafe {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::UdpConnection::open(host) { Err(_) => return std::ptr::null_mut(), Ok(value) => value, @@ -86,8 +88,8 @@ pub unsafe extern "C" fn sp_connection_send_packet( ) -> bool { assert!(!connection.is_null()); assert!(!packet.is_null()); - let packet = unsafe {Box::from_raw(packet)}; - unsafe {(*connection).0.send((*packet).0)}.is_ok() + let packet = unsafe { Box::from_raw(packet) }; + unsafe { (*connection).0.send((*packet).0) }.is_ok() } /// Sends a [SPCommand] to the display using the [SPConnection]. @@ -115,8 +117,8 @@ pub unsafe extern "C" fn sp_connection_send_command( ) -> bool { assert!(!connection.is_null()); assert!(!command.is_null()); - let command = (*unsafe {Box::from_raw(command)}).0; - unsafe{(*connection).0.send(command)}.is_ok() + let command = (*unsafe { Box::from_raw(command) }).0; + unsafe { (*connection).0.send(command) }.is_ok() } /// Closes and deallocates a [SPConnection]. @@ -134,5 +136,5 @@ pub unsafe extern "C" fn sp_connection_send_command( #[no_mangle] pub unsafe extern "C" fn sp_connection_free(connection: *mut SPConnection) { assert!(!connection.is_null()); - _ = unsafe {Box::from_raw(connection)}; + _ = unsafe { Box::from_raw(connection) }; } diff --git a/src/constants.rs b/src/constants.rs index ed4e52d..ad1e77c 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -43,6 +43,6 @@ impl TryFrom for CompressionCode { type Error = (); fn try_from(value: SPCompressionCode) -> Result { - CompressionCode::try_from(value as u16).map_err(|_|()) + CompressionCode::try_from(value as u16).map_err(|_| ()) } } diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index 712034c..89fcffc 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -71,9 +71,9 @@ pub unsafe extern "C" fn sp_cp437_grid_load( data_length: usize, ) -> *mut SPCp437Grid { assert!(data.is_null()); - let data = unsafe{std::slice::from_raw_parts(data, data_length)}; - let grid = servicepoint::Cp437Grid::load( width, height, data, ); - if let Some(grid ) = grid { + let data = unsafe { std::slice::from_raw_parts(data, data_length) }; + let grid = servicepoint::Cp437Grid::load(width, height, data); + if let Some(grid) = grid { Box::leak(Box::new(SPCp437Grid(grid))) } else { std::ptr::null_mut() @@ -101,7 +101,7 @@ pub unsafe extern "C" fn sp_cp437_grid_clone( cp437_grid: *const SPCp437Grid, ) -> NonNull { assert!(!cp437_grid.is_null()); - let result = Box::new(unsafe {(*cp437_grid).clone()}); + let result = Box::new(unsafe { (*cp437_grid).clone() }); NonNull::from(Box::leak(result)) } @@ -123,7 +123,7 @@ pub unsafe extern "C" fn sp_cp437_grid_clone( #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: *mut SPCp437Grid) { assert!(!cp437_grid.is_null()); - _ = unsafe {Box::from_raw(cp437_grid)}; + _ = unsafe { Box::from_raw(cp437_grid) }; } /// Gets the current value at the specified position. @@ -151,7 +151,7 @@ pub unsafe extern "C" fn sp_cp437_grid_get( y: usize, ) -> u8 { assert!(!cp437_grid.is_null()); - unsafe{(*cp437_grid).0.get(x, y)} + unsafe { (*cp437_grid).0.get(x, y) } } /// Sets the value of the specified position in the [SPCp437Grid]. @@ -185,7 +185,7 @@ pub unsafe extern "C" fn sp_cp437_grid_set( value: u8, ) { assert!(!cp437_grid.is_null()); - unsafe {(*cp437_grid).0.set(x, y, value)}; + unsafe { (*cp437_grid).0.set(x, y, value) }; } /// Sets the value of all cells in the [SPCp437Grid]. @@ -211,7 +211,7 @@ pub unsafe extern "C" fn sp_cp437_grid_fill( value: u8, ) { assert!(!cp437_grid.is_null()); - unsafe {(*cp437_grid).0.fill(value)}; + unsafe { (*cp437_grid).0.fill(value) }; } /// Gets the width of the [SPCp437Grid] instance. @@ -234,7 +234,7 @@ pub unsafe extern "C" fn sp_cp437_grid_width( cp437_grid: *const SPCp437Grid, ) -> usize { assert!(!cp437_grid.is_null()); - unsafe {(*cp437_grid).0.width()} + unsafe { (*cp437_grid).0.width() } } /// Gets the height of the [SPCp437Grid] instance. @@ -257,7 +257,7 @@ pub unsafe extern "C" fn sp_cp437_grid_height( cp437_grid: *const SPCp437Grid, ) -> usize { assert!(!cp437_grid.is_null()); - unsafe {(*cp437_grid).0.height()} + unsafe { (*cp437_grid).0.height() } } /// Gets an unsafe reference to the data of the [SPCp437Grid] instance. @@ -279,7 +279,7 @@ pub unsafe extern "C" fn sp_cp437_grid_height( pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref( cp437_grid: *mut SPCp437Grid, ) -> SPByteSlice { - let data = unsafe {(*cp437_grid).0.data_ref_mut()}; + let data = unsafe { (*cp437_grid).0.data_ref_mut() }; SPByteSlice { start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), length: data.len(), diff --git a/src/packet.rs b/src/packet.rs index 12afb34..fd36006 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -2,7 +2,7 @@ //! //! prefix `sp_packet_` -use std::ptr::{NonNull}; +use std::ptr::NonNull; use crate::SPCommand; @@ -31,10 +31,12 @@ pub unsafe extern "C" fn sp_packet_from_command( command: *mut SPCommand, ) -> *mut SPPacket { assert!(!command.is_null()); - let command = unsafe {*Box::from_raw(command)}; + let command = unsafe { *Box::from_raw(command) }; if let Ok(packet) = command.0.try_into() { Box::leak(Box::new(SPPacket(packet))) - } else { std::ptr::null_mut() } + } else { + std::ptr::null_mut() + } } /// Tries to load a [SPPacket] from the passed array with the specified length. @@ -59,7 +61,7 @@ pub unsafe extern "C" fn sp_packet_try_load( length: usize, ) -> *mut SPPacket { assert!(!data.is_null()); - let data = unsafe {std::slice::from_raw_parts(data, length)}; + let data = unsafe { std::slice::from_raw_parts(data, length) }; match servicepoint::Packet::try_from(data) { Err(_) => std::ptr::null_mut(), Ok(packet) => Box::into_raw(Box::new(SPPacket(packet))), @@ -105,7 +107,8 @@ pub unsafe extern "C" fn sp_packet_from_parts( let payload = if payload.is_null() { vec![] } else { - let payload = unsafe {std::slice::from_raw_parts(payload, payload_len) }; + let payload = + unsafe { std::slice::from_raw_parts(payload, payload_len) }; Vec::from(payload) }; @@ -144,7 +147,7 @@ pub unsafe extern "C" fn sp_packet_clone( packet: *const SPPacket, ) -> NonNull { assert!(!packet.is_null()); - let result = Box::new(SPPacket(unsafe {(*packet).0.clone()})); + let result = Box::new(SPPacket(unsafe { (*packet).0.clone() })); NonNull::from(Box::leak(result)) } @@ -163,5 +166,5 @@ pub unsafe extern "C" fn sp_packet_clone( #[no_mangle] pub unsafe extern "C" fn sp_packet_free(packet: *mut SPPacket) { assert!(!packet.is_null()); - _ = unsafe {Box::from_raw(packet)} + _ = unsafe { Box::from_raw(packet) } } -- 2.47.0 From d1ecd21114198737dac34f25cd48bf4aca531c26 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 10:54:47 +0200 Subject: [PATCH 05/25] wip remove newtypes --- Cargo.lock | 4 +- build.rs | 28 +-- cbindgen.toml | 8 +- example/main.c | 6 +- examples/lang_c/Makefile | 2 +- include/servicepoint.h | 426 +++++++++++++++++++++++---------------- src/bitmap.rs | 66 +++--- src/bitvec.rs | 12 +- src/brightness_grid.rs | 76 +++---- src/char_grid.rs | 81 ++++---- src/command.rs | 99 ++++----- src/connection.rs | 58 +++--- src/cp437_grid.rs | 1 + src/packet.rs | 60 +++--- 14 files changed, 497 insertions(+), 430 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 40ece4f..9641466 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "adler2" @@ -408,7 +408,7 @@ dependencies = [ [[package]] name = "servicepoint" version = "0.13.2" -source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#fe67160974d9fed542eb37e5e9a202eaf6fe00dc" +source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#aafa2bc9f91c3ae7d88607bf545d9665d50fc0db" dependencies = [ "bitvec", "bzip2", diff --git a/build.rs b/build.rs index 93bf703..0bc6e0a 100644 --- a/build.rs +++ b/build.rs @@ -6,28 +6,28 @@ use std::{env, fs::copy}; -use cbindgen::{generate_with_config, Config}; - fn main() { let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); println!("cargo::rerun-if-changed={crate_dir}"); - let config = - Config::from_file(crate_dir.clone() + "/cbindgen.toml").unwrap(); + let config = cbindgen::Config::from_file(crate_dir.clone() + "/cbindgen.toml").unwrap(); let output_dir = env::var("OUT_DIR").unwrap(); let header_file = output_dir.clone() + "/servicepoint.h"; - generate_with_config(crate_dir, config) - .unwrap() - .write_to_file(&header_file); - println!("cargo:include={output_dir}"); + if let Ok(bindings) = cbindgen::generate_with_config(crate_dir, config) { + bindings.write_to_file(&header_file); - println!("cargo::rerun-if-env-changed=SERVICEPOINT_HEADER_OUT"); - if let Ok(header_out) = env::var("SERVICEPOINT_HEADER_OUT") { - let header_copy = header_out + "/servicepoint.h"; - println!("cargo:warning=Copying header to {header_copy}"); - copy(header_file, &header_copy).unwrap(); - println!("cargo::rerun-if-changed={header_copy}"); + println!("cargo:include={output_dir}"); + + println!("cargo::rerun-if-env-changed=SERVICEPOINT_HEADER_OUT"); + if let Ok(header_out) = env::var("SERVICEPOINT_HEADER_OUT") { + let header_copy = header_out + "/servicepoint.h"; + println!("cargo:warning=Copying header to {header_copy}"); + copy(header_file, &header_copy).unwrap(); + println!("cargo::rerun-if-changed={header_copy}"); + } + } else { + eprintln!("cargo:warning=Servicepoint header could not be generated"); } } diff --git a/cbindgen.toml b/cbindgen.toml index bf2377c..3f619ed 100644 --- a/cbindgen.toml +++ b/cbindgen.toml @@ -19,11 +19,12 @@ line_endings = "LF" style = "type" usize_is_size_t = true -# this is needed because otherwise the order in the C# bindings is different on different machines +# this is needed because otherwise the order in the C bindings is different on different machines sort_by = "Name" [parse] -parse_deps = false +parse_deps = true +include = ["servicepoint"] [parse.expand] features = ["full"] @@ -32,5 +33,8 @@ features = ["full"] include = [] exclude = [] +[export.rename] +"TypedCommand" = "Command" + [enum] rename_variants = "QualifiedScreamingSnakeCase" diff --git a/example/main.c b/example/main.c index 6a4b30e..73f4726 100644 --- a/example/main.c +++ b/example/main.c @@ -2,17 +2,17 @@ #include "servicepoint.h" int main(void) { - SPConnection *connection = sp_connection_open("localhost:2342"); + UdpConnection *connection = sp_connection_open("localhost:2342"); if (connection == NULL) return 1; - SPBitmap *pixels = sp_bitmap_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT); + Bitmap *pixels = sp_bitmap_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT); if (pixels == NULL) return 1; sp_bitmap_fill(pixels, true); - SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, SP_COMPRESSION_CODE_UNCOMPRESSED); + Command *command = sp_command_bitmap_linear_win(0, 0, pixels, SP_COMPRESSION_CODE_UNCOMPRESSED); if (command == NULL) return 1; diff --git a/examples/lang_c/Makefile b/examples/lang_c/Makefile index 1be4009..aa31733 100644 --- a/examples/lang_c/Makefile +++ b/examples/lang_c/Makefile @@ -36,7 +36,7 @@ CCFLAGS := -static -Os \ -fvisibility=hidden \ -Bsymbolic \ -Wl,--exclude-libs,ALL \ - -fno-ident \ + -fno-ident #-fuse-ld=gold \ -fno-exceptions #-Wl,--icf=all \ diff --git a/include/servicepoint.h b/include/servicepoint.h index ca235ca..46fe3b8 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -86,6 +86,32 @@ enum SPCompressionCode typedef uint16_t SPCompressionCode; #endif // __cplusplus +/** + * A fixed-size 2D grid of booleans. + * + * The values are stored in packed bytes (8 values per byte) in the same order as used by the display for storing pixels. + * This means that no conversion is necessary for sending the data to the display. + * The downside is that the width has to be a multiple of 8. + * + * # Examples + * + * ```rust + * use servicepoint::Bitmap; + * let mut bitmap = Bitmap::new(8, 2); + * + * ``` + */ +typedef struct Bitmap Bitmap; + +/** + * The raw packet. + * + * Contents should probably only be used directly to use features not exposed by the library. + * + * You may want to use [`crate::Command`] or [`crate::TypedCommand`] instead. + */ +typedef struct Packet Packet; + /** * A vector of bits * @@ -99,108 +125,51 @@ typedef uint16_t SPCompressionCode; typedef struct SPBitVec SPBitVec; /** - * A grid of pixels. + * This enum contains all commands provided by the library. + * This is useful in case you want one data type for all kinds of commands without using `dyn`. * - * # Examples - * - * ```C - * Cp437Grid grid = sp_bitmap_new(8, 3); - * sp_bitmap_fill(grid, true); - * sp_bitmap_set(grid, 0, 0, false); - * sp_bitmap_free(grid); - * ``` + * Please look at the contained structs for documentation per command. */ -typedef struct SPBitmap SPBitmap; +typedef struct Command Command; /** - * A grid containing brightness values. + * A connection using the UDP protocol. * - * # Examples - * ```C - * SPConnection connection = sp_connection_open("127.0.0.1:2342"); - * if (connection == NULL) - * return 1; + * Use this when sending commands directly to the display. * - * SPBrightnessGrid grid = sp_brightness_grid_new(2, 2); - * sp_brightness_grid_set(grid, 0, 0, 0); - * sp_brightness_grid_set(grid, 1, 1, 10); - * - * SPCommand command = sp_command_char_brightness(grid); - * sp_connection_free(connection); - * ``` + * Requires the feature "`protocol_udp`" which is enabled by default. */ -typedef struct SPBrightnessGrid SPBrightnessGrid; +typedef struct UdpConnection UdpConnection; /** - * A C-wrapper for grid containing UTF-8 characters. + * A 2D grid of values. * - * As the rust [char] type is not FFI-safe, characters are passed in their UTF-32 form as 32bit unsigned integers. + * The memory layout is the one the display expects in [`crate::Command`]s. * - * The encoding is enforced in most cases by the rust standard library - * and will panic when provided with illegal characters. - * - * # Examples - * - * ```C - * CharGrid grid = sp_char_grid_new(4, 3); - * sp_char_grid_fill(grid, '?'); - * sp_char_grid_set(grid, 0, 0, '!'); - * sp_char_grid_free(grid); - * ``` + * This structure can be used with any type that implements the [Value] trait. + * You can also use the concrete type aliases provided in this crate, e.g. [`crate::CharGrid`] and [`crate::ByteGrid`]. */ -typedef struct SPCharGrid SPCharGrid; +typedef struct ValueGrid_Brightness ValueGrid_Brightness; /** - * A low-level display command. + * A 2D grid of values. * - * This struct and associated functions implement the UDP protocol for the display. + * The memory layout is the one the display expects in [`crate::Command`]s. * - * To send a [SPCommand], use a [SPConnection]. - * - * # Examples - * - * ```C - * sp_connection_send_command(connection, sp_command_clear()); - * sp_connection_send_command(connection, sp_command_brightness(5)); - * ``` - * - * [SPConnection]: [crate::SPConnection] + * This structure can be used with any type that implements the [Value] trait. + * You can also use the concrete type aliases provided in this crate, e.g. [`crate::CharGrid`] and [`crate::ByteGrid`]. */ -typedef struct SPCommand SPCommand; +typedef struct ValueGrid_char ValueGrid_char; /** - * A connection to the display. + * A 2D grid of values. * - * # Examples + * The memory layout is the one the display expects in [`crate::Command`]s. * - * ```C - * CConnection connection = sp_connection_open("172.23.42.29:2342"); - * if (connection != NULL) - * sp_connection_send_command(connection, sp_command_clear()); - * ``` + * This structure can be used with any type that implements the [Value] trait. + * You can also use the concrete type aliases provided in this crate, e.g. [`crate::CharGrid`] and [`crate::ByteGrid`]. */ -typedef struct SPConnection SPConnection; - -/** - * A C-wrapper for grid containing codepage 437 characters. - * - * The encoding is currently not enforced. - * - * # Examples - * - * ```C - * Cp437Grid grid = sp_cp437_grid_new(4, 3); - * sp_cp437_grid_fill(grid, '?'); - * sp_cp437_grid_set(grid, 0, 0, '!'); - * sp_cp437_grid_free(grid); - * ``` - */ -typedef struct SPCp437Grid SPCp437Grid; - -/** - * The raw packet - */ -typedef struct SPPacket SPPacket; +typedef struct ValueGrid_u8 ValueGrid_u8; /** * Represents a span of memory (`&mut [u8]` ) as a struct usable by C code. @@ -228,6 +197,105 @@ typedef struct { size_t length; } SPByteSlice; +/** + * A grid containing brightness values. + * + * # Examples + * + * ```rust + * # use servicepoint::*; + * let mut grid = BrightnessGrid::new(2,2); + * grid.set(0, 0, Brightness::MIN); + * grid.set(1, 1, Brightness::MIN); + * + * # let connection = FakeConnection; + * connection.send(BrightnessGridCommand { + * origin: Origin::new(3, 7), + * grid + * }).unwrap() + * ``` + */ +typedef ValueGrid_Brightness BrightnessGrid; + +/** + * A grid containing UTF-8 characters. + * + * To send a `CharGrid` to the display, use a [`crate::CharGridCommand`]. + * + * Also see [`ValueGrid`] for the non-specialized operations and examples. + * + * # Examples + * + * ```rust + * # use servicepoint::*; + * let grid = CharGrid::from("You can\nload multiline\nstrings directly"); + * assert_eq!(grid.get_row_str(1), Some("load multiline\0\0".to_string())); + * + * # let connection = FakeConnection; + * let command = CharGridCommand { origin: Origin::ZERO, grid }; + * connection.send(command).unwrap() + * ``` + */ +typedef ValueGrid_char CharGrid; + +/** + * A grid containing codepage 437 characters. + * + * The encoding is currently not enforced. + */ +typedef ValueGrid_u8 Cp437Grid; + +/** + * A C-wrapper for grid containing codepage 437 characters. + * + * The encoding is currently not enforced. + * + * # Examples + * + * ```C + * Cp437Grid grid = sp_cp437_grid_new(4, 3); + * sp_cp437_grid_fill(grid, '?'); + * sp_cp437_grid_set(grid, 0, 0, '!'); + * sp_cp437_grid_free(grid); + * ``` + */ +typedef Cp437Grid SPCp437Grid; + +/** + * A raw header. + * + * The header specifies the kind of command, the size of the payload and where to display the + * payload, where applicable. + * + * Because the meaning of most fields depend on the command, there are no speaking names for them. + * + * The contained values are in platform endian-ness and may need to be converted before sending. + */ +typedef struct { + /** + * The first two bytes specify which command this packet represents. + */ + uint16_t command_code; + /** + * First command-specific value + */ + uint16_t a; + /** + * Second command-specific value + */ + uint16_t b; + /** + * Third command-specific value + */ + uint16_t c; + /** + * Fourth command-specific value + */ + uint16_t d; +} Header; + + + #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -250,7 +318,7 @@ extern "C" { * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bitmap_free`. */ -SPBitmap *sp_bitmap_clone(const SPBitmap *bitmap); +Bitmap *sp_bitmap_clone(const Bitmap *bitmap); /** * Sets the state of all pixels in the [SPBitmap]. @@ -271,7 +339,7 @@ SPBitmap *sp_bitmap_clone(const SPBitmap *bitmap); * - `bitmap` points to a valid [SPBitmap] * - `bitmap` is not written to or read from concurrently */ -void sp_bitmap_fill(SPBitmap *bitmap, bool value); +void sp_bitmap_fill(Bitmap *bitmap, bool value); /** * Deallocates a [SPBitmap]. @@ -290,7 +358,7 @@ void sp_bitmap_fill(SPBitmap *bitmap, bool value); * * [SPCommand]: [crate::SPCommand] */ -void sp_bitmap_free(SPBitmap *bitmap); +void sp_bitmap_free(Bitmap *bitmap); /** * Gets the current value at the specified position in the [SPBitmap]. @@ -312,7 +380,7 @@ void sp_bitmap_free(SPBitmap *bitmap); * - `bitmap` points to a valid [SPBitmap] * - `bitmap` is not written to concurrently */ -bool sp_bitmap_get(const SPBitmap *bitmap, size_t x, size_t y); +bool sp_bitmap_get(const Bitmap *bitmap, size_t x, size_t y); /** * Gets the height in pixels of the [SPBitmap] instance. @@ -331,7 +399,7 @@ bool sp_bitmap_get(const SPBitmap *bitmap, size_t x, size_t y); * * - `bitmap` points to a valid [SPBitmap] */ -size_t sp_bitmap_height(const SPBitmap *bitmap); +size_t sp_bitmap_height(const Bitmap *bitmap); /** * Loads a [SPBitmap] with the specified dimensions from the provided data. @@ -362,10 +430,10 @@ size_t sp_bitmap_height(const SPBitmap *bitmap); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bitmap_free`. */ -SPBitmap *sp_bitmap_load(size_t width, - size_t height, - const uint8_t *data, - size_t data_length); +Bitmap *sp_bitmap_load(size_t width, + size_t height, + const uint8_t *data, + size_t data_length); /** * Creates a new [SPBitmap] with the specified dimensions. @@ -390,8 +458,8 @@ SPBitmap *sp_bitmap_load(size_t width, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bitmap_free`. */ -SPBitmap *sp_bitmap_new(size_t width, - size_t height); +Bitmap *sp_bitmap_new(size_t width, + size_t height); /** * Creates a new [SPBitmap] with a size matching the screen. @@ -405,7 +473,7 @@ SPBitmap *sp_bitmap_new(size_t width, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling [sp_bitmap_free]. */ -SPBitmap *sp_bitmap_new_screen_sized(void); +Bitmap *sp_bitmap_new_screen_sized(void); /** * Sets the value of the specified position in the [SPBitmap]. @@ -430,7 +498,7 @@ SPBitmap *sp_bitmap_new_screen_sized(void); * - `bitmap` points to a valid [SPBitmap] * - `bitmap` is not written to or read from concurrently */ -void sp_bitmap_set(SPBitmap *bitmap, size_t x, size_t y, bool value); +void sp_bitmap_set(Bitmap *bitmap, size_t x, size_t y, bool value); /** * Gets an unsafe reference to the data of the [SPBitmap] instance. @@ -447,7 +515,7 @@ void sp_bitmap_set(SPBitmap *bitmap, size_t x, size_t y, bool value); * - the returned memory range is never accessed after the passed [SPBitmap] has been freed * - the returned memory range is never accessed concurrently, either via the [SPBitmap] or directly */ -SPByteSlice sp_bitmap_unsafe_data_ref(SPBitmap *bitmap); +SPByteSlice sp_bitmap_unsafe_data_ref(Bitmap *bitmap); /** * Gets the width in pixels of the [SPBitmap] instance. @@ -466,7 +534,7 @@ SPByteSlice sp_bitmap_unsafe_data_ref(SPBitmap *bitmap); * * - `bitmap` points to a valid [SPBitmap] */ -size_t sp_bitmap_width(const SPBitmap *bitmap); +size_t sp_bitmap_width(const Bitmap *bitmap); /** * Clones a [SPBitVec]. @@ -699,7 +767,7 @@ SPByteSlice sp_bitvec_unsafe_data_ref(SPBitVec *bit_vec); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_brightness_grid_free`. */ -SPBrightnessGrid *sp_brightness_grid_clone(const SPBrightnessGrid *brightness_grid); +BrightnessGrid *sp_brightness_grid_clone(const BrightnessGrid *brightness_grid); /** * Sets the value of all cells in the [SPBrightnessGrid]. @@ -721,7 +789,7 @@ SPBrightnessGrid *sp_brightness_grid_clone(const SPBrightnessGrid *brightness_gr * - `brightness_grid` points to a valid [SPBrightnessGrid] * - `brightness_grid` is not written to or read from concurrently */ -void sp_brightness_grid_fill(SPBrightnessGrid *brightness_grid, uint8_t value); +void sp_brightness_grid_fill(BrightnessGrid *brightness_grid, uint8_t value); /** * Deallocates a [SPBrightnessGrid]. @@ -744,7 +812,7 @@ void sp_brightness_grid_fill(SPBrightnessGrid *brightness_grid, uint8_t value); * * [SPCommand]: [crate::SPCommand] */ -void sp_brightness_grid_free(SPBrightnessGrid *brightness_grid); +void sp_brightness_grid_free(BrightnessGrid *brightness_grid); /** * Gets the current value at the specified position. @@ -768,7 +836,7 @@ void sp_brightness_grid_free(SPBrightnessGrid *brightness_grid); * - `brightness_grid` points to a valid [SPBrightnessGrid] * - `brightness_grid` is not written to concurrently */ -uint8_t sp_brightness_grid_get(const SPBrightnessGrid *brightness_grid, +uint8_t sp_brightness_grid_get(const BrightnessGrid *brightness_grid, size_t x, size_t y); @@ -791,7 +859,7 @@ uint8_t sp_brightness_grid_get(const SPBrightnessGrid *brightness_grid, * * - `brightness_grid` points to a valid [SPBrightnessGrid] */ -size_t sp_brightness_grid_height(const SPBrightnessGrid *brightness_grid); +size_t sp_brightness_grid_height(const BrightnessGrid *brightness_grid); /** * Loads a [SPBrightnessGrid] with the specified dimensions from the provided data. @@ -812,10 +880,10 @@ size_t sp_brightness_grid_height(const SPBrightnessGrid *brightness_grid); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_brightness_grid_free`. */ -SPBrightnessGrid *sp_brightness_grid_load(size_t width, - size_t height, - const uint8_t *data, - size_t data_length); +BrightnessGrid *sp_brightness_grid_load(size_t width, + size_t height, + const uint8_t *data, + size_t data_length); /** * Creates a new [SPBrightnessGrid] with the specified dimensions. @@ -829,8 +897,8 @@ SPBrightnessGrid *sp_brightness_grid_load(size_t width, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_brightness_grid_free`. */ -SPBrightnessGrid *sp_brightness_grid_new(size_t width, - size_t height); +BrightnessGrid *sp_brightness_grid_new(size_t width, + size_t height); /** * Sets the value of the specified position in the [SPBrightnessGrid]. @@ -856,7 +924,7 @@ SPBrightnessGrid *sp_brightness_grid_new(size_t width, * - `brightness_grid` points to a valid [SPBrightnessGrid] * - `brightness_grid` is not written to or read from concurrently */ -void sp_brightness_grid_set(SPBrightnessGrid *brightness_grid, +void sp_brightness_grid_set(BrightnessGrid *brightness_grid, size_t x, size_t y, uint8_t value); @@ -882,7 +950,7 @@ void sp_brightness_grid_set(SPBrightnessGrid *brightness_grid, * - the returned memory range is never accessed after the passed [SPBrightnessGrid] has been freed * - the returned memory range is never accessed concurrently, either via the [SPBrightnessGrid] or directly */ -SPByteSlice sp_brightness_grid_unsafe_data_ref(SPBrightnessGrid *brightness_grid); +SPByteSlice sp_brightness_grid_unsafe_data_ref(BrightnessGrid *brightness_grid); /** * Gets the width of the [SPBrightnessGrid] instance. @@ -903,7 +971,7 @@ SPByteSlice sp_brightness_grid_unsafe_data_ref(SPBrightnessGrid *brightness_grid * * - `brightness_grid` points to a valid [SPBrightnessGrid] */ -size_t sp_brightness_grid_width(const SPBrightnessGrid *brightness_grid); +size_t sp_brightness_grid_width(const BrightnessGrid *brightness_grid); /** * Clones a [SPCharGrid]. @@ -923,7 +991,7 @@ size_t sp_brightness_grid_width(const SPBrightnessGrid *brightness_grid); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_char_grid_free`. */ -SPCharGrid *sp_char_grid_clone(const SPCharGrid *char_grid); +CharGrid *sp_char_grid_clone(const CharGrid *char_grid); /** * Sets the value of all cells in the [SPCharGrid]. @@ -944,7 +1012,7 @@ SPCharGrid *sp_char_grid_clone(const SPCharGrid *char_grid); * - `char_grid` points to a valid [SPCharGrid] * - `char_grid` is not written to or read from concurrently */ -void sp_char_grid_fill(SPCharGrid *char_grid, uint32_t value); +void sp_char_grid_fill(CharGrid *char_grid, uint32_t value); /** * Deallocates a [SPCharGrid]. @@ -963,7 +1031,7 @@ void sp_char_grid_fill(SPCharGrid *char_grid, uint32_t value); * * [SPCommand]: [crate::SPCommand] */ -void sp_char_grid_free(SPCharGrid *char_grid); +void sp_char_grid_free(CharGrid *char_grid); /** * Gets the current value at the specified position. @@ -985,7 +1053,7 @@ void sp_char_grid_free(SPCharGrid *char_grid); * - `char_grid` points to a valid [SPCharGrid] * - `char_grid` is not written to concurrently */ -uint32_t sp_char_grid_get(const SPCharGrid *char_grid, size_t x, size_t y); +uint32_t sp_char_grid_get(const CharGrid *char_grid, size_t x, size_t y); /** * Gets the height of the [SPCharGrid] instance. @@ -1004,7 +1072,7 @@ uint32_t sp_char_grid_get(const SPCharGrid *char_grid, size_t x, size_t y); * * - `char_grid` points to a valid [SPCharGrid] */ -size_t sp_char_grid_height(const SPCharGrid *char_grid); +size_t sp_char_grid_height(const CharGrid *char_grid); /** * Loads a [SPCharGrid] with the specified dimensions from the provided data. @@ -1026,10 +1094,10 @@ size_t sp_char_grid_height(const SPCharGrid *char_grid); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_char_grid_free`. */ -SPCharGrid *sp_char_grid_load(size_t width, - size_t height, - const uint8_t *data, - size_t data_length); +CharGrid *sp_char_grid_load(size_t width, + size_t height, + const uint8_t *data, + size_t data_length); /** * Creates a new [SPCharGrid] with the specified dimensions. @@ -1043,8 +1111,8 @@ SPCharGrid *sp_char_grid_load(size_t width, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_char_grid_free`. */ -SPCharGrid *sp_char_grid_new(size_t width, - size_t height); +CharGrid *sp_char_grid_new(size_t width, + size_t height); /** * Sets the value of the specified position in the [SPCharGrid]. @@ -1071,10 +1139,7 @@ SPCharGrid *sp_char_grid_new(size_t width, * * [SPBitVec]: [crate::SPBitVec] */ -void sp_char_grid_set(SPCharGrid *char_grid, - size_t x, - size_t y, - uint32_t value); +void sp_char_grid_set(CharGrid *char_grid, size_t x, size_t y, uint32_t value); /** * Gets the width of the [SPCharGrid] instance. @@ -1093,7 +1158,7 @@ void sp_char_grid_set(SPCharGrid *char_grid, * * - `char_grid` points to a valid [SPCharGrid] */ -size_t sp_char_grid_width(const SPCharGrid *char_grid); +size_t sp_char_grid_width(const CharGrid *char_grid); /** * Set pixel data starting at the pixel offset on screen. @@ -1122,9 +1187,9 @@ size_t sp_char_grid_width(const SPCharGrid *char_grid); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_bitmap_linear(size_t offset, - SPBitVec *bit_vec, - SPCompressionCode compression); +Command *sp_command_bitmap_linear(size_t offset, + SPBitVec *bit_vec, + SPCompressionCode compression); /** * Set pixel data according to an and-mask starting at the offset. @@ -1153,9 +1218,9 @@ SPCommand *sp_command_bitmap_linear(size_t offset, * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_bitmap_linear_and(size_t offset, - SPBitVec *bit_vec, - SPCompressionCode compression); +Command *sp_command_bitmap_linear_and(size_t offset, + SPBitVec *bit_vec, + SPCompressionCode compression); /** * Set pixel data according to an or-mask starting at the offset. @@ -1184,9 +1249,9 @@ SPCommand *sp_command_bitmap_linear_and(size_t offset, * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_bitmap_linear_or(size_t offset, - SPBitVec *bit_vec, - SPCompressionCode compression); +Command *sp_command_bitmap_linear_or(size_t offset, + SPBitVec *bit_vec, + SPCompressionCode compression); /** * Sets a window of pixels to the specified values. @@ -1210,10 +1275,10 @@ SPCommand *sp_command_bitmap_linear_or(size_t offset, * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_bitmap_linear_win(size_t x, - size_t y, - SPBitmap *bitmap, - SPCompressionCode compression); +Command *sp_command_bitmap_linear_win(size_t x, + size_t y, + Bitmap *bitmap, + SPCompressionCode compression); /** * Set pixel data according to a xor-mask starting at the offset. @@ -1242,9 +1307,9 @@ SPCommand *sp_command_bitmap_linear_win(size_t x, * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_bitmap_linear_xor(size_t offset, - SPBitVec *bit_vec, - SPCompressionCode compression); +Command *sp_command_bitmap_linear_xor(size_t offset, + SPBitVec *bit_vec, + SPCompressionCode compression); /** * Set the brightness of all tiles to the same value. @@ -1262,7 +1327,7 @@ SPCommand *sp_command_bitmap_linear_xor(size_t offset, * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_brightness(uint8_t brightness); +Command *sp_command_brightness(uint8_t brightness); /** * Set the brightness of individual tiles in a rectangular area of the display. @@ -1284,9 +1349,9 @@ SPCommand *sp_command_brightness(uint8_t brightness); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_char_brightness(size_t x, - size_t y, - SPBrightnessGrid *grid); +Command *sp_command_char_brightness(size_t x, + size_t y, + BrightnessGrid *grid); /** * Set all pixels to the off state. @@ -1308,7 +1373,7 @@ SPCommand *sp_command_char_brightness(size_t x, * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_clear(void); +Command *sp_command_clear(void); /** * Clones a [SPCommand] instance. @@ -1328,7 +1393,7 @@ SPCommand *sp_command_clear(void); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_clone(const SPCommand *command); +Command *sp_command_clone(const Command *command); /** * Show codepage 437 encoded text on the screen. @@ -1350,9 +1415,9 @@ SPCommand *sp_command_clone(const SPCommand *command); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_cp437_data(size_t x, - size_t y, - SPCp437Grid *grid); +Command *sp_command_cp437_data(size_t x, + size_t y, + SPCp437Grid *grid); /** * A yet-to-be-tested command. @@ -1366,7 +1431,7 @@ SPCommand *sp_command_cp437_data(size_t x, * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_fade_out(void); +Command *sp_command_fade_out(void); /** * Deallocates a [SPCommand]. @@ -1390,7 +1455,7 @@ SPCommand *sp_command_fade_out(void); * - `command` is not used concurrently or after this call * - `command` was not passed to another consuming function, e.g. to create a [SPPacket] */ -void sp_command_free(SPCommand *command); +void sp_command_free(Command *command); /** * Kills the udp daemon on the display, which usually results in a restart. @@ -1406,9 +1471,23 @@ void sp_command_free(SPCommand *command); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_hard_reset(void); +Command *sp_command_hard_reset(void); /** + * A low-level display command. + * + * This struct and associated functions implement the UDP protocol for the display. + * + * To send a [SPCommand], use a [SPConnection]. + * + * # Examples + * + * ```C + * sp_connection_send_command(connection, sp_command_clear()); + * sp_connection_send_command(connection, sp_command_brightness(5)); + * ``` + * + * [SPConnection]: [crate::SPConnection] * Tries to turn a [SPPacket] into a [SPCommand]. * * The packet is deallocated in the process. @@ -1429,7 +1508,7 @@ SPCommand *sp_command_hard_reset(void); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_try_from_packet(SPPacket *packet); +Command *sp_command_try_from_packet(Packet *packet); /** * Show UTF-8 encoded text on the screen. @@ -1451,9 +1530,9 @@ SPCommand *sp_command_try_from_packet(SPPacket *packet); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -SPCommand *sp_command_utf8_data(size_t x, - size_t y, - SPCharGrid *grid); +Command *sp_command_utf8_data(size_t x, + size_t y, + CharGrid *grid); /** * Closes and deallocates a [SPConnection]. @@ -1469,7 +1548,7 @@ SPCommand *sp_command_utf8_data(size_t x, * - `connection` points to a valid [SPConnection] * - `connection` is not used concurrently or after this call */ -void sp_connection_free(SPConnection *connection); +void sp_connection_free(UdpConnection *connection); /** * Creates a new instance of [SPConnection]. @@ -1487,7 +1566,7 @@ void sp_connection_free(SPConnection *connection); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_connection_free`. */ -SPConnection *sp_connection_open(const char *host); +UdpConnection *sp_connection_open(const char *host); /** * Sends a [SPCommand] to the display using the [SPConnection]. @@ -1509,8 +1588,8 @@ SPConnection *sp_connection_open(const char *host); * - `command` points to a valid instance of [SPPacket] * - `command` is not used concurrently or after this call */ -bool sp_connection_send_command(const SPConnection *connection, - SPCommand *command); +bool sp_connection_send_command(const UdpConnection *connection, + Command *command); /** * Sends a [SPPacket] to the display using the [SPConnection]. @@ -1532,8 +1611,7 @@ bool sp_connection_send_command(const SPConnection *connection, * - `packet` points to a valid instance of [SPPacket] * - `packet` is not used concurrently or after this call */ -bool sp_connection_send_packet(const SPConnection *connection, - SPPacket *packet); +bool sp_connection_send_packet(const UdpConnection *connection, Packet *packet); /** * Clones a [SPCp437Grid]. @@ -1761,7 +1839,7 @@ size_t sp_cp437_grid_width(const SPCp437Grid *cp437_grid); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_packet_free`. */ -SPPacket *sp_packet_clone(const SPPacket *packet); +Packet *sp_packet_clone(const Packet *packet); /** * Deallocates a [SPPacket]. @@ -1777,7 +1855,7 @@ SPPacket *sp_packet_clone(const SPPacket *packet); * - `packet` points to a valid [SPPacket] * - `packet` is not used concurrently or after this call */ -void sp_packet_free(SPPacket *packet); +void sp_packet_free(Packet *packet); /** * Turns a [SPCommand] into a [SPPacket]. @@ -1798,7 +1876,7 @@ void sp_packet_free(SPPacket *packet); * - the returned [SPPacket] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_packet_free`. */ -SPPacket *sp_packet_from_command(SPCommand *command); +Packet *sp_packet_from_command(Command *command); /** * Creates a raw [SPPacket] from parts. @@ -1826,13 +1904,11 @@ SPPacket *sp_packet_from_command(SPCommand *command); * - the returned [SPPacket] instance is freed in some way, either by using a consuming function or * by explicitly calling [sp_packet_free]. */ -SPPacket *sp_packet_from_parts(uint16_t command_code, - uint16_t a, - uint16_t b, - uint16_t c, - uint16_t d, - const uint8_t *payload, - size_t payload_len); +Packet *sp_packet_from_parts(Header header, + const uint8_t *payload, + size_t payload_len); + +Header sp_packet_get_header(const Packet *packet); /** * Tries to load a [SPPacket] from the passed array with the specified length. @@ -1852,8 +1928,8 @@ SPPacket *sp_packet_from_parts(uint16_t command_code, * - the returned [SPPacket] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_packet_free`. */ -SPPacket *sp_packet_try_load(const uint8_t *data, - size_t length); +Packet *sp_packet_try_load(const uint8_t *data, + size_t length); #ifdef __cplusplus } // extern "C" diff --git a/src/bitmap.rs b/src/bitmap.rs index eee5d24..9a9f59a 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -1,23 +1,23 @@ //! C functions for interacting with [SPBitmap]s //! //! prefix `sp_bitmap_` +//! +//! A grid of pixels. +//! +//! # Examples +//! +//! ```C +//! Cp437Grid grid = sp_bitmap_new(8, 3); +//! sp_bitmap_fill(grid, true); +//! sp_bitmap_set(grid, 0, 0, false); +//! sp_bitmap_free(grid); +//! ``` use servicepoint::{DataRef, Grid}; use std::ptr::NonNull; use crate::byte_slice::SPByteSlice; -/// A grid of pixels. -/// -/// # Examples -/// -/// ```C -/// Cp437Grid grid = sp_bitmap_new(8, 3); -/// sp_bitmap_fill(grid, true); -/// sp_bitmap_set(grid, 0, 0, false); -/// sp_bitmap_free(grid); -/// ``` -pub struct SPBitmap(pub(crate) servicepoint::Bitmap); /// Creates a new [SPBitmap] with the specified dimensions. /// @@ -44,9 +44,9 @@ pub struct SPBitmap(pub(crate) servicepoint::Bitmap); pub unsafe extern "C" fn sp_bitmap_new( width: usize, height: usize, -) -> *mut SPBitmap { +) -> *mut servicepoint::Bitmap { if let Some(bitmap) = servicepoint::Bitmap::new(width, height) { - Box::leak(Box::new(SPBitmap(bitmap))) + Box::leak(Box::new(bitmap)) } else { std::ptr::null_mut() } @@ -63,8 +63,8 @@ pub unsafe extern "C" fn sp_bitmap_new( /// - the returned instance is freed in some way, either by using a consuming function or /// by explicitly calling [sp_bitmap_free]. #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull { - let result = Box::new(SPBitmap(servicepoint::Bitmap::max_sized())); +pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull { + let result = Box::new(servicepoint::Bitmap::max_sized()); NonNull::from(Box::leak(result)) } @@ -101,11 +101,11 @@ pub unsafe extern "C" fn sp_bitmap_load( height: usize, data: *const u8, data_length: usize, -) -> *mut SPBitmap { +) -> *mut servicepoint::Bitmap { assert!(!data.is_null()); let data = unsafe { std::slice::from_raw_parts(data, data_length) }; if let Ok(bitmap) = servicepoint::Bitmap::load(width, height, data) { - Box::leak(Box::new(SPBitmap(bitmap))) + Box::leak(Box::new(bitmap)) } else { std::ptr::null_mut() } @@ -129,10 +129,10 @@ pub unsafe extern "C" fn sp_bitmap_load( /// by explicitly calling `sp_bitmap_free`. #[no_mangle] pub unsafe extern "C" fn sp_bitmap_clone( - bitmap: *const SPBitmap, -) -> NonNull { + bitmap: *const servicepoint::Bitmap, +) -> NonNull { assert!(!bitmap.is_null()); - let result = Box::new(SPBitmap(unsafe { (*bitmap).0.clone() })); + let result = Box::new(unsafe { (*bitmap).clone() }); NonNull::from(Box::leak(result)) } @@ -152,7 +152,7 @@ pub unsafe extern "C" fn sp_bitmap_clone( /// /// [SPCommand]: [crate::SPCommand] #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_free(bitmap: *mut SPBitmap) { +pub unsafe extern "C" fn sp_bitmap_free(bitmap: *mut servicepoint::Bitmap) { assert!(!bitmap.is_null()); _ = unsafe { Box::from_raw(bitmap) }; } @@ -177,12 +177,12 @@ pub unsafe extern "C" fn sp_bitmap_free(bitmap: *mut SPBitmap) { /// - `bitmap` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitmap_get( - bitmap: *const SPBitmap, + bitmap: *const servicepoint::Bitmap, x: usize, y: usize, ) -> bool { assert!(!bitmap.is_null()); - unsafe { (*bitmap).0.get(x, y) } + unsafe { (*bitmap).get(x, y) } } /// Sets the value of the specified position in the [SPBitmap]. @@ -208,13 +208,13 @@ pub unsafe extern "C" fn sp_bitmap_get( /// - `bitmap` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitmap_set( - bitmap: *mut SPBitmap, + bitmap: *mut servicepoint::Bitmap, x: usize, y: usize, value: bool, ) { assert!(!bitmap.is_null()); - unsafe { (*bitmap).0.set(x, y, value) }; + unsafe { (*bitmap).set(x, y, value) }; } /// Sets the state of all pixels in the [SPBitmap]. @@ -235,9 +235,9 @@ pub unsafe extern "C" fn sp_bitmap_set( /// - `bitmap` points to a valid [SPBitmap] /// - `bitmap` is not written to or read from concurrently #[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 servicepoint::Bitmap, value: bool) { assert!(!bitmap.is_null()); - unsafe { (*bitmap).0.fill(value) }; + unsafe { (*bitmap).fill(value) }; } /// Gets the width in pixels of the [SPBitmap] instance. @@ -256,9 +256,9 @@ pub unsafe extern "C" fn sp_bitmap_fill(bitmap: *mut SPBitmap, value: bool) { /// /// - `bitmap` points to a valid [SPBitmap] #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_width(bitmap: *const SPBitmap) -> usize { +pub unsafe extern "C" fn sp_bitmap_width(bitmap: *const servicepoint::Bitmap) -> usize { assert!(!bitmap.is_null()); - unsafe { (*bitmap).0.width() } + unsafe { (*bitmap).width() } } /// Gets the height in pixels of the [SPBitmap] instance. @@ -277,9 +277,9 @@ pub unsafe extern "C" fn sp_bitmap_width(bitmap: *const SPBitmap) -> usize { /// /// - `bitmap` points to a valid [SPBitmap] #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_height(bitmap: *const SPBitmap) -> usize { +pub unsafe extern "C" fn sp_bitmap_height(bitmap: *const servicepoint::Bitmap) -> usize { assert!(!bitmap.is_null()); - unsafe { (*bitmap).0.height() } + unsafe { (*bitmap).height() } } /// Gets an unsafe reference to the data of the [SPBitmap] instance. @@ -297,10 +297,10 @@ pub unsafe extern "C" fn sp_bitmap_height(bitmap: *const SPBitmap) -> usize { /// - the returned memory range is never accessed concurrently, either via the [SPBitmap] or directly #[no_mangle] pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref( - bitmap: *mut SPBitmap, + bitmap: *mut servicepoint::Bitmap, ) -> SPByteSlice { assert!(!bitmap.is_null()); - let data = unsafe { (*bitmap).0.data_ref_mut() }; + let data = unsafe { (*bitmap).data_ref_mut() }; SPByteSlice { start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), length: data.len(), diff --git a/src/bitvec.rs b/src/bitvec.rs index f17723b..676e617 100644 --- a/src/bitvec.rs +++ b/src/bitvec.rs @@ -13,15 +13,15 @@ use std::ptr::NonNull; /// sp_bitvec_set(vec, 5, true); /// sp_bitvec_free(vec); /// ``` -pub struct SPBitVec(servicepoint::BitVec); +pub struct SPBitVec(servicepoint::BitVecU8Msb0); -impl From for SPBitVec { - fn from(actual: servicepoint::BitVec) -> Self { +impl From for SPBitVec { + fn from(actual: servicepoint::BitVecU8Msb0) -> Self { Self(actual) } } -impl From for servicepoint::BitVec { +impl From for servicepoint::BitVecU8Msb0 { fn from(value: SPBitVec) -> Self { value.0 } @@ -53,7 +53,7 @@ impl Clone for SPBitVec { /// by explicitly calling `sp_bitvec_free`. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_new(size: usize) -> NonNull { - let result = Box::new(SPBitVec(servicepoint::BitVec::repeat(false, size))); + let result = Box::new(SPBitVec(servicepoint::BitVecU8Msb0::repeat(false, size))); NonNull::from(Box::leak(result)) } @@ -80,7 +80,7 @@ pub unsafe extern "C" fn sp_bitvec_load( ) -> NonNull { assert!(!data.is_null()); 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::BitVecU8Msb0::from_slice(data))); NonNull::from(Box::leak(result)) } diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index 97dce2c..e1780f2 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -1,9 +1,26 @@ //! C functions for interacting with [SPBrightnessGrid]s //! //! prefix `sp_brightness_grid_` +//! +//! +//! A grid containing brightness values. +//! +//! # Examples +//! ```C +//! SPConnection connection = sp_connection_open("127.0.0.1:2342"); +//! if (connection == NULL) +//! return 1; +//! +//! SPBrightnessGrid grid = sp_brightness_grid_new(2, 2); +//! sp_brightness_grid_set(grid, 0, 0, 0); +//! sp_brightness_grid_set(grid, 1, 1, 10); +//! +//! SPCommand command = sp_command_char_brightness(grid); +//! sp_connection_free(connection); +//! ``` use crate::SPByteSlice; -use servicepoint::{DataRef, Grid}; +use servicepoint::{BrightnessGrid, DataRef, Grid}; use std::convert::Into; use std::mem::transmute; use std::ptr::NonNull; @@ -15,23 +32,6 @@ pub const SP_BRIGHTNESS_MAX: u8 = 11; /// Count of possible brightness values pub const SP_BRIGHTNESS_LEVELS: u8 = 12; -/// A grid containing brightness values. -/// -/// # Examples -/// ```C -/// SPConnection connection = sp_connection_open("127.0.0.1:2342"); -/// if (connection == NULL) -/// return 1; -/// -/// SPBrightnessGrid grid = sp_brightness_grid_new(2, 2); -/// sp_brightness_grid_set(grid, 0, 0, 0); -/// sp_brightness_grid_set(grid, 1, 1, 10); -/// -/// SPCommand command = sp_command_char_brightness(grid); -/// sp_connection_free(connection); -/// ``` -#[derive(Clone)] -pub struct SPBrightnessGrid(pub(crate) servicepoint::BrightnessGrid); /// Creates a new [SPBrightnessGrid] with the specified dimensions. /// @@ -47,10 +47,10 @@ pub struct SPBrightnessGrid(pub(crate) servicepoint::BrightnessGrid); pub unsafe extern "C" fn sp_brightness_grid_new( width: usize, height: usize, -) -> NonNull { - let result = Box::new(SPBrightnessGrid(servicepoint::BrightnessGrid::new( +) -> NonNull { + let result = Box::new(servicepoint::BrightnessGrid::new( width, height, - ))); + )); NonNull::from(Box::leak(result)) } @@ -77,7 +77,7 @@ pub unsafe extern "C" fn sp_brightness_grid_load( height: usize, data: *const u8, data_length: usize, -) -> *mut SPBrightnessGrid { +) -> *mut BrightnessGrid { assert!(!data.is_null()); let data = unsafe { std::slice::from_raw_parts(data, data_length) }; let grid = match servicepoint::ByteGrid::load(width, height, data) { @@ -85,7 +85,7 @@ pub unsafe extern "C" fn sp_brightness_grid_load( Some(grid) => grid, }; if let Ok(grid) = servicepoint::BrightnessGrid::try_from(grid) { - Box::leak(Box::new(SPBrightnessGrid(grid))) + Box::leak(Box::new(grid)) } else { std::ptr::null_mut() } @@ -113,8 +113,8 @@ pub unsafe extern "C" fn sp_brightness_grid_load( /// by explicitly calling `sp_brightness_grid_free`. #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_clone( - brightness_grid: *const SPBrightnessGrid, -) -> NonNull { + brightness_grid: *const BrightnessGrid, +) -> NonNull { assert!(!brightness_grid.is_null()); let result = Box::new(unsafe { (*brightness_grid).clone() }); NonNull::from(Box::leak(result)) @@ -141,7 +141,7 @@ pub unsafe extern "C" fn sp_brightness_grid_clone( /// [SPCommand]: [crate::SPCommand] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_free( - brightness_grid: *mut SPBrightnessGrid, + brightness_grid: *mut BrightnessGrid, ) { assert!(!brightness_grid.is_null()); _ = unsafe { Box::from_raw(brightness_grid) }; @@ -169,12 +169,12 @@ pub unsafe extern "C" fn sp_brightness_grid_free( /// - `brightness_grid` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_get( - brightness_grid: *const SPBrightnessGrid, + brightness_grid: *const BrightnessGrid, x: usize, y: usize, ) -> u8 { assert!(!brightness_grid.is_null()); - unsafe { (*brightness_grid).0.get(x, y) }.into() + unsafe { (*brightness_grid).get(x, y) }.into() } /// Sets the value of the specified position in the [SPBrightnessGrid]. @@ -201,7 +201,7 @@ pub unsafe extern "C" fn sp_brightness_grid_get( /// - `brightness_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_set( - brightness_grid: *mut SPBrightnessGrid, + brightness_grid: *mut BrightnessGrid, x: usize, y: usize, value: u8, @@ -209,7 +209,7 @@ pub unsafe extern "C" fn sp_brightness_grid_set( assert!(!brightness_grid.is_null()); let brightness = servicepoint::Brightness::try_from(value) .expect("invalid brightness value"); - unsafe { (*brightness_grid).0.set(x, y, brightness) }; + unsafe { (*brightness_grid).set(x, y, brightness) }; } /// Sets the value of all cells in the [SPBrightnessGrid]. @@ -232,13 +232,13 @@ pub unsafe extern "C" fn sp_brightness_grid_set( /// - `brightness_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_fill( - brightness_grid: *mut SPBrightnessGrid, + brightness_grid: *mut BrightnessGrid, value: u8, ) { assert!(!brightness_grid.is_null()); let brightness = servicepoint::Brightness::try_from(value) .expect("invalid brightness value"); - unsafe { (*brightness_grid).0.fill(brightness) }; + unsafe { (*brightness_grid).fill(brightness) }; } /// Gets the width of the [SPBrightnessGrid] instance. @@ -260,10 +260,10 @@ pub unsafe extern "C" fn sp_brightness_grid_fill( /// - `brightness_grid` points to a valid [SPBrightnessGrid] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_width( - brightness_grid: *const SPBrightnessGrid, + brightness_grid: *const BrightnessGrid, ) -> usize { assert!(!brightness_grid.is_null()); - unsafe { (*brightness_grid).0.width() } + unsafe { (*brightness_grid).width() } } /// Gets the height of the [SPBrightnessGrid] instance. @@ -285,10 +285,10 @@ pub unsafe extern "C" fn sp_brightness_grid_width( /// - `brightness_grid` points to a valid [SPBrightnessGrid] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_height( - brightness_grid: *const SPBrightnessGrid, + brightness_grid: *const BrightnessGrid, ) -> usize { assert!(!brightness_grid.is_null()); - unsafe { (*brightness_grid).0.height() } + unsafe { (*brightness_grid).height() } } /// Gets an unsafe reference to the data of the [SPBrightnessGrid] instance. @@ -312,11 +312,11 @@ pub unsafe extern "C" fn sp_brightness_grid_height( /// - the returned memory range is never accessed concurrently, either via the [SPBrightnessGrid] or directly #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( - brightness_grid: *mut SPBrightnessGrid, + brightness_grid: *mut BrightnessGrid, ) -> SPByteSlice { assert!(!brightness_grid.is_null()); assert_eq!(core::mem::size_of::(), 1); - let data = unsafe { (*brightness_grid).0.data_ref_mut() }; + let data = unsafe { (*brightness_grid).data_ref_mut() }; // this assumes more about the memory layout than rust guarantees. yikes! let data: &mut [u8] = unsafe { transmute(data) }; SPByteSlice { diff --git a/src/char_grid.rs b/src/char_grid.rs index 5ed97c2..71013d5 100644 --- a/src/char_grid.rs +++ b/src/char_grid.rs @@ -1,33 +1,26 @@ //! C functions for interacting with [SPCharGrid]s //! //! prefix `sp_char_grid_` +//! +//! A C-wrapper for grid containing UTF-8 characters. +//! +//! As the rust [char] type is not FFI-safe, characters are passed in their UTF-32 form as 32bit unsigned integers. +//! +//! The encoding is enforced in most cases by the rust standard library +//! and will panic when provided with illegal characters. +//! +//! # Examples +//! +//! ```C +//! CharGrid grid = sp_char_grid_new(4, 3); +//! sp_char_grid_fill(grid, '?'); +//! sp_char_grid_set(grid, 0, 0, '!'); +//! sp_char_grid_free(grid); +//! ``` -use servicepoint::Grid; +use servicepoint::{CharGrid, Grid}; use std::ptr::NonNull; -/// A C-wrapper for grid containing UTF-8 characters. -/// -/// As the rust [char] type is not FFI-safe, characters are passed in their UTF-32 form as 32bit unsigned integers. -/// -/// The encoding is enforced in most cases by the rust standard library -/// and will panic when provided with illegal characters. -/// -/// # Examples -/// -/// ```C -/// CharGrid grid = sp_char_grid_new(4, 3); -/// sp_char_grid_fill(grid, '?'); -/// sp_char_grid_set(grid, 0, 0, '!'); -/// sp_char_grid_free(grid); -/// ``` -pub struct SPCharGrid(pub(crate) servicepoint::CharGrid); - -impl Clone for SPCharGrid { - fn clone(&self) -> Self { - SPCharGrid(self.0.clone()) - } -} - /// Creates a new [SPCharGrid] with the specified dimensions. /// /// returns: [SPCharGrid] initialized to 0. Will never return NULL. @@ -42,9 +35,8 @@ impl Clone for SPCharGrid { pub unsafe extern "C" fn sp_char_grid_new( width: usize, height: usize, -) -> NonNull { - let result = - Box::new(SPCharGrid(servicepoint::CharGrid::new(width, height))); +) -> NonNull { + let result = Box::new(CharGrid::new(width, height)); NonNull::from(Box::leak(result)) } @@ -72,13 +64,14 @@ pub unsafe extern "C" fn sp_char_grid_load( height: usize, data: *const u8, data_length: usize, -) -> NonNull { +) -> NonNull { assert!(data.is_null()); let data = unsafe { std::slice::from_raw_parts(data, data_length) }; - let result = Box::new(SPCharGrid( - servicepoint::CharGrid::load_utf8(width, height, data.to_vec()) + // TODO remove unwrap + let result = Box::new( + CharGrid::load_utf8(width, height, data.to_vec()) .unwrap(), - )); + ); NonNull::from(Box::leak(result)) } @@ -100,8 +93,8 @@ pub unsafe extern "C" fn sp_char_grid_load( /// by explicitly calling `sp_char_grid_free`. #[no_mangle] pub unsafe extern "C" fn sp_char_grid_clone( - char_grid: *const SPCharGrid, -) -> NonNull { + char_grid: *const CharGrid, +) -> NonNull { assert!(!char_grid.is_null()); let result = Box::new(unsafe { (*char_grid).clone() }); NonNull::from(Box::leak(result)) @@ -123,7 +116,7 @@ pub unsafe extern "C" fn sp_char_grid_clone( /// /// [SPCommand]: [crate::SPCommand] #[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 CharGrid) { assert!(!char_grid.is_null()); _ = unsafe { Box::from_raw(char_grid) }; } @@ -148,12 +141,12 @@ pub unsafe extern "C" fn sp_char_grid_free(char_grid: *mut SPCharGrid) { /// - `char_grid` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_char_grid_get( - char_grid: *const SPCharGrid, + char_grid: *const CharGrid, x: usize, y: usize, ) -> u32 { assert!(!char_grid.is_null()); - unsafe { (*char_grid).0.get(x, y) as u32 } + unsafe { (*char_grid).get(x, y) as u32 } } /// Sets the value of the specified position in the [SPCharGrid]. @@ -181,13 +174,13 @@ pub unsafe extern "C" fn sp_char_grid_get( /// [SPBitVec]: [crate::SPBitVec] #[no_mangle] pub unsafe extern "C" fn sp_char_grid_set( - char_grid: *mut SPCharGrid, + char_grid: *mut CharGrid, x: usize, y: usize, value: u32, ) { assert!(!char_grid.is_null()); - unsafe { (*char_grid).0.set(x, y, char::from_u32(value).unwrap()) }; + unsafe { (*char_grid).set(x, y, char::from_u32(value).unwrap()) }; } /// Sets the value of all cells in the [SPCharGrid]. @@ -209,11 +202,11 @@ pub unsafe extern "C" fn sp_char_grid_set( /// - `char_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_char_grid_fill( - char_grid: *mut SPCharGrid, + char_grid: *mut CharGrid, value: u32, ) { assert!(!char_grid.is_null()); - unsafe { (*char_grid).0.fill(char::from_u32(value).unwrap()) }; + unsafe { (*char_grid).fill(char::from_u32(value).unwrap()) }; } /// Gets the width of the [SPCharGrid] instance. @@ -233,10 +226,10 @@ pub unsafe extern "C" fn sp_char_grid_fill( /// - `char_grid` points to a valid [SPCharGrid] #[no_mangle] pub unsafe extern "C" fn sp_char_grid_width( - char_grid: *const SPCharGrid, + char_grid: *const CharGrid, ) -> usize { assert!(!char_grid.is_null()); - unsafe { (*char_grid).0.width() } + unsafe { (*char_grid).width() } } /// Gets the height of the [SPCharGrid] instance. @@ -256,8 +249,8 @@ pub unsafe extern "C" fn sp_char_grid_width( /// - `char_grid` points to a valid [SPCharGrid] #[no_mangle] pub unsafe extern "C" fn sp_char_grid_height( - char_grid: *const SPCharGrid, + char_grid: *const CharGrid, ) -> usize { assert!(!char_grid.is_null()); - unsafe { (*char_grid).0.height() } + unsafe { (*char_grid).height() } } diff --git a/src/command.rs b/src/command.rs index 8bfaee3..3e63eae 100644 --- a/src/command.rs +++ b/src/command.rs @@ -2,11 +2,8 @@ //! //! prefix `sp_command_` -use crate::{ - SPBitVec, SPBitmap, SPBrightnessGrid, SPCharGrid, SPCompressionCode, - SPCp437Grid, SPPacket, -}; -use servicepoint::{BinaryOperation, GlobalBrightnessCommand}; +use crate::{SPBitVec, SPCompressionCode, SPCp437Grid}; +use servicepoint::{BinaryOperation, BrightnessGrid, CharGrid, GlobalBrightnessCommand, Packet, TypedCommand}; use std::ptr::NonNull; /// A low-level display command. @@ -23,13 +20,7 @@ use std::ptr::NonNull; /// ``` /// /// [SPConnection]: [crate::SPConnection] -pub struct SPCommand(pub(crate) servicepoint::TypedCommand); -impl Clone for SPCommand { - fn clone(&self) -> Self { - SPCommand(self.0.clone()) - } -} /// Tries to turn a [SPPacket] into a [SPCommand]. /// @@ -52,12 +43,12 @@ impl Clone for SPCommand { /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_try_from_packet( - packet: *mut SPPacket, -) -> *mut SPCommand { + packet: *mut Packet, +) -> *mut TypedCommand { let packet = *unsafe { Box::from_raw(packet) }; - match servicepoint::TypedCommand::try_from(packet.0) { + match servicepoint::TypedCommand::try_from(packet) { Err(_) => std::ptr::null_mut(), - Ok(command) => Box::into_raw(Box::new(SPCommand(command))), + Ok(command) => Box::into_raw(Box::new(command)), } } @@ -79,8 +70,8 @@ pub unsafe extern "C" fn sp_command_try_from_packet( /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_clone( - command: *const SPCommand, -) -> NonNull { + command: *const TypedCommand, +) -> NonNull { assert!(!command.is_null()); let result = Box::new(unsafe { (*command).clone() }); NonNull::from(Box::leak(result)) @@ -105,8 +96,8 @@ pub unsafe extern "C" fn sp_command_clone( /// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] -pub unsafe extern "C" fn sp_command_clear() -> NonNull { - let result = Box::new(SPCommand(servicepoint::ClearCommand.into())); +pub unsafe extern "C" fn sp_command_clear() -> NonNull { + let result = Box::new(servicepoint::ClearCommand.into()); NonNull::from(Box::leak(result)) } @@ -123,8 +114,8 @@ pub unsafe extern "C" fn sp_command_clear() -> NonNull { /// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] -pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull { - let result = Box::new(SPCommand(servicepoint::HardResetCommand.into())); +pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull { + let result = Box::new(servicepoint::HardResetCommand.into()); NonNull::from(Box::leak(result)) } @@ -139,8 +130,8 @@ pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull { /// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] -pub unsafe extern "C" fn sp_command_fade_out() -> NonNull { - let result = Box::new(SPCommand(servicepoint::FadeOutCommand.into())); +pub unsafe extern "C" fn sp_command_fade_out() -> NonNull { + let result = Box::new(servicepoint::FadeOutCommand.into()); NonNull::from(Box::leak(result)) } @@ -161,11 +152,11 @@ pub unsafe extern "C" fn sp_command_fade_out() -> NonNull { #[no_mangle] pub unsafe extern "C" fn sp_command_brightness( brightness: u8, -) -> NonNull { +) -> NonNull { let brightness = servicepoint::Brightness::try_from(brightness) .expect("invalid brightness"); let result = - Box::new(SPCommand(GlobalBrightnessCommand::from(brightness).into())); + Box::new(GlobalBrightnessCommand::from(brightness).into()); NonNull::from(Box::leak(result)) } @@ -191,17 +182,17 @@ pub unsafe extern "C" fn sp_command_brightness( pub unsafe extern "C" fn sp_command_char_brightness( x: usize, y: usize, - grid: *mut SPBrightnessGrid, -) -> NonNull { + grid: *mut BrightnessGrid, +) -> NonNull { assert!(!grid.is_null()); - let byte_grid = unsafe { *Box::from_raw(grid) }; - let result = Box::new(SPCommand( + let grid = unsafe { *Box::from_raw(grid) }; + let result = Box::new( servicepoint::BrightnessGridCommand { origin: servicepoint::Origin::new(x, y), - grid: byte_grid.0, + grid, } .into(), - )); + ); NonNull::from(Box::leak(result)) } @@ -235,7 +226,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear( offset: usize, bit_vec: *mut SPBitVec, compression: SPCompressionCode, -) -> *mut SPCommand { +) -> *mut TypedCommand { unsafe { sp_command_bitmap_linear_internal( offset, @@ -276,7 +267,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and( offset: usize, bit_vec: *mut SPBitVec, compression: SPCompressionCode, -) -> *mut SPCommand { +) -> *mut TypedCommand { unsafe { sp_command_bitmap_linear_internal( offset, @@ -317,7 +308,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or( offset: usize, bit_vec: *mut SPBitVec, compression: SPCompressionCode, -) -> *mut SPCommand { +) -> *mut TypedCommand { unsafe { sp_command_bitmap_linear_internal( offset, @@ -358,7 +349,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor( offset: usize, bit_vec: *mut SPBitVec, compression: SPCompressionCode, -) -> *mut SPCommand { +) -> *mut TypedCommand { unsafe { sp_command_bitmap_linear_internal( offset, @@ -375,22 +366,20 @@ unsafe fn sp_command_bitmap_linear_internal( bit_vec: *mut SPBitVec, compression: SPCompressionCode, operation: BinaryOperation, -) -> *mut SPCommand { +) -> *mut TypedCommand { assert!(!bit_vec.is_null()); let bit_vec = unsafe { *Box::from_raw(bit_vec) }; let compression = match compression.try_into() { Ok(compression) => compression, Err(_) => return std::ptr::null_mut(), }; - let command = SPCommand( - servicepoint::BitVecCommand { + let command = servicepoint::BitVecCommand { offset, operation, bitvec: bit_vec.into(), compression, } - .into(), - ); + .into(); Box::leak(Box::new(command)) } @@ -417,16 +406,16 @@ pub unsafe extern "C" fn sp_command_cp437_data( x: usize, y: usize, grid: *mut SPCp437Grid, -) -> NonNull { +) -> NonNull { assert!(!grid.is_null()); let grid = *unsafe { Box::from_raw(grid) }; - let result = Box::new(SPCommand( + let result = Box::new( servicepoint::Cp437GridCommand { origin: servicepoint::Origin::new(x, y), grid: grid.0, } .into(), - )); + ); NonNull::from(Box::leak(result)) } @@ -452,17 +441,17 @@ pub unsafe extern "C" fn sp_command_cp437_data( pub unsafe extern "C" fn sp_command_utf8_data( x: usize, y: usize, - grid: *mut SPCharGrid, -) -> NonNull { + grid: *mut CharGrid, +) -> NonNull { assert!(!grid.is_null()); let grid = unsafe { *Box::from_raw(grid) }; - let result = Box::new(SPCommand( + let result = Box::new( servicepoint::CharGridCommand { origin: servicepoint::Origin::new(x, y), - grid: grid.0, + grid, } .into(), - )); + ); NonNull::from(Box::leak(result)) } @@ -490,23 +479,21 @@ pub unsafe extern "C" fn sp_command_utf8_data( pub unsafe extern "C" fn sp_command_bitmap_linear_win( x: usize, y: usize, - bitmap: *mut SPBitmap, + bitmap: *mut servicepoint::Bitmap, compression: SPCompressionCode, -) -> *mut SPCommand { +) -> *mut TypedCommand { assert!(!bitmap.is_null()); - let bitmap = unsafe { *Box::from_raw(bitmap) }.0; + let bitmap = unsafe { *Box::from_raw(bitmap) }; let compression = match compression.try_into() { Ok(compression) => compression, Err(_) => return std::ptr::null_mut(), }; - let command = SPCommand( - servicepoint::BitmapCommand { + let command = servicepoint::BitmapCommand { origin: servicepoint::Origin::new(x, y), bitmap, compression, } - .into(), - ); + .into(); Box::leak(Box::new(command)) } @@ -531,7 +518,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win( /// - `command` is not used concurrently or after this call /// - `command` was not passed to another consuming function, e.g. to create a [SPPacket] #[no_mangle] -pub unsafe extern "C" fn sp_command_free(command: *mut SPCommand) { +pub unsafe extern "C" fn sp_command_free(command: *mut TypedCommand) { assert!(!command.is_null()); _ = unsafe { Box::from_raw(command) }; } diff --git a/src/connection.rs b/src/connection.rs index 9e484ae..9458727 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,22 +1,20 @@ //! C functions for interacting with [SPConnection]s //! //! prefix `sp_connection_` +//! +//! 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()); +//! ``` -use crate::{SPCommand, SPPacket}; -use servicepoint::Connection; +use servicepoint::{Connection, Packet, TypedCommand, UdpConnection}; use std::ffi::{c_char, CStr}; -/// 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()); -/// ``` -pub struct SPConnection(pub(crate) servicepoint::UdpConnection); - /// Creates a new instance of [SPConnection]. /// /// returns: NULL if connection fails, or connected instance @@ -34,19 +32,31 @@ pub struct SPConnection(pub(crate) servicepoint::UdpConnection); #[no_mangle] pub unsafe extern "C" fn sp_connection_open( host: *const c_char, -) -> *mut SPConnection { +) -> *mut UdpConnection { assert!(!host.is_null()); let host = unsafe { CStr::from_ptr(host) } .to_str() .expect("Bad encoding"); - let connection = match servicepoint::UdpConnection::open(host) { + let connection = match UdpConnection::open(host) { Err(_) => return std::ptr::null_mut(), Ok(value) => value, }; - Box::into_raw(Box::new(SPConnection(connection))) + Box::into_raw(Box::new(connection)) } +//#[no_mangle] +//pub unsafe extern "C" fn sp_connection_open_ipv4( +// host: SocketAddrV4, +//) -> *mut SPConnection { +// let connection = match servicepoint::UdpConnection::open(host) { +// Err(_) => return std::ptr::null_mut(), +// Ok(value) => value, +// }; +// +// Box::into_raw(Box::new(SPConnection(connection))) +//} + // /// Creates a new instance of [SPUdpConnection] for testing that does not actually send anything. // /// // /// returns: a new instance. Will never return NULL. @@ -83,13 +93,13 @@ pub unsafe extern "C" fn sp_connection_open( /// - `packet` is not used concurrently or after this call #[no_mangle] pub unsafe extern "C" fn sp_connection_send_packet( - connection: *const SPConnection, - packet: *mut SPPacket, + connection: *const UdpConnection, + packet: *mut Packet, ) -> bool { assert!(!connection.is_null()); assert!(!packet.is_null()); let packet = unsafe { Box::from_raw(packet) }; - unsafe { (*connection).0.send((*packet).0) }.is_ok() + unsafe { (*connection).send(*packet) }.is_ok() } /// Sends a [SPCommand] to the display using the [SPConnection]. @@ -112,13 +122,13 @@ pub unsafe extern "C" fn sp_connection_send_packet( /// - `command` is not used concurrently or after this call #[no_mangle] pub unsafe extern "C" fn sp_connection_send_command( - connection: *const SPConnection, - command: *mut SPCommand, + connection: *const UdpConnection, + command: *mut TypedCommand, ) -> bool { assert!(!connection.is_null()); assert!(!command.is_null()); - let command = (*unsafe { Box::from_raw(command) }).0; - unsafe { (*connection).0.send(command) }.is_ok() + let command = *unsafe { Box::from_raw(command) }; + unsafe { (*connection).send(command) }.is_ok() } /// Closes and deallocates a [SPConnection]. @@ -134,7 +144,7 @@ pub unsafe extern "C" fn sp_connection_send_command( /// - `connection` points to a valid [SPConnection] /// - `connection` is not used concurrently or after this call #[no_mangle] -pub unsafe extern "C" fn sp_connection_free(connection: *mut SPConnection) { +pub unsafe extern "C" fn sp_connection_free(connection: *mut UdpConnection) { assert!(!connection.is_null()); _ = unsafe { Box::from_raw(connection) }; } diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index 89fcffc..e251d6f 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -18,6 +18,7 @@ use std::ptr::NonNull; /// sp_cp437_grid_set(grid, 0, 0, '!'); /// sp_cp437_grid_free(grid); /// ``` +#[repr(transparent)] pub struct SPCp437Grid(pub(crate) servicepoint::Cp437Grid); impl Clone for SPCp437Grid { diff --git a/src/packet.rs b/src/packet.rs index fd36006..199ce72 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,13 +1,12 @@ //! C functions for interacting with [SPPacket]s //! //! prefix `sp_packet_` +//! +//! +//! The raw packet use std::ptr::NonNull; - -use crate::SPCommand; - -/// The raw packet -pub struct SPPacket(pub(crate) servicepoint::Packet); +use servicepoint::{Header, Packet, TypedCommand}; /// Turns a [SPCommand] into a [SPPacket]. /// The [SPCommand] gets consumed. @@ -28,12 +27,12 @@ pub struct SPPacket(pub(crate) servicepoint::Packet); /// by explicitly calling `sp_packet_free`. #[no_mangle] pub unsafe extern "C" fn sp_packet_from_command( - command: *mut SPCommand, -) -> *mut SPPacket { + command: *mut TypedCommand, +) -> *mut Packet { assert!(!command.is_null()); let command = unsafe { *Box::from_raw(command) }; - if let Ok(packet) = command.0.try_into() { - Box::leak(Box::new(SPPacket(packet))) + if let Ok(packet) = command.try_into() { + Box::leak(Box::new(packet)) } else { std::ptr::null_mut() } @@ -59,12 +58,12 @@ pub unsafe extern "C" fn sp_packet_from_command( pub unsafe extern "C" fn sp_packet_try_load( data: *const u8, length: usize, -) -> *mut SPPacket { +) -> *mut Packet { assert!(!data.is_null()); let data = unsafe { std::slice::from_raw_parts(data, length) }; match servicepoint::Packet::try_from(data) { Err(_) => std::ptr::null_mut(), - Ok(packet) => Box::into_raw(Box::new(SPPacket(packet))), + Ok(packet) => Box::into_raw(Box::new(packet)), } } @@ -94,14 +93,10 @@ pub unsafe extern "C" fn sp_packet_try_load( /// by explicitly calling [sp_packet_free]. #[no_mangle] pub unsafe extern "C" fn sp_packet_from_parts( - command_code: u16, - a: u16, - b: u16, - c: u16, - d: u16, + header: Header, payload: *const u8, payload_len: usize, -) -> NonNull { +) -> NonNull { assert_eq!(payload.is_null(), payload_len == 0); let payload = if payload.is_null() { @@ -112,18 +107,19 @@ pub unsafe extern "C" fn sp_packet_from_parts( Vec::from(payload) }; - let packet = servicepoint::Packet { - header: servicepoint::Header { - command_code, - a, - b, - c, - d, - }, + let packet = Box::new(Packet { + header, payload, - }; - let result = Box::new(SPPacket(packet)); - NonNull::from(Box::leak(result)) + }); + NonNull::from(Box::leak(packet)) +} + +#[no_mangle] +pub unsafe extern "C" fn sp_packet_get_header( + packet: *const Packet, +) -> Header { + assert!(!packet.is_null()); + unsafe { (*packet).header } } /// Clones a [SPPacket]. @@ -144,10 +140,10 @@ pub unsafe extern "C" fn sp_packet_from_parts( /// by explicitly calling `sp_packet_free`. #[no_mangle] pub unsafe extern "C" fn sp_packet_clone( - packet: *const SPPacket, -) -> NonNull { + packet: *const Packet, +) -> NonNull { assert!(!packet.is_null()); - let result = Box::new(SPPacket(unsafe { (*packet).0.clone() })); + let result = Box::new(unsafe { (*packet).clone() }); NonNull::from(Box::leak(result)) } @@ -164,7 +160,7 @@ pub unsafe extern "C" fn sp_packet_clone( /// - `packet` points to a valid [SPPacket] /// - `packet` is not used concurrently or after this call #[no_mangle] -pub unsafe extern "C" fn sp_packet_free(packet: *mut SPPacket) { +pub unsafe extern "C" fn sp_packet_free(packet: *mut Packet) { assert!(!packet.is_null()); _ = unsafe { Box::from_raw(packet) } } -- 2.47.0 From 5120e220ecfcb0a85a9a1f8a91a1a266ea630329 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 12:05:19 +0200 Subject: [PATCH 06/25] functions for manipulating packets --- Cargo.lock | 2 +- example/main.c | 7 ++++++- include/servicepoint.h | 8 +++++++- src/bitmap.rs | 23 +++++++++++++---------- src/bitvec.rs | 6 +----- src/brightness_grid.rs | 7 ++----- src/byte_slice.rs | 19 +++++++++++++++++++ src/cp437_grid.rs | 6 +----- src/packet.rs | 40 +++++++++++++++++++++++++++++++--------- 9 files changed, 81 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9641466..c0b11c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -408,7 +408,7 @@ dependencies = [ [[package]] name = "servicepoint" version = "0.13.2" -source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#aafa2bc9f91c3ae7d88607bf545d9665d50fc0db" +source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#971bee5065139f220022e8108cfaa9c263b8a8a0" dependencies = [ "bitvec", "bzip2", diff --git a/example/main.c b/example/main.c index 73f4726..388218e 100644 --- a/example/main.c +++ b/example/main.c @@ -16,7 +16,12 @@ int main(void) { if (command == NULL) return 1; - sp_connection_send_command(connection, command); + Packet *packet = sp_packet_from_command(command); + + Header *header = sp_packet_get_header(packet); + printf("[%d, %d, %d, %d, %d]\n", header->command_code, header->a, header->b, header->c, header->d); + + sp_connection_send_packet(connection, packet); sp_connection_free(connection); return 0; diff --git a/include/servicepoint.h b/include/servicepoint.h index 46fe3b8..1de6cc5 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -1908,7 +1908,11 @@ Packet *sp_packet_from_parts(Header header, const uint8_t *payload, size_t payload_len); -Header sp_packet_get_header(const Packet *packet); +Header *sp_packet_get_header(Packet *packet); + +SPByteSlice sp_packet_get_payload(Packet *packet); + +void sp_packet_set_payload(Packet *packet, SPByteSlice data); /** * Tries to load a [SPPacket] from the passed array with the specified length. @@ -1931,6 +1935,8 @@ Header sp_packet_get_header(const Packet *packet); Packet *sp_packet_try_load(const uint8_t *data, size_t length); +void sp_packet_write_to(const Packet *packet, SPByteSlice buffer); + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/src/bitmap.rs b/src/bitmap.rs index 9a9f59a..1f6327f 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -18,7 +18,6 @@ use std::ptr::NonNull; use crate::byte_slice::SPByteSlice; - /// Creates a new [SPBitmap] with the specified dimensions. /// /// # Arguments @@ -63,7 +62,8 @@ pub unsafe extern "C" fn sp_bitmap_new( /// - the returned instance is freed in some way, either by using a consuming function or /// by explicitly calling [sp_bitmap_free]. #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull { +pub unsafe extern "C" fn sp_bitmap_new_screen_sized( +) -> NonNull { let result = Box::new(servicepoint::Bitmap::max_sized()); NonNull::from(Box::leak(result)) } @@ -235,7 +235,10 @@ pub unsafe extern "C" fn sp_bitmap_set( /// - `bitmap` points to a valid [SPBitmap] /// - `bitmap` is not written to or read from concurrently #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_fill(bitmap: *mut servicepoint::Bitmap, value: bool) { +pub unsafe extern "C" fn sp_bitmap_fill( + bitmap: *mut servicepoint::Bitmap, + value: bool, +) { assert!(!bitmap.is_null()); unsafe { (*bitmap).fill(value) }; } @@ -256,7 +259,9 @@ pub unsafe extern "C" fn sp_bitmap_fill(bitmap: *mut servicepoint::Bitmap, value /// /// - `bitmap` points to a valid [SPBitmap] #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_width(bitmap: *const servicepoint::Bitmap) -> usize { +pub unsafe extern "C" fn sp_bitmap_width( + bitmap: *const servicepoint::Bitmap, +) -> usize { assert!(!bitmap.is_null()); unsafe { (*bitmap).width() } } @@ -277,7 +282,9 @@ pub unsafe extern "C" fn sp_bitmap_width(bitmap: *const servicepoint::Bitmap) -> /// /// - `bitmap` points to a valid [SPBitmap] #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_height(bitmap: *const servicepoint::Bitmap) -> usize { +pub unsafe extern "C" fn sp_bitmap_height( + bitmap: *const servicepoint::Bitmap, +) -> usize { assert!(!bitmap.is_null()); unsafe { (*bitmap).height() } } @@ -300,9 +307,5 @@ pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref( bitmap: *mut servicepoint::Bitmap, ) -> SPByteSlice { assert!(!bitmap.is_null()); - let data = unsafe { (*bitmap).data_ref_mut() }; - SPByteSlice { - start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), - length: data.len(), - } + unsafe { SPByteSlice::from_slice((*bitmap).data_ref_mut()) } } diff --git a/src/bitvec.rs b/src/bitvec.rs index 676e617..104ca27 100644 --- a/src/bitvec.rs +++ b/src/bitvec.rs @@ -275,9 +275,5 @@ pub unsafe extern "C" fn sp_bitvec_unsafe_data_ref( bit_vec: *mut SPBitVec, ) -> SPByteSlice { assert!(!bit_vec.is_null()); - let data = unsafe { (*bit_vec).0.as_raw_mut_slice() }; - SPByteSlice { - start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), - length: data.len(), - } + unsafe { SPByteSlice::from_slice((*bit_vec).0.as_raw_mut_slice() ) } } diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index e1780f2..4620a7d 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -318,9 +318,6 @@ pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( assert_eq!(core::mem::size_of::(), 1); let data = unsafe { (*brightness_grid).data_ref_mut() }; // this assumes more about the memory layout than rust guarantees. yikes! - let data: &mut [u8] = unsafe { transmute(data) }; - SPByteSlice { - start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), - length: data.len(), - } + unsafe { SPByteSlice::from_slice(transmute(data)) } + } diff --git a/src/byte_slice.rs b/src/byte_slice.rs index 678a5d7..6ac4df3 100644 --- a/src/byte_slice.rs +++ b/src/byte_slice.rs @@ -22,3 +22,22 @@ pub struct SPByteSlice { /// The amount of memory in bytes pub length: usize, } + +impl SPByteSlice { + pub(crate) unsafe fn as_slice(&self) -> &[u8] { + unsafe { std::slice::from_raw_parts(self.start.as_ptr(), self.length) } + } + + pub(crate) unsafe fn as_slice_mut(&mut self) -> &mut [u8] { + unsafe { + std::slice::from_raw_parts_mut(self.start.as_ptr(), self.length) + } + } + + pub(crate) unsafe fn from_slice(slice: &mut [u8]) -> Self { + Self { + start: NonNull::new(slice.as_mut_ptr()).unwrap(), + length: slice.len(), + } + } +} diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index e251d6f..eeb63eb 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -280,9 +280,5 @@ pub unsafe extern "C" fn sp_cp437_grid_height( pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref( cp437_grid: *mut SPCp437Grid, ) -> SPByteSlice { - let data = unsafe { (*cp437_grid).0.data_ref_mut() }; - SPByteSlice { - start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), - length: data.len(), - } + unsafe {SPByteSlice::from_slice((*cp437_grid).0.data_ref_mut()) } } diff --git a/src/packet.rs b/src/packet.rs index 199ce72..71bbbae 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -5,8 +5,9 @@ //! //! The raw packet -use std::ptr::NonNull; +use crate::SPByteSlice; use servicepoint::{Header, Packet, TypedCommand}; +use std::ptr::NonNull; /// Turns a [SPCommand] into a [SPPacket]. /// The [SPCommand] gets consumed. @@ -107,19 +108,40 @@ pub unsafe extern "C" fn sp_packet_from_parts( Vec::from(payload) }; - let packet = Box::new(Packet { - header, - payload, - }); + let packet = Box::new(Packet { header, payload }); NonNull::from(Box::leak(packet)) } #[no_mangle] -pub unsafe extern "C" fn sp_packet_get_header( - packet: *const Packet, -) -> Header { +pub unsafe extern "C" fn sp_packet_get_header(packet: *mut Packet) -> *mut Header { assert!(!packet.is_null()); - unsafe { (*packet).header } + &mut unsafe { (*packet).header } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_packet_get_payload(packet: *mut Packet) -> SPByteSlice { + assert!(!packet.is_null()); + unsafe { SPByteSlice::from_slice(&mut *(*packet).payload) } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_packet_set_payload(packet: *mut Packet, data: SPByteSlice) { + assert!(!packet.is_null()); + unsafe { + (*packet).payload = data.as_slice().to_vec() + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_packet_write_to( + packet: *const Packet, + mut buffer: SPByteSlice, +) { + assert!(!packet.is_null()); + + unsafe { + (*packet).serialize_to(buffer.as_slice_mut()); + } } /// Clones a [SPPacket]. -- 2.47.0 From 35cb42df48f2cb895d252f364c7ae5d692519425 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 12:08:49 +0200 Subject: [PATCH 07/25] wip remove newtypes --- include/servicepoint.h | 46 ++++++++----------------- src/command.rs | 8 ++--- src/cp437_grid.rs | 78 +++++++++++++++++++----------------------- 3 files changed, 54 insertions(+), 78 deletions(-) diff --git a/include/servicepoint.h b/include/servicepoint.h index 1de6cc5..691fffe 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -245,22 +245,6 @@ typedef ValueGrid_char CharGrid; */ typedef ValueGrid_u8 Cp437Grid; -/** - * A C-wrapper for grid containing codepage 437 characters. - * - * The encoding is currently not enforced. - * - * # Examples - * - * ```C - * Cp437Grid grid = sp_cp437_grid_new(4, 3); - * sp_cp437_grid_fill(grid, '?'); - * sp_cp437_grid_set(grid, 0, 0, '!'); - * sp_cp437_grid_free(grid); - * ``` - */ -typedef Cp437Grid SPCp437Grid; - /** * A raw header. * @@ -1417,7 +1401,7 @@ Command *sp_command_clone(const Command *command); */ Command *sp_command_cp437_data(size_t x, size_t y, - SPCp437Grid *grid); + Cp437Grid *grid); /** * A yet-to-be-tested command. @@ -1631,7 +1615,7 @@ bool sp_connection_send_packet(const UdpConnection *connection, Packet *packet); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_cp437_grid_free`. */ -SPCp437Grid *sp_cp437_grid_clone(const SPCp437Grid *cp437_grid); +Cp437Grid *sp_cp437_grid_clone(const Cp437Grid *cp437_grid); /** * Sets the value of all cells in the [SPCp437Grid]. @@ -1652,7 +1636,7 @@ SPCp437Grid *sp_cp437_grid_clone(const SPCp437Grid *cp437_grid); * - `cp437_grid` points to a valid [SPCp437Grid] * - `cp437_grid` is not written to or read from concurrently */ -void sp_cp437_grid_fill(SPCp437Grid *cp437_grid, uint8_t value); +void sp_cp437_grid_fill(Cp437Grid *cp437_grid, uint8_t value); /** * Deallocates a [SPCp437Grid]. @@ -1671,7 +1655,7 @@ void sp_cp437_grid_fill(SPCp437Grid *cp437_grid, uint8_t value); * * [SPCommand]: [crate::SPCommand] */ -void sp_cp437_grid_free(SPCp437Grid *cp437_grid); +void sp_cp437_grid_free(Cp437Grid *cp437_grid); /** * Gets the current value at the specified position. @@ -1693,7 +1677,7 @@ void sp_cp437_grid_free(SPCp437Grid *cp437_grid); * - `cp437_grid` points to a valid [SPCp437Grid] * - `cp437_grid` is not written to concurrently */ -uint8_t sp_cp437_grid_get(const SPCp437Grid *cp437_grid, size_t x, size_t y); +uint8_t sp_cp437_grid_get(const Cp437Grid *cp437_grid, size_t x, size_t y); /** * Gets the height of the [SPCp437Grid] instance. @@ -1712,7 +1696,7 @@ uint8_t sp_cp437_grid_get(const SPCp437Grid *cp437_grid, size_t x, size_t y); * * - `cp437_grid` points to a valid [SPCp437Grid] */ -size_t sp_cp437_grid_height(const SPCp437Grid *cp437_grid); +size_t sp_cp437_grid_height(const Cp437Grid *cp437_grid); /** * Loads a [SPCp437Grid] with the specified dimensions from the provided data. @@ -1733,10 +1717,10 @@ size_t sp_cp437_grid_height(const SPCp437Grid *cp437_grid); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_cp437_grid_free`. */ -SPCp437Grid *sp_cp437_grid_load(size_t width, - size_t height, - const uint8_t *data, - size_t data_length); +Cp437Grid *sp_cp437_grid_load(size_t width, + size_t height, + const uint8_t *data, + size_t data_length); /** * Creates a new [SPCp437Grid] with the specified dimensions. @@ -1750,8 +1734,8 @@ SPCp437Grid *sp_cp437_grid_load(size_t width, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_cp437_grid_free`. */ -SPCp437Grid *sp_cp437_grid_new(size_t width, - size_t height); +Cp437Grid *sp_cp437_grid_new(size_t width, + size_t height); /** * Sets the value of the specified position in the [SPCp437Grid]. @@ -1778,7 +1762,7 @@ SPCp437Grid *sp_cp437_grid_new(size_t width, * * [SPBitVec]: [crate::SPBitVec] */ -void sp_cp437_grid_set(SPCp437Grid *cp437_grid, +void sp_cp437_grid_set(Cp437Grid *cp437_grid, size_t x, size_t y, uint8_t value); @@ -1800,7 +1784,7 @@ void sp_cp437_grid_set(SPCp437Grid *cp437_grid, * - the returned memory range is never accessed after the passed [SPCp437Grid] has been freed * - the returned memory range is never accessed concurrently, either via the [SPCp437Grid] or directly */ -SPByteSlice sp_cp437_grid_unsafe_data_ref(SPCp437Grid *cp437_grid); +SPByteSlice sp_cp437_grid_unsafe_data_ref(Cp437Grid *cp437_grid); /** * Gets the width of the [SPCp437Grid] instance. @@ -1819,7 +1803,7 @@ SPByteSlice sp_cp437_grid_unsafe_data_ref(SPCp437Grid *cp437_grid); * * - `cp437_grid` points to a valid [SPCp437Grid] */ -size_t sp_cp437_grid_width(const SPCp437Grid *cp437_grid); +size_t sp_cp437_grid_width(const Cp437Grid *cp437_grid); /** * Clones a [SPPacket]. diff --git a/src/command.rs b/src/command.rs index 3e63eae..de8b5d6 100644 --- a/src/command.rs +++ b/src/command.rs @@ -2,8 +2,8 @@ //! //! prefix `sp_command_` -use crate::{SPBitVec, SPCompressionCode, SPCp437Grid}; -use servicepoint::{BinaryOperation, BrightnessGrid, CharGrid, GlobalBrightnessCommand, Packet, TypedCommand}; +use crate::{SPBitVec, SPCompressionCode}; +use servicepoint::{BinaryOperation, BrightnessGrid, CharGrid, Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand}; use std::ptr::NonNull; /// A low-level display command. @@ -405,14 +405,14 @@ unsafe fn sp_command_bitmap_linear_internal( pub unsafe extern "C" fn sp_command_cp437_data( x: usize, y: usize, - grid: *mut SPCp437Grid, + grid: *mut Cp437Grid, ) -> NonNull { assert!(!grid.is_null()); let grid = *unsafe { Box::from_raw(grid) }; let result = Box::new( servicepoint::Cp437GridCommand { origin: servicepoint::Origin::new(x, y), - grid: grid.0, + grid, } .into(), ); diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index eeb63eb..2ec009d 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -1,32 +1,25 @@ //! C functions for interacting with [SPCp437Grid]s //! //! prefix `sp_cp437_grid_` +//! +//! +//! A C-wrapper for grid containing codepage 437 characters. +//! +//! The encoding is currently not enforced. +//! +//! # Examples +//! +//! ```C +//! Cp437Grid grid = sp_cp437_grid_new(4, 3); +//! sp_cp437_grid_fill(grid, '?'); +//! sp_cp437_grid_set(grid, 0, 0, '!'); +//! sp_cp437_grid_free(grid); +//! ``` use crate::SPByteSlice; -use servicepoint::{DataRef, Grid}; +use servicepoint::{Cp437Grid, DataRef, Grid}; use std::ptr::NonNull; -/// A C-wrapper for grid containing codepage 437 characters. -/// -/// The encoding is currently not enforced. -/// -/// # Examples -/// -/// ```C -/// Cp437Grid grid = sp_cp437_grid_new(4, 3); -/// sp_cp437_grid_fill(grid, '?'); -/// sp_cp437_grid_set(grid, 0, 0, '!'); -/// sp_cp437_grid_free(grid); -/// ``` -#[repr(transparent)] -pub struct SPCp437Grid(pub(crate) servicepoint::Cp437Grid); - -impl Clone for SPCp437Grid { - fn clone(&self) -> Self { - SPCp437Grid(self.0.clone()) - } -} - /// Creates a new [SPCp437Grid] with the specified dimensions. /// /// returns: [SPCp437Grid] initialized to 0. Will never return NULL. @@ -41,9 +34,8 @@ impl Clone for SPCp437Grid { pub unsafe extern "C" fn sp_cp437_grid_new( width: usize, height: usize, -) -> NonNull { - let result = - Box::new(SPCp437Grid(servicepoint::Cp437Grid::new(width, height))); +) -> NonNull { + let result = Box::new(Cp437Grid::new(width, height)); NonNull::from(Box::leak(result)) } @@ -70,12 +62,12 @@ pub unsafe extern "C" fn sp_cp437_grid_load( height: usize, data: *const u8, data_length: usize, -) -> *mut SPCp437Grid { +) -> *mut Cp437Grid { assert!(data.is_null()); let data = unsafe { std::slice::from_raw_parts(data, data_length) }; - let grid = servicepoint::Cp437Grid::load(width, height, data); + let grid = Cp437Grid::load(width, height, data); if let Some(grid) = grid { - Box::leak(Box::new(SPCp437Grid(grid))) + Box::leak(Box::new(grid)) } else { std::ptr::null_mut() } @@ -99,8 +91,8 @@ pub unsafe extern "C" fn sp_cp437_grid_load( /// by explicitly calling `sp_cp437_grid_free`. #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_clone( - cp437_grid: *const SPCp437Grid, -) -> NonNull { + cp437_grid: *const Cp437Grid, +) -> NonNull { assert!(!cp437_grid.is_null()); let result = Box::new(unsafe { (*cp437_grid).clone() }); NonNull::from(Box::leak(result)) @@ -122,7 +114,7 @@ pub unsafe extern "C" fn sp_cp437_grid_clone( /// /// [SPCommand]: [crate::SPCommand] #[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 Cp437Grid) { assert!(!cp437_grid.is_null()); _ = unsafe { Box::from_raw(cp437_grid) }; } @@ -147,12 +139,12 @@ pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: *mut SPCp437Grid) { /// - `cp437_grid` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_get( - cp437_grid: *const SPCp437Grid, + cp437_grid: *const Cp437Grid, x: usize, y: usize, ) -> u8 { assert!(!cp437_grid.is_null()); - unsafe { (*cp437_grid).0.get(x, y) } + unsafe { (*cp437_grid).get(x, y) } } /// Sets the value of the specified position in the [SPCp437Grid]. @@ -180,13 +172,13 @@ pub unsafe extern "C" fn sp_cp437_grid_get( /// [SPBitVec]: [crate::SPBitVec] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_set( - cp437_grid: *mut SPCp437Grid, + cp437_grid: *mut Cp437Grid, x: usize, y: usize, value: u8, ) { assert!(!cp437_grid.is_null()); - unsafe { (*cp437_grid).0.set(x, y, value) }; + unsafe { (*cp437_grid).set(x, y, value) }; } /// Sets the value of all cells in the [SPCp437Grid]. @@ -208,11 +200,11 @@ pub unsafe extern "C" fn sp_cp437_grid_set( /// - `cp437_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_fill( - cp437_grid: *mut SPCp437Grid, + cp437_grid: *mut Cp437Grid, value: u8, ) { assert!(!cp437_grid.is_null()); - unsafe { (*cp437_grid).0.fill(value) }; + unsafe { (*cp437_grid).fill(value) }; } /// Gets the width of the [SPCp437Grid] instance. @@ -232,10 +224,10 @@ pub unsafe extern "C" fn sp_cp437_grid_fill( /// - `cp437_grid` points to a valid [SPCp437Grid] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_width( - cp437_grid: *const SPCp437Grid, + cp437_grid: *const Cp437Grid, ) -> usize { assert!(!cp437_grid.is_null()); - unsafe { (*cp437_grid).0.width() } + unsafe { (*cp437_grid).width() } } /// Gets the height of the [SPCp437Grid] instance. @@ -255,10 +247,10 @@ pub unsafe extern "C" fn sp_cp437_grid_width( /// - `cp437_grid` points to a valid [SPCp437Grid] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_height( - cp437_grid: *const SPCp437Grid, + cp437_grid: *const Cp437Grid, ) -> usize { assert!(!cp437_grid.is_null()); - unsafe { (*cp437_grid).0.height() } + unsafe { (*cp437_grid).height() } } /// Gets an unsafe reference to the data of the [SPCp437Grid] instance. @@ -278,7 +270,7 @@ pub unsafe extern "C" fn sp_cp437_grid_height( /// - the returned memory range is never accessed concurrently, either via the [SPCp437Grid] or directly #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref( - cp437_grid: *mut SPCp437Grid, + cp437_grid: *mut Cp437Grid, ) -> SPByteSlice { - unsafe {SPByteSlice::from_slice((*cp437_grid).0.data_ref_mut()) } + unsafe {SPByteSlice::from_slice((*cp437_grid).data_ref_mut()) } } -- 2.47.0 From 24ff341f9d9416b20704f6b5ddaf3c063dd27af2 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 12:12:51 +0200 Subject: [PATCH 08/25] re-export constants from base lib --- cbindgen.toml | 1 + example/main.c | 4 +- include/servicepoint.h | 111 +++++++++++++++++++++++++++++------------ src/byte_slice.rs | 2 +- src/command.rs | 16 +++--- src/constants.rs | 48 ------------------ src/lib.rs | 8 ++- 7 files changed, 98 insertions(+), 92 deletions(-) delete mode 100644 src/constants.rs diff --git a/cbindgen.toml b/cbindgen.toml index 3f619ed..29c19a8 100644 --- a/cbindgen.toml +++ b/cbindgen.toml @@ -25,6 +25,7 @@ sort_by = "Name" [parse] parse_deps = true include = ["servicepoint"] +extra_bindings = ["servicepoint"] [parse.expand] features = ["full"] diff --git a/example/main.c b/example/main.c index 388218e..80a1756 100644 --- a/example/main.c +++ b/example/main.c @@ -6,13 +6,13 @@ int main(void) { if (connection == NULL) return 1; - Bitmap *pixels = sp_bitmap_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT); + Bitmap *pixels = sp_bitmap_new(PIXEL_WIDTH, PIXEL_HEIGHT); if (pixels == NULL) return 1; sp_bitmap_fill(pixels, true); - Command *command = sp_command_bitmap_linear_win(0, 0, pixels, SP_COMPRESSION_CODE_UNCOMPRESSED); + Command *command = sp_command_bitmap_linear_win(0, 0, pixels, COMPRESSION_CODE_UNCOMPRESSED); if (command == NULL) return 1; diff --git a/include/servicepoint.h b/include/servicepoint.h index 691fffe..63c1179 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -8,6 +8,35 @@ #include #include +/** + * pixel count on whole screen + */ +#define PIXEL_COUNT (PIXEL_WIDTH * PIXEL_HEIGHT) + +/** + * Display height in pixels + * + * # Examples + * + * ```rust + * # use servicepoint::{PIXEL_HEIGHT, PIXEL_WIDTH, Bitmap}; + * let grid = Bitmap::new(PIXEL_WIDTH, PIXEL_HEIGHT); + * ``` + */ +#define PIXEL_HEIGHT (TILE_HEIGHT * TILE_SIZE) + +/** + * Display width in pixels + * + * # Examples + * + * ```rust + * # use servicepoint::{PIXEL_HEIGHT, PIXEL_WIDTH, Bitmap}; + * let grid = Bitmap::new(PIXEL_WIDTH, PIXEL_HEIGHT); + * ``` + */ +#define PIXEL_WIDTH (TILE_WIDTH * TILE_SIZE) + /** * Count of possible brightness values */ @@ -23,40 +52,60 @@ */ #define SP_BRIGHTNESS_MIN 0 -/** - * pixel count on whole screen - */ -#define SP_PIXEL_COUNT (SP_PIXEL_WIDTH * SP_PIXEL_HEIGHT) - -/** - * Display height in pixels - */ -#define SP_PIXEL_HEIGHT (SP_TILE_HEIGHT * SP_TILE_SIZE) - -/** - * Display width in pixels - */ -#define SP_PIXEL_WIDTH (SP_TILE_WIDTH * SP_TILE_SIZE) - /** * Display tile count in the y-direction + * + * # Examples + * + * ```rust + * # use servicepoint::{Cp437Grid, TILE_HEIGHT, TILE_WIDTH}; + * let grid = Cp437Grid::new(TILE_WIDTH, TILE_HEIGHT); + * ``` */ -#define SP_TILE_HEIGHT 20 +#define TILE_HEIGHT 20 /** * size of a single tile in one dimension */ -#define SP_TILE_SIZE 8 +#define TILE_SIZE 8 /** * Display tile count in the x-direction + * + * # Examples + * + * ```rust + * # use servicepoint::{Cp437Grid, TILE_HEIGHT, TILE_WIDTH}; + * let grid = Cp437Grid::new(TILE_WIDTH, TILE_HEIGHT); + * ``` */ -#define SP_TILE_WIDTH 56 +#define TILE_WIDTH 56 /** - * Specifies the kind of compression to use. + * Specifies the kind of compression to use. Availability depends on features. + * + * # Examples + * + * ```rust + * # use servicepoint::*; + * // create command without payload compression + * # let pixels = Bitmap::max_sized(); + * _ = BitmapCommand { + * origin: Origin::ZERO, + * bitmap: pixels, + * compression: CompressionCode::Uncompressed + * }; + * + * // create command with payload compressed with lzma and appropriate header flags + * # let pixels = Bitmap::max_sized(); + * _ = BitmapCommand { + * origin: Origin::ZERO, + * bitmap: pixels, + * compression: CompressionCode::Lzma + * }; + * ``` */ -enum SPCompressionCode +enum CompressionCode #ifdef __cplusplus : uint16_t #endif // __cplusplus @@ -64,26 +113,26 @@ enum SPCompressionCode /** * no compression */ - SP_COMPRESSION_CODE_UNCOMPRESSED = 0, + COMPRESSION_CODE_UNCOMPRESSED = 0, /** * compress using flate2 with zlib header */ - SP_COMPRESSION_CODE_ZLIB = 26490, + COMPRESSION_CODE_ZLIB = 26490, /** * compress using bzip2 */ - SP_COMPRESSION_CODE_BZIP2 = 25210, + COMPRESSION_CODE_BZIP2 = 25210, /** * compress using lzma */ - SP_COMPRESSION_CODE_LZMA = 27770, + COMPRESSION_CODE_LZMA = 27770, /** * compress using Zstandard */ - SP_COMPRESSION_CODE_ZSTD = 31347, + COMPRESSION_CODE_ZSTD = 31347, }; #ifndef __cplusplus -typedef uint16_t SPCompressionCode; +typedef uint16_t CompressionCode; #endif // __cplusplus /** @@ -1173,7 +1222,7 @@ size_t sp_char_grid_width(const CharGrid *char_grid); */ Command *sp_command_bitmap_linear(size_t offset, SPBitVec *bit_vec, - SPCompressionCode compression); + CompressionCode compression); /** * Set pixel data according to an and-mask starting at the offset. @@ -1204,7 +1253,7 @@ Command *sp_command_bitmap_linear(size_t offset, */ Command *sp_command_bitmap_linear_and(size_t offset, SPBitVec *bit_vec, - SPCompressionCode compression); + CompressionCode compression); /** * Set pixel data according to an or-mask starting at the offset. @@ -1235,7 +1284,7 @@ Command *sp_command_bitmap_linear_and(size_t offset, */ Command *sp_command_bitmap_linear_or(size_t offset, SPBitVec *bit_vec, - SPCompressionCode compression); + CompressionCode compression); /** * Sets a window of pixels to the specified values. @@ -1262,7 +1311,7 @@ Command *sp_command_bitmap_linear_or(size_t offset, Command *sp_command_bitmap_linear_win(size_t x, size_t y, Bitmap *bitmap, - SPCompressionCode compression); + CompressionCode compression); /** * Set pixel data according to a xor-mask starting at the offset. @@ -1293,7 +1342,7 @@ Command *sp_command_bitmap_linear_win(size_t x, */ Command *sp_command_bitmap_linear_xor(size_t offset, SPBitVec *bit_vec, - SPCompressionCode compression); + CompressionCode compression); /** * Set the brightness of all tiles to the same value. diff --git a/src/byte_slice.rs b/src/byte_slice.rs index 6ac4df3..a87c952 100644 --- a/src/byte_slice.rs +++ b/src/byte_slice.rs @@ -2,7 +2,6 @@ use std::ptr::NonNull; -#[repr(C)] /// Represents a span of memory (`&mut [u8]` ) as a struct usable by C code. /// /// You should not create an instance of this type in your C code. @@ -16,6 +15,7 @@ use std::ptr::NonNull; /// the function returning this type. /// - an instance of this created from C is never passed to a consuming function, as the rust code /// will try to free the memory of a potentially separate allocator. +#[repr(C)] pub struct SPByteSlice { /// The start address of the memory pub start: NonNull, diff --git a/src/command.rs b/src/command.rs index de8b5d6..a4a2736 100644 --- a/src/command.rs +++ b/src/command.rs @@ -2,8 +2,8 @@ //! //! prefix `sp_command_` -use crate::{SPBitVec, SPCompressionCode}; -use servicepoint::{BinaryOperation, BrightnessGrid, CharGrid, Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand}; +use crate::{SPBitVec}; +use servicepoint::{BinaryOperation, BrightnessGrid, CharGrid, CompressionCode, Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand}; use std::ptr::NonNull; /// A low-level display command. @@ -225,7 +225,7 @@ pub unsafe extern "C" fn sp_command_char_brightness( pub unsafe extern "C" fn sp_command_bitmap_linear( offset: usize, bit_vec: *mut SPBitVec, - compression: SPCompressionCode, + compression: CompressionCode, ) -> *mut TypedCommand { unsafe { sp_command_bitmap_linear_internal( @@ -266,7 +266,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear( pub unsafe extern "C" fn sp_command_bitmap_linear_and( offset: usize, bit_vec: *mut SPBitVec, - compression: SPCompressionCode, + compression: CompressionCode, ) -> *mut TypedCommand { unsafe { sp_command_bitmap_linear_internal( @@ -307,7 +307,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and( pub unsafe extern "C" fn sp_command_bitmap_linear_or( offset: usize, bit_vec: *mut SPBitVec, - compression: SPCompressionCode, + compression: CompressionCode, ) -> *mut TypedCommand { unsafe { sp_command_bitmap_linear_internal( @@ -348,7 +348,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or( pub unsafe extern "C" fn sp_command_bitmap_linear_xor( offset: usize, bit_vec: *mut SPBitVec, - compression: SPCompressionCode, + compression: CompressionCode, ) -> *mut TypedCommand { unsafe { sp_command_bitmap_linear_internal( @@ -364,7 +364,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor( unsafe fn sp_command_bitmap_linear_internal( offset: usize, bit_vec: *mut SPBitVec, - compression: SPCompressionCode, + compression: CompressionCode, operation: BinaryOperation, ) -> *mut TypedCommand { assert!(!bit_vec.is_null()); @@ -480,7 +480,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win( x: usize, y: usize, bitmap: *mut servicepoint::Bitmap, - compression: SPCompressionCode, + compression: CompressionCode, ) -> *mut TypedCommand { assert!(!bitmap.is_null()); let bitmap = unsafe { *Box::from_raw(bitmap) }; diff --git a/src/constants.rs b/src/constants.rs deleted file mode 100644 index ad1e77c..0000000 --- a/src/constants.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! re-exported constants for use in C - -use servicepoint::CompressionCode; -use std::time::Duration; - -/// size of a single tile in one dimension -pub const SP_TILE_SIZE: usize = 8; - -/// Display tile count in the x-direction -pub const SP_TILE_WIDTH: usize = 56; - -/// Display tile count in the y-direction -pub const SP_TILE_HEIGHT: usize = 20; - -/// Display width in pixels -pub const SP_PIXEL_WIDTH: usize = SP_TILE_WIDTH * SP_TILE_SIZE; - -/// Display height in pixels -pub const SP_PIXEL_HEIGHT: usize = SP_TILE_HEIGHT * SP_TILE_SIZE; - -/// pixel count on whole screen -pub const SP_PIXEL_COUNT: usize = SP_PIXEL_WIDTH * SP_PIXEL_HEIGHT; - -/// Actual hardware limit is around 28-29ms/frame. Rounded up for less dropped packets. -pub const SP_FRAME_PACING_MS: u128 = Duration::from_millis(30).as_millis(); - -/// Specifies the kind of compression to use. -#[repr(u16)] -pub enum SPCompressionCode { - /// no compression - Uncompressed = 0x0, - /// compress using flate2 with zlib header - Zlib = 0x677a, - /// compress using bzip2 - Bzip2 = 0x627a, - /// compress using lzma - Lzma = 0x6c7a, - /// compress using Zstandard - Zstd = 0x7a73, -} - -impl TryFrom for CompressionCode { - type Error = (); - - fn try_from(value: SPCompressionCode) -> Result { - CompressionCode::try_from(value as u16).map_err(|_| ()) - } -} diff --git a/src/lib.rs b/src/lib.rs index 887fb40..d00e579 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,7 +32,6 @@ pub use crate::byte_slice::*; pub use crate::char_grid::*; pub use crate::command::*; pub use crate::connection::*; -pub use crate::constants::*; pub use crate::cp437_grid::*; pub use crate::packet::*; @@ -43,6 +42,11 @@ mod byte_slice; mod char_grid; mod command; mod connection; -mod constants; mod cp437_grid; mod packet; + + +use std::time::Duration; + +/// Actual hardware limit is around 28-29ms/frame. Rounded up for less dropped packets. +pub const SP_FRAME_PACING_MS: u128 = Duration::from_millis(30).as_millis(); -- 2.47.0 From b443adc3aba956f23be99925bf04d9ecbedae399 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 12:19:10 +0200 Subject: [PATCH 09/25] add /*notnull*/ comments in header --- cbindgen.toml | 3 ++ include/servicepoint.h | 76 +++++++++++++++++++++--------------------- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/cbindgen.toml b/cbindgen.toml index 29c19a8..48ef574 100644 --- a/cbindgen.toml +++ b/cbindgen.toml @@ -39,3 +39,6 @@ exclude = [] [enum] rename_variants = "QualifiedScreamingSnakeCase" + +[ptr] +non_null_attribute = "/*notnull*/" diff --git a/include/servicepoint.h b/include/servicepoint.h index 63c1179..4e7843f 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -239,7 +239,7 @@ typedef struct { /** * The start address of the memory */ - uint8_t *start; + uint8_t */*notnull*/ start; /** * The amount of memory in bytes */ @@ -351,7 +351,7 @@ extern "C" { * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bitmap_free`. */ -Bitmap *sp_bitmap_clone(const Bitmap *bitmap); +Bitmap */*notnull*/ sp_bitmap_clone(const Bitmap *bitmap); /** * Sets the state of all pixels in the [SPBitmap]. @@ -506,7 +506,7 @@ Bitmap *sp_bitmap_new(size_t width, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling [sp_bitmap_free]. */ -Bitmap *sp_bitmap_new_screen_sized(void); +Bitmap */*notnull*/ sp_bitmap_new_screen_sized(void); /** * Sets the value of the specified position in the [SPBitmap]. @@ -587,7 +587,7 @@ size_t sp_bitmap_width(const Bitmap *bitmap); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bitvec_free`. */ -SPBitVec *sp_bitvec_clone(const SPBitVec *bit_vec); +SPBitVec */*notnull*/ sp_bitvec_clone(const SPBitVec *bit_vec); /** * Sets the value of all bits in the [SPBitVec]. @@ -709,8 +709,8 @@ size_t sp_bitvec_len(const SPBitVec *bit_vec); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bitvec_free`. */ -SPBitVec *sp_bitvec_load(const uint8_t *data, - size_t data_length); +SPBitVec */*notnull*/ sp_bitvec_load(const uint8_t *data, + size_t data_length); /** * Creates a new [SPBitVec] instance. @@ -732,7 +732,7 @@ SPBitVec *sp_bitvec_load(const uint8_t *data, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bitvec_free`. */ -SPBitVec *sp_bitvec_new(size_t size); +SPBitVec */*notnull*/ sp_bitvec_new(size_t size); /** * Sets the value of a bit in the [SPBitVec]. @@ -800,7 +800,7 @@ SPByteSlice sp_bitvec_unsafe_data_ref(SPBitVec *bit_vec); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_brightness_grid_free`. */ -BrightnessGrid *sp_brightness_grid_clone(const BrightnessGrid *brightness_grid); +BrightnessGrid */*notnull*/ sp_brightness_grid_clone(const BrightnessGrid *brightness_grid); /** * Sets the value of all cells in the [SPBrightnessGrid]. @@ -930,8 +930,8 @@ BrightnessGrid *sp_brightness_grid_load(size_t width, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_brightness_grid_free`. */ -BrightnessGrid *sp_brightness_grid_new(size_t width, - size_t height); +BrightnessGrid */*notnull*/ sp_brightness_grid_new(size_t width, + size_t height); /** * Sets the value of the specified position in the [SPBrightnessGrid]. @@ -1024,7 +1024,7 @@ size_t sp_brightness_grid_width(const BrightnessGrid *brightness_grid); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_char_grid_free`. */ -CharGrid *sp_char_grid_clone(const CharGrid *char_grid); +CharGrid */*notnull*/ sp_char_grid_clone(const CharGrid *char_grid); /** * Sets the value of all cells in the [SPCharGrid]. @@ -1127,10 +1127,10 @@ size_t sp_char_grid_height(const CharGrid *char_grid); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_char_grid_free`. */ -CharGrid *sp_char_grid_load(size_t width, - size_t height, - const uint8_t *data, - size_t data_length); +CharGrid */*notnull*/ sp_char_grid_load(size_t width, + size_t height, + const uint8_t *data, + size_t data_length); /** * Creates a new [SPCharGrid] with the specified dimensions. @@ -1144,8 +1144,8 @@ CharGrid *sp_char_grid_load(size_t width, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_char_grid_free`. */ -CharGrid *sp_char_grid_new(size_t width, - size_t height); +CharGrid */*notnull*/ sp_char_grid_new(size_t width, + size_t height); /** * Sets the value of the specified position in the [SPCharGrid]. @@ -1360,7 +1360,7 @@ Command *sp_command_bitmap_linear_xor(size_t offset, * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_brightness(uint8_t brightness); +Command */*notnull*/ sp_command_brightness(uint8_t brightness); /** * Set the brightness of individual tiles in a rectangular area of the display. @@ -1382,9 +1382,9 @@ Command *sp_command_brightness(uint8_t brightness); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_char_brightness(size_t x, - size_t y, - BrightnessGrid *grid); +Command */*notnull*/ sp_command_char_brightness(size_t x, + size_t y, + BrightnessGrid *grid); /** * Set all pixels to the off state. @@ -1406,7 +1406,7 @@ Command *sp_command_char_brightness(size_t x, * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_clear(void); +Command */*notnull*/ sp_command_clear(void); /** * Clones a [SPCommand] instance. @@ -1426,7 +1426,7 @@ Command *sp_command_clear(void); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_clone(const Command *command); +Command */*notnull*/ sp_command_clone(const Command *command); /** * Show codepage 437 encoded text on the screen. @@ -1448,9 +1448,9 @@ Command *sp_command_clone(const Command *command); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_cp437_data(size_t x, - size_t y, - Cp437Grid *grid); +Command */*notnull*/ sp_command_cp437_data(size_t x, + size_t y, + Cp437Grid *grid); /** * A yet-to-be-tested command. @@ -1464,7 +1464,7 @@ Command *sp_command_cp437_data(size_t x, * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_fade_out(void); +Command */*notnull*/ sp_command_fade_out(void); /** * Deallocates a [SPCommand]. @@ -1504,7 +1504,7 @@ void sp_command_free(Command *command); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_hard_reset(void); +Command */*notnull*/ sp_command_hard_reset(void); /** * A low-level display command. @@ -1563,9 +1563,9 @@ Command *sp_command_try_from_packet(Packet *packet); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_utf8_data(size_t x, - size_t y, - CharGrid *grid); +Command */*notnull*/ sp_command_utf8_data(size_t x, + size_t y, + CharGrid *grid); /** * Closes and deallocates a [SPConnection]. @@ -1664,7 +1664,7 @@ bool sp_connection_send_packet(const UdpConnection *connection, Packet *packet); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_cp437_grid_free`. */ -Cp437Grid *sp_cp437_grid_clone(const Cp437Grid *cp437_grid); +Cp437Grid */*notnull*/ sp_cp437_grid_clone(const Cp437Grid *cp437_grid); /** * Sets the value of all cells in the [SPCp437Grid]. @@ -1783,8 +1783,8 @@ Cp437Grid *sp_cp437_grid_load(size_t width, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_cp437_grid_free`. */ -Cp437Grid *sp_cp437_grid_new(size_t width, - size_t height); +Cp437Grid */*notnull*/ sp_cp437_grid_new(size_t width, + size_t height); /** * Sets the value of the specified position in the [SPCp437Grid]. @@ -1872,7 +1872,7 @@ size_t sp_cp437_grid_width(const Cp437Grid *cp437_grid); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_packet_free`. */ -Packet *sp_packet_clone(const Packet *packet); +Packet */*notnull*/ sp_packet_clone(const Packet *packet); /** * Deallocates a [SPPacket]. @@ -1937,9 +1937,9 @@ Packet *sp_packet_from_command(Command *command); * - the returned [SPPacket] instance is freed in some way, either by using a consuming function or * by explicitly calling [sp_packet_free]. */ -Packet *sp_packet_from_parts(Header header, - const uint8_t *payload, - size_t payload_len); +Packet */*notnull*/ sp_packet_from_parts(Header header, + const uint8_t *payload, + size_t payload_len); Header *sp_packet_get_header(Packet *packet); -- 2.47.0 From 30bec50f7cfd6d64f88ed7251c3c082596c3ee9a Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 12:33:36 +0200 Subject: [PATCH 10/25] use NotNull for parameters --- build.rs | 4 +- include/servicepoint.h | 154 ++++++++++++++++++++--------------------- src/bitmap.rs | 72 +++++++------------ src/bitvec.rs | 71 ++++++++----------- src/brightness_grid.rs | 56 ++++++--------- src/byte_slice.rs | 2 +- src/char_grid.rs | 50 ++++++------- src/command.rs | 84 +++++++++++----------- src/connection.rs | 33 ++++----- src/cp437_grid.rs | 47 +++++-------- src/lib.rs | 1 - src/packet.rs | 63 +++++++---------- 12 files changed, 274 insertions(+), 363 deletions(-) diff --git a/build.rs b/build.rs index 0bc6e0a..83e9641 100644 --- a/build.rs +++ b/build.rs @@ -10,7 +10,9 @@ fn main() { let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); println!("cargo::rerun-if-changed={crate_dir}"); - let config = cbindgen::Config::from_file(crate_dir.clone() + "/cbindgen.toml").unwrap(); + let config = + cbindgen::Config::from_file(crate_dir.clone() + "/cbindgen.toml") + .unwrap(); let output_dir = env::var("OUT_DIR").unwrap(); let header_file = output_dir.clone() + "/servicepoint.h"; diff --git a/include/servicepoint.h b/include/servicepoint.h index 4e7843f..4a0af95 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -351,7 +351,7 @@ extern "C" { * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bitmap_free`. */ -Bitmap */*notnull*/ sp_bitmap_clone(const Bitmap *bitmap); +Bitmap */*notnull*/ sp_bitmap_clone(Bitmap */*notnull*/ bitmap); /** * Sets the state of all pixels in the [SPBitmap]. @@ -372,7 +372,7 @@ Bitmap */*notnull*/ sp_bitmap_clone(const Bitmap *bitmap); * - `bitmap` points to a valid [SPBitmap] * - `bitmap` is not written to or read from concurrently */ -void sp_bitmap_fill(Bitmap *bitmap, bool value); +void sp_bitmap_fill(Bitmap */*notnull*/ bitmap, bool value); /** * Deallocates a [SPBitmap]. @@ -386,12 +386,10 @@ void sp_bitmap_fill(Bitmap *bitmap, bool value); * The caller has to make sure that: * * - `bitmap` points to a valid [SPBitmap] - * - `bitmap` is not used concurrently or after bitmap call - * - `bitmap` was not passed to another consuming function, e.g. to create a [SPCommand] * * [SPCommand]: [crate::SPCommand] */ -void sp_bitmap_free(Bitmap *bitmap); +void sp_bitmap_free(Bitmap */*notnull*/ bitmap); /** * Gets the current value at the specified position in the [SPBitmap]. @@ -413,7 +411,7 @@ void sp_bitmap_free(Bitmap *bitmap); * - `bitmap` points to a valid [SPBitmap] * - `bitmap` is not written to concurrently */ -bool sp_bitmap_get(const Bitmap *bitmap, size_t x, size_t y); +bool sp_bitmap_get(Bitmap */*notnull*/ bitmap, size_t x, size_t y); /** * Gets the height in pixels of the [SPBitmap] instance. @@ -432,7 +430,7 @@ bool sp_bitmap_get(const Bitmap *bitmap, size_t x, size_t y); * * - `bitmap` points to a valid [SPBitmap] */ -size_t sp_bitmap_height(const Bitmap *bitmap); +size_t sp_bitmap_height(Bitmap */*notnull*/ bitmap); /** * Loads a [SPBitmap] with the specified dimensions from the provided data. @@ -465,8 +463,7 @@ size_t sp_bitmap_height(const Bitmap *bitmap); */ Bitmap *sp_bitmap_load(size_t width, size_t height, - const uint8_t *data, - size_t data_length); + SPByteSlice data); /** * Creates a new [SPBitmap] with the specified dimensions. @@ -531,7 +528,7 @@ Bitmap */*notnull*/ sp_bitmap_new_screen_sized(void); * - `bitmap` points to a valid [SPBitmap] * - `bitmap` is not written to or read from concurrently */ -void sp_bitmap_set(Bitmap *bitmap, size_t x, size_t y, bool value); +void sp_bitmap_set(Bitmap */*notnull*/ bitmap, size_t x, size_t y, bool value); /** * Gets an unsafe reference to the data of the [SPBitmap] instance. @@ -548,7 +545,7 @@ void sp_bitmap_set(Bitmap *bitmap, size_t x, size_t y, bool value); * - the returned memory range is never accessed after the passed [SPBitmap] has been freed * - the returned memory range is never accessed concurrently, either via the [SPBitmap] or directly */ -SPByteSlice sp_bitmap_unsafe_data_ref(Bitmap *bitmap); +SPByteSlice sp_bitmap_unsafe_data_ref(Bitmap */*notnull*/ bitmap); /** * Gets the width in pixels of the [SPBitmap] instance. @@ -567,7 +564,7 @@ SPByteSlice sp_bitmap_unsafe_data_ref(Bitmap *bitmap); * * - `bitmap` points to a valid [SPBitmap] */ -size_t sp_bitmap_width(const Bitmap *bitmap); +size_t sp_bitmap_width(Bitmap */*notnull*/ bitmap); /** * Clones a [SPBitVec]. @@ -587,7 +584,7 @@ size_t sp_bitmap_width(const Bitmap *bitmap); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bitvec_free`. */ -SPBitVec */*notnull*/ sp_bitvec_clone(const SPBitVec *bit_vec); +SPBitVec */*notnull*/ sp_bitvec_clone(SPBitVec */*notnull*/ bit_vec); /** * Sets the value of all bits in the [SPBitVec]. @@ -608,7 +605,7 @@ SPBitVec */*notnull*/ sp_bitvec_clone(const SPBitVec *bit_vec); * - `bit_vec` points to a valid [SPBitVec] * - `bit_vec` is not written to or read from concurrently */ -void sp_bitvec_fill(SPBitVec *bit_vec, bool value); +void sp_bitvec_fill(SPBitVec */*notnull*/ bit_vec, bool value); /** * Deallocates a [SPBitVec]. @@ -627,7 +624,7 @@ void sp_bitvec_fill(SPBitVec *bit_vec, bool value); * * [SPCommand]: [crate::SPCommand] */ -void sp_bitvec_free(SPBitVec *bit_vec); +void sp_bitvec_free(SPBitVec */*notnull*/ bit_vec); /** * Gets the value of a bit from the [SPBitVec]. @@ -651,7 +648,7 @@ void sp_bitvec_free(SPBitVec *bit_vec); * - `bit_vec` points to a valid [SPBitVec] * - `bit_vec` is not written to concurrently */ -bool sp_bitvec_get(const SPBitVec *bit_vec, size_t index); +bool sp_bitvec_get(SPBitVec */*notnull*/ bit_vec, size_t index); /** * Returns true if length is 0. @@ -670,7 +667,7 @@ bool sp_bitvec_get(const SPBitVec *bit_vec, size_t index); * * - `bit_vec` points to a valid [SPBitVec] */ -bool sp_bitvec_is_empty(const SPBitVec *bit_vec); +bool sp_bitvec_is_empty(SPBitVec */*notnull*/ bit_vec); /** * Gets the length of the [SPBitVec] in bits. @@ -689,7 +686,7 @@ bool sp_bitvec_is_empty(const SPBitVec *bit_vec); * * - `bit_vec` points to a valid [SPBitVec] */ -size_t sp_bitvec_len(const SPBitVec *bit_vec); +size_t sp_bitvec_len(SPBitVec */*notnull*/ bit_vec); /** * Interpret the data as a series of bits and load then into a new [SPBitVec] instance. @@ -709,8 +706,7 @@ size_t sp_bitvec_len(const SPBitVec *bit_vec); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bitvec_free`. */ -SPBitVec */*notnull*/ sp_bitvec_load(const uint8_t *data, - size_t data_length); +SPBitVec */*notnull*/ sp_bitvec_load(SPByteSlice data); /** * Creates a new [SPBitVec] instance. @@ -755,7 +751,7 @@ SPBitVec */*notnull*/ sp_bitvec_new(size_t size); * - `bit_vec` points to a valid [SPBitVec] * - `bit_vec` is not written to or read from concurrently */ -void sp_bitvec_set(SPBitVec *bit_vec, size_t index, bool value); +void sp_bitvec_set(SPBitVec */*notnull*/ bit_vec, size_t index, bool value); /** * Gets an unsafe reference to the data of the [SPBitVec] instance. @@ -776,7 +772,7 @@ void sp_bitvec_set(SPBitVec *bit_vec, size_t index, bool value); * - the returned memory range is never accessed after the passed [SPBitVec] has been freed * - the returned memory range is never accessed concurrently, either via the [SPBitVec] or directly */ -SPByteSlice sp_bitvec_unsafe_data_ref(SPBitVec *bit_vec); +SPByteSlice sp_bitvec_unsafe_data_ref(SPBitVec */*notnull*/ bit_vec); /** * Clones a [SPBrightnessGrid]. @@ -800,7 +796,7 @@ SPByteSlice sp_bitvec_unsafe_data_ref(SPBitVec *bit_vec); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_brightness_grid_free`. */ -BrightnessGrid */*notnull*/ sp_brightness_grid_clone(const BrightnessGrid *brightness_grid); +BrightnessGrid */*notnull*/ sp_brightness_grid_clone(BrightnessGrid */*notnull*/ brightness_grid); /** * Sets the value of all cells in the [SPBrightnessGrid]. @@ -822,7 +818,8 @@ BrightnessGrid */*notnull*/ sp_brightness_grid_clone(const BrightnessGrid *brigh * - `brightness_grid` points to a valid [SPBrightnessGrid] * - `brightness_grid` is not written to or read from concurrently */ -void sp_brightness_grid_fill(BrightnessGrid *brightness_grid, uint8_t value); +void sp_brightness_grid_fill(BrightnessGrid */*notnull*/ brightness_grid, + uint8_t value); /** * Deallocates a [SPBrightnessGrid]. @@ -845,7 +842,7 @@ void sp_brightness_grid_fill(BrightnessGrid *brightness_grid, uint8_t value); * * [SPCommand]: [crate::SPCommand] */ -void sp_brightness_grid_free(BrightnessGrid *brightness_grid); +void sp_brightness_grid_free(BrightnessGrid */*notnull*/ brightness_grid); /** * Gets the current value at the specified position. @@ -869,7 +866,7 @@ void sp_brightness_grid_free(BrightnessGrid *brightness_grid); * - `brightness_grid` points to a valid [SPBrightnessGrid] * - `brightness_grid` is not written to concurrently */ -uint8_t sp_brightness_grid_get(const BrightnessGrid *brightness_grid, +uint8_t sp_brightness_grid_get(BrightnessGrid */*notnull*/ brightness_grid, size_t x, size_t y); @@ -892,7 +889,7 @@ uint8_t sp_brightness_grid_get(const BrightnessGrid *brightness_grid, * * - `brightness_grid` points to a valid [SPBrightnessGrid] */ -size_t sp_brightness_grid_height(const BrightnessGrid *brightness_grid); +size_t sp_brightness_grid_height(BrightnessGrid */*notnull*/ brightness_grid); /** * Loads a [SPBrightnessGrid] with the specified dimensions from the provided data. @@ -915,8 +912,7 @@ size_t sp_brightness_grid_height(const BrightnessGrid *brightness_grid); */ BrightnessGrid *sp_brightness_grid_load(size_t width, size_t height, - const uint8_t *data, - size_t data_length); + SPByteSlice data); /** * Creates a new [SPBrightnessGrid] with the specified dimensions. @@ -957,7 +953,7 @@ BrightnessGrid */*notnull*/ sp_brightness_grid_new(size_t width, * - `brightness_grid` points to a valid [SPBrightnessGrid] * - `brightness_grid` is not written to or read from concurrently */ -void sp_brightness_grid_set(BrightnessGrid *brightness_grid, +void sp_brightness_grid_set(BrightnessGrid */*notnull*/ brightness_grid, size_t x, size_t y, uint8_t value); @@ -983,7 +979,7 @@ void sp_brightness_grid_set(BrightnessGrid *brightness_grid, * - the returned memory range is never accessed after the passed [SPBrightnessGrid] has been freed * - the returned memory range is never accessed concurrently, either via the [SPBrightnessGrid] or directly */ -SPByteSlice sp_brightness_grid_unsafe_data_ref(BrightnessGrid *brightness_grid); +SPByteSlice sp_brightness_grid_unsafe_data_ref(BrightnessGrid */*notnull*/ brightness_grid); /** * Gets the width of the [SPBrightnessGrid] instance. @@ -1004,7 +1000,7 @@ SPByteSlice sp_brightness_grid_unsafe_data_ref(BrightnessGrid *brightness_grid); * * - `brightness_grid` points to a valid [SPBrightnessGrid] */ -size_t sp_brightness_grid_width(const BrightnessGrid *brightness_grid); +size_t sp_brightness_grid_width(BrightnessGrid */*notnull*/ brightness_grid); /** * Clones a [SPCharGrid]. @@ -1024,7 +1020,7 @@ size_t sp_brightness_grid_width(const BrightnessGrid *brightness_grid); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_char_grid_free`. */ -CharGrid */*notnull*/ sp_char_grid_clone(const CharGrid *char_grid); +CharGrid */*notnull*/ sp_char_grid_clone(CharGrid */*notnull*/ char_grid); /** * Sets the value of all cells in the [SPCharGrid]. @@ -1045,7 +1041,7 @@ CharGrid */*notnull*/ sp_char_grid_clone(const CharGrid *char_grid); * - `char_grid` points to a valid [SPCharGrid] * - `char_grid` is not written to or read from concurrently */ -void sp_char_grid_fill(CharGrid *char_grid, uint32_t value); +void sp_char_grid_fill(CharGrid */*notnull*/ char_grid, uint32_t value); /** * Deallocates a [SPCharGrid]. @@ -1064,7 +1060,7 @@ void sp_char_grid_fill(CharGrid *char_grid, uint32_t value); * * [SPCommand]: [crate::SPCommand] */ -void sp_char_grid_free(CharGrid *char_grid); +void sp_char_grid_free(CharGrid */*notnull*/ char_grid); /** * Gets the current value at the specified position. @@ -1086,7 +1082,7 @@ void sp_char_grid_free(CharGrid *char_grid); * - `char_grid` points to a valid [SPCharGrid] * - `char_grid` is not written to concurrently */ -uint32_t sp_char_grid_get(const CharGrid *char_grid, size_t x, size_t y); +uint32_t sp_char_grid_get(CharGrid */*notnull*/ char_grid, size_t x, size_t y); /** * Gets the height of the [SPCharGrid] instance. @@ -1105,7 +1101,7 @@ uint32_t sp_char_grid_get(const CharGrid *char_grid, size_t x, size_t y); * * - `char_grid` points to a valid [SPCharGrid] */ -size_t sp_char_grid_height(const CharGrid *char_grid); +size_t sp_char_grid_height(CharGrid */*notnull*/ char_grid); /** * Loads a [SPCharGrid] with the specified dimensions from the provided data. @@ -1129,8 +1125,7 @@ size_t sp_char_grid_height(const CharGrid *char_grid); */ CharGrid */*notnull*/ sp_char_grid_load(size_t width, size_t height, - const uint8_t *data, - size_t data_length); + SPByteSlice data); /** * Creates a new [SPCharGrid] with the specified dimensions. @@ -1172,7 +1167,10 @@ CharGrid */*notnull*/ sp_char_grid_new(size_t width, * * [SPBitVec]: [crate::SPBitVec] */ -void sp_char_grid_set(CharGrid *char_grid, size_t x, size_t y, uint32_t value); +void sp_char_grid_set(CharGrid */*notnull*/ char_grid, + size_t x, + size_t y, + uint32_t value); /** * Gets the width of the [SPCharGrid] instance. @@ -1191,7 +1189,7 @@ void sp_char_grid_set(CharGrid *char_grid, size_t x, size_t y, uint32_t value); * * - `char_grid` points to a valid [SPCharGrid] */ -size_t sp_char_grid_width(const CharGrid *char_grid); +size_t sp_char_grid_width(CharGrid */*notnull*/ char_grid); /** * Set pixel data starting at the pixel offset on screen. @@ -1221,7 +1219,7 @@ size_t sp_char_grid_width(const CharGrid *char_grid); * by explicitly calling `sp_command_free`. */ Command *sp_command_bitmap_linear(size_t offset, - SPBitVec *bit_vec, + SPBitVec */*notnull*/ bit_vec, CompressionCode compression); /** @@ -1252,7 +1250,7 @@ Command *sp_command_bitmap_linear(size_t offset, * by explicitly calling `sp_command_free`. */ Command *sp_command_bitmap_linear_and(size_t offset, - SPBitVec *bit_vec, + SPBitVec */*notnull*/ bit_vec, CompressionCode compression); /** @@ -1283,7 +1281,7 @@ Command *sp_command_bitmap_linear_and(size_t offset, * by explicitly calling `sp_command_free`. */ Command *sp_command_bitmap_linear_or(size_t offset, - SPBitVec *bit_vec, + SPBitVec */*notnull*/ bit_vec, CompressionCode compression); /** @@ -1310,7 +1308,7 @@ Command *sp_command_bitmap_linear_or(size_t offset, */ Command *sp_command_bitmap_linear_win(size_t x, size_t y, - Bitmap *bitmap, + Bitmap */*notnull*/ bitmap, CompressionCode compression); /** @@ -1341,7 +1339,7 @@ Command *sp_command_bitmap_linear_win(size_t x, * by explicitly calling `sp_command_free`. */ Command *sp_command_bitmap_linear_xor(size_t offset, - SPBitVec *bit_vec, + SPBitVec */*notnull*/ bit_vec, CompressionCode compression); /** @@ -1384,7 +1382,7 @@ Command */*notnull*/ sp_command_brightness(uint8_t brightness); */ Command */*notnull*/ sp_command_char_brightness(size_t x, size_t y, - BrightnessGrid *grid); + BrightnessGrid */*notnull*/ grid); /** * Set all pixels to the off state. @@ -1426,7 +1424,7 @@ Command */*notnull*/ sp_command_clear(void); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command */*notnull*/ sp_command_clone(const Command *command); +Command */*notnull*/ sp_command_clone(Command */*notnull*/ command); /** * Show codepage 437 encoded text on the screen. @@ -1450,7 +1448,7 @@ Command */*notnull*/ sp_command_clone(const Command *command); */ Command */*notnull*/ sp_command_cp437_data(size_t x, size_t y, - Cp437Grid *grid); + Cp437Grid */*notnull*/ grid); /** * A yet-to-be-tested command. @@ -1488,7 +1486,7 @@ Command */*notnull*/ sp_command_fade_out(void); * - `command` is not used concurrently or after this call * - `command` was not passed to another consuming function, e.g. to create a [SPPacket] */ -void sp_command_free(Command *command); +void sp_command_free(Command */*notnull*/ command); /** * Kills the udp daemon on the display, which usually results in a restart. @@ -1541,7 +1539,7 @@ Command */*notnull*/ sp_command_hard_reset(void); * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_try_from_packet(Packet *packet); +Command *sp_command_try_from_packet(Packet */*notnull*/ packet); /** * Show UTF-8 encoded text on the screen. @@ -1565,7 +1563,7 @@ Command *sp_command_try_from_packet(Packet *packet); */ Command */*notnull*/ sp_command_utf8_data(size_t x, size_t y, - CharGrid *grid); + CharGrid */*notnull*/ grid); /** * Closes and deallocates a [SPConnection]. @@ -1581,7 +1579,7 @@ Command */*notnull*/ sp_command_utf8_data(size_t x, * - `connection` points to a valid [SPConnection] * - `connection` is not used concurrently or after this call */ -void sp_connection_free(UdpConnection *connection); +void sp_connection_free(UdpConnection */*notnull*/ connection); /** * Creates a new instance of [SPConnection]. @@ -1599,7 +1597,7 @@ void sp_connection_free(UdpConnection *connection); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_connection_free`. */ -UdpConnection *sp_connection_open(const char *host); +UdpConnection *sp_connection_open(char */*notnull*/ host); /** * Sends a [SPCommand] to the display using the [SPConnection]. @@ -1621,8 +1619,8 @@ UdpConnection *sp_connection_open(const char *host); * - `command` points to a valid instance of [SPPacket] * - `command` is not used concurrently or after this call */ -bool sp_connection_send_command(const UdpConnection *connection, - Command *command); +bool sp_connection_send_command(UdpConnection */*notnull*/ connection, + Command */*notnull*/ command); /** * Sends a [SPPacket] to the display using the [SPConnection]. @@ -1644,7 +1642,8 @@ bool sp_connection_send_command(const UdpConnection *connection, * - `packet` points to a valid instance of [SPPacket] * - `packet` is not used concurrently or after this call */ -bool sp_connection_send_packet(const UdpConnection *connection, Packet *packet); +bool sp_connection_send_packet(UdpConnection */*notnull*/ connection, + Packet */*notnull*/ packet); /** * Clones a [SPCp437Grid]. @@ -1664,7 +1663,7 @@ bool sp_connection_send_packet(const UdpConnection *connection, Packet *packet); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_cp437_grid_free`. */ -Cp437Grid */*notnull*/ sp_cp437_grid_clone(const Cp437Grid *cp437_grid); +Cp437Grid */*notnull*/ sp_cp437_grid_clone(Cp437Grid */*notnull*/ cp437_grid); /** * Sets the value of all cells in the [SPCp437Grid]. @@ -1685,7 +1684,7 @@ Cp437Grid */*notnull*/ sp_cp437_grid_clone(const Cp437Grid *cp437_grid); * - `cp437_grid` points to a valid [SPCp437Grid] * - `cp437_grid` is not written to or read from concurrently */ -void sp_cp437_grid_fill(Cp437Grid *cp437_grid, uint8_t value); +void sp_cp437_grid_fill(Cp437Grid */*notnull*/ cp437_grid, uint8_t value); /** * Deallocates a [SPCp437Grid]. @@ -1704,7 +1703,7 @@ void sp_cp437_grid_fill(Cp437Grid *cp437_grid, uint8_t value); * * [SPCommand]: [crate::SPCommand] */ -void sp_cp437_grid_free(Cp437Grid *cp437_grid); +void sp_cp437_grid_free(Cp437Grid */*notnull*/ cp437_grid); /** * Gets the current value at the specified position. @@ -1726,7 +1725,9 @@ void sp_cp437_grid_free(Cp437Grid *cp437_grid); * - `cp437_grid` points to a valid [SPCp437Grid] * - `cp437_grid` is not written to concurrently */ -uint8_t sp_cp437_grid_get(const Cp437Grid *cp437_grid, size_t x, size_t y); +uint8_t sp_cp437_grid_get(Cp437Grid */*notnull*/ cp437_grid, + size_t x, + size_t y); /** * Gets the height of the [SPCp437Grid] instance. @@ -1745,7 +1746,7 @@ uint8_t sp_cp437_grid_get(const Cp437Grid *cp437_grid, size_t x, size_t y); * * - `cp437_grid` points to a valid [SPCp437Grid] */ -size_t sp_cp437_grid_height(const Cp437Grid *cp437_grid); +size_t sp_cp437_grid_height(Cp437Grid */*notnull*/ cp437_grid); /** * Loads a [SPCp437Grid] with the specified dimensions from the provided data. @@ -1768,8 +1769,7 @@ size_t sp_cp437_grid_height(const Cp437Grid *cp437_grid); */ Cp437Grid *sp_cp437_grid_load(size_t width, size_t height, - const uint8_t *data, - size_t data_length); + SPByteSlice data); /** * Creates a new [SPCp437Grid] with the specified dimensions. @@ -1811,7 +1811,7 @@ Cp437Grid */*notnull*/ sp_cp437_grid_new(size_t width, * * [SPBitVec]: [crate::SPBitVec] */ -void sp_cp437_grid_set(Cp437Grid *cp437_grid, +void sp_cp437_grid_set(Cp437Grid */*notnull*/ cp437_grid, size_t x, size_t y, uint8_t value); @@ -1833,7 +1833,7 @@ void sp_cp437_grid_set(Cp437Grid *cp437_grid, * - the returned memory range is never accessed after the passed [SPCp437Grid] has been freed * - the returned memory range is never accessed concurrently, either via the [SPCp437Grid] or directly */ -SPByteSlice sp_cp437_grid_unsafe_data_ref(Cp437Grid *cp437_grid); +SPByteSlice sp_cp437_grid_unsafe_data_ref(Cp437Grid */*notnull*/ cp437_grid); /** * Gets the width of the [SPCp437Grid] instance. @@ -1852,7 +1852,7 @@ SPByteSlice sp_cp437_grid_unsafe_data_ref(Cp437Grid *cp437_grid); * * - `cp437_grid` points to a valid [SPCp437Grid] */ -size_t sp_cp437_grid_width(const Cp437Grid *cp437_grid); +size_t sp_cp437_grid_width(Cp437Grid */*notnull*/ cp437_grid); /** * Clones a [SPPacket]. @@ -1872,7 +1872,7 @@ size_t sp_cp437_grid_width(const Cp437Grid *cp437_grid); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_packet_free`. */ -Packet */*notnull*/ sp_packet_clone(const Packet *packet); +Packet */*notnull*/ sp_packet_clone(Packet */*notnull*/ packet); /** * Deallocates a [SPPacket]. @@ -1888,7 +1888,7 @@ Packet */*notnull*/ sp_packet_clone(const Packet *packet); * - `packet` points to a valid [SPPacket] * - `packet` is not used concurrently or after this call */ -void sp_packet_free(Packet *packet); +void sp_packet_free(Packet */*notnull*/ packet); /** * Turns a [SPCommand] into a [SPPacket]. @@ -1909,7 +1909,7 @@ void sp_packet_free(Packet *packet); * - the returned [SPPacket] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_packet_free`. */ -Packet *sp_packet_from_command(Command *command); +Packet *sp_packet_from_command(Command */*notnull*/ command); /** * Creates a raw [SPPacket] from parts. @@ -1938,14 +1938,13 @@ Packet *sp_packet_from_command(Command *command); * by explicitly calling [sp_packet_free]. */ Packet */*notnull*/ sp_packet_from_parts(Header header, - const uint8_t *payload, - size_t payload_len); + const SPByteSlice *payload); -Header *sp_packet_get_header(Packet *packet); +Header */*notnull*/ sp_packet_get_header(Packet */*notnull*/ packet); -SPByteSlice sp_packet_get_payload(Packet *packet); +SPByteSlice sp_packet_get_payload(Packet */*notnull*/ packet); -void sp_packet_set_payload(Packet *packet, SPByteSlice data); +void sp_packet_set_payload(Packet */*notnull*/ packet, SPByteSlice data); /** * Tries to load a [SPPacket] from the passed array with the specified length. @@ -1965,10 +1964,9 @@ void sp_packet_set_payload(Packet *packet, SPByteSlice data); * - the returned [SPPacket] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_packet_free`. */ -Packet *sp_packet_try_load(const uint8_t *data, - size_t length); +Packet *sp_packet_try_load(SPByteSlice data); -void sp_packet_write_to(const Packet *packet, SPByteSlice buffer); +void sp_packet_write_to(Packet */*notnull*/ packet, SPByteSlice buffer); #ifdef __cplusplus } // extern "C" diff --git a/src/bitmap.rs b/src/bitmap.rs index 1f6327f..2e70efc 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -13,7 +13,7 @@ //! sp_bitmap_free(grid); //! ``` -use servicepoint::{DataRef, Grid}; +use servicepoint::{Bitmap, DataRef, Grid}; use std::ptr::NonNull; use crate::byte_slice::SPByteSlice; @@ -43,8 +43,8 @@ use crate::byte_slice::SPByteSlice; pub unsafe extern "C" fn sp_bitmap_new( width: usize, height: usize, -) -> *mut servicepoint::Bitmap { - if let Some(bitmap) = servicepoint::Bitmap::new(width, height) { +) -> *mut Bitmap { + if let Some(bitmap) = Bitmap::new(width, height) { Box::leak(Box::new(bitmap)) } else { std::ptr::null_mut() @@ -62,9 +62,8 @@ pub unsafe extern "C" fn sp_bitmap_new( /// - the returned instance is freed in some way, either by using a consuming function or /// by explicitly calling [sp_bitmap_free]. #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_new_screen_sized( -) -> NonNull { - let result = Box::new(servicepoint::Bitmap::max_sized()); +pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull { + let result = Box::new(Bitmap::max_sized()); NonNull::from(Box::leak(result)) } @@ -99,12 +98,10 @@ pub unsafe extern "C" fn sp_bitmap_new_screen_sized( pub unsafe extern "C" fn sp_bitmap_load( width: usize, height: usize, - data: *const u8, - data_length: usize, -) -> *mut servicepoint::Bitmap { - assert!(!data.is_null()); - let data = unsafe { std::slice::from_raw_parts(data, data_length) }; - if let Ok(bitmap) = servicepoint::Bitmap::load(width, height, data) { + data: SPByteSlice, +) -> *mut Bitmap { + let data = unsafe { data.as_slice() }; + if let Ok(bitmap) = Bitmap::load(width, height, data) { Box::leak(Box::new(bitmap)) } else { std::ptr::null_mut() @@ -129,10 +126,9 @@ pub unsafe extern "C" fn sp_bitmap_load( /// by explicitly calling `sp_bitmap_free`. #[no_mangle] pub unsafe extern "C" fn sp_bitmap_clone( - bitmap: *const servicepoint::Bitmap, -) -> NonNull { - assert!(!bitmap.is_null()); - let result = Box::new(unsafe { (*bitmap).clone() }); + bitmap: NonNull, +) -> NonNull { + let result = Box::new(unsafe { bitmap.as_ref().clone() }); NonNull::from(Box::leak(result)) } @@ -147,14 +143,11 @@ pub unsafe extern "C" fn sp_bitmap_clone( /// The caller has to make sure that: /// /// - `bitmap` points to a valid [SPBitmap] -/// - `bitmap` is not used concurrently or after bitmap call -/// - `bitmap` was not passed to another consuming function, e.g. to create a [SPCommand] /// /// [SPCommand]: [crate::SPCommand] #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_free(bitmap: *mut servicepoint::Bitmap) { - assert!(!bitmap.is_null()); - _ = unsafe { Box::from_raw(bitmap) }; +pub unsafe extern "C" fn sp_bitmap_free(bitmap: NonNull) { + _ = unsafe { Box::from_raw(bitmap.as_ptr()) }; } /// Gets the current value at the specified position in the [SPBitmap]. @@ -177,12 +170,11 @@ pub unsafe extern "C" fn sp_bitmap_free(bitmap: *mut servicepoint::Bitmap) { /// - `bitmap` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitmap_get( - bitmap: *const servicepoint::Bitmap, + bitmap: NonNull, x: usize, y: usize, ) -> bool { - assert!(!bitmap.is_null()); - unsafe { (*bitmap).get(x, y) } + unsafe { bitmap.as_ref().get(x, y) } } /// Sets the value of the specified position in the [SPBitmap]. @@ -208,13 +200,12 @@ pub unsafe extern "C" fn sp_bitmap_get( /// - `bitmap` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitmap_set( - bitmap: *mut servicepoint::Bitmap, + bitmap: NonNull, x: usize, y: usize, value: bool, ) { - assert!(!bitmap.is_null()); - unsafe { (*bitmap).set(x, y, value) }; + unsafe { (*bitmap.as_ptr()).set(x, y, value) }; } /// Sets the state of all pixels in the [SPBitmap]. @@ -235,12 +226,8 @@ pub unsafe extern "C" fn sp_bitmap_set( /// - `bitmap` points to a valid [SPBitmap] /// - `bitmap` is not written to or read from concurrently #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_fill( - bitmap: *mut servicepoint::Bitmap, - value: bool, -) { - assert!(!bitmap.is_null()); - unsafe { (*bitmap).fill(value) }; +pub unsafe extern "C" fn sp_bitmap_fill(bitmap: NonNull, value: bool) { + unsafe { (*bitmap.as_ptr()).fill(value) }; } /// Gets the width in pixels of the [SPBitmap] instance. @@ -259,11 +246,8 @@ pub unsafe extern "C" fn sp_bitmap_fill( /// /// - `bitmap` points to a valid [SPBitmap] #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_width( - bitmap: *const servicepoint::Bitmap, -) -> usize { - assert!(!bitmap.is_null()); - unsafe { (*bitmap).width() } +pub unsafe extern "C" fn sp_bitmap_width(bitmap: NonNull) -> usize { + unsafe { bitmap.as_ref().width() } } /// Gets the height in pixels of the [SPBitmap] instance. @@ -282,11 +266,8 @@ pub unsafe extern "C" fn sp_bitmap_width( /// /// - `bitmap` points to a valid [SPBitmap] #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_height( - bitmap: *const servicepoint::Bitmap, -) -> usize { - assert!(!bitmap.is_null()); - unsafe { (*bitmap).height() } +pub unsafe extern "C" fn sp_bitmap_height(bitmap: NonNull) -> usize { + unsafe { bitmap.as_ref().height() } } /// Gets an unsafe reference to the data of the [SPBitmap] instance. @@ -304,8 +285,7 @@ pub unsafe extern "C" fn sp_bitmap_height( /// - the returned memory range is never accessed concurrently, either via the [SPBitmap] or directly #[no_mangle] pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref( - bitmap: *mut servicepoint::Bitmap, + mut bitmap: NonNull, ) -> SPByteSlice { - assert!(!bitmap.is_null()); - unsafe { SPByteSlice::from_slice((*bitmap).data_ref_mut()) } + unsafe { SPByteSlice::from_slice(bitmap.as_mut().data_ref_mut()) } } diff --git a/src/bitvec.rs b/src/bitvec.rs index 104ca27..c32ce78 100644 --- a/src/bitvec.rs +++ b/src/bitvec.rs @@ -13,19 +13,7 @@ use std::ptr::NonNull; /// sp_bitvec_set(vec, 5, true); /// sp_bitvec_free(vec); /// ``` -pub struct SPBitVec(servicepoint::BitVecU8Msb0); - -impl From for SPBitVec { - fn from(actual: servicepoint::BitVecU8Msb0) -> Self { - Self(actual) - } -} - -impl From for servicepoint::BitVecU8Msb0 { - fn from(value: SPBitVec) -> Self { - value.0 - } -} +pub struct SPBitVec(pub(crate) servicepoint::BitVecU8Msb0); impl Clone for SPBitVec { fn clone(&self) -> Self { @@ -53,7 +41,8 @@ impl Clone for SPBitVec { /// by explicitly calling `sp_bitvec_free`. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_new(size: usize) -> NonNull { - let result = Box::new(SPBitVec(servicepoint::BitVecU8Msb0::repeat(false, size))); + let result = + Box::new(SPBitVec(servicepoint::BitVecU8Msb0::repeat(false, size))); NonNull::from(Box::leak(result)) } @@ -75,12 +64,11 @@ pub unsafe extern "C" fn sp_bitvec_new(size: usize) -> NonNull { /// by explicitly calling `sp_bitvec_free`. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_load( - data: *const u8, - data_length: usize, + data: SPByteSlice, ) -> NonNull { - assert!(!data.is_null()); - let data = unsafe { std::slice::from_raw_parts(data, data_length) }; - let result = Box::new(SPBitVec(servicepoint::BitVecU8Msb0::from_slice(data))); + let data = unsafe { data.as_slice() }; + let result = + Box::new(SPBitVec(servicepoint::BitVecU8Msb0::from_slice(data))); NonNull::from(Box::leak(result)) } @@ -102,10 +90,9 @@ pub unsafe extern "C" fn sp_bitvec_load( /// by explicitly calling `sp_bitvec_free`. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_clone( - bit_vec: *const SPBitVec, + bit_vec: NonNull, ) -> NonNull { - assert!(!bit_vec.is_null()); - let result = Box::new(unsafe { (*bit_vec).clone() }); + let result = Box::new(unsafe { bit_vec.as_ref().clone() }); NonNull::from(Box::leak(result)) } @@ -125,9 +112,8 @@ pub unsafe extern "C" fn sp_bitvec_clone( /// /// [SPCommand]: [crate::SPCommand] #[no_mangle] -pub unsafe extern "C" fn sp_bitvec_free(bit_vec: *mut SPBitVec) { - assert!(!bit_vec.is_null()); - _ = unsafe { Box::from_raw(bit_vec) }; +pub unsafe extern "C" fn sp_bitvec_free(bit_vec: NonNull) { + _ = unsafe { Box::from_raw(bit_vec.as_ptr()) }; } /// Gets the value of a bit from the [SPBitVec]. @@ -152,11 +138,10 @@ pub unsafe extern "C" fn sp_bitvec_free(bit_vec: *mut SPBitVec) { /// - `bit_vec` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitvec_get( - bit_vec: *const SPBitVec, + bit_vec: NonNull, index: usize, ) -> bool { - assert!(!bit_vec.is_null()); - unsafe { *(*bit_vec).0.get(index).unwrap() } + unsafe { *bit_vec.as_ref().0.get(index).unwrap() } } /// Sets the value of a bit in the [SPBitVec]. @@ -180,12 +165,11 @@ pub unsafe extern "C" fn sp_bitvec_get( /// - `bit_vec` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitvec_set( - bit_vec: *mut SPBitVec, + bit_vec: NonNull, index: usize, value: bool, ) { - assert!(!bit_vec.is_null()); - unsafe { (*bit_vec).0.set(index, value) } + unsafe { (*bit_vec.as_ptr()).0.set(index, value) } } /// Sets the value of all bits in the [SPBitVec]. @@ -206,9 +190,11 @@ pub unsafe extern "C" fn sp_bitvec_set( /// - `bit_vec` points to a valid [SPBitVec] /// - `bit_vec` is not written to or read from concurrently #[no_mangle] -pub unsafe extern "C" fn sp_bitvec_fill(bit_vec: *mut SPBitVec, value: bool) { - assert!(!bit_vec.is_null()); - unsafe { (*bit_vec).0.fill(value) } +pub unsafe extern "C" fn sp_bitvec_fill( + bit_vec: NonNull, + value: bool, +) { + unsafe { (*bit_vec.as_ptr()).0.fill(value) } } /// Gets the length of the [SPBitVec] in bits. @@ -227,9 +213,8 @@ pub unsafe extern "C" fn sp_bitvec_fill(bit_vec: *mut SPBitVec, value: bool) { /// /// - `bit_vec` points to a valid [SPBitVec] #[no_mangle] -pub unsafe extern "C" fn sp_bitvec_len(bit_vec: *const SPBitVec) -> usize { - assert!(!bit_vec.is_null()); - unsafe { (*bit_vec).0.len() } +pub unsafe extern "C" fn sp_bitvec_len(bit_vec: NonNull) -> usize { + unsafe { bit_vec.as_ref().0.len() } } /// Returns true if length is 0. @@ -248,9 +233,10 @@ pub unsafe extern "C" fn sp_bitvec_len(bit_vec: *const SPBitVec) -> usize { /// /// - `bit_vec` points to a valid [SPBitVec] #[no_mangle] -pub unsafe extern "C" fn sp_bitvec_is_empty(bit_vec: *const SPBitVec) -> bool { - assert!(!bit_vec.is_null()); - unsafe { (*bit_vec).0.is_empty() } +pub unsafe extern "C" fn sp_bitvec_is_empty( + bit_vec: NonNull, +) -> bool { + unsafe { bit_vec.as_ref().0.is_empty() } } /// Gets an unsafe reference to the data of the [SPBitVec] instance. @@ -272,8 +258,7 @@ pub unsafe extern "C" fn sp_bitvec_is_empty(bit_vec: *const SPBitVec) -> bool { /// - the returned memory range is never accessed concurrently, either via the [SPBitVec] or directly #[no_mangle] pub unsafe extern "C" fn sp_bitvec_unsafe_data_ref( - bit_vec: *mut SPBitVec, + bit_vec: NonNull, ) -> SPByteSlice { - assert!(!bit_vec.is_null()); - unsafe { SPByteSlice::from_slice((*bit_vec).0.as_raw_mut_slice() ) } + unsafe { SPByteSlice::from_slice((*bit_vec.as_ptr()).0.as_raw_mut_slice()) } } diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index 4620a7d..c6abbb4 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -32,7 +32,6 @@ pub const SP_BRIGHTNESS_MAX: u8 = 11; /// Count of possible brightness values pub const SP_BRIGHTNESS_LEVELS: u8 = 12; - /// Creates a new [SPBrightnessGrid] with the specified dimensions. /// /// returns: [SPBrightnessGrid] initialized to 0. Will never return NULL. @@ -48,9 +47,7 @@ pub unsafe extern "C" fn sp_brightness_grid_new( width: usize, height: usize, ) -> NonNull { - let result = Box::new(servicepoint::BrightnessGrid::new( - width, height, - )); + let result = Box::new(BrightnessGrid::new(width, height)); NonNull::from(Box::leak(result)) } @@ -75,16 +72,14 @@ pub unsafe extern "C" fn sp_brightness_grid_new( pub unsafe extern "C" fn sp_brightness_grid_load( width: usize, height: usize, - data: *const u8, - data_length: usize, + data: SPByteSlice, ) -> *mut BrightnessGrid { - assert!(!data.is_null()); - let data = unsafe { std::slice::from_raw_parts(data, data_length) }; + let data = unsafe { data.as_slice() }; let grid = match servicepoint::ByteGrid::load(width, height, data) { None => return std::ptr::null_mut(), Some(grid) => grid, }; - if let Ok(grid) = servicepoint::BrightnessGrid::try_from(grid) { + if let Ok(grid) = BrightnessGrid::try_from(grid) { Box::leak(Box::new(grid)) } else { std::ptr::null_mut() @@ -113,10 +108,9 @@ pub unsafe extern "C" fn sp_brightness_grid_load( /// by explicitly calling `sp_brightness_grid_free`. #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_clone( - brightness_grid: *const BrightnessGrid, + brightness_grid: NonNull, ) -> NonNull { - assert!(!brightness_grid.is_null()); - let result = Box::new(unsafe { (*brightness_grid).clone() }); + let result = Box::new(unsafe { brightness_grid.as_ref().clone() }); NonNull::from(Box::leak(result)) } @@ -141,10 +135,9 @@ pub unsafe extern "C" fn sp_brightness_grid_clone( /// [SPCommand]: [crate::SPCommand] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_free( - brightness_grid: *mut BrightnessGrid, + brightness_grid: NonNull, ) { - assert!(!brightness_grid.is_null()); - _ = unsafe { Box::from_raw(brightness_grid) }; + _ = unsafe { Box::from_raw(brightness_grid.as_ptr()) }; } /// Gets the current value at the specified position. @@ -169,12 +162,11 @@ pub unsafe extern "C" fn sp_brightness_grid_free( /// - `brightness_grid` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_get( - brightness_grid: *const BrightnessGrid, + brightness_grid: NonNull, x: usize, y: usize, ) -> u8 { - assert!(!brightness_grid.is_null()); - unsafe { (*brightness_grid).get(x, y) }.into() + unsafe { brightness_grid.as_ref().get(x, y) }.into() } /// Sets the value of the specified position in the [SPBrightnessGrid]. @@ -201,15 +193,14 @@ pub unsafe extern "C" fn sp_brightness_grid_get( /// - `brightness_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_set( - brightness_grid: *mut BrightnessGrid, + brightness_grid: NonNull, x: usize, y: usize, value: u8, ) { - assert!(!brightness_grid.is_null()); let brightness = servicepoint::Brightness::try_from(value) .expect("invalid brightness value"); - unsafe { (*brightness_grid).set(x, y, brightness) }; + unsafe { (*brightness_grid.as_ptr()).set(x, y, brightness) }; } /// Sets the value of all cells in the [SPBrightnessGrid]. @@ -232,13 +223,12 @@ pub unsafe extern "C" fn sp_brightness_grid_set( /// - `brightness_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_fill( - brightness_grid: *mut BrightnessGrid, + brightness_grid: NonNull, value: u8, ) { - assert!(!brightness_grid.is_null()); let brightness = servicepoint::Brightness::try_from(value) .expect("invalid brightness value"); - unsafe { (*brightness_grid).fill(brightness) }; + unsafe { (*brightness_grid.as_ptr()).fill(brightness) }; } /// Gets the width of the [SPBrightnessGrid] instance. @@ -260,10 +250,9 @@ pub unsafe extern "C" fn sp_brightness_grid_fill( /// - `brightness_grid` points to a valid [SPBrightnessGrid] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_width( - brightness_grid: *const BrightnessGrid, + brightness_grid: NonNull, ) -> usize { - assert!(!brightness_grid.is_null()); - unsafe { (*brightness_grid).width() } + unsafe { brightness_grid.as_ref().width() } } /// Gets the height of the [SPBrightnessGrid] instance. @@ -285,10 +274,9 @@ pub unsafe extern "C" fn sp_brightness_grid_width( /// - `brightness_grid` points to a valid [SPBrightnessGrid] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_height( - brightness_grid: *const BrightnessGrid, + brightness_grid: NonNull, ) -> usize { - assert!(!brightness_grid.is_null()); - unsafe { (*brightness_grid).height() } + unsafe { brightness_grid.as_ref().height() } } /// Gets an unsafe reference to the data of the [SPBrightnessGrid] instance. @@ -312,12 +300,10 @@ pub unsafe extern "C" fn sp_brightness_grid_height( /// - the returned memory range is never accessed concurrently, either via the [SPBrightnessGrid] or directly #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( - brightness_grid: *mut BrightnessGrid, + brightness_grid: NonNull, ) -> SPByteSlice { - assert!(!brightness_grid.is_null()); - assert_eq!(core::mem::size_of::(), 1); - let data = unsafe { (*brightness_grid).data_ref_mut() }; + assert_eq!(size_of::(), 1); + let data = unsafe { (*brightness_grid.as_ptr()).data_ref_mut() }; // this assumes more about the memory layout than rust guarantees. yikes! unsafe { SPByteSlice::from_slice(transmute(data)) } - } diff --git a/src/byte_slice.rs b/src/byte_slice.rs index a87c952..066a405 100644 --- a/src/byte_slice.rs +++ b/src/byte_slice.rs @@ -28,7 +28,7 @@ impl SPByteSlice { unsafe { std::slice::from_raw_parts(self.start.as_ptr(), self.length) } } - pub(crate) unsafe fn as_slice_mut(&mut self) -> &mut [u8] { + pub(crate) unsafe fn as_slice_mut(&self) -> &mut [u8] { unsafe { std::slice::from_raw_parts_mut(self.start.as_ptr(), self.length) } diff --git a/src/char_grid.rs b/src/char_grid.rs index 71013d5..a845f4e 100644 --- a/src/char_grid.rs +++ b/src/char_grid.rs @@ -18,6 +18,7 @@ //! sp_char_grid_free(grid); //! ``` +use crate::SPByteSlice; use servicepoint::{CharGrid, Grid}; use std::ptr::NonNull; @@ -36,7 +37,7 @@ pub unsafe extern "C" fn sp_char_grid_new( width: usize, height: usize, ) -> NonNull { - let result = Box::new(CharGrid::new(width, height)); + let result = Box::new(CharGrid::new(width, height)); NonNull::from(Box::leak(result)) } @@ -62,16 +63,12 @@ pub unsafe extern "C" fn sp_char_grid_new( pub unsafe extern "C" fn sp_char_grid_load( width: usize, height: usize, - data: *const u8, - data_length: usize, + data: SPByteSlice, ) -> NonNull { - assert!(data.is_null()); - let data = unsafe { std::slice::from_raw_parts(data, data_length) }; + let data = unsafe { data.as_slice() }; // TODO remove unwrap - let result = Box::new( - CharGrid::load_utf8(width, height, data.to_vec()) - .unwrap(), - ); + let result = + Box::new(CharGrid::load_utf8(width, height, data.to_vec()).unwrap()); NonNull::from(Box::leak(result)) } @@ -93,10 +90,9 @@ pub unsafe extern "C" fn sp_char_grid_load( /// by explicitly calling `sp_char_grid_free`. #[no_mangle] pub unsafe extern "C" fn sp_char_grid_clone( - char_grid: *const CharGrid, + char_grid: NonNull, ) -> NonNull { - assert!(!char_grid.is_null()); - let result = Box::new(unsafe { (*char_grid).clone() }); + let result = Box::new(unsafe { char_grid.as_ref().clone() }); NonNull::from(Box::leak(result)) } @@ -116,9 +112,8 @@ pub unsafe extern "C" fn sp_char_grid_clone( /// /// [SPCommand]: [crate::SPCommand] #[no_mangle] -pub unsafe extern "C" fn sp_char_grid_free(char_grid: *mut CharGrid) { - assert!(!char_grid.is_null()); - _ = unsafe { Box::from_raw(char_grid) }; +pub unsafe extern "C" fn sp_char_grid_free(char_grid: NonNull) { + _ = unsafe { Box::from_raw(char_grid.as_ptr()) }; } /// Gets the current value at the specified position. @@ -141,12 +136,11 @@ pub unsafe extern "C" fn sp_char_grid_free(char_grid: *mut CharGrid) { /// - `char_grid` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_char_grid_get( - char_grid: *const CharGrid, + char_grid: NonNull, x: usize, y: usize, ) -> u32 { - assert!(!char_grid.is_null()); - unsafe { (*char_grid).get(x, y) as u32 } + unsafe { char_grid.as_ref().get(x, y) as u32 } } /// Sets the value of the specified position in the [SPCharGrid]. @@ -174,13 +168,12 @@ pub unsafe extern "C" fn sp_char_grid_get( /// [SPBitVec]: [crate::SPBitVec] #[no_mangle] pub unsafe extern "C" fn sp_char_grid_set( - char_grid: *mut CharGrid, + char_grid: NonNull, x: usize, y: usize, value: u32, ) { - assert!(!char_grid.is_null()); - unsafe { (*char_grid).set(x, y, char::from_u32(value).unwrap()) }; + unsafe { (*char_grid.as_ptr()).set(x, y, char::from_u32(value).unwrap()) }; } /// Sets the value of all cells in the [SPCharGrid]. @@ -202,11 +195,10 @@ pub unsafe extern "C" fn sp_char_grid_set( /// - `char_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_char_grid_fill( - char_grid: *mut CharGrid, + char_grid: NonNull, value: u32, ) { - assert!(!char_grid.is_null()); - unsafe { (*char_grid).fill(char::from_u32(value).unwrap()) }; + unsafe { (*char_grid.as_ptr()).fill(char::from_u32(value).unwrap()) }; } /// Gets the width of the [SPCharGrid] instance. @@ -226,10 +218,9 @@ pub unsafe extern "C" fn sp_char_grid_fill( /// - `char_grid` points to a valid [SPCharGrid] #[no_mangle] pub unsafe extern "C" fn sp_char_grid_width( - char_grid: *const CharGrid, + char_grid: NonNull, ) -> usize { - assert!(!char_grid.is_null()); - unsafe { (*char_grid).width() } + unsafe { char_grid.as_ref().width() } } /// Gets the height of the [SPCharGrid] instance. @@ -249,8 +240,7 @@ pub unsafe extern "C" fn sp_char_grid_width( /// - `char_grid` points to a valid [SPCharGrid] #[no_mangle] pub unsafe extern "C" fn sp_char_grid_height( - char_grid: *const CharGrid, + char_grid: NonNull, ) -> usize { - assert!(!char_grid.is_null()); - unsafe { (*char_grid).height() } + unsafe { char_grid.as_ref().height() } } diff --git a/src/command.rs b/src/command.rs index a4a2736..eccac1b 100644 --- a/src/command.rs +++ b/src/command.rs @@ -2,8 +2,11 @@ //! //! prefix `sp_command_` -use crate::{SPBitVec}; -use servicepoint::{BinaryOperation, BrightnessGrid, CharGrid, CompressionCode, Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand}; +use crate::SPBitVec; +use servicepoint::{ + BinaryOperation, Bitmap, BrightnessGrid, CharGrid, CompressionCode, + Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand, +}; use std::ptr::NonNull; /// A low-level display command. @@ -21,7 +24,6 @@ use std::ptr::NonNull; /// /// [SPConnection]: [crate::SPConnection] - /// Tries to turn a [SPPacket] into a [SPCommand]. /// /// The packet is deallocated in the process. @@ -43,9 +45,9 @@ use std::ptr::NonNull; /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_try_from_packet( - packet: *mut Packet, + packet: NonNull, ) -> *mut TypedCommand { - let packet = *unsafe { Box::from_raw(packet) }; + let packet = *unsafe { Box::from_raw(packet.as_ptr()) }; match servicepoint::TypedCommand::try_from(packet) { Err(_) => std::ptr::null_mut(), Ok(command) => Box::into_raw(Box::new(command)), @@ -70,10 +72,9 @@ pub unsafe extern "C" fn sp_command_try_from_packet( /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_clone( - command: *const TypedCommand, + command: NonNull, ) -> NonNull { - assert!(!command.is_null()); - let result = Box::new(unsafe { (*command).clone() }); + let result = Box::new(unsafe { command.as_ref().clone() }); NonNull::from(Box::leak(result)) } @@ -155,8 +156,7 @@ pub unsafe extern "C" fn sp_command_brightness( ) -> NonNull { let brightness = servicepoint::Brightness::try_from(brightness) .expect("invalid brightness"); - let result = - Box::new(GlobalBrightnessCommand::from(brightness).into()); + let result = Box::new(GlobalBrightnessCommand::from(brightness).into()); NonNull::from(Box::leak(result)) } @@ -182,10 +182,9 @@ pub unsafe extern "C" fn sp_command_brightness( pub unsafe extern "C" fn sp_command_char_brightness( x: usize, y: usize, - grid: *mut BrightnessGrid, + grid: NonNull, ) -> NonNull { - assert!(!grid.is_null()); - let grid = unsafe { *Box::from_raw(grid) }; + let grid = unsafe { *Box::from_raw(grid.as_ptr()) }; let result = Box::new( servicepoint::BrightnessGridCommand { origin: servicepoint::Origin::new(x, y), @@ -224,7 +223,7 @@ pub unsafe extern "C" fn sp_command_char_brightness( #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear( offset: usize, - bit_vec: *mut SPBitVec, + bit_vec: NonNull, compression: CompressionCode, ) -> *mut TypedCommand { unsafe { @@ -265,7 +264,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear( #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_and( offset: usize, - bit_vec: *mut SPBitVec, + bit_vec: NonNull, compression: CompressionCode, ) -> *mut TypedCommand { unsafe { @@ -306,7 +305,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and( #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_or( offset: usize, - bit_vec: *mut SPBitVec, + bit_vec: NonNull, compression: CompressionCode, ) -> *mut TypedCommand { unsafe { @@ -347,7 +346,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or( #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_xor( offset: usize, - bit_vec: *mut SPBitVec, + bit_vec: NonNull, compression: CompressionCode, ) -> *mut TypedCommand { unsafe { @@ -363,23 +362,22 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor( #[inline] unsafe fn sp_command_bitmap_linear_internal( offset: usize, - bit_vec: *mut SPBitVec, + bit_vec: NonNull, compression: CompressionCode, operation: BinaryOperation, ) -> *mut TypedCommand { - assert!(!bit_vec.is_null()); - let bit_vec = unsafe { *Box::from_raw(bit_vec) }; + let bit_vec = unsafe { *Box::from_raw(bit_vec.as_ptr()) }; let compression = match compression.try_into() { Ok(compression) => compression, Err(_) => return std::ptr::null_mut(), }; - let command = servicepoint::BitVecCommand { - offset, - operation, - bitvec: bit_vec.into(), - compression, - } - .into(); + let command = servicepoint::BitVecCommand { + offset, + operation, + bitvec: bit_vec.0, + compression, + } + .into(); Box::leak(Box::new(command)) } @@ -405,10 +403,9 @@ unsafe fn sp_command_bitmap_linear_internal( pub unsafe extern "C" fn sp_command_cp437_data( x: usize, y: usize, - grid: *mut Cp437Grid, + grid: NonNull, ) -> NonNull { - assert!(!grid.is_null()); - let grid = *unsafe { Box::from_raw(grid) }; + let grid = *unsafe { Box::from_raw(grid.as_ptr()) }; let result = Box::new( servicepoint::Cp437GridCommand { origin: servicepoint::Origin::new(x, y), @@ -441,10 +438,9 @@ pub unsafe extern "C" fn sp_command_cp437_data( pub unsafe extern "C" fn sp_command_utf8_data( x: usize, y: usize, - grid: *mut CharGrid, + grid: NonNull, ) -> NonNull { - assert!(!grid.is_null()); - let grid = unsafe { *Box::from_raw(grid) }; + let grid = unsafe { *Box::from_raw(grid.as_ptr()) }; let result = Box::new( servicepoint::CharGridCommand { origin: servicepoint::Origin::new(x, y), @@ -479,21 +475,20 @@ pub unsafe extern "C" fn sp_command_utf8_data( pub unsafe extern "C" fn sp_command_bitmap_linear_win( x: usize, y: usize, - bitmap: *mut servicepoint::Bitmap, + bitmap: NonNull, compression: CompressionCode, ) -> *mut TypedCommand { - assert!(!bitmap.is_null()); - let bitmap = unsafe { *Box::from_raw(bitmap) }; + let bitmap = unsafe { *Box::from_raw(bitmap.as_ptr()) }; let compression = match compression.try_into() { Ok(compression) => compression, Err(_) => return std::ptr::null_mut(), }; - let command = servicepoint::BitmapCommand { - origin: servicepoint::Origin::new(x, y), - bitmap, - compression, - } - .into(); + let command = servicepoint::BitmapCommand { + origin: servicepoint::Origin::new(x, y), + bitmap, + compression, + } + .into(); Box::leak(Box::new(command)) } @@ -518,7 +513,6 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win( /// - `command` is not used concurrently or after this call /// - `command` was not passed to another consuming function, e.g. to create a [SPPacket] #[no_mangle] -pub unsafe extern "C" fn sp_command_free(command: *mut TypedCommand) { - assert!(!command.is_null()); - _ = unsafe { Box::from_raw(command) }; +pub unsafe extern "C" fn sp_command_free(command: NonNull) { + _ = unsafe { Box::from_raw(command.as_ptr()) }; } diff --git a/src/connection.rs b/src/connection.rs index 9458727..1705538 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -14,6 +14,7 @@ use servicepoint::{Connection, Packet, TypedCommand, UdpConnection}; use std::ffi::{c_char, CStr}; +use std::ptr::NonNull; /// Creates a new instance of [SPConnection]. /// @@ -31,10 +32,9 @@ use std::ffi::{c_char, CStr}; /// by explicitly calling `sp_connection_free`. #[no_mangle] pub unsafe extern "C" fn sp_connection_open( - host: *const c_char, + host: NonNull, ) -> *mut UdpConnection { - assert!(!host.is_null()); - let host = unsafe { CStr::from_ptr(host) } + let host = unsafe { CStr::from_ptr(host.as_ptr()) } .to_str() .expect("Bad encoding"); let connection = match UdpConnection::open(host) { @@ -93,13 +93,11 @@ pub unsafe extern "C" fn sp_connection_open( /// - `packet` is not used concurrently or after this call #[no_mangle] pub unsafe extern "C" fn sp_connection_send_packet( - connection: *const UdpConnection, - packet: *mut Packet, + connection: NonNull, + packet: NonNull, ) -> bool { - assert!(!connection.is_null()); - assert!(!packet.is_null()); - let packet = unsafe { Box::from_raw(packet) }; - unsafe { (*connection).send(*packet) }.is_ok() + let packet = unsafe { Box::from_raw(packet.as_ptr()) }; + unsafe { connection.as_ref().send(*packet) }.is_ok() } /// Sends a [SPCommand] to the display using the [SPConnection]. @@ -122,13 +120,11 @@ pub unsafe extern "C" fn sp_connection_send_packet( /// - `command` is not used concurrently or after this call #[no_mangle] pub unsafe extern "C" fn sp_connection_send_command( - connection: *const UdpConnection, - command: *mut TypedCommand, + connection: NonNull, + command: NonNull, ) -> bool { - assert!(!connection.is_null()); - assert!(!command.is_null()); - let command = *unsafe { Box::from_raw(command) }; - unsafe { (*connection).send(command) }.is_ok() + let command = *unsafe { Box::from_raw(command.as_ptr()) }; + unsafe { connection.as_ref().send(command) }.is_ok() } /// Closes and deallocates a [SPConnection]. @@ -144,7 +140,8 @@ pub unsafe extern "C" fn sp_connection_send_command( /// - `connection` points to a valid [SPConnection] /// - `connection` is not used concurrently or after this call #[no_mangle] -pub unsafe extern "C" fn sp_connection_free(connection: *mut UdpConnection) { - assert!(!connection.is_null()); - _ = unsafe { Box::from_raw(connection) }; +pub unsafe extern "C" fn sp_connection_free( + connection: NonNull, +) { + _ = unsafe { Box::from_raw(connection.as_ptr()) }; } diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index 2ec009d..e635247 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -35,7 +35,7 @@ pub unsafe extern "C" fn sp_cp437_grid_new( width: usize, height: usize, ) -> NonNull { - let result = Box::new(Cp437Grid::new(width, height)); + let result = Box::new(Cp437Grid::new(width, height)); NonNull::from(Box::leak(result)) } @@ -60,11 +60,9 @@ pub unsafe extern "C" fn sp_cp437_grid_new( pub unsafe extern "C" fn sp_cp437_grid_load( width: usize, height: usize, - data: *const u8, - data_length: usize, + data: SPByteSlice, ) -> *mut Cp437Grid { - assert!(data.is_null()); - let data = unsafe { std::slice::from_raw_parts(data, data_length) }; + let data = unsafe { data.as_slice() }; let grid = Cp437Grid::load(width, height, data); if let Some(grid) = grid { Box::leak(Box::new(grid)) @@ -91,10 +89,9 @@ pub unsafe extern "C" fn sp_cp437_grid_load( /// by explicitly calling `sp_cp437_grid_free`. #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_clone( - cp437_grid: *const Cp437Grid, + cp437_grid: NonNull, ) -> NonNull { - assert!(!cp437_grid.is_null()); - let result = Box::new(unsafe { (*cp437_grid).clone() }); + let result = Box::new(unsafe { cp437_grid.as_ref().clone() }); NonNull::from(Box::leak(result)) } @@ -114,9 +111,8 @@ pub unsafe extern "C" fn sp_cp437_grid_clone( /// /// [SPCommand]: [crate::SPCommand] #[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: *mut Cp437Grid) { - assert!(!cp437_grid.is_null()); - _ = unsafe { Box::from_raw(cp437_grid) }; +pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: NonNull) { + _ = unsafe { Box::from_raw(cp437_grid.as_ptr()) }; } /// Gets the current value at the specified position. @@ -139,12 +135,11 @@ pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: *mut Cp437Grid) { /// - `cp437_grid` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_get( - cp437_grid: *const Cp437Grid, + cp437_grid: NonNull, x: usize, y: usize, ) -> u8 { - assert!(!cp437_grid.is_null()); - unsafe { (*cp437_grid).get(x, y) } + unsafe { cp437_grid.as_ref().get(x, y) } } /// Sets the value of the specified position in the [SPCp437Grid]. @@ -172,13 +167,12 @@ pub unsafe extern "C" fn sp_cp437_grid_get( /// [SPBitVec]: [crate::SPBitVec] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_set( - cp437_grid: *mut Cp437Grid, + cp437_grid: NonNull, x: usize, y: usize, value: u8, ) { - assert!(!cp437_grid.is_null()); - unsafe { (*cp437_grid).set(x, y, value) }; + unsafe { (*cp437_grid.as_ptr()).set(x, y, value) }; } /// Sets the value of all cells in the [SPCp437Grid]. @@ -200,11 +194,10 @@ pub unsafe extern "C" fn sp_cp437_grid_set( /// - `cp437_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_fill( - cp437_grid: *mut Cp437Grid, + cp437_grid: NonNull, value: u8, ) { - assert!(!cp437_grid.is_null()); - unsafe { (*cp437_grid).fill(value) }; + unsafe { (*cp437_grid.as_ptr()).fill(value) }; } /// Gets the width of the [SPCp437Grid] instance. @@ -224,10 +217,9 @@ pub unsafe extern "C" fn sp_cp437_grid_fill( /// - `cp437_grid` points to a valid [SPCp437Grid] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_width( - cp437_grid: *const Cp437Grid, + cp437_grid: NonNull, ) -> usize { - assert!(!cp437_grid.is_null()); - unsafe { (*cp437_grid).width() } + unsafe { cp437_grid.as_ref().width() } } /// Gets the height of the [SPCp437Grid] instance. @@ -247,10 +239,9 @@ pub unsafe extern "C" fn sp_cp437_grid_width( /// - `cp437_grid` points to a valid [SPCp437Grid] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_height( - cp437_grid: *const Cp437Grid, + cp437_grid: NonNull, ) -> usize { - assert!(!cp437_grid.is_null()); - unsafe { (*cp437_grid).height() } + unsafe { cp437_grid.as_ref().height() } } /// Gets an unsafe reference to the data of the [SPCp437Grid] instance. @@ -270,7 +261,7 @@ pub unsafe extern "C" fn sp_cp437_grid_height( /// - the returned memory range is never accessed concurrently, either via the [SPCp437Grid] or directly #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref( - cp437_grid: *mut Cp437Grid, + cp437_grid: NonNull, ) -> SPByteSlice { - unsafe {SPByteSlice::from_slice((*cp437_grid).data_ref_mut()) } + unsafe { SPByteSlice::from_slice((*cp437_grid.as_ptr()).data_ref_mut()) } } diff --git a/src/lib.rs b/src/lib.rs index d00e579..831daea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,7 +45,6 @@ mod connection; mod cp437_grid; mod packet; - use std::time::Duration; /// Actual hardware limit is around 28-29ms/frame. Rounded up for less dropped packets. diff --git a/src/packet.rs b/src/packet.rs index 71bbbae..f8235ab 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -28,10 +28,9 @@ use std::ptr::NonNull; /// by explicitly calling `sp_packet_free`. #[no_mangle] pub unsafe extern "C" fn sp_packet_from_command( - command: *mut TypedCommand, + command: NonNull, ) -> *mut Packet { - assert!(!command.is_null()); - let command = unsafe { *Box::from_raw(command) }; + let command = unsafe { *Box::from_raw(command.as_ptr()) }; if let Ok(packet) = command.try_into() { Box::leak(Box::new(packet)) } else { @@ -56,12 +55,8 @@ pub unsafe extern "C" fn sp_packet_from_command( /// - the returned [SPPacket] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_packet_free`. #[no_mangle] -pub unsafe extern "C" fn sp_packet_try_load( - data: *const u8, - length: usize, -) -> *mut Packet { - assert!(!data.is_null()); - let data = unsafe { std::slice::from_raw_parts(data, length) }; +pub unsafe extern "C" fn sp_packet_try_load(data: SPByteSlice) -> *mut Packet { + let data = unsafe { data.as_slice() }; match servicepoint::Packet::try_from(data) { Err(_) => std::ptr::null_mut(), Ok(packet) => Box::into_raw(Box::new(packet)), @@ -95,16 +90,12 @@ pub unsafe extern "C" fn sp_packet_try_load( #[no_mangle] pub unsafe extern "C" fn sp_packet_from_parts( header: Header, - payload: *const u8, - payload_len: usize, + payload: *const SPByteSlice, ) -> NonNull { - assert_eq!(payload.is_null(), payload_len == 0); - let payload = if payload.is_null() { vec![] } else { - let payload = - unsafe { std::slice::from_raw_parts(payload, payload_len) }; + let payload = unsafe { (*payload).as_slice() }; Vec::from(payload) }; @@ -113,34 +104,34 @@ pub unsafe extern "C" fn sp_packet_from_parts( } #[no_mangle] -pub unsafe extern "C" fn sp_packet_get_header(packet: *mut Packet) -> *mut Header { - assert!(!packet.is_null()); - &mut unsafe { (*packet).header } +pub unsafe extern "C" fn sp_packet_get_header( + packet: NonNull, +) -> NonNull
{ + NonNull::from(&mut unsafe { (*packet.as_ptr()).header }) } #[no_mangle] -pub unsafe extern "C" fn sp_packet_get_payload(packet: *mut Packet) -> SPByteSlice { - assert!(!packet.is_null()); - unsafe { SPByteSlice::from_slice(&mut *(*packet).payload) } +pub unsafe extern "C" fn sp_packet_get_payload( + packet: NonNull, +) -> SPByteSlice { + unsafe { SPByteSlice::from_slice(&mut *(*packet.as_ptr()).payload) } } #[no_mangle] -pub unsafe extern "C" fn sp_packet_set_payload(packet: *mut Packet, data: SPByteSlice) { - assert!(!packet.is_null()); - unsafe { - (*packet).payload = data.as_slice().to_vec() - } +pub unsafe extern "C" fn sp_packet_set_payload( + packet: NonNull, + data: SPByteSlice, +) { + unsafe { (*packet.as_ptr()).payload = data.as_slice().to_vec() } } #[no_mangle] pub unsafe extern "C" fn sp_packet_write_to( - packet: *const Packet, - mut buffer: SPByteSlice, + packet: NonNull, + buffer: SPByteSlice, ) { - assert!(!packet.is_null()); - unsafe { - (*packet).serialize_to(buffer.as_slice_mut()); + packet.as_ref().serialize_to(buffer.as_slice_mut()); } } @@ -162,10 +153,9 @@ pub unsafe extern "C" fn sp_packet_write_to( /// by explicitly calling `sp_packet_free`. #[no_mangle] pub unsafe extern "C" fn sp_packet_clone( - packet: *const Packet, + packet: NonNull, ) -> NonNull { - assert!(!packet.is_null()); - let result = Box::new(unsafe { (*packet).clone() }); + let result = Box::new(unsafe { packet.as_ref().clone() }); NonNull::from(Box::leak(result)) } @@ -182,7 +172,6 @@ pub unsafe extern "C" fn sp_packet_clone( /// - `packet` points to a valid [SPPacket] /// - `packet` is not used concurrently or after this call #[no_mangle] -pub unsafe extern "C" fn sp_packet_free(packet: *mut Packet) { - assert!(!packet.is_null()); - _ = unsafe { Box::from_raw(packet) } +pub unsafe extern "C" fn sp_packet_free(packet: NonNull) { + _ = unsafe { Box::from_raw(packet.as_ptr()) } } -- 2.47.0 From cf2c72de7c7a4fd1b6a250fb84a8a64fc5265314 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 13:12:50 +0200 Subject: [PATCH 11/25] use brightness type from base crate --- include/servicepoint.h | 37 +++++++++++++++++++++++++++++++------ src/brightness_grid.rs | 31 ++++++++++--------------------- src/command.rs | 9 ++------- 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/include/servicepoint.h b/include/servicepoint.h index 4a0af95..b63e9bf 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -266,6 +266,31 @@ typedef struct { */ typedef ValueGrid_Brightness BrightnessGrid; +/** + * A display brightness value, checked for correct value range + * + * # Examples + * + * ``` + * # use servicepoint::*; + * let b = Brightness::MAX; + * let val: u8 = b.into(); + * + * let b = Brightness::try_from(7).unwrap(); + * # let connection = FakeConnection; + * let result = connection.send(GlobalBrightnessCommand::from(b)); + * ``` + */ +typedef uint8_t Brightness; +/** + * highest possible brightness value, 11 + */ +#define Brightness_MAX 11 +/** + * lowest possible brightness value, 0 + */ +#define Brightness_MIN 0 + /** * A grid containing UTF-8 characters. * @@ -819,7 +844,7 @@ BrightnessGrid */*notnull*/ sp_brightness_grid_clone(BrightnessGrid */*notnull*/ * - `brightness_grid` is not written to or read from concurrently */ void sp_brightness_grid_fill(BrightnessGrid */*notnull*/ brightness_grid, - uint8_t value); + Brightness value); /** * Deallocates a [SPBrightnessGrid]. @@ -866,9 +891,9 @@ void sp_brightness_grid_free(BrightnessGrid */*notnull*/ brightness_grid); * - `brightness_grid` points to a valid [SPBrightnessGrid] * - `brightness_grid` is not written to concurrently */ -uint8_t sp_brightness_grid_get(BrightnessGrid */*notnull*/ brightness_grid, - size_t x, - size_t y); +Brightness sp_brightness_grid_get(BrightnessGrid */*notnull*/ brightness_grid, + size_t x, + size_t y); /** * Gets the height of the [SPBrightnessGrid] instance. @@ -956,7 +981,7 @@ BrightnessGrid */*notnull*/ sp_brightness_grid_new(size_t width, void sp_brightness_grid_set(BrightnessGrid */*notnull*/ brightness_grid, size_t x, size_t y, - uint8_t value); + Brightness value); /** * Gets an unsafe reference to the data of the [SPBrightnessGrid] instance. @@ -1358,7 +1383,7 @@ Command *sp_command_bitmap_linear_xor(size_t offset, * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command */*notnull*/ sp_command_brightness(uint8_t brightness); +Command */*notnull*/ sp_command_brightness(Brightness brightness); /** * Set the brightness of individual tiles in a rectangular area of the display. diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index c6abbb4..0e9a052 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -20,18 +20,10 @@ //! ``` use crate::SPByteSlice; -use servicepoint::{BrightnessGrid, DataRef, Grid}; -use std::convert::Into; +use servicepoint::{Brightness, BrightnessGrid, DataRef, Grid}; use std::mem::transmute; use std::ptr::NonNull; -/// see [servicepoint::Brightness::MIN] -pub const SP_BRIGHTNESS_MIN: u8 = 0; -/// see [servicepoint::Brightness::MAX] -pub const SP_BRIGHTNESS_MAX: u8 = 11; -/// Count of possible brightness values -pub const SP_BRIGHTNESS_LEVELS: u8 = 12; - /// Creates a new [SPBrightnessGrid] with the specified dimensions. /// /// returns: [SPBrightnessGrid] initialized to 0. Will never return NULL. @@ -165,8 +157,8 @@ pub unsafe extern "C" fn sp_brightness_grid_get( brightness_grid: NonNull, x: usize, y: usize, -) -> u8 { - unsafe { brightness_grid.as_ref().get(x, y) }.into() +) -> Brightness { + unsafe { brightness_grid.as_ref().get(x, y) } } /// Sets the value of the specified position in the [SPBrightnessGrid]. @@ -196,11 +188,9 @@ pub unsafe extern "C" fn sp_brightness_grid_set( brightness_grid: NonNull, x: usize, y: usize, - value: u8, + value: Brightness, ) { - let brightness = servicepoint::Brightness::try_from(value) - .expect("invalid brightness value"); - unsafe { (*brightness_grid.as_ptr()).set(x, y, brightness) }; + unsafe { (*brightness_grid.as_ptr()).set(x, y, value) }; } /// Sets the value of all cells in the [SPBrightnessGrid]. @@ -224,11 +214,9 @@ pub unsafe extern "C" fn sp_brightness_grid_set( #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_fill( brightness_grid: NonNull, - value: u8, + value: Brightness, ) { - let brightness = servicepoint::Brightness::try_from(value) - .expect("invalid brightness value"); - unsafe { (*brightness_grid.as_ptr()).fill(brightness) }; + unsafe { (*brightness_grid.as_ptr()).fill(value) }; } /// Gets the width of the [SPBrightnessGrid] instance. @@ -302,8 +290,9 @@ pub unsafe extern "C" fn sp_brightness_grid_height( pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( brightness_grid: NonNull, ) -> SPByteSlice { - assert_eq!(size_of::(), 1); + //noinspection RsAssertEqual + const _: () = assert!(size_of::() == 1); + let data = unsafe { (*brightness_grid.as_ptr()).data_ref_mut() }; - // this assumes more about the memory layout than rust guarantees. yikes! unsafe { SPByteSlice::from_slice(transmute(data)) } } diff --git a/src/command.rs b/src/command.rs index eccac1b..e107c07 100644 --- a/src/command.rs +++ b/src/command.rs @@ -3,10 +3,7 @@ //! prefix `sp_command_` use crate::SPBitVec; -use servicepoint::{ - BinaryOperation, Bitmap, BrightnessGrid, CharGrid, CompressionCode, - Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand, -}; +use servicepoint::{BinaryOperation, Bitmap, Brightness, BrightnessGrid, CharGrid, CompressionCode, Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand}; use std::ptr::NonNull; /// A low-level display command. @@ -152,10 +149,8 @@ pub unsafe extern "C" fn sp_command_fade_out() -> NonNull { /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_brightness( - brightness: u8, + brightness: Brightness, ) -> NonNull { - let brightness = servicepoint::Brightness::try_from(brightness) - .expect("invalid brightness"); let result = Box::new(GlobalBrightnessCommand::from(brightness).into()); NonNull::from(Box::leak(result)) } -- 2.47.0 From 0c3bc0b0040b1b5513de64afa1efdab05f6a39dd Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 13:34:02 +0200 Subject: [PATCH 12/25] wip fix documentation --- cbindgen.toml | 3 +- example/main.c | 2 +- examples/.gitignore | 4 + include/servicepoint.h | 414 +++++++++++++++++++++-------------------- src/bitmap.rs | 74 ++++---- src/bitvec.rs | 4 +- src/brightness_grid.rs | 56 +++--- src/char_grid.rs | 36 ++-- src/command.rs | 72 ++++--- src/connection.rs | 24 +-- src/cp437_grid.rs | 44 ++--- src/lib.rs | 6 +- src/packet.rs | 46 +++-- 13 files changed, 405 insertions(+), 380 deletions(-) create mode 100644 examples/.gitignore diff --git a/cbindgen.toml b/cbindgen.toml index 48ef574..363d001 100644 --- a/cbindgen.toml +++ b/cbindgen.toml @@ -35,7 +35,8 @@ include = [] exclude = [] [export.rename] -"TypedCommand" = "Command" +"SpBitVec" = "BitVec" +"SpByteSlice" = "ByteSlice" [enum] rename_variants = "QualifiedScreamingSnakeCase" diff --git a/example/main.c b/example/main.c index 80a1756..4e63dec 100644 --- a/example/main.c +++ b/example/main.c @@ -12,7 +12,7 @@ int main(void) { sp_bitmap_fill(pixels, true); - Command *command = sp_command_bitmap_linear_win(0, 0, pixels, COMPRESSION_CODE_UNCOMPRESSED); + TypedCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, COMPRESSION_CODE_UNCOMPRESSED); if (command == NULL) return 1; diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 0000000..9415aeb --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,4 @@ +# examples only use library in this repo +Cargo.lock +out +target diff --git a/include/servicepoint.h b/include/servicepoint.h index b63e9bf..07bc8f8 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -37,21 +37,6 @@ */ #define PIXEL_WIDTH (TILE_WIDTH * TILE_SIZE) -/** - * Count of possible brightness values - */ -#define SP_BRIGHTNESS_LEVELS 12 - -/** - * see [servicepoint::Brightness::MAX] - */ -#define SP_BRIGHTNESS_MAX 11 - -/** - * see [servicepoint::Brightness::MIN] - */ -#define SP_BRIGHTNESS_MIN 0 - /** * Display tile count in the y-direction * @@ -179,7 +164,7 @@ typedef struct SPBitVec SPBitVec; * * Please look at the contained structs for documentation per command. */ -typedef struct Command Command; +typedef struct TypedCommand TypedCommand; /** * A connection using the UDP protocol. @@ -359,7 +344,7 @@ extern "C" { #endif // __cplusplus /** - * Clones a [SPBitmap]. + * Clones a [Bitmap]. * * Will never return NULL. * @@ -371,7 +356,7 @@ extern "C" { * * The caller has to make sure that: * - * - `bitmap` points to a valid [SPBitmap] + * - `bitmap` points to a valid [Bitmap] * - `bitmap` is not written to concurrently * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bitmap_free`. @@ -379,7 +364,7 @@ extern "C" { Bitmap */*notnull*/ sp_bitmap_clone(Bitmap */*notnull*/ bitmap); /** - * Sets the state of all pixels in the [SPBitmap]. + * Sets the state of all pixels in the [Bitmap]. * * # Arguments * @@ -394,13 +379,13 @@ Bitmap */*notnull*/ sp_bitmap_clone(Bitmap */*notnull*/ bitmap); * * The caller has to make sure that: * - * - `bitmap` points to a valid [SPBitmap] + * - `bitmap` points to a valid [Bitmap] * - `bitmap` is not written to or read from concurrently */ void sp_bitmap_fill(Bitmap */*notnull*/ bitmap, bool value); /** - * Deallocates a [SPBitmap]. + * Deallocates a [Bitmap]. * * # Panics * @@ -410,14 +395,14 @@ void sp_bitmap_fill(Bitmap */*notnull*/ bitmap, bool value); * * The caller has to make sure that: * - * - `bitmap` points to a valid [SPBitmap] + * - `bitmap` points to a valid [Bitmap] * - * [SPCommand]: [crate::SPCommand] + * [TypedCommand]: [crate::TypedCommand] */ void sp_bitmap_free(Bitmap */*notnull*/ bitmap); /** - * Gets the current value at the specified position in the [SPBitmap]. + * Gets the current value at the specified position in the [Bitmap]. * * # Arguments * @@ -433,13 +418,13 @@ void sp_bitmap_free(Bitmap */*notnull*/ bitmap); * * The caller has to make sure that: * - * - `bitmap` points to a valid [SPBitmap] + * - `bitmap` points to a valid [Bitmap] * - `bitmap` is not written to concurrently */ bool sp_bitmap_get(Bitmap */*notnull*/ bitmap, size_t x, size_t y); /** - * Gets the height in pixels of the [SPBitmap] instance. + * Gets the height in pixels of the [Bitmap] instance. * * # Arguments * @@ -453,19 +438,19 @@ bool sp_bitmap_get(Bitmap */*notnull*/ bitmap, size_t x, size_t y); * * The caller has to make sure that: * - * - `bitmap` points to a valid [SPBitmap] + * - `bitmap` points to a valid [Bitmap] */ size_t sp_bitmap_height(Bitmap */*notnull*/ bitmap); /** - * Loads a [SPBitmap] with the specified dimensions from the provided data. + * Loads a [Bitmap] with the specified dimensions from the provided data. * * # Arguments * * - `width`: size in pixels in x-direction * - `height`: size in pixels in y-direction * - * returns: [SPBitmap] 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. * * # Errors * @@ -491,14 +476,14 @@ Bitmap *sp_bitmap_load(size_t width, SPByteSlice data); /** - * Creates a new [SPBitmap] with the specified dimensions. + * Creates a new [Bitmap] with the specified dimensions. * * # Arguments * * - `width`: size in pixels in x-direction * - `height`: size in pixels in y-direction * - * returns: [SPBitmap] 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 * @@ -512,14 +497,23 @@ Bitmap *sp_bitmap_load(size_t width, * * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bitmap_free`. + * + * # Examples + * + * ```C + * Cp437Grid grid = sp_bitmap_new(8, 3); + * sp_bitmap_fill(grid, true); + * sp_bitmap_set(grid, 0, 0, false); + * sp_bitmap_free(grid); + * ``` */ Bitmap *sp_bitmap_new(size_t width, size_t height); /** - * Creates a new [SPBitmap] with a size matching the screen. + * Creates a new [Bitmap] with a size matching the screen. * - * returns: [SPBitmap] initialized to all pixels off. Will never return NULL. + * returns: [Bitmap] initialized to all pixels off. Will never return NULL. * * # Safety * @@ -531,7 +525,7 @@ Bitmap *sp_bitmap_new(size_t width, Bitmap */*notnull*/ sp_bitmap_new_screen_sized(void); /** - * Sets the value of the specified position in the [SPBitmap]. + * Sets the value of the specified position in the [Bitmap]. * * # Arguments * @@ -550,13 +544,13 @@ Bitmap */*notnull*/ sp_bitmap_new_screen_sized(void); * * The caller has to make sure that: * - * - `bitmap` points to a valid [SPBitmap] + * - `bitmap` points to a valid [Bitmap] * - `bitmap` is not written to or read from concurrently */ void sp_bitmap_set(Bitmap */*notnull*/ bitmap, size_t x, size_t y, bool value); /** - * Gets an unsafe reference to the data of the [SPBitmap] instance. + * Gets an unsafe reference to the data of the [Bitmap] instance. * * # Panics * @@ -566,14 +560,14 @@ void sp_bitmap_set(Bitmap */*notnull*/ bitmap, size_t x, size_t y, bool value); * * The caller has to make sure that: * - * - `bitmap` points to a valid [SPBitmap] - * - the returned memory range is never accessed after the passed [SPBitmap] has been freed - * - the returned memory range is never accessed concurrently, either via the [SPBitmap] or directly + * - `bitmap` points to a valid [Bitmap] + * - the returned memory range is never accessed after the passed [Bitmap] has been freed + * - the returned memory range is never accessed concurrently, either via the [Bitmap] or directly */ SPByteSlice sp_bitmap_unsafe_data_ref(Bitmap */*notnull*/ bitmap); /** - * Gets the width in pixels of the [SPBitmap] instance. + * Gets the width in pixels of the [Bitmap] instance. * * # Arguments * @@ -587,7 +581,7 @@ SPByteSlice sp_bitmap_unsafe_data_ref(Bitmap */*notnull*/ bitmap); * * The caller has to make sure that: * - * - `bitmap` points to a valid [SPBitmap] + * - `bitmap` points to a valid [Bitmap] */ size_t sp_bitmap_width(Bitmap */*notnull*/ bitmap); @@ -645,9 +639,9 @@ void sp_bitvec_fill(SPBitVec */*notnull*/ bit_vec, bool value); * * - `bit_vec` points to a valid [SPBitVec] * - `bit_vec` is not used concurrently or after this call - * - `bit_vec` was not passed to another consuming function, e.g. to create a [SPCommand] + * - `bit_vec` was not passed to another consuming function, e.g. to create a [TypedCommand] * - * [SPCommand]: [crate::SPCommand] + * [TypedCommand]: [crate::TypedCommand] */ void sp_bitvec_free(SPBitVec */*notnull*/ bit_vec); @@ -800,13 +794,13 @@ void sp_bitvec_set(SPBitVec */*notnull*/ bit_vec, size_t index, bool value); SPByteSlice sp_bitvec_unsafe_data_ref(SPBitVec */*notnull*/ bit_vec); /** - * Clones a [SPBrightnessGrid]. + * Clones a [BrightnessGrid]. * * # Arguments * * - `brightness_grid`: instance to read from * - * returns: new [SPBrightnessGrid] instance. Will never return NULL. + * returns: new [BrightnessGrid] instance. Will never return NULL. * * # Panics * @@ -816,7 +810,7 @@ SPByteSlice sp_bitvec_unsafe_data_ref(SPBitVec */*notnull*/ bit_vec); * * The caller has to make sure that: * - * - `brightness_grid` points to a valid [SPBrightnessGrid] + * - `brightness_grid` points to a valid [BrightnessGrid] * - `brightness_grid` is not written to concurrently * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_brightness_grid_free`. @@ -824,7 +818,7 @@ SPByteSlice sp_bitvec_unsafe_data_ref(SPBitVec */*notnull*/ bit_vec); BrightnessGrid */*notnull*/ sp_brightness_grid_clone(BrightnessGrid */*notnull*/ brightness_grid); /** - * Sets the value of all cells in the [SPBrightnessGrid]. + * Sets the value of all cells in the [BrightnessGrid]. * * # Arguments * @@ -840,14 +834,14 @@ BrightnessGrid */*notnull*/ sp_brightness_grid_clone(BrightnessGrid */*notnull*/ * * The caller has to make sure that: * - * - `brightness_grid` points to a valid [SPBrightnessGrid] + * - `brightness_grid` points to a valid [BrightnessGrid] * - `brightness_grid` is not written to or read from concurrently */ void sp_brightness_grid_fill(BrightnessGrid */*notnull*/ brightness_grid, Brightness value); /** - * Deallocates a [SPBrightnessGrid]. + * Deallocates a [BrightnessGrid]. * * # Arguments * @@ -861,11 +855,11 @@ void sp_brightness_grid_fill(BrightnessGrid */*notnull*/ brightness_grid, * * The caller has to make sure that: * - * - `brightness_grid` points to a valid [SPBrightnessGrid] + * - `brightness_grid` points to a valid [BrightnessGrid] * - `brightness_grid` is not used concurrently or after this call - * - `brightness_grid` was not passed to another consuming function, e.g. to create a [SPCommand] + * - `brightness_grid` was not passed to another consuming function, e.g. to create a [TypedCommand] * - * [SPCommand]: [crate::SPCommand] + * [TypedCommand]: [crate::TypedCommand] */ void sp_brightness_grid_free(BrightnessGrid */*notnull*/ brightness_grid); @@ -888,7 +882,7 @@ void sp_brightness_grid_free(BrightnessGrid */*notnull*/ brightness_grid); * * The caller has to make sure that: * - * - `brightness_grid` points to a valid [SPBrightnessGrid] + * - `brightness_grid` points to a valid [BrightnessGrid] * - `brightness_grid` is not written to concurrently */ Brightness sp_brightness_grid_get(BrightnessGrid */*notnull*/ brightness_grid, @@ -896,7 +890,7 @@ Brightness sp_brightness_grid_get(BrightnessGrid */*notnull*/ brightness_grid, size_t y); /** - * Gets the height of the [SPBrightnessGrid] instance. + * Gets the height of the [BrightnessGrid] instance. * * # Arguments * @@ -912,14 +906,14 @@ Brightness sp_brightness_grid_get(BrightnessGrid */*notnull*/ brightness_grid, * * The caller has to make sure that: * - * - `brightness_grid` points to a valid [SPBrightnessGrid] + * - `brightness_grid` points to a valid [BrightnessGrid] */ size_t sp_brightness_grid_height(BrightnessGrid */*notnull*/ brightness_grid); /** - * Loads a [SPBrightnessGrid] with the specified dimensions from the provided data. + * Loads a [BrightnessGrid] with the specified dimensions from the provided data. * - * returns: new [SPBrightnessGrid] instance. Will never return NULL. + * returns: new [BrightnessGrid] instance. Will never return NULL. * * # Panics * @@ -940,9 +934,9 @@ BrightnessGrid *sp_brightness_grid_load(size_t width, SPByteSlice data); /** - * Creates a new [SPBrightnessGrid] with the specified dimensions. + * Creates a new [BrightnessGrid] with the specified dimensions. * - * returns: [SPBrightnessGrid] initialized to 0. Will never return NULL. + * returns: [BrightnessGrid] initialized to 0. Will never return NULL. * * # Safety * @@ -955,7 +949,7 @@ BrightnessGrid */*notnull*/ sp_brightness_grid_new(size_t width, size_t height); /** - * Sets the value of the specified position in the [SPBrightnessGrid]. + * Sets the value of the specified position in the [BrightnessGrid]. * * # Arguments * @@ -975,7 +969,7 @@ BrightnessGrid */*notnull*/ sp_brightness_grid_new(size_t width, * * The caller has to make sure that: * - * - `brightness_grid` points to a valid [SPBrightnessGrid] + * - `brightness_grid` points to a valid [BrightnessGrid] * - `brightness_grid` is not written to or read from concurrently */ void sp_brightness_grid_set(BrightnessGrid */*notnull*/ brightness_grid, @@ -984,7 +978,7 @@ void sp_brightness_grid_set(BrightnessGrid */*notnull*/ brightness_grid, Brightness value); /** - * Gets an unsafe reference to the data of the [SPBrightnessGrid] instance. + * Gets an unsafe reference to the data of the [BrightnessGrid] instance. * * # Arguments * @@ -1000,14 +994,14 @@ void sp_brightness_grid_set(BrightnessGrid */*notnull*/ brightness_grid, * * The caller has to make sure that: * - * - `brightness_grid` points to a valid [SPBrightnessGrid] - * - the returned memory range is never accessed after the passed [SPBrightnessGrid] has been freed - * - the returned memory range is never accessed concurrently, either via the [SPBrightnessGrid] or directly + * - `brightness_grid` points to a valid [BrightnessGrid] + * - the returned memory range is never accessed after the passed [BrightnessGrid] has been freed + * - the returned memory range is never accessed concurrently, either via the [BrightnessGrid] or directly */ SPByteSlice sp_brightness_grid_unsafe_data_ref(BrightnessGrid */*notnull*/ brightness_grid); /** - * Gets the width of the [SPBrightnessGrid] instance. + * Gets the width of the [BrightnessGrid] instance. * * # Arguments * @@ -1023,12 +1017,12 @@ SPByteSlice sp_brightness_grid_unsafe_data_ref(BrightnessGrid */*notnull*/ brigh * * The caller has to make sure that: * - * - `brightness_grid` points to a valid [SPBrightnessGrid] + * - `brightness_grid` points to a valid [BrightnessGrid] */ size_t sp_brightness_grid_width(BrightnessGrid */*notnull*/ brightness_grid); /** - * Clones a [SPCharGrid]. + * Clones a [CharGrid]. * * Will never return NULL. * @@ -1040,7 +1034,7 @@ size_t sp_brightness_grid_width(BrightnessGrid */*notnull*/ brightness_grid); * * The caller has to make sure that: * - * - `char_grid` points to a valid [SPCharGrid] + * - `char_grid` points to a valid [CharGrid] * - `char_grid` is not written to concurrently * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_char_grid_free`. @@ -1048,7 +1042,7 @@ size_t sp_brightness_grid_width(BrightnessGrid */*notnull*/ brightness_grid); CharGrid */*notnull*/ sp_char_grid_clone(CharGrid */*notnull*/ char_grid); /** - * Sets the value of all cells in the [SPCharGrid]. + * Sets the value of all cells in the [CharGrid]. * * # Arguments * @@ -1063,13 +1057,13 @@ CharGrid */*notnull*/ sp_char_grid_clone(CharGrid */*notnull*/ char_grid); * * The caller has to make sure that: * - * - `char_grid` points to a valid [SPCharGrid] + * - `char_grid` points to a valid [CharGrid] * - `char_grid` is not written to or read from concurrently */ void sp_char_grid_fill(CharGrid */*notnull*/ char_grid, uint32_t value); /** - * Deallocates a [SPCharGrid]. + * Deallocates a [CharGrid]. * * # Panics * @@ -1079,11 +1073,11 @@ void sp_char_grid_fill(CharGrid */*notnull*/ char_grid, uint32_t value); * * The caller has to make sure that: * - * - `char_grid` points to a valid [SPCharGrid] + * - `char_grid` points to a valid [CharGrid] * - `char_grid` is not used concurrently or after char_grid call - * - `char_grid` was not passed to another consuming function, e.g. to create a [SPCommand] + * - `char_grid` was not passed to another consuming function, e.g. to create a [TypedCommand] * - * [SPCommand]: [crate::SPCommand] + * [TypedCommand]: [crate::TypedCommand] */ void sp_char_grid_free(CharGrid */*notnull*/ char_grid); @@ -1104,13 +1098,13 @@ void sp_char_grid_free(CharGrid */*notnull*/ char_grid); * * The caller has to make sure that: * - * - `char_grid` points to a valid [SPCharGrid] + * - `char_grid` points to a valid [CharGrid] * - `char_grid` is not written to concurrently */ uint32_t sp_char_grid_get(CharGrid */*notnull*/ char_grid, size_t x, size_t y); /** - * Gets the height of the [SPCharGrid] instance. + * Gets the height of the [CharGrid] instance. * * # Arguments * @@ -1124,12 +1118,12 @@ uint32_t sp_char_grid_get(CharGrid */*notnull*/ char_grid, size_t x, size_t y); * * The caller has to make sure that: * - * - `char_grid` points to a valid [SPCharGrid] + * - `char_grid` points to a valid [CharGrid] */ size_t sp_char_grid_height(CharGrid */*notnull*/ char_grid); /** - * Loads a [SPCharGrid] with the specified dimensions from the provided data. + * Loads a [CharGrid] with the specified dimensions from the provided data. * * Will never return NULL. * @@ -1153,9 +1147,9 @@ CharGrid */*notnull*/ sp_char_grid_load(size_t width, SPByteSlice data); /** - * Creates a new [SPCharGrid] with the specified dimensions. + * Creates a new [CharGrid] with the specified dimensions. * - * returns: [SPCharGrid] initialized to 0. Will never return NULL. + * returns: [CharGrid] initialized to 0. Will never return NULL. * * # Safety * @@ -1168,7 +1162,7 @@ CharGrid */*notnull*/ sp_char_grid_new(size_t width, size_t height); /** - * Sets the value of the specified position in the [SPCharGrid]. + * Sets the value of the specified position in the [CharGrid]. * * # Arguments * @@ -1198,7 +1192,7 @@ void sp_char_grid_set(CharGrid */*notnull*/ char_grid, uint32_t value); /** - * Gets the width of the [SPCharGrid] instance. + * Gets the width of the [CharGrid] instance. * * # Arguments * @@ -1212,7 +1206,7 @@ void sp_char_grid_set(CharGrid */*notnull*/ char_grid, * * The caller has to make sure that: * - * - `char_grid` points to a valid [SPCharGrid] + * - `char_grid` points to a valid [CharGrid] */ size_t sp_char_grid_width(CharGrid */*notnull*/ char_grid); @@ -1240,12 +1234,12 @@ size_t sp_char_grid_width(CharGrid */*notnull*/ char_grid); * - `bit_vec` points to a valid instance of [SPBitVec] * - `bit_vec` is not used concurrently or after this call * - `compression` matches one of the allowed enum values - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_bitmap_linear(size_t offset, - SPBitVec */*notnull*/ bit_vec, - CompressionCode compression); +TypedCommand *sp_command_bitmap_linear(size_t offset, + SPBitVec */*notnull*/ bit_vec, + CompressionCode compression); /** * Set pixel data according to an and-mask starting at the offset. @@ -1271,12 +1265,12 @@ Command *sp_command_bitmap_linear(size_t offset, * - `bit_vec` points to a valid instance of [SPBitVec] * - `bit_vec` is not used concurrently or after this call * - `compression` matches one of the allowed enum values - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_bitmap_linear_and(size_t offset, - SPBitVec */*notnull*/ bit_vec, - CompressionCode compression); +TypedCommand *sp_command_bitmap_linear_and(size_t offset, + SPBitVec */*notnull*/ bit_vec, + CompressionCode compression); /** * Set pixel data according to an or-mask starting at the offset. @@ -1302,17 +1296,17 @@ Command *sp_command_bitmap_linear_and(size_t offset, * - `bit_vec` points to a valid instance of [SPBitVec] * - `bit_vec` is not used concurrently or after this call * - `compression` matches one of the allowed enum values - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_bitmap_linear_or(size_t offset, - SPBitVec */*notnull*/ bit_vec, - CompressionCode compression); +TypedCommand *sp_command_bitmap_linear_or(size_t offset, + SPBitVec */*notnull*/ bit_vec, + CompressionCode compression); /** * Sets a window of pixels to the specified values. * - * The passed [SPBitmap] gets consumed. + * The passed [Bitmap] gets consumed. * * Returns: a new [servicepoint::Command::BitmapLinearWin] instance. Will never return NULL. * @@ -1325,16 +1319,16 @@ Command *sp_command_bitmap_linear_or(size_t offset, * * The caller has to make sure that: * - * - `bitmap` points to a valid instance of [SPBitmap] + * - `bitmap` points to a valid instance of [Bitmap] * - `bitmap` is not used concurrently or after this call * - `compression` matches one of the allowed enum values - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_bitmap_linear_win(size_t x, - size_t y, - Bitmap */*notnull*/ bitmap, - CompressionCode compression); +TypedCommand *sp_command_bitmap_linear_win(size_t x, + size_t y, + Bitmap */*notnull*/ bitmap, + CompressionCode compression); /** * Set pixel data according to a xor-mask starting at the offset. @@ -1360,12 +1354,12 @@ Command *sp_command_bitmap_linear_win(size_t x, * - `bit_vec` points to a valid instance of [SPBitVec] * - `bit_vec` is not used concurrently or after this call * - `compression` matches one of the allowed enum values - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_bitmap_linear_xor(size_t offset, - SPBitVec */*notnull*/ bit_vec, - CompressionCode compression); +TypedCommand *sp_command_bitmap_linear_xor(size_t offset, + SPBitVec */*notnull*/ bit_vec, + CompressionCode compression); /** * Set the brightness of all tiles to the same value. @@ -1380,15 +1374,15 @@ Command *sp_command_bitmap_linear_xor(size_t offset, * * The caller has to make sure that: * - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command */*notnull*/ sp_command_brightness(Brightness brightness); +TypedCommand */*notnull*/ sp_command_brightness(Brightness brightness); /** * Set the brightness of individual tiles in a rectangular area of the display. * - * The passed [SPBrightnessGrid] gets consumed. + * The passed [BrightnessGrid] gets consumed. * * Returns: a new [servicepoint::Command::CharBrightness] instance. Will never return NULL. * @@ -1400,14 +1394,14 @@ Command */*notnull*/ sp_command_brightness(Brightness brightness); * * The caller has to make sure that: * - * - `grid` points to a valid instance of [SPBrightnessGrid] + * - `grid` points to a valid instance of [BrightnessGrid] * - `grid` is not used concurrently or after this call - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command */*notnull*/ sp_command_char_brightness(size_t x, - size_t y, - BrightnessGrid */*notnull*/ grid); +TypedCommand */*notnull*/ sp_command_char_brightness(size_t x, + size_t y, + BrightnessGrid */*notnull*/ grid); /** * Set all pixels to the off state. @@ -1426,15 +1420,15 @@ Command */*notnull*/ sp_command_char_brightness(size_t x, * * The caller has to make sure that: * - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command */*notnull*/ sp_command_clear(void); +TypedCommand */*notnull*/ sp_command_clear(void); /** - * Clones a [SPCommand] instance. + * Clones a [TypedCommand] instance. * - * returns: new [SPCommand] instance. Will never return NULL. + * returns: new [TypedCommand] instance. Will never return NULL. * * # Panics * @@ -1444,17 +1438,17 @@ Command */*notnull*/ sp_command_clear(void); * * The caller has to make sure that: * - * - `command` points to a valid instance of [SPCommand] + * - `command` points to a valid instance of [TypedCommand] * - `command` is not written to concurrently - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command */*notnull*/ sp_command_clone(Command */*notnull*/ command); +TypedCommand */*notnull*/ sp_command_clone(TypedCommand */*notnull*/ command); /** * Show codepage 437 encoded text on the screen. * - * The passed [SPCp437Grid] gets consumed. + * The passed [Cp437Grid] gets consumed. * * Returns: a new [servicepoint::Command::Cp437Data] instance. Will never return NULL. * @@ -1466,14 +1460,14 @@ Command */*notnull*/ sp_command_clone(Command */*notnull*/ command); * * The caller has to make sure that: * - * - `grid` points to a valid instance of [SPCp437Grid] + * - `grid` points to a valid instance of [Cp437Grid] * - `grid` is not used concurrently or after this call - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command */*notnull*/ sp_command_cp437_data(size_t x, - size_t y, - Cp437Grid */*notnull*/ grid); +TypedCommand */*notnull*/ sp_command_cp437_data(size_t x, + size_t y, + Cp437Grid */*notnull*/ grid); /** * A yet-to-be-tested command. @@ -1484,18 +1478,18 @@ Command */*notnull*/ sp_command_cp437_data(size_t x, * * The caller has to make sure that: * - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command */*notnull*/ sp_command_fade_out(void); +TypedCommand */*notnull*/ sp_command_fade_out(void); /** - * Deallocates a [SPCommand]. + * Deallocates a [TypedCommand]. * * # Examples * * ```C - * SPCommand c = sp_command_clear(); + * TypedCommand c = sp_command_clear(); * sp_command_free(c); * ``` * @@ -1507,11 +1501,11 @@ Command */*notnull*/ sp_command_fade_out(void); * * The caller has to make sure that: * - * - `command` points to a valid [SPCommand] + * - `command` points to a valid [TypedCommand] * - `command` is not used concurrently or after this call - * - `command` was not passed to another consuming function, e.g. to create a [SPPacket] + * - `command` was not passed to another consuming function, e.g. to create a [Packet] */ -void sp_command_free(Command */*notnull*/ command); +void sp_command_free(TypedCommand */*notnull*/ command); /** * Kills the udp daemon on the display, which usually results in a restart. @@ -1524,17 +1518,17 @@ void sp_command_free(Command */*notnull*/ command); * * The caller has to make sure that: * - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command */*notnull*/ sp_command_hard_reset(void); +TypedCommand */*notnull*/ sp_command_hard_reset(void); /** * A low-level display command. * * This struct and associated functions implement the UDP protocol for the display. * - * To send a [SPCommand], use a [SPConnection]. + * To send a [TypedCommand], use a [UdpConnection]. * * # Examples * @@ -1542,13 +1536,11 @@ Command */*notnull*/ sp_command_hard_reset(void); * sp_connection_send_command(connection, sp_command_clear()); * sp_connection_send_command(connection, sp_command_brightness(5)); * ``` - * - * [SPConnection]: [crate::SPConnection] - * Tries to turn a [SPPacket] into a [SPCommand]. + * Tries to turn a [Packet] into a [TypedCommand]. * * The packet is deallocated in the process. * - * Returns: pointer to new [SPCommand] instance or NULL if parsing failed. + * Returns: pointer to new [TypedCommand] instance or NULL if parsing failed. * * # Panics * @@ -1558,18 +1550,18 @@ Command */*notnull*/ sp_command_hard_reset(void); * * The caller has to make sure that: * - * - [SPPacket] points to a valid instance of [SPPacket] - * - [SPPacket] is not used concurrently or after this call + * - [Packet] points to a valid instance of [Packet] + * - [Packet] is not used concurrently or after this call * - the result is checked for NULL - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command *sp_command_try_from_packet(Packet */*notnull*/ packet); +TypedCommand *sp_command_try_from_packet(Packet */*notnull*/ packet); /** * Show UTF-8 encoded text on the screen. * - * The passed [SPCharGrid] gets consumed. + * The passed [CharGrid] gets consumed. * * Returns: a new [servicepoint::Command::Utf8Data] instance. Will never return NULL. * @@ -1581,17 +1573,17 @@ Command *sp_command_try_from_packet(Packet */*notnull*/ packet); * * The caller has to make sure that: * - * - `grid` points to a valid instance of [SPCharGrid] + * - `grid` points to a valid instance of [CharGrid] * - `grid` is not used concurrently or after this call - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or + * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_free`. */ -Command */*notnull*/ sp_command_utf8_data(size_t x, - size_t y, - CharGrid */*notnull*/ grid); +TypedCommand */*notnull*/ sp_command_utf8_data(size_t x, + size_t y, + CharGrid */*notnull*/ grid); /** - * Closes and deallocates a [SPConnection]. + * Closes and deallocates a [UdpConnection]. * * # Panics * @@ -1601,13 +1593,13 @@ Command */*notnull*/ sp_command_utf8_data(size_t x, * * The caller has to make sure that: * - * - `connection` points to a valid [SPConnection] + * - `connection` points to a valid [UdpConnection] * - `connection` is not used concurrently or after this call */ void sp_connection_free(UdpConnection */*notnull*/ connection); /** - * Creates a new instance of [SPConnection]. + * Creates a new instance of [UdpConnection]. * * returns: NULL if connection fails, or connected instance * @@ -1625,7 +1617,7 @@ void sp_connection_free(UdpConnection */*notnull*/ connection); UdpConnection *sp_connection_open(char */*notnull*/ host); /** - * Sends a [SPCommand] to the display using the [SPConnection]. + * Sends a [TypedCommand] to the display using the [UdpConnection]. * * The passed `command` gets consumed. * @@ -1640,15 +1632,15 @@ UdpConnection *sp_connection_open(char */*notnull*/ host); * * The caller has to make sure that: * - * - `connection` points to a valid instance of [SPConnection] - * - `command` points to a valid instance of [SPPacket] + * - `connection` points to a valid instance of [UdpConnection] + * - `command` points to a valid instance of [Packet] * - `command` is not used concurrently or after this call */ bool sp_connection_send_command(UdpConnection */*notnull*/ connection, - Command */*notnull*/ command); + TypedCommand */*notnull*/ command); /** - * Sends a [SPPacket] to the display using the [SPConnection]. + * Sends a [Packet] to the display using the [UdpConnection]. * * The passed `packet` gets consumed. * @@ -1663,15 +1655,15 @@ bool sp_connection_send_command(UdpConnection */*notnull*/ connection, * * The caller has to make sure that: * - * - `connection` points to a valid instance of [SPConnection] - * - `packet` points to a valid instance of [SPPacket] + * - `connection` points to a valid instance of [UdpConnection] + * - `packet` points to a valid instance of [Packet] * - `packet` is not used concurrently or after this call */ bool sp_connection_send_packet(UdpConnection */*notnull*/ connection, Packet */*notnull*/ packet); /** - * Clones a [SPCp437Grid]. + * Clones a [Cp437Grid]. * * Will never return NULL. * @@ -1683,7 +1675,7 @@ bool sp_connection_send_packet(UdpConnection */*notnull*/ connection, * * The caller has to make sure that: * - * - `cp437_grid` points to a valid [SPCp437Grid] + * - `cp437_grid` points to a valid [Cp437Grid] * - `cp437_grid` is not written to concurrently * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_cp437_grid_free`. @@ -1691,7 +1683,7 @@ bool sp_connection_send_packet(UdpConnection */*notnull*/ connection, Cp437Grid */*notnull*/ sp_cp437_grid_clone(Cp437Grid */*notnull*/ cp437_grid); /** - * Sets the value of all cells in the [SPCp437Grid]. + * Sets the value of all cells in the [Cp437Grid]. * * # Arguments * @@ -1706,13 +1698,13 @@ Cp437Grid */*notnull*/ sp_cp437_grid_clone(Cp437Grid */*notnull*/ cp437_grid); * * The caller has to make sure that: * - * - `cp437_grid` points to a valid [SPCp437Grid] + * - `cp437_grid` points to a valid [Cp437Grid] * - `cp437_grid` is not written to or read from concurrently */ void sp_cp437_grid_fill(Cp437Grid */*notnull*/ cp437_grid, uint8_t value); /** - * Deallocates a [SPCp437Grid]. + * Deallocates a [Cp437Grid]. * * # Panics * @@ -1722,11 +1714,11 @@ void sp_cp437_grid_fill(Cp437Grid */*notnull*/ cp437_grid, uint8_t value); * * The caller has to make sure that: * - * - `cp437_grid` points to a valid [SPCp437Grid] + * - `cp437_grid` points to a valid [Cp437Grid] * - `cp437_grid` is not used concurrently or after cp437_grid call - * - `cp437_grid` was not passed to another consuming function, e.g. to create a [SPCommand] + * - `cp437_grid` was not passed to another consuming function, e.g. to create a [TypedCommand] * - * [SPCommand]: [crate::SPCommand] + * [TypedCommand]: [crate::TypedCommand] */ void sp_cp437_grid_free(Cp437Grid */*notnull*/ cp437_grid); @@ -1747,7 +1739,7 @@ void sp_cp437_grid_free(Cp437Grid */*notnull*/ cp437_grid); * * The caller has to make sure that: * - * - `cp437_grid` points to a valid [SPCp437Grid] + * - `cp437_grid` points to a valid [Cp437Grid] * - `cp437_grid` is not written to concurrently */ uint8_t sp_cp437_grid_get(Cp437Grid */*notnull*/ cp437_grid, @@ -1755,7 +1747,7 @@ uint8_t sp_cp437_grid_get(Cp437Grid */*notnull*/ cp437_grid, size_t y); /** - * Gets the height of the [SPCp437Grid] instance. + * Gets the height of the [Cp437Grid] instance. * * # Arguments * @@ -1769,12 +1761,12 @@ uint8_t sp_cp437_grid_get(Cp437Grid */*notnull*/ cp437_grid, * * The caller has to make sure that: * - * - `cp437_grid` points to a valid [SPCp437Grid] + * - `cp437_grid` points to a valid [Cp437Grid] */ size_t sp_cp437_grid_height(Cp437Grid */*notnull*/ cp437_grid); /** - * Loads a [SPCp437Grid] with the specified dimensions from the provided data. + * Loads a [Cp437Grid] with the specified dimensions from the provided data. * * Will never return NULL. * @@ -1797,9 +1789,9 @@ Cp437Grid *sp_cp437_grid_load(size_t width, SPByteSlice data); /** - * Creates a new [SPCp437Grid] with the specified dimensions. + * Creates a new [Cp437Grid] with the specified dimensions. * - * returns: [SPCp437Grid] initialized to 0. Will never return NULL. + * returns: [Cp437Grid] initialized to 0. Will never return NULL. * * # Safety * @@ -1812,7 +1804,7 @@ Cp437Grid */*notnull*/ sp_cp437_grid_new(size_t width, size_t height); /** - * Sets the value of the specified position in the [SPCp437Grid]. + * Sets the value of the specified position in the [Cp437Grid]. * * # Arguments * @@ -1842,7 +1834,7 @@ void sp_cp437_grid_set(Cp437Grid */*notnull*/ cp437_grid, uint8_t value); /** - * Gets an unsafe reference to the data of the [SPCp437Grid] instance. + * Gets an unsafe reference to the data of the [Cp437Grid] instance. * * Will never return NULL. * @@ -1854,14 +1846,14 @@ void sp_cp437_grid_set(Cp437Grid */*notnull*/ cp437_grid, * * The caller has to make sure that: * - * - `cp437_grid` points to a valid [SPCp437Grid] - * - the returned memory range is never accessed after the passed [SPCp437Grid] has been freed - * - the returned memory range is never accessed concurrently, either via the [SPCp437Grid] or directly + * - `cp437_grid` points to a valid [Cp437Grid] + * - the returned memory range is never accessed after the passed [Cp437Grid] has been freed + * - the returned memory range is never accessed concurrently, either via the [Cp437Grid] or directly */ SPByteSlice sp_cp437_grid_unsafe_data_ref(Cp437Grid */*notnull*/ cp437_grid); /** - * Gets the width of the [SPCp437Grid] instance. + * Gets the width of the [Cp437Grid] instance. * * # Arguments * @@ -1875,12 +1867,12 @@ SPByteSlice sp_cp437_grid_unsafe_data_ref(Cp437Grid */*notnull*/ cp437_grid); * * The caller has to make sure that: * - * - `cp437_grid` points to a valid [SPCp437Grid] + * - `cp437_grid` points to a valid [Cp437Grid] */ size_t sp_cp437_grid_width(Cp437Grid */*notnull*/ cp437_grid); /** - * Clones a [SPPacket]. + * Clones a [Packet]. * * Will never return NULL. * @@ -1892,7 +1884,7 @@ size_t sp_cp437_grid_width(Cp437Grid */*notnull*/ cp437_grid); * * The caller has to make sure that: * - * - `packet` points to a valid [SPPacket] + * - `packet` points to a valid [Packet] * - `packet` is not written to concurrently * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_packet_free`. @@ -1900,7 +1892,7 @@ size_t sp_cp437_grid_width(Cp437Grid */*notnull*/ cp437_grid); Packet */*notnull*/ sp_packet_clone(Packet */*notnull*/ packet); /** - * Deallocates a [SPPacket]. + * Deallocates a [Packet]. * * # Panics * @@ -1910,16 +1902,16 @@ Packet */*notnull*/ sp_packet_clone(Packet */*notnull*/ packet); * * The caller has to make sure that: * - * - `packet` points to a valid [SPPacket] + * - `packet` points to a valid [Packet] * - `packet` is not used concurrently or after this call */ void sp_packet_free(Packet */*notnull*/ packet); /** - * Turns a [SPCommand] into a [SPPacket]. - * The [SPCommand] gets consumed. + * Turns a [TypedCommand] into a [Packet]. + * The [TypedCommand] gets consumed. * - * Will never return NULL. + * Returns NULL in case of an error. * * # Panics * @@ -1929,15 +1921,15 @@ void sp_packet_free(Packet */*notnull*/ packet); * * The caller has to make sure that: * - * - [SPCommand] points to a valid instance of [SPCommand] - * - [SPCommand] is not used concurrently or after this call - * - the returned [SPPacket] instance is freed in some way, either by using a consuming function or + * - [TypedCommand] points to a valid instance of [TypedCommand] + * - [TypedCommand] is not used concurrently or after this call + * - the returned [Packet] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_packet_free`. */ -Packet *sp_packet_from_command(Command */*notnull*/ command); +Packet *sp_packet_from_command(TypedCommand */*notnull*/ command); /** - * Creates a raw [SPPacket] from parts. + * Creates a raw [Packet] from parts. * * # Arguments * @@ -1959,20 +1951,44 @@ Packet *sp_packet_from_command(Command */*notnull*/ command); * * - `payload` points to a valid memory region of at least `payload_len` bytes * - `payload` is not written to concurrently - * - the returned [SPPacket] instance is freed in some way, either by using a consuming function or + * - the returned [Packet] instance is freed in some way, either by using a consuming function or * by explicitly calling [sp_packet_free]. */ Packet */*notnull*/ sp_packet_from_parts(Header header, const SPByteSlice *payload); +/** + * Returns a pointer to the header field of the provided packet. + * + * The returned header can be changed and will be valid for the lifetime of the packet. + */ Header */*notnull*/ sp_packet_get_header(Packet */*notnull*/ packet); +/** + * Returns a pointer to the current payload of the provided packet. + * + * The returned memory can be changed and will be valid until a new payload is set. + */ SPByteSlice sp_packet_get_payload(Packet */*notnull*/ packet); +/** + * Serialize the packet into the provided buffer. + * + * # Panics + * + * - if the buffer is not big enough to hold header+payload. + */ +void sp_packet_serialize_to(Packet */*notnull*/ packet, SPByteSlice buffer); + +/** + * Sets the payload of the provided packet to the provided data. + * + * This makes previous payload pointers invalid. + */ void sp_packet_set_payload(Packet */*notnull*/ packet, SPByteSlice data); /** - * Tries to load a [SPPacket] from the passed array with the specified length. + * 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 * @@ -1986,13 +2002,11 @@ void sp_packet_set_payload(Packet */*notnull*/ packet, SPByteSlice data); * * - `data` points to a valid memory region of at least `length` bytes * - `data` is not written to concurrently - * - the returned [SPPacket] instance is freed in some way, either by using a consuming function or + * - the returned [Packet] instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_packet_free`. */ Packet *sp_packet_try_load(SPByteSlice data); -void sp_packet_write_to(Packet */*notnull*/ packet, SPByteSlice buffer); - #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/src/bitmap.rs b/src/bitmap.rs index 2e70efc..5da6e7e 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -1,31 +1,16 @@ -//! C functions for interacting with [SPBitmap]s -//! -//! prefix `sp_bitmap_` -//! -//! A grid of pixels. -//! -//! # Examples -//! -//! ```C -//! Cp437Grid grid = sp_bitmap_new(8, 3); -//! sp_bitmap_fill(grid, true); -//! sp_bitmap_set(grid, 0, 0, false); -//! sp_bitmap_free(grid); -//! ``` - use servicepoint::{Bitmap, DataRef, Grid}; use std::ptr::NonNull; use crate::byte_slice::SPByteSlice; -/// Creates a new [SPBitmap] with the specified dimensions. +/// Creates a new [Bitmap] with the specified dimensions. /// /// # Arguments /// /// - `width`: size in pixels in x-direction /// - `height`: size in pixels in y-direction /// -/// returns: [SPBitmap] 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 /// @@ -39,6 +24,15 @@ use crate::byte_slice::SPByteSlice; /// /// - the returned instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_bitmap_free`. +/// +/// # Examples +/// +/// ```C +/// Cp437Grid grid = sp_bitmap_new(8, 3); +/// sp_bitmap_fill(grid, true); +/// sp_bitmap_set(grid, 0, 0, false); +/// sp_bitmap_free(grid); +/// ``` #[no_mangle] pub unsafe extern "C" fn sp_bitmap_new( width: usize, @@ -51,9 +45,9 @@ pub unsafe extern "C" fn sp_bitmap_new( } } -/// Creates a new [SPBitmap] with a size matching the screen. +/// Creates a new [Bitmap] with a size matching the screen. /// -/// returns: [SPBitmap] initialized to all pixels off. Will never return NULL. +/// returns: [Bitmap] initialized to all pixels off. Will never return NULL. /// /// # Safety /// @@ -67,14 +61,14 @@ pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull { NonNull::from(Box::leak(result)) } -/// Loads a [SPBitmap] with the specified dimensions from the provided data. +/// Loads a [Bitmap] with the specified dimensions from the provided data. /// /// # Arguments /// /// - `width`: size in pixels in x-direction /// - `height`: size in pixels in y-direction /// -/// returns: [SPBitmap] 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. /// /// # Errors /// @@ -108,7 +102,7 @@ pub unsafe extern "C" fn sp_bitmap_load( } } -/// Clones a [SPBitmap]. +/// Clones a [Bitmap]. /// /// Will never return NULL. /// @@ -120,7 +114,7 @@ pub unsafe extern "C" fn sp_bitmap_load( /// /// The caller has to make sure that: /// -/// - `bitmap` points to a valid [SPBitmap] +/// - `bitmap` points to a valid [Bitmap] /// - `bitmap` is not written to concurrently /// - the returned instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_bitmap_free`. @@ -132,7 +126,7 @@ pub unsafe extern "C" fn sp_bitmap_clone( NonNull::from(Box::leak(result)) } -/// Deallocates a [SPBitmap]. +/// Deallocates a [Bitmap]. /// /// # Panics /// @@ -142,15 +136,15 @@ pub unsafe extern "C" fn sp_bitmap_clone( /// /// The caller has to make sure that: /// -/// - `bitmap` points to a valid [SPBitmap] +/// - `bitmap` points to a valid [Bitmap] /// -/// [SPCommand]: [crate::SPCommand] +/// [TypedCommand]: [crate::TypedCommand] #[no_mangle] pub unsafe extern "C" fn sp_bitmap_free(bitmap: NonNull) { _ = unsafe { Box::from_raw(bitmap.as_ptr()) }; } -/// Gets the current value at the specified position in the [SPBitmap]. +/// Gets the current value at the specified position in the [Bitmap]. /// /// # Arguments /// @@ -166,7 +160,7 @@ pub unsafe extern "C" fn sp_bitmap_free(bitmap: NonNull) { /// /// The caller has to make sure that: /// -/// - `bitmap` points to a valid [SPBitmap] +/// - `bitmap` points to a valid [Bitmap] /// - `bitmap` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitmap_get( @@ -177,7 +171,7 @@ pub unsafe extern "C" fn sp_bitmap_get( unsafe { bitmap.as_ref().get(x, y) } } -/// Sets the value of the specified position in the [SPBitmap]. +/// Sets the value of the specified position in the [Bitmap]. /// /// # Arguments /// @@ -196,7 +190,7 @@ pub unsafe extern "C" fn sp_bitmap_get( /// /// The caller has to make sure that: /// -/// - `bitmap` points to a valid [SPBitmap] +/// - `bitmap` points to a valid [Bitmap] /// - `bitmap` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitmap_set( @@ -208,7 +202,7 @@ pub unsafe extern "C" fn sp_bitmap_set( unsafe { (*bitmap.as_ptr()).set(x, y, value) }; } -/// Sets the state of all pixels in the [SPBitmap]. +/// Sets the state of all pixels in the [Bitmap]. /// /// # Arguments /// @@ -223,14 +217,14 @@ pub unsafe extern "C" fn sp_bitmap_set( /// /// The caller has to make sure that: /// -/// - `bitmap` points to a valid [SPBitmap] +/// - `bitmap` points to a valid [Bitmap] /// - `bitmap` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitmap_fill(bitmap: NonNull, value: bool) { unsafe { (*bitmap.as_ptr()).fill(value) }; } -/// Gets the width in pixels of the [SPBitmap] instance. +/// Gets the width in pixels of the [Bitmap] instance. /// /// # Arguments /// @@ -244,13 +238,13 @@ pub unsafe extern "C" fn sp_bitmap_fill(bitmap: NonNull, value: bool) { /// /// The caller has to make sure that: /// -/// - `bitmap` points to a valid [SPBitmap] +/// - `bitmap` points to a valid [Bitmap] #[no_mangle] pub unsafe extern "C" fn sp_bitmap_width(bitmap: NonNull) -> usize { unsafe { bitmap.as_ref().width() } } -/// Gets the height in pixels of the [SPBitmap] instance. +/// Gets the height in pixels of the [Bitmap] instance. /// /// # Arguments /// @@ -264,13 +258,13 @@ pub unsafe extern "C" fn sp_bitmap_width(bitmap: NonNull) -> usize { /// /// The caller has to make sure that: /// -/// - `bitmap` points to a valid [SPBitmap] +/// - `bitmap` points to a valid [Bitmap] #[no_mangle] pub unsafe extern "C" fn sp_bitmap_height(bitmap: NonNull) -> usize { unsafe { bitmap.as_ref().height() } } -/// Gets an unsafe reference to the data of the [SPBitmap] instance. +/// Gets an unsafe reference to the data of the [Bitmap] instance. /// /// # Panics /// @@ -280,9 +274,9 @@ pub unsafe extern "C" fn sp_bitmap_height(bitmap: NonNull) -> usize { /// /// The caller has to make sure that: /// -/// - `bitmap` points to a valid [SPBitmap] -/// - the returned memory range is never accessed after the passed [SPBitmap] has been freed -/// - the returned memory range is never accessed concurrently, either via the [SPBitmap] or directly +/// - `bitmap` points to a valid [Bitmap] +/// - the returned memory range is never accessed after the passed [Bitmap] has been freed +/// - the returned memory range is never accessed concurrently, either via the [Bitmap] or directly #[no_mangle] pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref( mut bitmap: NonNull, diff --git a/src/bitvec.rs b/src/bitvec.rs index c32ce78..a2ff022 100644 --- a/src/bitvec.rs +++ b/src/bitvec.rs @@ -108,9 +108,9 @@ pub unsafe extern "C" fn sp_bitvec_clone( /// /// - `bit_vec` points to a valid [SPBitVec] /// - `bit_vec` is not used concurrently or after this call -/// - `bit_vec` was not passed to another consuming function, e.g. to create a [SPCommand] +/// - `bit_vec` was not passed to another consuming function, e.g. to create a [TypedCommand] /// -/// [SPCommand]: [crate::SPCommand] +/// [TypedCommand]: [crate::TypedCommand] #[no_mangle] pub unsafe extern "C" fn sp_bitvec_free(bit_vec: NonNull) { _ = unsafe { Box::from_raw(bit_vec.as_ptr()) }; diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index 0e9a052..ff40ef9 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -1,4 +1,4 @@ -//! C functions for interacting with [SPBrightnessGrid]s +//! C functions for interacting with [BrightnessGrid]s //! //! prefix `sp_brightness_grid_` //! @@ -7,15 +7,15 @@ //! //! # Examples //! ```C -//! SPConnection connection = sp_connection_open("127.0.0.1:2342"); +//! UdpConnection connection = sp_connection_open("127.0.0.1:2342"); //! if (connection == NULL) //! return 1; //! -//! SPBrightnessGrid grid = sp_brightness_grid_new(2, 2); +//! BrightnessGrid grid = sp_brightness_grid_new(2, 2); //! sp_brightness_grid_set(grid, 0, 0, 0); //! sp_brightness_grid_set(grid, 1, 1, 10); //! -//! SPCommand command = sp_command_char_brightness(grid); +//! TypedCommand command = sp_command_char_brightness(grid); //! sp_connection_free(connection); //! ``` @@ -24,9 +24,9 @@ use servicepoint::{Brightness, BrightnessGrid, DataRef, Grid}; use std::mem::transmute; use std::ptr::NonNull; -/// Creates a new [SPBrightnessGrid] with the specified dimensions. +/// Creates a new [BrightnessGrid] with the specified dimensions. /// -/// returns: [SPBrightnessGrid] initialized to 0. Will never return NULL. +/// returns: [BrightnessGrid] initialized to 0. Will never return NULL. /// /// # Safety /// @@ -43,9 +43,9 @@ pub unsafe extern "C" fn sp_brightness_grid_new( NonNull::from(Box::leak(result)) } -/// Loads a [SPBrightnessGrid] with the specified dimensions from the provided data. +/// Loads a [BrightnessGrid] with the specified dimensions from the provided data. /// -/// returns: new [SPBrightnessGrid] instance. Will never return NULL. +/// returns: new [BrightnessGrid] instance. Will never return NULL. /// /// # Panics /// @@ -78,13 +78,13 @@ pub unsafe extern "C" fn sp_brightness_grid_load( } } -/// Clones a [SPBrightnessGrid]. +/// Clones a [BrightnessGrid]. /// /// # Arguments /// /// - `brightness_grid`: instance to read from /// -/// returns: new [SPBrightnessGrid] instance. Will never return NULL. +/// returns: new [BrightnessGrid] instance. Will never return NULL. /// /// # Panics /// @@ -94,7 +94,7 @@ pub unsafe extern "C" fn sp_brightness_grid_load( /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] +/// - `brightness_grid` points to a valid [BrightnessGrid] /// - `brightness_grid` is not written to concurrently /// - the returned instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_brightness_grid_free`. @@ -106,7 +106,7 @@ pub unsafe extern "C" fn sp_brightness_grid_clone( NonNull::from(Box::leak(result)) } -/// Deallocates a [SPBrightnessGrid]. +/// Deallocates a [BrightnessGrid]. /// /// # Arguments /// @@ -120,11 +120,11 @@ pub unsafe extern "C" fn sp_brightness_grid_clone( /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] +/// - `brightness_grid` points to a valid [BrightnessGrid] /// - `brightness_grid` is not used concurrently or after this call -/// - `brightness_grid` was not passed to another consuming function, e.g. to create a [SPCommand] +/// - `brightness_grid` was not passed to another consuming function, e.g. to create a [TypedCommand] /// -/// [SPCommand]: [crate::SPCommand] +/// [TypedCommand]: [crate::TypedCommand] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_free( brightness_grid: NonNull, @@ -150,7 +150,7 @@ pub unsafe extern "C" fn sp_brightness_grid_free( /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] +/// - `brightness_grid` points to a valid [BrightnessGrid] /// - `brightness_grid` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_get( @@ -161,7 +161,7 @@ pub unsafe extern "C" fn sp_brightness_grid_get( unsafe { brightness_grid.as_ref().get(x, y) } } -/// Sets the value of the specified position in the [SPBrightnessGrid]. +/// Sets the value of the specified position in the [BrightnessGrid]. /// /// # Arguments /// @@ -181,7 +181,7 @@ pub unsafe extern "C" fn sp_brightness_grid_get( /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] +/// - `brightness_grid` points to a valid [BrightnessGrid] /// - `brightness_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_set( @@ -193,7 +193,7 @@ pub unsafe extern "C" fn sp_brightness_grid_set( unsafe { (*brightness_grid.as_ptr()).set(x, y, value) }; } -/// Sets the value of all cells in the [SPBrightnessGrid]. +/// Sets the value of all cells in the [BrightnessGrid]. /// /// # Arguments /// @@ -209,7 +209,7 @@ pub unsafe extern "C" fn sp_brightness_grid_set( /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] +/// - `brightness_grid` points to a valid [BrightnessGrid] /// - `brightness_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_fill( @@ -219,7 +219,7 @@ pub unsafe extern "C" fn sp_brightness_grid_fill( unsafe { (*brightness_grid.as_ptr()).fill(value) }; } -/// Gets the width of the [SPBrightnessGrid] instance. +/// Gets the width of the [BrightnessGrid] instance. /// /// # Arguments /// @@ -235,7 +235,7 @@ pub unsafe extern "C" fn sp_brightness_grid_fill( /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] +/// - `brightness_grid` points to a valid [BrightnessGrid] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_width( brightness_grid: NonNull, @@ -243,7 +243,7 @@ pub unsafe extern "C" fn sp_brightness_grid_width( unsafe { brightness_grid.as_ref().width() } } -/// Gets the height of the [SPBrightnessGrid] instance. +/// Gets the height of the [BrightnessGrid] instance. /// /// # Arguments /// @@ -259,7 +259,7 @@ pub unsafe extern "C" fn sp_brightness_grid_width( /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] +/// - `brightness_grid` points to a valid [BrightnessGrid] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_height( brightness_grid: NonNull, @@ -267,7 +267,7 @@ pub unsafe extern "C" fn sp_brightness_grid_height( unsafe { brightness_grid.as_ref().height() } } -/// Gets an unsafe reference to the data of the [SPBrightnessGrid] instance. +/// Gets an unsafe reference to the data of the [BrightnessGrid] instance. /// /// # Arguments /// @@ -283,9 +283,9 @@ pub unsafe extern "C" fn sp_brightness_grid_height( /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] -/// - the returned memory range is never accessed after the passed [SPBrightnessGrid] has been freed -/// - the returned memory range is never accessed concurrently, either via the [SPBrightnessGrid] or directly +/// - `brightness_grid` points to a valid [BrightnessGrid] +/// - the returned memory range is never accessed after the passed [BrightnessGrid] has been freed +/// - the returned memory range is never accessed concurrently, either via the [BrightnessGrid] or directly #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( brightness_grid: NonNull, diff --git a/src/char_grid.rs b/src/char_grid.rs index a845f4e..30e9953 100644 --- a/src/char_grid.rs +++ b/src/char_grid.rs @@ -1,4 +1,4 @@ -//! C functions for interacting with [SPCharGrid]s +//! C functions for interacting with [CharGrid]s //! //! prefix `sp_char_grid_` //! @@ -22,9 +22,9 @@ use crate::SPByteSlice; use servicepoint::{CharGrid, Grid}; use std::ptr::NonNull; -/// Creates a new [SPCharGrid] with the specified dimensions. +/// Creates a new [CharGrid] with the specified dimensions. /// -/// returns: [SPCharGrid] initialized to 0. Will never return NULL. +/// returns: [CharGrid] initialized to 0. Will never return NULL. /// /// # Safety /// @@ -41,7 +41,7 @@ pub unsafe extern "C" fn sp_char_grid_new( NonNull::from(Box::leak(result)) } -/// Loads a [SPCharGrid] with the specified dimensions from the provided data. +/// Loads a [CharGrid] with the specified dimensions from the provided data. /// /// Will never return NULL. /// @@ -72,7 +72,7 @@ pub unsafe extern "C" fn sp_char_grid_load( NonNull::from(Box::leak(result)) } -/// Clones a [SPCharGrid]. +/// Clones a [CharGrid]. /// /// Will never return NULL. /// @@ -84,7 +84,7 @@ pub unsafe extern "C" fn sp_char_grid_load( /// /// The caller has to make sure that: /// -/// - `char_grid` points to a valid [SPCharGrid] +/// - `char_grid` points to a valid [CharGrid] /// - `char_grid` is not written to concurrently /// - the returned instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_char_grid_free`. @@ -96,7 +96,7 @@ pub unsafe extern "C" fn sp_char_grid_clone( NonNull::from(Box::leak(result)) } -/// Deallocates a [SPCharGrid]. +/// Deallocates a [CharGrid]. /// /// # Panics /// @@ -106,11 +106,11 @@ pub unsafe extern "C" fn sp_char_grid_clone( /// /// The caller has to make sure that: /// -/// - `char_grid` points to a valid [SPCharGrid] +/// - `char_grid` points to a valid [CharGrid] /// - `char_grid` is not used concurrently or after char_grid call -/// - `char_grid` was not passed to another consuming function, e.g. to create a [SPCommand] +/// - `char_grid` was not passed to another consuming function, e.g. to create a [TypedCommand] /// -/// [SPCommand]: [crate::SPCommand] +/// [TypedCommand]: [crate::TypedCommand] #[no_mangle] pub unsafe extern "C" fn sp_char_grid_free(char_grid: NonNull) { _ = unsafe { Box::from_raw(char_grid.as_ptr()) }; @@ -132,7 +132,7 @@ pub unsafe extern "C" fn sp_char_grid_free(char_grid: NonNull) { /// /// The caller has to make sure that: /// -/// - `char_grid` points to a valid [SPCharGrid] +/// - `char_grid` points to a valid [CharGrid] /// - `char_grid` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_char_grid_get( @@ -143,7 +143,7 @@ pub unsafe extern "C" fn sp_char_grid_get( unsafe { char_grid.as_ref().get(x, y) as u32 } } -/// Sets the value of the specified position in the [SPCharGrid]. +/// Sets the value of the specified position in the [CharGrid]. /// /// # Arguments /// @@ -176,7 +176,7 @@ pub unsafe extern "C" fn sp_char_grid_set( unsafe { (*char_grid.as_ptr()).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 [CharGrid]. /// /// # Arguments /// @@ -191,7 +191,7 @@ pub unsafe extern "C" fn sp_char_grid_set( /// /// The caller has to make sure that: /// -/// - `char_grid` points to a valid [SPCharGrid] +/// - `char_grid` points to a valid [CharGrid] /// - `char_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_char_grid_fill( @@ -201,7 +201,7 @@ pub unsafe extern "C" fn sp_char_grid_fill( unsafe { (*char_grid.as_ptr()).fill(char::from_u32(value).unwrap()) }; } -/// Gets the width of the [SPCharGrid] instance. +/// Gets the width of the [CharGrid] instance. /// /// # Arguments /// @@ -215,7 +215,7 @@ pub unsafe extern "C" fn sp_char_grid_fill( /// /// The caller has to make sure that: /// -/// - `char_grid` points to a valid [SPCharGrid] +/// - `char_grid` points to a valid [CharGrid] #[no_mangle] pub unsafe extern "C" fn sp_char_grid_width( char_grid: NonNull, @@ -223,7 +223,7 @@ pub unsafe extern "C" fn sp_char_grid_width( unsafe { char_grid.as_ref().width() } } -/// Gets the height of the [SPCharGrid] instance. +/// Gets the height of the [CharGrid] instance. /// /// # Arguments /// @@ -237,7 +237,7 @@ pub unsafe extern "C" fn sp_char_grid_width( /// /// The caller has to make sure that: /// -/// - `char_grid` points to a valid [SPCharGrid] +/// - `char_grid` points to a valid [CharGrid] #[no_mangle] pub unsafe extern "C" fn sp_char_grid_height( char_grid: NonNull, diff --git a/src/command.rs b/src/command.rs index e107c07..2ed7415 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,4 +1,4 @@ -//! C functions for interacting with [SPCommand]s +//! C functions for interacting with [TypedCommand]s //! //! prefix `sp_command_` @@ -10,7 +10,7 @@ use std::ptr::NonNull; /// /// This struct and associated functions implement the UDP protocol for the display. /// -/// To send a [SPCommand], use a [SPConnection]. +/// To send a [TypedCommand], use a [UdpConnection]. /// /// # Examples /// @@ -18,14 +18,12 @@ use std::ptr::NonNull; /// sp_connection_send_command(connection, sp_command_clear()); /// sp_connection_send_command(connection, sp_command_brightness(5)); /// ``` -/// -/// [SPConnection]: [crate::SPConnection] -/// Tries to turn a [SPPacket] into a [SPCommand]. +/// Tries to turn a [Packet] into a [TypedCommand]. /// /// The packet is deallocated in the process. /// -/// Returns: pointer to new [SPCommand] instance or NULL if parsing failed. +/// Returns: pointer to new [TypedCommand] instance or NULL if parsing failed. /// /// # Panics /// @@ -35,10 +33,10 @@ use std::ptr::NonNull; /// /// The caller has to make sure that: /// -/// - [SPPacket] points to a valid instance of [SPPacket] -/// - [SPPacket] is not used concurrently or after this call +/// - [Packet] points to a valid instance of [Packet] +/// - [Packet] is not used concurrently or after this call /// - the result is checked for NULL -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_try_from_packet( @@ -51,9 +49,9 @@ pub unsafe extern "C" fn sp_command_try_from_packet( } } -/// Clones a [SPCommand] instance. +/// Clones a [TypedCommand] instance. /// -/// returns: new [SPCommand] instance. Will never return NULL. +/// returns: new [TypedCommand] instance. Will never return NULL. /// /// # Panics /// @@ -63,9 +61,9 @@ pub unsafe extern "C" fn sp_command_try_from_packet( /// /// The caller has to make sure that: /// -/// - `command` points to a valid instance of [SPCommand] +/// - `command` points to a valid instance of [TypedCommand] /// - `command` is not written to concurrently -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_clone( @@ -91,7 +89,7 @@ pub unsafe extern "C" fn sp_command_clone( /// /// The caller has to make sure that: /// -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_clear() -> NonNull { @@ -109,7 +107,7 @@ pub unsafe extern "C" fn sp_command_clear() -> NonNull { /// /// The caller has to make sure that: /// -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull { @@ -125,7 +123,7 @@ pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull { /// /// The caller has to make sure that: /// -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_fade_out() -> NonNull { @@ -145,7 +143,7 @@ pub unsafe extern "C" fn sp_command_fade_out() -> NonNull { /// /// The caller has to make sure that: /// -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_brightness( @@ -157,7 +155,7 @@ pub unsafe extern "C" fn sp_command_brightness( /// Set the brightness of individual tiles in a rectangular area of the display. /// -/// The passed [SPBrightnessGrid] gets consumed. +/// The passed [BrightnessGrid] gets consumed. /// /// Returns: a new [servicepoint::Command::CharBrightness] instance. Will never return NULL. /// @@ -169,9 +167,9 @@ pub unsafe extern "C" fn sp_command_brightness( /// /// The caller has to make sure that: /// -/// - `grid` points to a valid instance of [SPBrightnessGrid] +/// - `grid` points to a valid instance of [BrightnessGrid] /// - `grid` is not used concurrently or after this call -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_char_brightness( @@ -213,7 +211,7 @@ pub unsafe extern "C" fn sp_command_char_brightness( /// - `bit_vec` points to a valid instance of [SPBitVec] /// - `bit_vec` is not used concurrently or after this call /// - `compression` matches one of the allowed enum values -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear( @@ -254,7 +252,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear( /// - `bit_vec` points to a valid instance of [SPBitVec] /// - `bit_vec` is not used concurrently or after this call /// - `compression` matches one of the allowed enum values -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_and( @@ -295,7 +293,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and( /// - `bit_vec` points to a valid instance of [SPBitVec] /// - `bit_vec` is not used concurrently or after this call /// - `compression` matches one of the allowed enum values -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_or( @@ -336,7 +334,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or( /// - `bit_vec` points to a valid instance of [SPBitVec] /// - `bit_vec` is not used concurrently or after this call /// - `compression` matches one of the allowed enum values -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_xor( @@ -378,7 +376,7 @@ unsafe fn sp_command_bitmap_linear_internal( /// Show codepage 437 encoded text on the screen. /// -/// The passed [SPCp437Grid] gets consumed. +/// The passed [Cp437Grid] gets consumed. /// /// Returns: a new [servicepoint::Command::Cp437Data] instance. Will never return NULL. /// @@ -390,9 +388,9 @@ unsafe fn sp_command_bitmap_linear_internal( /// /// The caller has to make sure that: /// -/// - `grid` points to a valid instance of [SPCp437Grid] +/// - `grid` points to a valid instance of [Cp437Grid] /// - `grid` is not used concurrently or after this call -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_cp437_data( @@ -413,7 +411,7 @@ pub unsafe extern "C" fn sp_command_cp437_data( /// Show UTF-8 encoded text on the screen. /// -/// The passed [SPCharGrid] gets consumed. +/// The passed [CharGrid] gets consumed. /// /// Returns: a new [servicepoint::Command::Utf8Data] instance. Will never return NULL. /// @@ -425,9 +423,9 @@ pub unsafe extern "C" fn sp_command_cp437_data( /// /// The caller has to make sure that: /// -/// - `grid` points to a valid instance of [SPCharGrid] +/// - `grid` points to a valid instance of [CharGrid] /// - `grid` is not used concurrently or after this call -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_utf8_data( @@ -448,7 +446,7 @@ pub unsafe extern "C" fn sp_command_utf8_data( /// Sets a window of pixels to the specified values. /// -/// The passed [SPBitmap] gets consumed. +/// The passed [Bitmap] gets consumed. /// /// Returns: a new [servicepoint::Command::BitmapLinearWin] instance. Will never return NULL. /// @@ -461,10 +459,10 @@ pub unsafe extern "C" fn sp_command_utf8_data( /// /// The caller has to make sure that: /// -/// - `bitmap` points to a valid instance of [SPBitmap] +/// - `bitmap` points to a valid instance of [Bitmap] /// - `bitmap` is not used concurrently or after this call /// - `compression` matches one of the allowed enum values -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or +/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_win( @@ -487,12 +485,12 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win( Box::leak(Box::new(command)) } -/// Deallocates a [SPCommand]. +/// Deallocates a [TypedCommand]. /// /// # Examples /// /// ```C -/// SPCommand c = sp_command_clear(); +/// TypedCommand c = sp_command_clear(); /// sp_command_free(c); /// ``` /// @@ -504,9 +502,9 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win( /// /// The caller has to make sure that: /// -/// - `command` points to a valid [SPCommand] +/// - `command` points to a valid [TypedCommand] /// - `command` is not used concurrently or after this call -/// - `command` was not passed to another consuming function, e.g. to create a [SPPacket] +/// - `command` was not passed to another consuming function, e.g. to create a [Packet] #[no_mangle] pub unsafe extern "C" fn sp_command_free(command: NonNull) { _ = unsafe { Box::from_raw(command.as_ptr()) }; diff --git a/src/connection.rs b/src/connection.rs index 1705538..79e2e33 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,4 +1,4 @@ -//! C functions for interacting with [SPConnection]s +//! C functions for interacting with [UdpConnection]s //! //! prefix `sp_connection_` //! @@ -16,7 +16,7 @@ use servicepoint::{Connection, Packet, TypedCommand, UdpConnection}; use std::ffi::{c_char, CStr}; use std::ptr::NonNull; -/// Creates a new instance of [SPConnection]. +/// Creates a new instance of [UdpConnection]. /// /// returns: NULL if connection fails, or connected instance /// @@ -48,13 +48,13 @@ pub unsafe extern "C" fn sp_connection_open( //#[no_mangle] //pub unsafe extern "C" fn sp_connection_open_ipv4( // host: SocketAddrV4, -//) -> *mut SPConnection { +//) -> *mut UdpConnection { // let connection = match servicepoint::UdpConnection::open(host) { // Err(_) => return std::ptr::null_mut(), // Ok(value) => value, // }; // -// Box::into_raw(Box::new(SPConnection(connection))) +// Box::into_raw(Box::new(UdpConnection(connection))) //} // /// Creates a new instance of [SPUdpConnection] for testing that does not actually send anything. @@ -73,7 +73,7 @@ pub unsafe extern "C" fn sp_connection_open( // NonNull::from(Box::leak(result)) // } -/// Sends a [SPPacket] to the display using the [SPConnection]. +/// Sends a [Packet] to the display using the [UdpConnection]. /// /// The passed `packet` gets consumed. /// @@ -88,8 +88,8 @@ pub unsafe extern "C" fn sp_connection_open( /// /// The caller has to make sure that: /// -/// - `connection` points to a valid instance of [SPConnection] -/// - `packet` points to a valid instance of [SPPacket] +/// - `connection` points to a valid instance of [UdpConnection] +/// - `packet` points to a valid instance of [Packet] /// - `packet` is not used concurrently or after this call #[no_mangle] pub unsafe extern "C" fn sp_connection_send_packet( @@ -100,7 +100,7 @@ pub unsafe extern "C" fn sp_connection_send_packet( unsafe { connection.as_ref().send(*packet) }.is_ok() } -/// Sends a [SPCommand] to the display using the [SPConnection]. +/// Sends a [TypedCommand] to the display using the [UdpConnection]. /// /// The passed `command` gets consumed. /// @@ -115,8 +115,8 @@ pub unsafe extern "C" fn sp_connection_send_packet( /// /// The caller has to make sure that: /// -/// - `connection` points to a valid instance of [SPConnection] -/// - `command` points to a valid instance of [SPPacket] +/// - `connection` points to a valid instance of [UdpConnection] +/// - `command` points to a valid instance of [Packet] /// - `command` is not used concurrently or after this call #[no_mangle] pub unsafe extern "C" fn sp_connection_send_command( @@ -127,7 +127,7 @@ pub unsafe extern "C" fn sp_connection_send_command( unsafe { connection.as_ref().send(command) }.is_ok() } -/// Closes and deallocates a [SPConnection]. +/// Closes and deallocates a [UdpConnection]. /// /// # Panics /// @@ -137,7 +137,7 @@ pub unsafe extern "C" fn sp_connection_send_command( /// /// The caller has to make sure that: /// -/// - `connection` points to a valid [SPConnection] +/// - `connection` points to a valid [UdpConnection] /// - `connection` is not used concurrently or after this call #[no_mangle] pub unsafe extern "C" fn sp_connection_free( diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index e635247..96db2db 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -1,4 +1,4 @@ -//! C functions for interacting with [SPCp437Grid]s +//! C functions for interacting with [Cp437Grid]s //! //! prefix `sp_cp437_grid_` //! @@ -20,9 +20,9 @@ use crate::SPByteSlice; use servicepoint::{Cp437Grid, DataRef, Grid}; use std::ptr::NonNull; -/// Creates a new [SPCp437Grid] with the specified dimensions. +/// Creates a new [Cp437Grid] with the specified dimensions. /// -/// returns: [SPCp437Grid] initialized to 0. Will never return NULL. +/// returns: [Cp437Grid] initialized to 0. Will never return NULL. /// /// # Safety /// @@ -39,7 +39,7 @@ pub unsafe extern "C" fn sp_cp437_grid_new( NonNull::from(Box::leak(result)) } -/// Loads a [SPCp437Grid] with the specified dimensions from the provided data. +/// Loads a [Cp437Grid] with the specified dimensions from the provided data. /// /// Will never return NULL. /// @@ -71,7 +71,7 @@ pub unsafe extern "C" fn sp_cp437_grid_load( } } -/// Clones a [SPCp437Grid]. +/// Clones a [Cp437Grid]. /// /// Will never return NULL. /// @@ -83,7 +83,7 @@ pub unsafe extern "C" fn sp_cp437_grid_load( /// /// The caller has to make sure that: /// -/// - `cp437_grid` points to a valid [SPCp437Grid] +/// - `cp437_grid` points to a valid [Cp437Grid] /// - `cp437_grid` is not written to concurrently /// - the returned instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_cp437_grid_free`. @@ -95,7 +95,7 @@ pub unsafe extern "C" fn sp_cp437_grid_clone( NonNull::from(Box::leak(result)) } -/// Deallocates a [SPCp437Grid]. +/// Deallocates a [Cp437Grid]. /// /// # Panics /// @@ -105,11 +105,11 @@ pub unsafe extern "C" fn sp_cp437_grid_clone( /// /// The caller has to make sure that: /// -/// - `cp437_grid` points to a valid [SPCp437Grid] +/// - `cp437_grid` points to a valid [Cp437Grid] /// - `cp437_grid` is not used concurrently or after cp437_grid call -/// - `cp437_grid` was not passed to another consuming function, e.g. to create a [SPCommand] +/// - `cp437_grid` was not passed to another consuming function, e.g. to create a [TypedCommand] /// -/// [SPCommand]: [crate::SPCommand] +/// [TypedCommand]: [crate::TypedCommand] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: NonNull) { _ = unsafe { Box::from_raw(cp437_grid.as_ptr()) }; @@ -131,7 +131,7 @@ pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: NonNull) { /// /// The caller has to make sure that: /// -/// - `cp437_grid` points to a valid [SPCp437Grid] +/// - `cp437_grid` points to a valid [Cp437Grid] /// - `cp437_grid` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_get( @@ -142,7 +142,7 @@ pub unsafe extern "C" fn sp_cp437_grid_get( unsafe { cp437_grid.as_ref().get(x, y) } } -/// Sets the value of the specified position in the [SPCp437Grid]. +/// Sets the value of the specified position in the [Cp437Grid]. /// /// # Arguments /// @@ -175,7 +175,7 @@ pub unsafe extern "C" fn sp_cp437_grid_set( unsafe { (*cp437_grid.as_ptr()).set(x, y, value) }; } -/// Sets the value of all cells in the [SPCp437Grid]. +/// Sets the value of all cells in the [Cp437Grid]. /// /// # Arguments /// @@ -190,7 +190,7 @@ pub unsafe extern "C" fn sp_cp437_grid_set( /// /// The caller has to make sure that: /// -/// - `cp437_grid` points to a valid [SPCp437Grid] +/// - `cp437_grid` points to a valid [Cp437Grid] /// - `cp437_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_fill( @@ -200,7 +200,7 @@ pub unsafe extern "C" fn sp_cp437_grid_fill( unsafe { (*cp437_grid.as_ptr()).fill(value) }; } -/// Gets the width of the [SPCp437Grid] instance. +/// Gets the width of the [Cp437Grid] instance. /// /// # Arguments /// @@ -214,7 +214,7 @@ pub unsafe extern "C" fn sp_cp437_grid_fill( /// /// The caller has to make sure that: /// -/// - `cp437_grid` points to a valid [SPCp437Grid] +/// - `cp437_grid` points to a valid [Cp437Grid] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_width( cp437_grid: NonNull, @@ -222,7 +222,7 @@ pub unsafe extern "C" fn sp_cp437_grid_width( unsafe { cp437_grid.as_ref().width() } } -/// Gets the height of the [SPCp437Grid] instance. +/// Gets the height of the [Cp437Grid] instance. /// /// # Arguments /// @@ -236,7 +236,7 @@ pub unsafe extern "C" fn sp_cp437_grid_width( /// /// The caller has to make sure that: /// -/// - `cp437_grid` points to a valid [SPCp437Grid] +/// - `cp437_grid` points to a valid [Cp437Grid] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_height( cp437_grid: NonNull, @@ -244,7 +244,7 @@ pub unsafe extern "C" fn sp_cp437_grid_height( unsafe { cp437_grid.as_ref().height() } } -/// Gets an unsafe reference to the data of the [SPCp437Grid] instance. +/// Gets an unsafe reference to the data of the [Cp437Grid] instance. /// /// Will never return NULL. /// @@ -256,9 +256,9 @@ pub unsafe extern "C" fn sp_cp437_grid_height( /// /// The caller has to make sure that: /// -/// - `cp437_grid` points to a valid [SPCp437Grid] -/// - the returned memory range is never accessed after the passed [SPCp437Grid] has been freed -/// - the returned memory range is never accessed concurrently, either via the [SPCp437Grid] or directly +/// - `cp437_grid` points to a valid [Cp437Grid] +/// - the returned memory range is never accessed after the passed [Cp437Grid] has been freed +/// - the returned memory range is never accessed concurrently, either via the [Cp437Grid] or directly #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref( cp437_grid: NonNull, diff --git a/src/lib.rs b/src/lib.rs index 831daea..4d4e386 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,14 +9,14 @@ //! #include "servicepoint.h" //! //! int main(void) { -//! SPConnection *connection = sp_connection_open("172.23.42.29:2342"); +//! UdpConnection *connection = sp_connection_open("172.23.42.29:2342"); //! if (connection == NULL) //! return 1; //! -//! SPBitmap *pixels = sp_bitmap_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT); +//! Bitmap *pixels = sp_bitmap_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT); //! sp_bitmap_fill(pixels, true); //! -//! SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed); +//! TypedCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed); //! while (sp_connection_send_command(connection, sp_command_clone(command))); //! //! sp_command_free(command); diff --git a/src/packet.rs b/src/packet.rs index f8235ab..ae37058 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,4 +1,4 @@ -//! C functions for interacting with [SPPacket]s +//! C functions for interacting with [Packet]s //! //! prefix `sp_packet_` //! @@ -9,10 +9,10 @@ use crate::SPByteSlice; use servicepoint::{Header, Packet, TypedCommand}; use std::ptr::NonNull; -/// Turns a [SPCommand] into a [SPPacket]. -/// The [SPCommand] gets consumed. +/// Turns a [TypedCommand] into a [Packet]. +/// The [TypedCommand] gets consumed. /// -/// Will never return NULL. +/// Returns NULL in case of an error. /// /// # Panics /// @@ -22,9 +22,9 @@ use std::ptr::NonNull; /// /// The caller has to make sure that: /// -/// - [SPCommand] points to a valid instance of [SPCommand] -/// - [SPCommand] is not used concurrently or after this call -/// - the returned [SPPacket] instance is freed in some way, either by using a consuming function or +/// - [TypedCommand] points to a valid instance of [TypedCommand] +/// - [TypedCommand] is not used concurrently or after this call +/// - the returned [Packet] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_packet_free`. #[no_mangle] pub unsafe extern "C" fn sp_packet_from_command( @@ -38,7 +38,7 @@ pub unsafe extern "C" fn sp_packet_from_command( } } -/// Tries to load a [SPPacket] from the passed array with the specified length. +/// 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 /// @@ -52,7 +52,7 @@ pub unsafe extern "C" fn sp_packet_from_command( /// /// - `data` points to a valid memory region of at least `length` bytes /// - `data` is not written to concurrently -/// - the returned [SPPacket] instance is freed in some way, either by using a consuming function or +/// - the returned [Packet] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_packet_free`. #[no_mangle] pub unsafe extern "C" fn sp_packet_try_load(data: SPByteSlice) -> *mut Packet { @@ -63,7 +63,7 @@ pub unsafe extern "C" fn sp_packet_try_load(data: SPByteSlice) -> *mut Packet { } } -/// Creates a raw [SPPacket] from parts. +/// Creates a raw [Packet] from parts. /// /// # Arguments /// @@ -85,7 +85,7 @@ pub unsafe extern "C" fn sp_packet_try_load(data: SPByteSlice) -> *mut Packet { /// /// - `payload` points to a valid memory region of at least `payload_len` bytes /// - `payload` is not written to concurrently -/// - the returned [SPPacket] instance is freed in some way, either by using a consuming function or +/// - the returned [Packet] instance is freed in some way, either by using a consuming function or /// by explicitly calling [sp_packet_free]. #[no_mangle] pub unsafe extern "C" fn sp_packet_from_parts( @@ -103,6 +103,9 @@ pub unsafe extern "C" fn sp_packet_from_parts( NonNull::from(Box::leak(packet)) } +/// Returns a pointer to the header field of the provided packet. +/// +/// The returned header can be changed and will be valid for the lifetime of the packet. #[no_mangle] pub unsafe extern "C" fn sp_packet_get_header( packet: NonNull, @@ -110,6 +113,9 @@ pub unsafe extern "C" fn sp_packet_get_header( NonNull::from(&mut unsafe { (*packet.as_ptr()).header }) } +/// Returns a pointer to the current payload of the provided packet. +/// +/// The returned memory can be changed and will be valid until a new payload is set. #[no_mangle] pub unsafe extern "C" fn sp_packet_get_payload( packet: NonNull, @@ -117,6 +123,9 @@ pub unsafe extern "C" fn sp_packet_get_payload( unsafe { SPByteSlice::from_slice(&mut *(*packet.as_ptr()).payload) } } +/// Sets the payload of the provided packet to the provided data. +/// +/// This makes previous payload pointers invalid. #[no_mangle] pub unsafe extern "C" fn sp_packet_set_payload( packet: NonNull, @@ -125,8 +134,13 @@ pub unsafe extern "C" fn sp_packet_set_payload( unsafe { (*packet.as_ptr()).payload = data.as_slice().to_vec() } } +/// Serialize the packet into the provided buffer. +/// +/// # Panics +/// +/// - if the buffer is not big enough to hold header+payload. #[no_mangle] -pub unsafe extern "C" fn sp_packet_write_to( +pub unsafe extern "C" fn sp_packet_serialize_to( packet: NonNull, buffer: SPByteSlice, ) { @@ -135,7 +149,7 @@ pub unsafe extern "C" fn sp_packet_write_to( } } -/// Clones a [SPPacket]. +/// Clones a [Packet]. /// /// Will never return NULL. /// @@ -147,7 +161,7 @@ pub unsafe extern "C" fn sp_packet_write_to( /// /// The caller has to make sure that: /// -/// - `packet` points to a valid [SPPacket] +/// - `packet` points to a valid [Packet] /// - `packet` is not written to concurrently /// - the returned instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_packet_free`. @@ -159,7 +173,7 @@ pub unsafe extern "C" fn sp_packet_clone( NonNull::from(Box::leak(result)) } -/// Deallocates a [SPPacket]. +/// Deallocates a [Packet]. /// /// # Panics /// @@ -169,7 +183,7 @@ pub unsafe extern "C" fn sp_packet_clone( /// /// The caller has to make sure that: /// -/// - `packet` points to a valid [SPPacket] +/// - `packet` points to a valid [Packet] /// - `packet` is not used concurrently or after this call #[no_mangle] pub unsafe extern "C" fn sp_packet_free(packet: NonNull) { -- 2.47.0 From 7c8ede61b04b78f29fe3b1231215690482373b08 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 16:22:39 +0200 Subject: [PATCH 13/25] move generic safety information into README --- README.md | 15 + include/servicepoint.h | 996 ++++------------------------------------- src/bitmap.rs | 121 +---- src/bitvec.rs | 134 +----- src/brightness_grid.rs | 167 +------ src/byte_slice.rs | 14 +- src/char_grid.rs | 150 +------ src/command.rs | 229 +--------- src/connection.rs | 71 +-- src/cp437_grid.rs | 143 +----- src/packet.rs | 94 +--- 11 files changed, 196 insertions(+), 1938 deletions(-) diff --git a/README.md b/README.md index e085b1b..2f089d3 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,21 @@ You have the choice of linking statically (recommended) or dynamically. - documentation is included in the header and available [online](https://docs.rs/servicepoint_binding_c/latest/servicepoint_binding_c/) +## Safety + +Functions expect that C code honors NonNull annotations. + +Any created instances have to be freed in some way. +Pointers to those instances cannot be used anymore after that. + +Instances cannot be shared between threads and need to be locked in the using code. + +Enum values have to be used as-is. Do not pass values that are not part of the enum. + +UTF-8 or UTF-32 encoding has to be used properly. + +Brightness values provided as u8 parameters must be in range. + ## Everything else Look at the main project [README](https://git.berlin.ccc.de/servicepoint/servicepoint/src/branch/main/README.md) for diff --git a/include/servicepoint.h b/include/servicepoint.h index 07bc8f8..dbce14d 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -206,9 +206,7 @@ typedef struct ValueGrid_char ValueGrid_char; typedef struct ValueGrid_u8 ValueGrid_u8; /** - * Represents a span of memory (`&mut [u8]` ) as a struct usable by C code. - * - * You should not create an instance of this type in your C code. + * Represents a span of memory (`&mut [u8]` ) as a struct. * * # Safety * @@ -217,19 +215,17 @@ typedef struct ValueGrid_u8 ValueGrid_u8; * - accesses to the memory pointed to with `start` is never accessed outside `length` * - the lifetime of the `CByteSlice` does not outlive the memory it points to, as described in * the function returning this type. - * - an instance of this created from C is never passed to a consuming function, as the rust code - * will try to free the memory of a potentially separate allocator. */ typedef struct { /** - * The start address of the memory + * The start address of the memory. */ uint8_t */*notnull*/ start; /** - * The amount of memory in bytes + * The amount of memory in bytes. */ size_t length; -} SPByteSlice; +} ByteSlice; /** * A grid containing brightness values. @@ -345,21 +341,6 @@ extern "C" { /** * Clones a [Bitmap]. - * - * Will never return NULL. - * - * # Panics - * - * - when `bitmap` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [Bitmap] - * - `bitmap` is not written to concurrently - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_bitmap_free`. */ Bitmap */*notnull*/ sp_bitmap_clone(Bitmap */*notnull*/ bitmap); @@ -370,34 +351,11 @@ Bitmap */*notnull*/ sp_bitmap_clone(Bitmap */*notnull*/ bitmap); * * - `bitmap`: instance to write to * - `value`: the value to set all pixels to - * - * # Panics - * - * - when `bitmap` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [Bitmap] - * - `bitmap` is not written to or read from concurrently */ void sp_bitmap_fill(Bitmap */*notnull*/ bitmap, bool value); /** * Deallocates a [Bitmap]. - * - * # Panics - * - * - when `bitmap` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [Bitmap] - * - * [TypedCommand]: [crate::TypedCommand] */ void sp_bitmap_free(Bitmap */*notnull*/ bitmap); @@ -411,15 +369,7 @@ void sp_bitmap_free(Bitmap */*notnull*/ bitmap); * * # Panics * - * - when `bitmap` is NULL * - when accessing `x` or `y` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [Bitmap] - * - `bitmap` is not written to concurrently */ bool sp_bitmap_get(Bitmap */*notnull*/ bitmap, size_t x, size_t y); @@ -429,16 +379,6 @@ bool sp_bitmap_get(Bitmap */*notnull*/ bitmap, size_t x, size_t y); * # Arguments * * - `bitmap`: instance to read from - * - * # Panics - * - * - when `bitmap` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [Bitmap] */ size_t sp_bitmap_height(Bitmap */*notnull*/ bitmap); @@ -451,29 +391,10 @@ size_t sp_bitmap_height(Bitmap */*notnull*/ bitmap); * - `height`: size in pixels in y-direction * * returns: [Bitmap] 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 - * - * - when `data` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `data` points to a valid memory location of at least `data_length` bytes in size. - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_bitmap_free`. */ Bitmap *sp_bitmap_load(size_t width, size_t height, - SPByteSlice data); + ByteSlice data); /** * Creates a new [Bitmap] with the specified dimensions. @@ -491,13 +412,6 @@ Bitmap *sp_bitmap_load(size_t width, * * - when the width is not dividable by 8 * - * # 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_bitmap_free`. - * * # Examples * * ```C @@ -507,20 +421,12 @@ Bitmap *sp_bitmap_load(size_t width, * sp_bitmap_free(grid); * ``` */ -Bitmap *sp_bitmap_new(size_t width, - size_t height); +Bitmap *sp_bitmap_new(size_t width, size_t height); /** * Creates a new [Bitmap] with a size matching the screen. * - * returns: [Bitmap] initialized to all pixels off. 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_bitmap_free]. + * returns: [Bitmap] initialized to all pixels off. */ Bitmap */*notnull*/ sp_bitmap_new_screen_sized(void); @@ -533,38 +439,18 @@ Bitmap */*notnull*/ sp_bitmap_new_screen_sized(void); * - `x` and `y`: position of the cell * - `value`: the value to write to the cell * - * returns: old value of the cell - * * # Panics * - * - when `bitmap` is NULL * - when accessing `x` or `y` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [Bitmap] - * - `bitmap` is not written to or read from concurrently */ void sp_bitmap_set(Bitmap */*notnull*/ bitmap, size_t x, size_t y, bool value); /** * Gets an unsafe reference to the data of the [Bitmap] instance. * - * # Panics - * - * - when `bitmap` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [Bitmap] - * - the returned memory range is never accessed after the passed [Bitmap] has been freed - * - the returned memory range is never accessed concurrently, either via the [Bitmap] or directly + * The returned memory is valid for the lifetime of the bitmap. */ -SPByteSlice sp_bitmap_unsafe_data_ref(Bitmap */*notnull*/ bitmap); +ByteSlice sp_bitmap_unsafe_data_ref(Bitmap */*notnull*/ bitmap); /** * Gets the width in pixels of the [Bitmap] instance. @@ -587,21 +473,6 @@ size_t sp_bitmap_width(Bitmap */*notnull*/ bitmap); /** * Clones a [SPBitVec]. - * - * returns: new [SPBitVec] instance. Will never return NULL. - * - * # Panics - * - * - when `bit_vec` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - * - `bit_vec` is not written to concurrently - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_bitvec_free`. */ SPBitVec */*notnull*/ sp_bitvec_clone(SPBitVec */*notnull*/ bit_vec); @@ -612,36 +483,11 @@ SPBitVec */*notnull*/ sp_bitvec_clone(SPBitVec */*notnull*/ bit_vec); * * - `bit_vec`: instance to write to * - `value`: the value to set all bits to - * - * # Panics - * - * - when `bit_vec` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - * - `bit_vec` is not written to or read from concurrently */ void sp_bitvec_fill(SPBitVec */*notnull*/ bit_vec, bool value); /** * Deallocates a [SPBitVec]. - * - * # Panics - * - * - when `but_vec` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - * - `bit_vec` is not used concurrently or after this call - * - `bit_vec` was not passed to another consuming function, e.g. to create a [TypedCommand] - * - * [TypedCommand]: [crate::TypedCommand] */ void sp_bitvec_free(SPBitVec */*notnull*/ bit_vec); @@ -657,15 +503,7 @@ void sp_bitvec_free(SPBitVec */*notnull*/ bit_vec); * * # Panics * - * - when `bit_vec` is NULL * - when accessing `index` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - * - `bit_vec` is not written to concurrently */ bool sp_bitvec_get(SPBitVec */*notnull*/ bit_vec, size_t index); @@ -675,16 +513,6 @@ bool sp_bitvec_get(SPBitVec */*notnull*/ bit_vec, size_t index); * # Arguments * * - `bit_vec`: instance to write to - * - * # Panics - * - * - when `bit_vec` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] */ bool sp_bitvec_is_empty(SPBitVec */*notnull*/ bit_vec); @@ -694,38 +522,15 @@ bool sp_bitvec_is_empty(SPBitVec */*notnull*/ bit_vec); * # Arguments * * - `bit_vec`: instance to write to - * - * # Panics - * - * - when `bit_vec` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] */ size_t sp_bitvec_len(SPBitVec */*notnull*/ bit_vec); /** * Interpret the data as a series of bits and load then into a new [SPBitVec] instance. * - * returns: [SPBitVec] instance containing data. Will never return NULL. - * - * # Panics - * - * - when `data` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `data` points to a valid memory location of at least `data_length` - * bytes in size. - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_bitvec_free`. + * returns: [SPBitVec] instance containing data. */ -SPBitVec */*notnull*/ sp_bitvec_load(SPByteSlice data); +SPBitVec */*notnull*/ sp_bitvec_load(ByteSlice data); /** * Creates a new [SPBitVec] instance. @@ -734,18 +539,11 @@ SPBitVec */*notnull*/ sp_bitvec_load(SPByteSlice data); * * - `size`: size in bits. * - * returns: [SPBitVec] with all bits set to false. Will never return NULL. + * returns: [SPBitVec] with all bits set to false. * * # Panics * * - when `size` is not divisible by 8. - * - * # 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_bitvec_free`. */ SPBitVec */*notnull*/ sp_bitvec_new(size_t size); @@ -760,60 +558,23 @@ SPBitVec */*notnull*/ sp_bitvec_new(size_t size); * * # Panics * - * - when `bit_vec` is NULL * - when accessing `index` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - * - `bit_vec` is not written to or read from concurrently */ void sp_bitvec_set(SPBitVec */*notnull*/ bit_vec, size_t index, bool value); /** * Gets an unsafe reference to the data of the [SPBitVec] instance. * + * The returned memory is valid for the lifetime of the bitvec. + * * # Arguments * * - `bit_vec`: instance to write to - * - * # Panics - * - * - when `bit_vec` is NULL - * - * ## Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - * - the returned memory range is never accessed after the passed [SPBitVec] has been freed - * - the returned memory range is never accessed concurrently, either via the [SPBitVec] or directly */ -SPByteSlice sp_bitvec_unsafe_data_ref(SPBitVec */*notnull*/ bit_vec); +ByteSlice sp_bitvec_unsafe_data_ref(SPBitVec */*notnull*/ bit_vec); /** * Clones a [BrightnessGrid]. - * - * # Arguments - * - * - `brightness_grid`: instance to read from - * - * returns: new [BrightnessGrid] instance. Will never return NULL. - * - * # Panics - * - * - when `brightness_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [BrightnessGrid] - * - `brightness_grid` is not written to concurrently - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_brightness_grid_free`. */ BrightnessGrid */*notnull*/ sp_brightness_grid_clone(BrightnessGrid */*notnull*/ brightness_grid); @@ -824,42 +585,12 @@ BrightnessGrid */*notnull*/ sp_brightness_grid_clone(BrightnessGrid */*notnull*/ * * - `brightness_grid`: instance to write to * - `value`: the value to set all cells to - * - * # Panics - * - * - when `brightness_grid` is NULL - * - When providing an invalid brightness value - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [BrightnessGrid] - * - `brightness_grid` is not written to or read from concurrently */ void sp_brightness_grid_fill(BrightnessGrid */*notnull*/ brightness_grid, Brightness value); /** * Deallocates a [BrightnessGrid]. - * - * # Arguments - * - * - `brightness_grid`: instance to read from - * - * # Panics - * - * - when `brightness_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [BrightnessGrid] - * - `brightness_grid` is not used concurrently or after this call - * - `brightness_grid` was not passed to another consuming function, e.g. to create a [TypedCommand] - * - * [TypedCommand]: [crate::TypedCommand] */ void sp_brightness_grid_free(BrightnessGrid */*notnull*/ brightness_grid); @@ -874,16 +605,7 @@ void sp_brightness_grid_free(BrightnessGrid */*notnull*/ brightness_grid); * returns: value at position * * # Panics - * - * - when `brightness_grid` is NULL * - When accessing `x` or `y` out of bounds. - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [BrightnessGrid] - * - `brightness_grid` is not written to concurrently */ Brightness sp_brightness_grid_get(BrightnessGrid */*notnull*/ brightness_grid, size_t x, @@ -897,56 +619,38 @@ Brightness sp_brightness_grid_get(BrightnessGrid */*notnull*/ brightness_grid, * - `brightness_grid`: instance to read from * * returns: height - * - * # Panics - * - * - when `brightness_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [BrightnessGrid] */ size_t sp_brightness_grid_height(BrightnessGrid */*notnull*/ brightness_grid); /** * Loads a [BrightnessGrid] with the specified dimensions from the provided data. * - * returns: new [BrightnessGrid] instance. Will never return NULL. - * - * # Panics - * - * - when `data` is NULL - * - when the provided `data_length` does not match `height` and `width` - * - * # Safety - * - * The caller has to make sure that: - * - * - `data` points to a valid memory location of at least `data_length` - * bytes in size. - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_brightness_grid_free`. + * returns: new [BrightnessGrid] instance, or NULL in case of an error. */ BrightnessGrid *sp_brightness_grid_load(size_t width, size_t height, - SPByteSlice data); + ByteSlice data); /** * Creates a new [BrightnessGrid] with the specified dimensions. * - * returns: [BrightnessGrid] initialized to 0. Will never return NULL. + * returns: [BrightnessGrid] initialized to 0. * - * # Safety + * # Examples + * ```C + * UdpConnection connection = sp_connection_open("127.0.0.1:2342"); + * if (connection == NULL) + * return 1; * - * The caller has to make sure that: + * BrightnessGrid grid = sp_brightness_grid_new(2, 2); + * sp_brightness_grid_set(grid, 0, 0, 0); + * sp_brightness_grid_set(grid, 1, 1, 10); * - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_brightness_grid_free`. + * TypedCommand command = sp_command_char_brightness(grid); + * sp_connection_free(connection); + * ``` */ -BrightnessGrid */*notnull*/ sp_brightness_grid_new(size_t width, - size_t height); +BrightnessGrid */*notnull*/ sp_brightness_grid_new(size_t width, size_t height); /** * Sets the value of the specified position in the [BrightnessGrid]. @@ -961,16 +665,7 @@ BrightnessGrid */*notnull*/ sp_brightness_grid_new(size_t width, * * # Panics * - * - when `brightness_grid` is NULL * - When accessing `x` or `y` out of bounds. - * - When providing an invalid brightness value - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [BrightnessGrid] - * - `brightness_grid` is not written to or read from concurrently */ void sp_brightness_grid_set(BrightnessGrid */*notnull*/ brightness_grid, size_t x, @@ -980,25 +675,15 @@ void sp_brightness_grid_set(BrightnessGrid */*notnull*/ brightness_grid, /** * Gets an unsafe reference to the data of the [BrightnessGrid] instance. * + * The returned memory is valid for the lifetime of the brightness grid. + * * # Arguments * * - `brightness_grid`: instance to read from * * returns: slice of bytes underlying the `brightness_grid`. - * - * # Panics - * - * - when `brightness_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [BrightnessGrid] - * - the returned memory range is never accessed after the passed [BrightnessGrid] has been freed - * - the returned memory range is never accessed concurrently, either via the [BrightnessGrid] or directly */ -SPByteSlice sp_brightness_grid_unsafe_data_ref(BrightnessGrid */*notnull*/ brightness_grid); +ByteSlice sp_brightness_grid_unsafe_data_ref(BrightnessGrid */*notnull*/ brightness_grid); /** * Gets the width of the [BrightnessGrid] instance. @@ -1008,36 +693,11 @@ SPByteSlice sp_brightness_grid_unsafe_data_ref(BrightnessGrid */*notnull*/ brigh * - `brightness_grid`: instance to read from * * returns: width - * - * # Panics - * - * - when `brightness_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [BrightnessGrid] */ size_t sp_brightness_grid_width(BrightnessGrid */*notnull*/ brightness_grid); /** * Clones a [CharGrid]. - * - * Will never return NULL. - * - * # Panics - * - * - when `char_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [CharGrid] - * - `char_grid` is not written to concurrently - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_char_grid_free`. */ CharGrid */*notnull*/ sp_char_grid_clone(CharGrid */*notnull*/ char_grid); @@ -1048,41 +708,16 @@ CharGrid */*notnull*/ sp_char_grid_clone(CharGrid */*notnull*/ char_grid); * * - `char_grid`: instance to write to * - `value`: the value to set all cells to - * - * # Panics - * - * - when `char_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [CharGrid] - * - `char_grid` is not written to or read from concurrently */ void sp_char_grid_fill(CharGrid */*notnull*/ char_grid, uint32_t value); /** * Deallocates a [CharGrid]. - * - * # Panics - * - * - when `char_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [CharGrid] - * - `char_grid` is not used concurrently or after char_grid call - * - `char_grid` was not passed to another consuming function, e.g. to create a [TypedCommand] - * - * [TypedCommand]: [crate::TypedCommand] */ void sp_char_grid_free(CharGrid */*notnull*/ char_grid); /** - * Gets the current value at the specified position. + * Returns the current value at the specified position. * * # Arguments * @@ -1091,15 +726,7 @@ void sp_char_grid_free(CharGrid */*notnull*/ char_grid); * * # Panics * - * - when `char_grid` is NULL * - when accessing `x` or `y` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [CharGrid] - * - `char_grid` is not written to concurrently */ uint32_t sp_char_grid_get(CharGrid */*notnull*/ char_grid, size_t x, size_t y); @@ -1109,57 +736,31 @@ uint32_t sp_char_grid_get(CharGrid */*notnull*/ char_grid, size_t x, size_t y); * # Arguments * * - `char_grid`: instance to read from - * - * # Panics - * - * - when `char_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [CharGrid] */ size_t sp_char_grid_height(CharGrid */*notnull*/ char_grid); /** * Loads a [CharGrid] with the specified dimensions from the provided data. * - * Will never return NULL. - * - * # Panics - * - * - when `data` is NULL - * - when the provided `data_length` does not match `height` and `width` - * - when `data` is not valid UTF-8 - * - * # Safety - * - * The caller has to make sure that: - * - * - `data` points to a valid memory location of at least `data_length` - * bytes in size. - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_char_grid_free`. + * returns: new CharGrid or NULL in case of an error */ -CharGrid */*notnull*/ sp_char_grid_load(size_t width, - size_t height, - SPByteSlice data); +CharGrid *sp_char_grid_load(size_t width, size_t height, ByteSlice data); /** * Creates a new [CharGrid] with the specified dimensions. * - * returns: [CharGrid] initialized to 0. Will never return NULL. + * returns: [CharGrid] initialized to 0. * - * # Safety + * # Examples * - * 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_char_grid_free`. + * ```C + * CharGrid grid = sp_char_grid_new(4, 3); + * sp_char_grid_fill(grid, '?'); + * sp_char_grid_set(grid, 0, 0, '!'); + * sp_char_grid_free(grid); + * ``` */ -CharGrid */*notnull*/ sp_char_grid_new(size_t width, - size_t height); +CharGrid */*notnull*/ sp_char_grid_new(size_t width, size_t height); /** * Sets the value of the specified position in the [CharGrid]. @@ -1174,17 +775,7 @@ CharGrid */*notnull*/ sp_char_grid_new(size_t width, * * # Panics * - * - when `char_grid` is NULL * - when accessing `x` or `y` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [SPBitVec] - * - `char_grid` is not written to or read from concurrently - * - * [SPBitVec]: [crate::SPBitVec] */ void sp_char_grid_set(CharGrid */*notnull*/ char_grid, size_t x, @@ -1197,16 +788,6 @@ void sp_char_grid_set(CharGrid */*notnull*/ char_grid, * # Arguments * * - `char_grid`: instance to read from - * - * # Panics - * - * - when `char_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [CharGrid] */ size_t sp_char_grid_width(CharGrid */*notnull*/ char_grid); @@ -1220,22 +801,7 @@ size_t sp_char_grid_width(CharGrid */*notnull*/ char_grid); * * The passed [SPBitVec] gets consumed. * - * Returns: a new [servicepoint::Command::BitmapLinear] instance. Will never return NULL. - * - * # Panics - * - * - when `bit_vec` is null - * - when `compression_code` is not a valid value - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid instance of [SPBitVec] - * - `bit_vec` is not used concurrently or after this call - * - `compression` matches one of the allowed enum values - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. + * Returns: a new [servicepoint::Command::BitmapLinear] instance. */ TypedCommand *sp_command_bitmap_linear(size_t offset, SPBitVec */*notnull*/ bit_vec, @@ -1251,22 +817,7 @@ TypedCommand *sp_command_bitmap_linear(size_t offset, * * The passed [SPBitVec] gets consumed. * - * Returns: a new [servicepoint::Command::BitmapLinearAnd] instance. Will never return NULL. - * - * # Panics - * - * - when `bit_vec` is null - * - when `compression_code` is not a valid value - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid instance of [SPBitVec] - * - `bit_vec` is not used concurrently or after this call - * - `compression` matches one of the allowed enum values - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. + * Returns: a new [servicepoint::Command::BitmapLinearAnd] instance. */ TypedCommand *sp_command_bitmap_linear_and(size_t offset, SPBitVec */*notnull*/ bit_vec, @@ -1282,22 +833,7 @@ TypedCommand *sp_command_bitmap_linear_and(size_t offset, * * The passed [SPBitVec] gets consumed. * - * Returns: a new [servicepoint::Command::BitmapLinearOr] instance. Will never return NULL. - * - * # Panics - * - * - when `bit_vec` is null - * - when `compression_code` is not a valid value - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid instance of [SPBitVec] - * - `bit_vec` is not used concurrently or after this call - * - `compression` matches one of the allowed enum values - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. + * Returns: a new [servicepoint::Command::BitmapLinearOr] instance. */ TypedCommand *sp_command_bitmap_linear_or(size_t offset, SPBitVec */*notnull*/ bit_vec, @@ -1308,22 +844,7 @@ TypedCommand *sp_command_bitmap_linear_or(size_t offset, * * The passed [Bitmap] gets consumed. * - * Returns: a new [servicepoint::Command::BitmapLinearWin] instance. Will never return NULL. - * - * # Panics - * - * - when `bitmap` is null - * - when `compression_code` is not a valid value - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid instance of [Bitmap] - * - `bitmap` is not used concurrently or after this call - * - `compression` matches one of the allowed enum values - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. + * Returns: a new [servicepoint::Command::BitmapLinearWin] instance. */ TypedCommand *sp_command_bitmap_linear_win(size_t x, size_t y, @@ -1340,22 +861,7 @@ TypedCommand *sp_command_bitmap_linear_win(size_t x, * * The passed [SPBitVec] gets consumed. * - * Returns: a new [servicepoint::Command::BitmapLinearXor] instance. Will never return NULL. - * - * # Panics - * - * - when `bit_vec` is null - * - when `compression_code` is not a valid value - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid instance of [SPBitVec] - * - `bit_vec` is not used concurrently or after this call - * - `compression` matches one of the allowed enum values - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. + * Returns: a new [servicepoint::Command::BitmapLinearXor] instance. */ TypedCommand *sp_command_bitmap_linear_xor(size_t offset, SPBitVec */*notnull*/ bit_vec, @@ -1364,18 +870,7 @@ TypedCommand *sp_command_bitmap_linear_xor(size_t offset, /** * Set the brightness of all tiles to the same value. * - * Returns: a new [servicepoint::Command::Brightness] instance. Will never return NULL. - * - * # Panics - * - * - When the provided brightness value is out of range (0-11). - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. + * Returns: a new [servicepoint::Command::Brightness] instance. */ TypedCommand */*notnull*/ sp_command_brightness(Brightness brightness); @@ -1384,20 +879,7 @@ TypedCommand */*notnull*/ sp_command_brightness(Brightness brightness); * * The passed [BrightnessGrid] gets consumed. * - * Returns: a new [servicepoint::Command::CharBrightness] instance. Will never return NULL. - * - * # Panics - * - * - when `grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `grid` points to a valid instance of [BrightnessGrid] - * - `grid` is not used concurrently or after this call - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. + * Returns: a new [servicepoint::Command::CharBrightness] instance. */ TypedCommand */*notnull*/ sp_command_char_brightness(size_t x, size_t y, @@ -1408,40 +890,20 @@ TypedCommand */*notnull*/ sp_command_char_brightness(size_t x, * * Does not affect brightness. * - * Returns: a new [servicepoint::Command::Clear] instance. Will never return NULL. + * Returns: a new [servicepoint::Command::Clear] instance. * * # Examples * * ```C * sp_connection_send_command(connection, sp_command_clear()); * ``` - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. */ TypedCommand */*notnull*/ sp_command_clear(void); /** * Clones a [TypedCommand] instance. * - * returns: new [TypedCommand] instance. Will never return NULL. - * - * # Panics - * - * - when `command` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `command` points to a valid instance of [TypedCommand] - * - `command` is not written to concurrently - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. + * returns: new [TypedCommand] instance. */ TypedCommand */*notnull*/ sp_command_clone(TypedCommand */*notnull*/ command); @@ -1450,20 +912,7 @@ TypedCommand */*notnull*/ sp_command_clone(TypedCommand */*notnull*/ command); * * The passed [Cp437Grid] gets consumed. * - * Returns: a new [servicepoint::Command::Cp437Data] instance. Will never return NULL. - * - * # Panics - * - * - when `grid` is null - * - * # Safety - * - * The caller has to make sure that: - * - * - `grid` points to a valid instance of [Cp437Grid] - * - `grid` is not used concurrently or after this call - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. + * Returns: a new [servicepoint::Command::Cp437Data] instance. */ TypedCommand */*notnull*/ sp_command_cp437_data(size_t x, size_t y, @@ -1472,14 +921,7 @@ TypedCommand */*notnull*/ sp_command_cp437_data(size_t x, /** * A yet-to-be-tested command. * - * Returns: a new [servicepoint::Command::FadeOut] instance. Will never return NULL. - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. + * Returns: a new [servicepoint::Command::FadeOut] instance. */ TypedCommand */*notnull*/ sp_command_fade_out(void); @@ -1492,18 +934,6 @@ TypedCommand */*notnull*/ sp_command_fade_out(void); * TypedCommand c = sp_command_clear(); * sp_command_free(c); * ``` - * - * # Panics - * - * - when `command` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `command` points to a valid [TypedCommand] - * - `command` is not used concurrently or after this call - * - `command` was not passed to another consuming function, e.g. to create a [Packet] */ void sp_command_free(TypedCommand */*notnull*/ command); @@ -1512,49 +942,16 @@ void sp_command_free(TypedCommand */*notnull*/ command); * * Please do not send this in your normal program flow. * - * Returns: a new [servicepoint::Command::HardReset] instance. Will never return NULL. - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. + * Returns: a new [servicepoint::Command::HardReset] instance. */ TypedCommand */*notnull*/ sp_command_hard_reset(void); /** - * A low-level display command. - * - * This struct and associated functions implement the UDP protocol for the display. - * - * To send a [TypedCommand], use a [UdpConnection]. - * - * # Examples - * - * ```C - * sp_connection_send_command(connection, sp_command_clear()); - * sp_connection_send_command(connection, sp_command_brightness(5)); - * ``` * Tries to turn a [Packet] into a [TypedCommand]. * * The packet is deallocated in the process. * * Returns: pointer to new [TypedCommand] instance or NULL if parsing failed. - * - * # Panics - * - * - when `packet` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - [Packet] points to a valid instance of [Packet] - * - [Packet] is not used concurrently or after this call - * - the result is checked for NULL - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. */ TypedCommand *sp_command_try_from_packet(Packet */*notnull*/ packet); @@ -1563,20 +960,7 @@ TypedCommand *sp_command_try_from_packet(Packet */*notnull*/ packet); * * The passed [CharGrid] gets consumed. * - * Returns: a new [servicepoint::Command::Utf8Data] instance. Will never return NULL. - * - * # Panics - * - * - when `grid` is null - * - * # Safety - * - * The caller has to make sure that: - * - * - `grid` points to a valid instance of [CharGrid] - * - `grid` is not used concurrently or after this call - * - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. + * Returns: a new [servicepoint::Command::Utf8Data] instance. */ TypedCommand */*notnull*/ sp_command_utf8_data(size_t x, size_t y, @@ -1584,17 +968,6 @@ TypedCommand */*notnull*/ sp_command_utf8_data(size_t x, /** * Closes and deallocates a [UdpConnection]. - * - * # Panics - * - * - when `connection` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `connection` points to a valid [UdpConnection] - * - `connection` is not used concurrently or after this call */ void sp_connection_free(UdpConnection */*notnull*/ connection); @@ -1603,16 +976,13 @@ void sp_connection_free(UdpConnection */*notnull*/ connection); * * returns: NULL if connection fails, or connected instance * - * # Panics + * # Examples * - * - when `host` is null or an invalid host - * - * # 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`. + * ```C + * CConnection connection = sp_connection_open("172.23.42.29:2342"); + * if (connection != NULL) + * sp_connection_send_command(connection, sp_command_clear()); + * ``` */ UdpConnection *sp_connection_open(char */*notnull*/ host); @@ -1623,18 +993,12 @@ UdpConnection *sp_connection_open(char */*notnull*/ host); * * returns: true in case of success * - * # Panics + * # Examples * - * - when `connection` is NULL - * - when `command` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `connection` points to a valid instance of [UdpConnection] - * - `command` points to a valid instance of [Packet] - * - `command` is not used concurrently or after this call + * ```C + * sp_connection_send_command(connection, sp_command_clear()); + * sp_connection_send_command(connection, sp_command_brightness(5)); + * ``` */ bool sp_connection_send_command(UdpConnection */*notnull*/ connection, TypedCommand */*notnull*/ command); @@ -1645,40 +1009,12 @@ bool sp_connection_send_command(UdpConnection */*notnull*/ connection, * The passed `packet` gets consumed. * * returns: true in case of success - * - * # Panics - * - * - when `connection` is NULL - * - when `packet` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `connection` points to a valid instance of [UdpConnection] - * - `packet` points to a valid instance of [Packet] - * - `packet` is not used concurrently or after this call */ bool sp_connection_send_packet(UdpConnection */*notnull*/ connection, Packet */*notnull*/ packet); /** * Clones a [Cp437Grid]. - * - * Will never return NULL. - * - * # Panics - * - * - when `cp437_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [Cp437Grid] - * - `cp437_grid` is not written to concurrently - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_cp437_grid_free`. */ Cp437Grid */*notnull*/ sp_cp437_grid_clone(Cp437Grid */*notnull*/ cp437_grid); @@ -1689,36 +1025,11 @@ Cp437Grid */*notnull*/ sp_cp437_grid_clone(Cp437Grid */*notnull*/ cp437_grid); * * - `cp437_grid`: instance to write to * - `value`: the value to set all cells to - * - * # Panics - * - * - when `cp437_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [Cp437Grid] - * - `cp437_grid` is not written to or read from concurrently */ void sp_cp437_grid_fill(Cp437Grid */*notnull*/ cp437_grid, uint8_t value); /** * Deallocates a [Cp437Grid]. - * - * # Panics - * - * - when `cp437_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [Cp437Grid] - * - `cp437_grid` is not used concurrently or after cp437_grid call - * - `cp437_grid` was not passed to another consuming function, e.g. to create a [TypedCommand] - * - * [TypedCommand]: [crate::TypedCommand] */ void sp_cp437_grid_free(Cp437Grid */*notnull*/ cp437_grid); @@ -1732,15 +1043,7 @@ void sp_cp437_grid_free(Cp437Grid */*notnull*/ cp437_grid); * * # Panics * - * - when `cp437_grid` is NULL * - when accessing `x` or `y` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [Cp437Grid] - * - `cp437_grid` is not written to concurrently */ uint8_t sp_cp437_grid_get(Cp437Grid */*notnull*/ cp437_grid, size_t x, @@ -1752,56 +1055,20 @@ uint8_t sp_cp437_grid_get(Cp437Grid */*notnull*/ cp437_grid, * # Arguments * * - `cp437_grid`: instance to read from - * - * # Panics - * - * - when `cp437_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [Cp437Grid] */ size_t sp_cp437_grid_height(Cp437Grid */*notnull*/ cp437_grid); /** * Loads a [Cp437Grid] with the specified dimensions from the provided data. - * - * Will never return NULL. - * - * # Panics - * - * - when `data` is NULL - * - when the provided `data_length` does not match `height` and `width` - * - * # Safety - * - * The caller has to make sure that: - * - * - `data` points to a valid memory location of at least `data_length` - * bytes in size. - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_cp437_grid_free`. */ -Cp437Grid *sp_cp437_grid_load(size_t width, - size_t height, - SPByteSlice data); +Cp437Grid *sp_cp437_grid_load(size_t width, size_t height, ByteSlice data); /** * Creates a new [Cp437Grid] with the specified dimensions. * - * returns: [Cp437Grid] initialized to 0. 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_cp437_grid_free`. + * returns: [Cp437Grid] initialized to 0. */ -Cp437Grid */*notnull*/ sp_cp437_grid_new(size_t width, - size_t height); +Cp437Grid */*notnull*/ sp_cp437_grid_new(size_t width, size_t height); /** * Sets the value of the specified position in the [Cp437Grid]. @@ -1816,17 +1083,7 @@ Cp437Grid */*notnull*/ sp_cp437_grid_new(size_t width, * * # Panics * - * - when `cp437_grid` is NULL * - when accessing `x` or `y` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [SPBitVec] - * - `cp437_grid` is not written to or read from concurrently - * - * [SPBitVec]: [crate::SPBitVec] */ void sp_cp437_grid_set(Cp437Grid */*notnull*/ cp437_grid, size_t x, @@ -1836,21 +1093,9 @@ void sp_cp437_grid_set(Cp437Grid */*notnull*/ cp437_grid, /** * Gets an unsafe reference to the data of the [Cp437Grid] instance. * - * Will never return NULL. - * - * # Panics - * - * - when `cp437_grid` is NULL - * - * ## Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [Cp437Grid] - * - the returned memory range is never accessed after the passed [Cp437Grid] has been freed - * - the returned memory range is never accessed concurrently, either via the [Cp437Grid] or directly + * The returned memory is valid for the lifetime of the grid. */ -SPByteSlice sp_cp437_grid_unsafe_data_ref(Cp437Grid */*notnull*/ cp437_grid); +ByteSlice sp_cp437_grid_unsafe_data_ref(Cp437Grid */*notnull*/ cp437_grid); /** * Gets the width of the [Cp437Grid] instance. @@ -1858,52 +1103,16 @@ SPByteSlice sp_cp437_grid_unsafe_data_ref(Cp437Grid */*notnull*/ cp437_grid); * # Arguments * * - `cp437_grid`: instance to read from - * - * # Panics - * - * - when `cp437_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [Cp437Grid] */ size_t sp_cp437_grid_width(Cp437Grid */*notnull*/ cp437_grid); /** * Clones a [Packet]. - * - * Will never return NULL. - * - * # Panics - * - * - when `packet` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `packet` points to a valid [Packet] - * - `packet` is not written to concurrently - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_packet_free`. */ Packet */*notnull*/ sp_packet_clone(Packet */*notnull*/ packet); /** * Deallocates a [Packet]. - * - * # Panics - * - * - when `packet` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `packet` points to a valid [Packet] - * - `packet` is not used concurrently or after this call */ void sp_packet_free(Packet */*notnull*/ packet); @@ -1912,50 +1121,16 @@ void sp_packet_free(Packet */*notnull*/ packet); * The [TypedCommand] gets consumed. * * Returns NULL in case of an error. - * - * # Panics - * - * - when `command` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - [TypedCommand] points to a valid instance of [TypedCommand] - * - [TypedCommand] is not used concurrently or after this call - * - the returned [Packet] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_packet_free`. */ Packet *sp_packet_from_command(TypedCommand */*notnull*/ command); /** * Creates a raw [Packet] from parts. * - * # Arguments - * - * - `command_code` specifies which command this packet contains - * - `a`, `b`, `c` and `d` are command-specific header values - * - `payload` is the optional data that is part of the command - * - `payload_len` is the size of the payload - * * returns: new instance. Will never return null. - * - * # Panics - * - * - when `payload` is null, but `payload_len` is not zero - * - when `payload_len` is zero, but `payload` is nonnull - * - * # Safety - * - * The caller has to make sure that: - * - * - `payload` points to a valid memory region of at least `payload_len` bytes - * - `payload` is not written to concurrently - * - the returned [Packet] instance is freed in some way, either by using a consuming function or - * by explicitly calling [sp_packet_free]. */ Packet */*notnull*/ sp_packet_from_parts(Header header, - const SPByteSlice *payload); + const ByteSlice *payload); /** * Returns a pointer to the header field of the provided packet. @@ -1969,7 +1144,7 @@ Header */*notnull*/ sp_packet_get_header(Packet */*notnull*/ packet); * * The returned memory can be changed and will be valid until a new payload is set. */ -SPByteSlice sp_packet_get_payload(Packet */*notnull*/ packet); +ByteSlice sp_packet_get_payload(Packet */*notnull*/ packet); /** * Serialize the packet into the provided buffer. @@ -1978,34 +1153,21 @@ SPByteSlice sp_packet_get_payload(Packet */*notnull*/ packet); * * - if the buffer is not big enough to hold header+payload. */ -void sp_packet_serialize_to(Packet */*notnull*/ packet, SPByteSlice buffer); +void sp_packet_serialize_to(Packet */*notnull*/ packet, ByteSlice buffer); /** * Sets the payload of the provided packet to the provided data. * * This makes previous payload pointers invalid. */ -void sp_packet_set_payload(Packet */*notnull*/ packet, SPByteSlice data); +void sp_packet_set_payload(Packet */*notnull*/ packet, ByteSlice data); /** * 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 - * - * # Panics - * - * - when `data` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `data` points to a valid memory region of at least `length` bytes - * - `data` is not written to concurrently - * - the returned [Packet] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_packet_free`. */ -Packet *sp_packet_try_load(SPByteSlice data); +Packet *sp_packet_try_load(ByteSlice data); #ifdef __cplusplus } // extern "C" diff --git a/src/bitmap.rs b/src/bitmap.rs index 5da6e7e..f9b6882 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -1,7 +1,7 @@ use servicepoint::{Bitmap, DataRef, Grid}; use std::ptr::NonNull; -use crate::byte_slice::SPByteSlice; +use crate::byte_slice::ByteSlice; /// Creates a new [Bitmap] with the specified dimensions. /// @@ -18,13 +18,6 @@ use crate::byte_slice::SPByteSlice; /// /// - when the width is not dividable by 8 /// -/// # 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_bitmap_free`. -/// /// # Examples /// /// ```C @@ -47,14 +40,7 @@ pub unsafe extern "C" fn sp_bitmap_new( /// Creates a new [Bitmap] with a size matching the screen. /// -/// returns: [Bitmap] initialized to all pixels off. 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_bitmap_free]. +/// returns: [Bitmap] initialized to all pixels off. #[no_mangle] pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull { let result = Box::new(Bitmap::max_sized()); @@ -69,30 +55,11 @@ pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull { /// - `height`: size in pixels in y-direction /// /// returns: [Bitmap] 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 -/// -/// - when `data` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `data` points to a valid memory location of at least `data_length` bytes in size. -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_bitmap_free`. #[no_mangle] pub unsafe extern "C" fn sp_bitmap_load( width: usize, height: usize, - data: SPByteSlice, + data: ByteSlice, ) -> *mut Bitmap { let data = unsafe { data.as_slice() }; if let Ok(bitmap) = Bitmap::load(width, height, data) { @@ -103,21 +70,6 @@ pub unsafe extern "C" fn sp_bitmap_load( } /// Clones a [Bitmap]. -/// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `bitmap` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [Bitmap] -/// - `bitmap` is not written to concurrently -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_bitmap_free`. #[no_mangle] pub unsafe extern "C" fn sp_bitmap_clone( bitmap: NonNull, @@ -127,18 +79,6 @@ pub unsafe extern "C" fn sp_bitmap_clone( } /// Deallocates a [Bitmap]. -/// -/// # Panics -/// -/// - when `bitmap` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [Bitmap] -/// -/// [TypedCommand]: [crate::TypedCommand] #[no_mangle] pub unsafe extern "C" fn sp_bitmap_free(bitmap: NonNull) { _ = unsafe { Box::from_raw(bitmap.as_ptr()) }; @@ -153,15 +93,7 @@ pub unsafe extern "C" fn sp_bitmap_free(bitmap: NonNull) { /// /// # Panics /// -/// - when `bitmap` is NULL /// - when accessing `x` or `y` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [Bitmap] -/// - `bitmap` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitmap_get( bitmap: NonNull, @@ -179,19 +111,9 @@ pub unsafe extern "C" fn sp_bitmap_get( /// - `x` and `y`: position of the cell /// - `value`: the value to write to the cell /// -/// returns: old value of the cell -/// /// # Panics /// -/// - when `bitmap` is NULL /// - when accessing `x` or `y` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [Bitmap] -/// - `bitmap` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitmap_set( bitmap: NonNull, @@ -208,17 +130,6 @@ pub unsafe extern "C" fn sp_bitmap_set( /// /// - `bitmap`: instance to write to /// - `value`: the value to set all pixels to -/// -/// # Panics -/// -/// - when `bitmap` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [Bitmap] -/// - `bitmap` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitmap_fill(bitmap: NonNull, value: bool) { unsafe { (*bitmap.as_ptr()).fill(value) }; @@ -249,16 +160,6 @@ pub unsafe extern "C" fn sp_bitmap_width(bitmap: NonNull) -> usize { /// # Arguments /// /// - `bitmap`: instance to read from -/// -/// # Panics -/// -/// - when `bitmap` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [Bitmap] #[no_mangle] pub unsafe extern "C" fn sp_bitmap_height(bitmap: NonNull) -> usize { unsafe { bitmap.as_ref().height() } @@ -266,20 +167,10 @@ pub unsafe extern "C" fn sp_bitmap_height(bitmap: NonNull) -> usize { /// Gets an unsafe reference to the data of the [Bitmap] instance. /// -/// # Panics -/// -/// - when `bitmap` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [Bitmap] -/// - the returned memory range is never accessed after the passed [Bitmap] has been freed -/// - the returned memory range is never accessed concurrently, either via the [Bitmap] or directly +/// The returned memory is valid for the lifetime of the bitmap. #[no_mangle] pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref( mut bitmap: NonNull, -) -> SPByteSlice { - unsafe { SPByteSlice::from_slice(bitmap.as_mut().data_ref_mut()) } +) -> ByteSlice { + unsafe { ByteSlice::from_slice(bitmap.as_mut().data_ref_mut()) } } diff --git a/src/bitvec.rs b/src/bitvec.rs index a2ff022..f87423d 100644 --- a/src/bitvec.rs +++ b/src/bitvec.rs @@ -1,9 +1,6 @@ -//! C functions for interacting with [SPBitVec]s -//! -//! prefix `sp_bitvec_` - -use crate::SPByteSlice; +use crate::ByteSlice; use std::ptr::NonNull; +use servicepoint::BitVecU8Msb0; /// A vector of bits /// @@ -13,7 +10,7 @@ use std::ptr::NonNull; /// sp_bitvec_set(vec, 5, true); /// sp_bitvec_free(vec); /// ``` -pub struct SPBitVec(pub(crate) servicepoint::BitVecU8Msb0); +pub struct SPBitVec(pub(crate) BitVecU8Msb0); impl Clone for SPBitVec { fn clone(&self) -> Self { @@ -27,67 +24,31 @@ impl Clone for SPBitVec { /// /// - `size`: size in bits. /// -/// returns: [SPBitVec] with all bits set to false. Will never return NULL. +/// returns: [SPBitVec] with all bits set to false. /// /// # Panics /// /// - when `size` is not divisible by 8. -/// -/// # 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_bitvec_free`. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_new(size: usize) -> NonNull { let result = - Box::new(SPBitVec(servicepoint::BitVecU8Msb0::repeat(false, size))); + Box::new(SPBitVec(BitVecU8Msb0::repeat(false, size))); NonNull::from(Box::leak(result)) } /// Interpret the data as a series of bits and load then into a new [SPBitVec] instance. /// -/// returns: [SPBitVec] instance containing data. Will never return NULL. -/// -/// # Panics -/// -/// - when `data` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `data` points to a valid memory location of at least `data_length` -/// bytes in size. -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_bitvec_free`. +/// returns: [SPBitVec] instance containing data. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_load( - data: SPByteSlice, + data: ByteSlice, ) -> NonNull { let data = unsafe { data.as_slice() }; - let result = - Box::new(SPBitVec(servicepoint::BitVecU8Msb0::from_slice(data))); + let result = Box::new(SPBitVec(BitVecU8Msb0::from_slice(data))); NonNull::from(Box::leak(result)) } /// Clones a [SPBitVec]. -/// -/// returns: new [SPBitVec] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `bit_vec` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -/// - `bit_vec` is not written to concurrently -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_bitvec_free`. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_clone( bit_vec: NonNull, @@ -97,20 +58,6 @@ pub unsafe extern "C" fn sp_bitvec_clone( } /// Deallocates a [SPBitVec]. -/// -/// # Panics -/// -/// - when `but_vec` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -/// - `bit_vec` is not used concurrently or after this call -/// - `bit_vec` was not passed to another consuming function, e.g. to create a [TypedCommand] -/// -/// [TypedCommand]: [crate::TypedCommand] #[no_mangle] pub unsafe extern "C" fn sp_bitvec_free(bit_vec: NonNull) { _ = unsafe { Box::from_raw(bit_vec.as_ptr()) }; @@ -127,15 +74,7 @@ pub unsafe extern "C" fn sp_bitvec_free(bit_vec: NonNull) { /// /// # Panics /// -/// - when `bit_vec` is NULL /// - when accessing `index` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -/// - `bit_vec` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitvec_get( bit_vec: NonNull, @@ -154,15 +93,7 @@ pub unsafe extern "C" fn sp_bitvec_get( /// /// # Panics /// -/// - when `bit_vec` is NULL /// - when accessing `index` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -/// - `bit_vec` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitvec_set( bit_vec: NonNull, @@ -178,17 +109,6 @@ pub unsafe extern "C" fn sp_bitvec_set( /// /// - `bit_vec`: instance to write to /// - `value`: the value to set all bits to -/// -/// # Panics -/// -/// - when `bit_vec` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -/// - `bit_vec` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_bitvec_fill( bit_vec: NonNull, @@ -202,16 +122,6 @@ pub unsafe extern "C" fn sp_bitvec_fill( /// # Arguments /// /// - `bit_vec`: instance to write to -/// -/// # Panics -/// -/// - when `bit_vec` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] #[no_mangle] pub unsafe extern "C" fn sp_bitvec_len(bit_vec: NonNull) -> usize { unsafe { bit_vec.as_ref().0.len() } @@ -222,16 +132,6 @@ pub unsafe extern "C" fn sp_bitvec_len(bit_vec: NonNull) -> usize { /// # Arguments /// /// - `bit_vec`: instance to write to -/// -/// # Panics -/// -/// - when `bit_vec` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] #[no_mangle] pub unsafe extern "C" fn sp_bitvec_is_empty( bit_vec: NonNull, @@ -241,24 +141,14 @@ pub unsafe extern "C" fn sp_bitvec_is_empty( /// Gets an unsafe reference to the data of the [SPBitVec] instance. /// +/// The returned memory is valid for the lifetime of the bitvec. +/// /// # Arguments /// /// - `bit_vec`: instance to write to -/// -/// # Panics -/// -/// - when `bit_vec` is NULL -/// -/// ## Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -/// - the returned memory range is never accessed after the passed [SPBitVec] has been freed -/// - the returned memory range is never accessed concurrently, either via the [SPBitVec] or directly #[no_mangle] pub unsafe extern "C" fn sp_bitvec_unsafe_data_ref( bit_vec: NonNull, -) -> SPByteSlice { - unsafe { SPByteSlice::from_slice((*bit_vec.as_ptr()).0.as_raw_mut_slice()) } +) -> ByteSlice { + unsafe { ByteSlice::from_slice((*bit_vec.as_ptr()).0.as_raw_mut_slice()) } } diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index ff40ef9..5cd7a16 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -1,39 +1,25 @@ -//! C functions for interacting with [BrightnessGrid]s -//! -//! prefix `sp_brightness_grid_` -//! -//! -//! A grid containing brightness values. -//! -//! # Examples -//! ```C -//! UdpConnection connection = sp_connection_open("127.0.0.1:2342"); -//! if (connection == NULL) -//! return 1; -//! -//! BrightnessGrid grid = sp_brightness_grid_new(2, 2); -//! sp_brightness_grid_set(grid, 0, 0, 0); -//! sp_brightness_grid_set(grid, 1, 1, 10); -//! -//! TypedCommand command = sp_command_char_brightness(grid); -//! sp_connection_free(connection); -//! ``` - -use crate::SPByteSlice; -use servicepoint::{Brightness, BrightnessGrid, DataRef, Grid}; +use crate::ByteSlice; +use servicepoint::{Brightness, BrightnessGrid, ByteGrid, DataRef, Grid}; use std::mem::transmute; use std::ptr::NonNull; /// Creates a new [BrightnessGrid] with the specified dimensions. /// -/// returns: [BrightnessGrid] initialized to 0. Will never return NULL. +/// returns: [BrightnessGrid] initialized to 0. /// -/// # Safety +/// # Examples +/// ```C +/// UdpConnection connection = sp_connection_open("127.0.0.1:2342"); +/// if (connection == NULL) +/// return 1; /// -/// The caller has to make sure that: +/// BrightnessGrid grid = sp_brightness_grid_new(2, 2); +/// sp_brightness_grid_set(grid, 0, 0, 0); +/// sp_brightness_grid_set(grid, 1, 1, 10); /// -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_brightness_grid_free`. +/// TypedCommand command = sp_command_char_brightness(grid); +/// sp_connection_free(connection); +/// ``` #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_new( width: usize, @@ -45,29 +31,15 @@ pub unsafe extern "C" fn sp_brightness_grid_new( /// Loads a [BrightnessGrid] with the specified dimensions from the provided data. /// -/// returns: new [BrightnessGrid] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `data` is NULL -/// - when the provided `data_length` does not match `height` and `width` -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `data` points to a valid memory location of at least `data_length` -/// bytes in size. -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_brightness_grid_free`. +/// returns: new [BrightnessGrid] instance, or NULL in case of an error. #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_load( width: usize, height: usize, - data: SPByteSlice, + data: ByteSlice, ) -> *mut BrightnessGrid { let data = unsafe { data.as_slice() }; - let grid = match servicepoint::ByteGrid::load(width, height, data) { + let grid = match ByteGrid::load(width, height, data) { None => return std::ptr::null_mut(), Some(grid) => grid, }; @@ -79,25 +51,6 @@ pub unsafe extern "C" fn sp_brightness_grid_load( } /// Clones a [BrightnessGrid]. -/// -/// # Arguments -/// -/// - `brightness_grid`: instance to read from -/// -/// returns: new [BrightnessGrid] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [BrightnessGrid] -/// - `brightness_grid` is not written to concurrently -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_brightness_grid_free`. #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_clone( brightness_grid: NonNull, @@ -107,24 +60,6 @@ pub unsafe extern "C" fn sp_brightness_grid_clone( } /// Deallocates a [BrightnessGrid]. -/// -/// # Arguments -/// -/// - `brightness_grid`: instance to read from -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [BrightnessGrid] -/// - `brightness_grid` is not used concurrently or after this call -/// - `brightness_grid` was not passed to another consuming function, e.g. to create a [TypedCommand] -/// -/// [TypedCommand]: [crate::TypedCommand] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_free( brightness_grid: NonNull, @@ -142,16 +77,7 @@ pub unsafe extern "C" fn sp_brightness_grid_free( /// returns: value at position /// /// # Panics -/// -/// - when `brightness_grid` is NULL /// - When accessing `x` or `y` out of bounds. -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [BrightnessGrid] -/// - `brightness_grid` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_get( brightness_grid: NonNull, @@ -173,16 +99,7 @@ pub unsafe extern "C" fn sp_brightness_grid_get( /// /// # Panics /// -/// - when `brightness_grid` is NULL /// - When accessing `x` or `y` out of bounds. -/// - When providing an invalid brightness value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [BrightnessGrid] -/// - `brightness_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_set( brightness_grid: NonNull, @@ -199,18 +116,6 @@ pub unsafe extern "C" fn sp_brightness_grid_set( /// /// - `brightness_grid`: instance to write to /// - `value`: the value to set all cells to -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// - When providing an invalid brightness value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [BrightnessGrid] -/// - `brightness_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_fill( brightness_grid: NonNull, @@ -226,16 +131,6 @@ pub unsafe extern "C" fn sp_brightness_grid_fill( /// - `brightness_grid`: instance to read from /// /// returns: width -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [BrightnessGrid] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_width( brightness_grid: NonNull, @@ -250,16 +145,6 @@ pub unsafe extern "C" fn sp_brightness_grid_width( /// - `brightness_grid`: instance to read from /// /// returns: height -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [BrightnessGrid] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_height( brightness_grid: NonNull, @@ -269,30 +154,20 @@ pub unsafe extern "C" fn sp_brightness_grid_height( /// Gets an unsafe reference to the data of the [BrightnessGrid] instance. /// +/// The returned memory is valid for the lifetime of the brightness grid. +/// /// # Arguments /// /// - `brightness_grid`: instance to read from /// /// returns: slice of bytes underlying the `brightness_grid`. -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [BrightnessGrid] -/// - the returned memory range is never accessed after the passed [BrightnessGrid] has been freed -/// - the returned memory range is never accessed concurrently, either via the [BrightnessGrid] or directly #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( brightness_grid: NonNull, -) -> SPByteSlice { +) -> ByteSlice { //noinspection RsAssertEqual const _: () = assert!(size_of::() == 1); let data = unsafe { (*brightness_grid.as_ptr()).data_ref_mut() }; - unsafe { SPByteSlice::from_slice(transmute(data)) } + unsafe { ByteSlice::from_slice(transmute(data)) } } diff --git a/src/byte_slice.rs b/src/byte_slice.rs index 066a405..001a616 100644 --- a/src/byte_slice.rs +++ b/src/byte_slice.rs @@ -2,9 +2,7 @@ use std::ptr::NonNull; -/// Represents a span of memory (`&mut [u8]` ) as a struct usable by C code. -/// -/// You should not create an instance of this type in your C code. +/// Represents a span of memory (`&mut [u8]` ) as a struct. /// /// # Safety /// @@ -13,17 +11,15 @@ use std::ptr::NonNull; /// - accesses to the memory pointed to with `start` is never accessed outside `length` /// - the lifetime of the `CByteSlice` does not outlive the memory it points to, as described in /// the function returning this type. -/// - an instance of this created from C is never passed to a consuming function, as the rust code -/// will try to free the memory of a potentially separate allocator. #[repr(C)] -pub struct SPByteSlice { - /// The start address of the memory +pub struct ByteSlice { + /// The start address of the memory. pub start: NonNull, - /// The amount of memory in bytes + /// The amount of memory in bytes. pub length: usize, } -impl SPByteSlice { +impl ByteSlice { pub(crate) unsafe fn as_slice(&self) -> &[u8] { unsafe { std::slice::from_raw_parts(self.start.as_ptr(), self.length) } } diff --git a/src/char_grid.rs b/src/char_grid.rs index 30e9953..a287d70 100644 --- a/src/char_grid.rs +++ b/src/char_grid.rs @@ -1,37 +1,19 @@ -//! C functions for interacting with [CharGrid]s -//! -//! prefix `sp_char_grid_` -//! -//! A C-wrapper for grid containing UTF-8 characters. -//! -//! As the rust [char] type is not FFI-safe, characters are passed in their UTF-32 form as 32bit unsigned integers. -//! -//! The encoding is enforced in most cases by the rust standard library -//! and will panic when provided with illegal characters. -//! -//! # Examples -//! -//! ```C -//! CharGrid grid = sp_char_grid_new(4, 3); -//! sp_char_grid_fill(grid, '?'); -//! sp_char_grid_set(grid, 0, 0, '!'); -//! sp_char_grid_free(grid); -//! ``` - -use crate::SPByteSlice; +use crate::ByteSlice; use servicepoint::{CharGrid, Grid}; use std::ptr::NonNull; /// Creates a new [CharGrid] with the specified dimensions. /// -/// returns: [CharGrid] initialized to 0. Will never return NULL. +/// returns: [CharGrid] initialized to 0. /// -/// # Safety +/// # Examples /// -/// 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_char_grid_free`. +/// ```C +/// CharGrid grid = sp_char_grid_new(4, 3); +/// sp_char_grid_fill(grid, '?'); +/// sp_char_grid_set(grid, 0, 0, '!'); +/// sp_char_grid_free(grid); +/// ``` #[no_mangle] pub unsafe extern "C" fn sp_char_grid_new( width: usize, @@ -43,80 +25,37 @@ pub unsafe extern "C" fn sp_char_grid_new( /// Loads a [CharGrid] with the specified dimensions from the provided data. /// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `data` is NULL -/// - when the provided `data_length` does not match `height` and `width` -/// - when `data` is not valid UTF-8 -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `data` points to a valid memory location of at least `data_length` -/// bytes in size. -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_char_grid_free`. +/// returns: new CharGrid or NULL in case of an error #[no_mangle] pub unsafe extern "C" fn sp_char_grid_load( width: usize, height: usize, - data: SPByteSlice, -) -> NonNull { + data: ByteSlice, +) -> *mut CharGrid { let data = unsafe { data.as_slice() }; - // TODO remove unwrap - let result = - Box::new(CharGrid::load_utf8(width, height, data.to_vec()).unwrap()); - NonNull::from(Box::leak(result)) + if let Ok(grid) = CharGrid::load_utf8(width, height, data.to_vec()) { + Box::leak(Box::new(grid)) + } else { + std::ptr::null_mut() + } } /// Clones a [CharGrid]. -/// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `char_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [CharGrid] -/// - `char_grid` is not written to concurrently -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_char_grid_free`. #[no_mangle] pub unsafe extern "C" fn sp_char_grid_clone( char_grid: NonNull, ) -> NonNull { - let result = Box::new(unsafe { char_grid.as_ref().clone() }); - NonNull::from(Box::leak(result)) + let result = unsafe { char_grid.as_ref().clone() }; + NonNull::from(Box::leak(Box::new(result))) } /// Deallocates a [CharGrid]. -/// -/// # Panics -/// -/// - when `char_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [CharGrid] -/// - `char_grid` is not used concurrently or after char_grid call -/// - `char_grid` was not passed to another consuming function, e.g. to create a [TypedCommand] -/// -/// [TypedCommand]: [crate::TypedCommand] #[no_mangle] pub unsafe extern "C" fn sp_char_grid_free(char_grid: NonNull) { _ = unsafe { Box::from_raw(char_grid.as_ptr()) }; } -/// Gets the current value at the specified position. +/// Returns the current value at the specified position. /// /// # Arguments /// @@ -125,15 +64,7 @@ pub unsafe extern "C" fn sp_char_grid_free(char_grid: NonNull) { /// /// # Panics /// -/// - when `char_grid` is NULL /// - when accessing `x` or `y` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [CharGrid] -/// - `char_grid` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_char_grid_get( char_grid: NonNull, @@ -155,17 +86,7 @@ pub unsafe extern "C" fn sp_char_grid_get( /// /// # Panics /// -/// - when `char_grid` is NULL /// - when accessing `x` or `y` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [SPBitVec] -/// - `char_grid` is not written to or read from concurrently -/// -/// [SPBitVec]: [crate::SPBitVec] #[no_mangle] pub unsafe extern "C" fn sp_char_grid_set( char_grid: NonNull, @@ -182,17 +103,6 @@ pub unsafe extern "C" fn sp_char_grid_set( /// /// - `char_grid`: instance to write to /// - `value`: the value to set all cells to -/// -/// # Panics -/// -/// - when `char_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [CharGrid] -/// - `char_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_char_grid_fill( char_grid: NonNull, @@ -206,16 +116,6 @@ pub unsafe extern "C" fn sp_char_grid_fill( /// # Arguments /// /// - `char_grid`: instance to read from -/// -/// # Panics -/// -/// - when `char_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [CharGrid] #[no_mangle] pub unsafe extern "C" fn sp_char_grid_width( char_grid: NonNull, @@ -228,16 +128,6 @@ pub unsafe extern "C" fn sp_char_grid_width( /// # Arguments /// /// - `char_grid`: instance to read from -/// -/// # Panics -/// -/// - when `char_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [CharGrid] #[no_mangle] pub unsafe extern "C" fn sp_char_grid_height( char_grid: NonNull, diff --git a/src/command.rs b/src/command.rs index 2ed7415..b867eba 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,43 +1,12 @@ -//! C functions for interacting with [TypedCommand]s -//! -//! prefix `sp_command_` - use crate::SPBitVec; use servicepoint::{BinaryOperation, Bitmap, Brightness, BrightnessGrid, CharGrid, CompressionCode, Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand}; use std::ptr::NonNull; -/// A low-level display command. -/// -/// This struct and associated functions implement the UDP protocol for the display. -/// -/// To send a [TypedCommand], use a [UdpConnection]. -/// -/// # Examples -/// -/// ```C -/// sp_connection_send_command(connection, sp_command_clear()); -/// sp_connection_send_command(connection, sp_command_brightness(5)); -/// ``` - /// Tries to turn a [Packet] into a [TypedCommand]. /// /// The packet is deallocated in the process. /// /// Returns: pointer to new [TypedCommand] instance or NULL if parsing failed. -/// -/// # Panics -/// -/// - when `packet` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - [Packet] points to a valid instance of [Packet] -/// - [Packet] is not used concurrently or after this call -/// - the result is checked for NULL -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_try_from_packet( packet: NonNull, @@ -51,20 +20,7 @@ pub unsafe extern "C" fn sp_command_try_from_packet( /// Clones a [TypedCommand] instance. /// -/// returns: new [TypedCommand] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `command` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `command` points to a valid instance of [TypedCommand] -/// - `command` is not written to concurrently -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. +/// returns: new [TypedCommand] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_clone( command: NonNull, @@ -77,20 +33,13 @@ pub unsafe extern "C" fn sp_command_clone( /// /// Does not affect brightness. /// -/// Returns: a new [servicepoint::Command::Clear] instance. Will never return NULL. +/// Returns: a new [servicepoint::Command::Clear] instance. /// /// # Examples /// /// ```C /// sp_connection_send_command(connection, sp_command_clear()); /// ``` -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_clear() -> NonNull { let result = Box::new(servicepoint::ClearCommand.into()); @@ -101,14 +50,7 @@ pub unsafe extern "C" fn sp_command_clear() -> NonNull { /// /// Please do not send this in your normal program flow. /// -/// Returns: a new [servicepoint::Command::HardReset] instance. Will never return NULL. -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. +/// Returns: a new [servicepoint::Command::HardReset] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull { let result = Box::new(servicepoint::HardResetCommand.into()); @@ -117,14 +59,7 @@ pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull { /// A yet-to-be-tested command. /// -/// Returns: a new [servicepoint::Command::FadeOut] instance. Will never return NULL. -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. +/// Returns: a new [servicepoint::Command::FadeOut] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_fade_out() -> NonNull { let result = Box::new(servicepoint::FadeOutCommand.into()); @@ -133,18 +68,7 @@ pub unsafe extern "C" fn sp_command_fade_out() -> NonNull { /// Set the brightness of all tiles to the same value. /// -/// Returns: a new [servicepoint::Command::Brightness] instance. Will never return NULL. -/// -/// # Panics -/// -/// - When the provided brightness value is out of range (0-11). -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. +/// Returns: a new [servicepoint::Command::Brightness] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_brightness( brightness: Brightness, @@ -157,20 +81,7 @@ pub unsafe extern "C" fn sp_command_brightness( /// /// The passed [BrightnessGrid] gets consumed. /// -/// Returns: a new [servicepoint::Command::CharBrightness] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `grid` points to a valid instance of [BrightnessGrid] -/// - `grid` is not used concurrently or after this call -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. +/// Returns: a new [servicepoint::Command::CharBrightness] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_char_brightness( x: usize, @@ -197,22 +108,7 @@ pub unsafe extern "C" fn sp_command_char_brightness( /// /// The passed [SPBitVec] gets consumed. /// -/// Returns: a new [servicepoint::Command::BitmapLinear] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `bit_vec` is null -/// - when `compression_code` is not a valid value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid instance of [SPBitVec] -/// - `bit_vec` is not used concurrently or after this call -/// - `compression` matches one of the allowed enum values -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. +/// Returns: a new [servicepoint::Command::BitmapLinear] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear( offset: usize, @@ -238,22 +134,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear( /// /// The passed [SPBitVec] gets consumed. /// -/// Returns: a new [servicepoint::Command::BitmapLinearAnd] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `bit_vec` is null -/// - when `compression_code` is not a valid value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid instance of [SPBitVec] -/// - `bit_vec` is not used concurrently or after this call -/// - `compression` matches one of the allowed enum values -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. +/// Returns: a new [servicepoint::Command::BitmapLinearAnd] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_and( offset: usize, @@ -279,22 +160,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and( /// /// The passed [SPBitVec] gets consumed. /// -/// Returns: a new [servicepoint::Command::BitmapLinearOr] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `bit_vec` is null -/// - when `compression_code` is not a valid value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid instance of [SPBitVec] -/// - `bit_vec` is not used concurrently or after this call -/// - `compression` matches one of the allowed enum values -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. +/// Returns: a new [servicepoint::Command::BitmapLinearOr] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_or( offset: usize, @@ -320,22 +186,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or( /// /// The passed [SPBitVec] gets consumed. /// -/// Returns: a new [servicepoint::Command::BitmapLinearXor] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `bit_vec` is null -/// - when `compression_code` is not a valid value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid instance of [SPBitVec] -/// - `bit_vec` is not used concurrently or after this call -/// - `compression` matches one of the allowed enum values -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. +/// Returns: a new [servicepoint::Command::BitmapLinearXor] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_xor( offset: usize, @@ -352,7 +203,6 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor( } } -#[inline] unsafe fn sp_command_bitmap_linear_internal( offset: usize, bit_vec: NonNull, @@ -378,20 +228,7 @@ unsafe fn sp_command_bitmap_linear_internal( /// /// The passed [Cp437Grid] gets consumed. /// -/// Returns: a new [servicepoint::Command::Cp437Data] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `grid` is null -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `grid` points to a valid instance of [Cp437Grid] -/// - `grid` is not used concurrently or after this call -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. +/// Returns: a new [servicepoint::Command::Cp437Data] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_cp437_data( x: usize, @@ -413,20 +250,7 @@ pub unsafe extern "C" fn sp_command_cp437_data( /// /// The passed [CharGrid] gets consumed. /// -/// Returns: a new [servicepoint::Command::Utf8Data] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `grid` is null -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `grid` points to a valid instance of [CharGrid] -/// - `grid` is not used concurrently or after this call -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. +/// Returns: a new [servicepoint::Command::Utf8Data] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_utf8_data( x: usize, @@ -448,22 +272,7 @@ pub unsafe extern "C" fn sp_command_utf8_data( /// /// The passed [Bitmap] gets consumed. /// -/// Returns: a new [servicepoint::Command::BitmapLinearWin] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `bitmap` is null -/// - when `compression_code` is not a valid value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid instance of [Bitmap] -/// - `bitmap` is not used concurrently or after this call -/// - `compression` matches one of the allowed enum values -/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. +/// Returns: a new [servicepoint::Command::BitmapLinearWin] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_win( x: usize, @@ -493,18 +302,6 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win( /// TypedCommand c = sp_command_clear(); /// sp_command_free(c); /// ``` -/// -/// # Panics -/// -/// - when `command` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `command` points to a valid [TypedCommand] -/// - `command` is not used concurrently or after this call -/// - `command` was not passed to another consuming function, e.g. to create a [Packet] #[no_mangle] pub unsafe extern "C" fn sp_command_free(command: NonNull) { _ = unsafe { Box::from_raw(command.as_ptr()) }; diff --git a/src/connection.rs b/src/connection.rs index 79e2e33..5feb528 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,17 +1,3 @@ -//! C functions for interacting with [UdpConnection]s -//! -//! prefix `sp_connection_` -//! -//! 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()); -//! ``` - use servicepoint::{Connection, Packet, TypedCommand, UdpConnection}; use std::ffi::{c_char, CStr}; use std::ptr::NonNull; @@ -20,16 +6,13 @@ use std::ptr::NonNull; /// /// returns: NULL if connection fails, or connected instance /// -/// # Panics +/// # Examples /// -/// - when `host` is null or an invalid host -/// -/// # 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`. +/// ```C +/// CConnection connection = sp_connection_open("172.23.42.29:2342"); +/// if (connection != NULL) +/// sp_connection_send_command(connection, sp_command_clear()); +/// ``` #[no_mangle] pub unsafe extern "C" fn sp_connection_open( host: NonNull, @@ -59,7 +42,7 @@ pub unsafe extern "C" fn sp_connection_open( // /// 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. // /// // /// # Safety // /// @@ -78,19 +61,6 @@ pub unsafe extern "C" fn sp_connection_open( /// The passed `packet` gets consumed. /// /// returns: true in case of success -/// -/// # Panics -/// -/// - when `connection` is NULL -/// - when `packet` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `connection` points to a valid instance of [UdpConnection] -/// - `packet` points to a valid instance of [Packet] -/// - `packet` is not used concurrently or after this call #[no_mangle] pub unsafe extern "C" fn sp_connection_send_packet( connection: NonNull, @@ -106,18 +76,12 @@ pub unsafe extern "C" fn sp_connection_send_packet( /// /// returns: true in case of success /// -/// # Panics +/// # Examples /// -/// - when `connection` is NULL -/// - when `command` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `connection` points to a valid instance of [UdpConnection] -/// - `command` points to a valid instance of [Packet] -/// - `command` is not used concurrently or after this call +/// ```C +/// sp_connection_send_command(connection, sp_command_clear()); +/// sp_connection_send_command(connection, sp_command_brightness(5)); +/// ``` #[no_mangle] pub unsafe extern "C" fn sp_connection_send_command( connection: NonNull, @@ -128,17 +92,6 @@ pub unsafe extern "C" fn sp_connection_send_command( } /// Closes and deallocates a [UdpConnection]. -/// -/// # Panics -/// -/// - when `connection` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `connection` points to a valid [UdpConnection] -/// - `connection` is not used concurrently or after this call #[no_mangle] pub unsafe extern "C" fn sp_connection_free( connection: NonNull, diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index 96db2db..3904354 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -1,35 +1,10 @@ -//! C functions for interacting with [Cp437Grid]s -//! -//! prefix `sp_cp437_grid_` -//! -//! -//! A C-wrapper for grid containing codepage 437 characters. -//! -//! The encoding is currently not enforced. -//! -//! # Examples -//! -//! ```C -//! Cp437Grid grid = sp_cp437_grid_new(4, 3); -//! sp_cp437_grid_fill(grid, '?'); -//! sp_cp437_grid_set(grid, 0, 0, '!'); -//! sp_cp437_grid_free(grid); -//! ``` - -use crate::SPByteSlice; +use crate::ByteSlice; use servicepoint::{Cp437Grid, DataRef, Grid}; use std::ptr::NonNull; /// Creates a new [Cp437Grid] with the specified dimensions. /// -/// returns: [Cp437Grid] initialized to 0. 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_cp437_grid_free`. +/// returns: [Cp437Grid] initialized to 0. #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_new( width: usize, @@ -40,27 +15,11 @@ pub unsafe extern "C" fn sp_cp437_grid_new( } /// Loads a [Cp437Grid] with the specified dimensions from the provided data. -/// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `data` is NULL -/// - when the provided `data_length` does not match `height` and `width` -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `data` points to a valid memory location of at least `data_length` -/// bytes in size. -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_cp437_grid_free`. #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_load( width: usize, height: usize, - data: SPByteSlice, + data: ByteSlice, ) -> *mut Cp437Grid { let data = unsafe { data.as_slice() }; let grid = Cp437Grid::load(width, height, data); @@ -72,21 +31,6 @@ pub unsafe extern "C" fn sp_cp437_grid_load( } /// Clones a [Cp437Grid]. -/// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [Cp437Grid] -/// - `cp437_grid` is not written to concurrently -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_cp437_grid_free`. #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_clone( cp437_grid: NonNull, @@ -96,20 +40,6 @@ pub unsafe extern "C" fn sp_cp437_grid_clone( } /// Deallocates a [Cp437Grid]. -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [Cp437Grid] -/// - `cp437_grid` is not used concurrently or after cp437_grid call -/// - `cp437_grid` was not passed to another consuming function, e.g. to create a [TypedCommand] -/// -/// [TypedCommand]: [crate::TypedCommand] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: NonNull) { _ = unsafe { Box::from_raw(cp437_grid.as_ptr()) }; @@ -124,15 +54,7 @@ pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: NonNull) { /// /// # Panics /// -/// - when `cp437_grid` is NULL /// - when accessing `x` or `y` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [Cp437Grid] -/// - `cp437_grid` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_get( cp437_grid: NonNull, @@ -154,17 +76,7 @@ pub unsafe extern "C" fn sp_cp437_grid_get( /// /// # Panics /// -/// - when `cp437_grid` is NULL /// - when accessing `x` or `y` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [SPBitVec] -/// - `cp437_grid` is not written to or read from concurrently -/// -/// [SPBitVec]: [crate::SPBitVec] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_set( cp437_grid: NonNull, @@ -181,17 +93,6 @@ pub unsafe extern "C" fn sp_cp437_grid_set( /// /// - `cp437_grid`: instance to write to /// - `value`: the value to set all cells to -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [Cp437Grid] -/// - `cp437_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_fill( cp437_grid: NonNull, @@ -205,16 +106,6 @@ pub unsafe extern "C" fn sp_cp437_grid_fill( /// # Arguments /// /// - `cp437_grid`: instance to read from -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [Cp437Grid] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_width( cp437_grid: NonNull, @@ -227,16 +118,6 @@ pub unsafe extern "C" fn sp_cp437_grid_width( /// # Arguments /// /// - `cp437_grid`: instance to read from -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [Cp437Grid] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_height( cp437_grid: NonNull, @@ -246,22 +127,10 @@ pub unsafe extern "C" fn sp_cp437_grid_height( /// Gets an unsafe reference to the data of the [Cp437Grid] instance. /// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// -/// ## Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [Cp437Grid] -/// - the returned memory range is never accessed after the passed [Cp437Grid] has been freed -/// - the returned memory range is never accessed concurrently, either via the [Cp437Grid] or directly +/// The returned memory is valid for the lifetime of the grid. #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref( cp437_grid: NonNull, -) -> SPByteSlice { - unsafe { SPByteSlice::from_slice((*cp437_grid.as_ptr()).data_ref_mut()) } +) -> ByteSlice { + unsafe { ByteSlice::from_slice((*cp437_grid.as_ptr()).data_ref_mut()) } } diff --git a/src/packet.rs b/src/packet.rs index ae37058..996c83d 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,11 +1,4 @@ -//! C functions for interacting with [Packet]s -//! -//! prefix `sp_packet_` -//! -//! -//! The raw packet - -use crate::SPByteSlice; +use crate::ByteSlice; use servicepoint::{Header, Packet, TypedCommand}; use std::ptr::NonNull; @@ -13,19 +6,6 @@ use std::ptr::NonNull; /// The [TypedCommand] gets consumed. /// /// Returns NULL in case of an error. -/// -/// # Panics -/// -/// - when `command` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - [TypedCommand] points to a valid instance of [TypedCommand] -/// - [TypedCommand] is not used concurrently or after this call -/// - the returned [Packet] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_packet_free`. #[no_mangle] pub unsafe extern "C" fn sp_packet_from_command( command: NonNull, @@ -41,21 +21,8 @@ pub unsafe extern "C" fn sp_packet_from_command( /// 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 -/// -/// # Panics -/// -/// - when `data` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `data` points to a valid memory region of at least `length` bytes -/// - `data` is not written to concurrently -/// - the returned [Packet] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_packet_free`. #[no_mangle] -pub unsafe extern "C" fn sp_packet_try_load(data: SPByteSlice) -> *mut Packet { +pub unsafe extern "C" fn sp_packet_try_load(data: ByteSlice) -> *mut Packet { let data = unsafe { data.as_slice() }; match servicepoint::Packet::try_from(data) { Err(_) => std::ptr::null_mut(), @@ -65,32 +32,11 @@ pub unsafe extern "C" fn sp_packet_try_load(data: SPByteSlice) -> *mut Packet { /// Creates a raw [Packet] from parts. /// -/// # Arguments -/// -/// - `command_code` specifies which command this packet contains -/// - `a`, `b`, `c` and `d` are command-specific header values -/// - `payload` is the optional data that is part of the command -/// - `payload_len` is the size of the payload -/// /// returns: new instance. Will never return null. -/// -/// # Panics -/// -/// - when `payload` is null, but `payload_len` is not zero -/// - when `payload_len` is zero, but `payload` is nonnull -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `payload` points to a valid memory region of at least `payload_len` bytes -/// - `payload` is not written to concurrently -/// - the returned [Packet] instance is freed in some way, either by using a consuming function or -/// by explicitly calling [sp_packet_free]. #[no_mangle] pub unsafe extern "C" fn sp_packet_from_parts( header: Header, - payload: *const SPByteSlice, + payload: *const ByteSlice, ) -> NonNull { let payload = if payload.is_null() { vec![] @@ -119,8 +65,8 @@ pub unsafe extern "C" fn sp_packet_get_header( #[no_mangle] pub unsafe extern "C" fn sp_packet_get_payload( packet: NonNull, -) -> SPByteSlice { - unsafe { SPByteSlice::from_slice(&mut *(*packet.as_ptr()).payload) } +) -> ByteSlice { + unsafe { ByteSlice::from_slice(&mut *(*packet.as_ptr()).payload) } } /// Sets the payload of the provided packet to the provided data. @@ -129,7 +75,7 @@ pub unsafe extern "C" fn sp_packet_get_payload( #[no_mangle] pub unsafe extern "C" fn sp_packet_set_payload( packet: NonNull, - data: SPByteSlice, + data: ByteSlice, ) { unsafe { (*packet.as_ptr()).payload = data.as_slice().to_vec() } } @@ -142,7 +88,7 @@ pub unsafe extern "C" fn sp_packet_set_payload( #[no_mangle] pub unsafe extern "C" fn sp_packet_serialize_to( packet: NonNull, - buffer: SPByteSlice, + buffer: ByteSlice, ) { unsafe { packet.as_ref().serialize_to(buffer.as_slice_mut()); @@ -150,21 +96,6 @@ pub unsafe extern "C" fn sp_packet_serialize_to( } /// Clones a [Packet]. -/// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `packet` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `packet` points to a valid [Packet] -/// - `packet` is not written to concurrently -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_packet_free`. #[no_mangle] pub unsafe extern "C" fn sp_packet_clone( packet: NonNull, @@ -174,17 +105,6 @@ pub unsafe extern "C" fn sp_packet_clone( } /// Deallocates a [Packet]. -/// -/// # Panics -/// -/// - when `packet` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `packet` points to a valid [Packet] -/// - `packet` is not used concurrently or after this call #[no_mangle] pub unsafe extern "C" fn sp_packet_free(packet: NonNull) { _ = unsafe { Box::from_raw(packet.as_ptr()) } -- 2.47.0 From 613f21310e7126ed4db2e6739dcc86ae3c491e8b Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 16:33:39 +0200 Subject: [PATCH 14/25] fix rebase --- example/Makefile | 59 +++++++++++++++++++++++++++----- examples/.gitignore | 4 --- examples/lang_c/Makefile | 73 ---------------------------------------- 3 files changed, 51 insertions(+), 85 deletions(-) delete mode 100644 examples/.gitignore delete mode 100644 examples/lang_c/Makefile diff --git a/example/Makefile b/example/Makefile index abdd69f..e7d858f 100644 --- a/example/Makefile +++ b/example/Makefile @@ -1,7 +1,47 @@ CC := gcc +CARGO := rustup run nightly cargo THIS_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) REPO_ROOT := $(THIS_DIR)/.. +RUST_TARGET_DIR := $(REPO_ROOT)/target/x86_64-unknown-linux-musl/size-optimized + +RUSTFLAGS := -Zlocation-detail=none \ + -Zfmt-debug=none \ + -C linker=musl-gcc \ + -C link-arg=-s \ + -C link-arg=--gc-sections \ + -C link-arg=-z,norelro \ + -C link-arg=--hash-style=gnu \ + --crate-type=staticlib \ + -C panic=abort + +CARGOFLAGS := --manifest-path=$(REPO_ROOT)/Cargo.toml \ + --profile=size-optimized \ + --no-default-features \ + --target=x86_64-unknown-linux-musl \ + -Zbuild-std="core,std,alloc,proc_macro,panic_abort" \ + -Zbuild-std-features="panic_immediate_abort" \ + +CCFLAGS := -static -Os \ + -ffunction-sections -fdata-sections \ + -fwrapv -fomit-frame-pointer -fno-stack-protector\ + -fwhole-program \ + -nodefaultlibs -lservicepoint_binding_c -lc \ + -Wl,--gc-sections \ + -fno-unroll-loops \ + -fno-unwind-tables -fno-asynchronous-unwind-tables \ + -fmerge-all-constants \ + -Wl,-z,norelro \ + -Wl,--hash-style=gnu \ + -fvisibility=hidden \ + -Bsymbolic \ + -Wl,--exclude-libs,ALL \ + -fno-ident + #-fuse-ld=gold \ + -fno-exceptions + #-Wl,--icf=all \ + +export SERVICEPOINT_HEADER_OUT := $(REPO_ROOT)/include build: out/example @@ -15,16 +55,19 @@ run: out/example PHONY: build clean dependencies run -out/example: dependencies main.c +out/example_unstripped: dependencies main.c mkdir -p out || true ${CC} main.c \ - -I $(REPO_ROOT)/include \ - -L $(REPO_ROOT)/target/release \ - -Wl,-Bstatic -lservicepoint_binding_c \ - -Wl,-Bdynamic -llzma \ - -o out/example + -I $(SERVICEPOINT_HEADER_OUT) \ + -L $(RUST_TARGET_DIR)\ + $(CCFLAGS) \ + -o out/example_unstripped +out/example: out/example_unstripped + strip -s -R .comment -R .gnu.version --strip-unneeded out/example_unstripped -o out/example +#strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag dependencies: FORCE - cargo build --manifest-path=$(REPO_ROOT)/Cargo.toml --release - + mkdir -p include || true + # generate servicepoint header and binary to link against + ${CARGO} rustc $(CARGOFLAGS) -- $(RUSTFLAGS) FORCE: ; diff --git a/examples/.gitignore b/examples/.gitignore deleted file mode 100644 index 9415aeb..0000000 --- a/examples/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# examples only use library in this repo -Cargo.lock -out -target diff --git a/examples/lang_c/Makefile b/examples/lang_c/Makefile deleted file mode 100644 index aa31733..0000000 --- a/examples/lang_c/Makefile +++ /dev/null @@ -1,73 +0,0 @@ -CC := gcc -CARGO := rustup run nightly cargo - -THIS_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) -REPO_ROOT := $(THIS_DIR)/../../ -RUST_TARGET_DIR := $(REPO_ROOT)/target/x86_64-unknown-linux-musl/size-optimized - -RUSTFLAGS := -Zlocation-detail=none \ - -Zfmt-debug=none \ - -C linker=musl-gcc \ - -C link-arg=-s \ - -C link-arg=--gc-sections \ - -C link-arg=-z,norelro \ - -C link-arg=--hash-style=gnu \ - --crate-type=staticlib \ - -C panic=abort - -CARGOFLAGS := --manifest-path=$(REPO_ROOT)/Cargo.toml \ - --profile=size-optimized \ - --no-default-features \ - --target=x86_64-unknown-linux-musl \ - -Zbuild-std="core,std,alloc,proc_macro,panic_abort" \ - -Zbuild-std-features="panic_immediate_abort" \ - -CCFLAGS := -static -Os \ - -ffunction-sections -fdata-sections \ - -fwrapv -fomit-frame-pointer -fno-stack-protector\ - -fwhole-program \ - -nodefaultlibs -lservicepoint_binding_c -lc \ - -Wl,--gc-sections \ - -fno-unroll-loops \ - -fno-unwind-tables -fno-asynchronous-unwind-tables \ - -fmerge-all-constants \ - -Wl,-z,norelro \ - -Wl,--hash-style=gnu \ - -fvisibility=hidden \ - -Bsymbolic \ - -Wl,--exclude-libs,ALL \ - -fno-ident - #-fuse-ld=gold \ - -fno-exceptions - #-Wl,--icf=all \ - -export SERVICEPOINT_HEADER_OUT := $(THIS_DIR)/include - -build: out/lang_c - -clean: - rm -r out || true - rm include/servicepoint.h || true - cargo clean - -run: out/lang_c - out/lang_c - -PHONY: build clean dependencies run - -out/lang_c_unstripped: dependencies src/main.c - mkdir -p out || true - ${CC} src/main.c \ - -I $(SERVICEPOINT_HEADER_OUT) \ - -L $(RUST_TARGET_DIR)\ - $(CCFLAGS) \ - -o out/lang_c_unstripped -out/lang_c: out/lang_c_unstripped - strip -s -R .comment -R .gnu.version --strip-unneeded out/lang_c_unstripped -o out/lang_c -#strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag - -dependencies: FORCE - mkdir -p include || true - # generate servicepoint header and binary to link against - ${CARGO} rustc $(CARGOFLAGS) -- $(RUSTFLAGS) -FORCE: ; -- 2.47.0 From 2d3828fb2bbd33ce8f90c4a4394ceb54e36535ef Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 16:47:40 +0200 Subject: [PATCH 15/25] add fn to pass ip:port as values --- example/main.c | 2 +- include/servicepoint.h | 21 ++++++++++++++++++++- src/connection.rs | 37 +++++++++++++++++++++++++------------ 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/example/main.c b/example/main.c index 4e63dec..e3cfc8f 100644 --- a/example/main.c +++ b/example/main.c @@ -2,7 +2,7 @@ #include "servicepoint.h" int main(void) { - UdpConnection *connection = sp_connection_open("localhost:2342"); + UdpConnection *connection = sp_connection_open_ipv4(127,0,0,1,2342); if (connection == NULL) return 1; diff --git a/include/servicepoint.h b/include/servicepoint.h index dbce14d..7c0c819 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -979,13 +979,32 @@ void sp_connection_free(UdpConnection */*notnull*/ connection); * # Examples * * ```C - * CConnection connection = sp_connection_open("172.23.42.29:2342"); + * UdpConnection connection = sp_connection_open("172.23.42.29:2342"); * if (connection != NULL) * sp_connection_send_command(connection, sp_command_clear()); * ``` */ UdpConnection *sp_connection_open(char */*notnull*/ host); +/** + * Creates a new instance of [UdpConnection]. + * + * returns: NULL if connection fails, or connected instance + * + * # Examples + * + * ```C + * UdpConnection connection = sp_connection_open_ipv4(172, 23, 42, 29, 2342); + * if (connection != NULL) + * sp_connection_send_command(connection, sp_command_clear()); + * ``` + */ +UdpConnection *sp_connection_open_ipv4(uint8_t ip1, + uint8_t ip2, + uint8_t ip3, + uint8_t ip4, + uint16_t port); + /** * Sends a [TypedCommand] to the display using the [UdpConnection]. * diff --git a/src/connection.rs b/src/connection.rs index 5feb528..d6ffb83 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,5 +1,6 @@ use servicepoint::{Connection, Packet, TypedCommand, UdpConnection}; use std::ffi::{c_char, CStr}; +use std::net::{Ipv4Addr, SocketAddrV4}; use std::ptr::NonNull; /// Creates a new instance of [UdpConnection]. @@ -9,7 +10,7 @@ use std::ptr::NonNull; /// # Examples /// /// ```C -/// CConnection connection = sp_connection_open("172.23.42.29:2342"); +/// UdpConnection connection = sp_connection_open("172.23.42.29:2342"); /// if (connection != NULL) /// sp_connection_send_command(connection, sp_command_clear()); /// ``` @@ -28,17 +29,29 @@ pub unsafe extern "C" fn sp_connection_open( Box::into_raw(Box::new(connection)) } -//#[no_mangle] -//pub unsafe extern "C" fn sp_connection_open_ipv4( -// host: SocketAddrV4, -//) -> *mut UdpConnection { -// let connection = match servicepoint::UdpConnection::open(host) { -// Err(_) => return std::ptr::null_mut(), -// Ok(value) => value, -// }; -// -// Box::into_raw(Box::new(UdpConnection(connection))) -//} +/// Creates a new instance of [UdpConnection]. +/// +/// returns: NULL if connection fails, or connected instance +/// +/// # Examples +/// +/// ```C +/// UdpConnection connection = sp_connection_open_ipv4(172, 23, 42, 29, 2342); +/// if (connection != NULL) +/// sp_connection_send_command(connection, sp_command_clear()); +/// ``` +#[no_mangle] +pub unsafe extern "C" fn sp_connection_open_ipv4( + ip1: u8, ip2: u8, ip3: u8, ip4: u8, + port: u16, +) -> *mut UdpConnection { + let addr = SocketAddrV4::new(Ipv4Addr::from( [ip1, ip2, ip3, ip4]), port); + let connection = match UdpConnection::open(addr) { + Err(_) => return std::ptr::null_mut(), + Ok(value) => value, + }; + Box::into_raw(Box::new(connection)) +} // /// Creates a new instance of [SPUdpConnection] for testing that does not actually send anything. // /// -- 2.47.0 From d6331ea9a7eb8c5b95e68e36b127872760c72fcf Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 17:38:19 +0200 Subject: [PATCH 16/25] rename/merge functions to match rust side more --- Cargo.lock | 2 +- example/Makefile | 12 +- example/main.c | 10 +- include/servicepoint.h | 276 +++++++++++++++++++---------------------- src/bitmap.rs | 2 +- src/command.rs | 117 ++--------------- src/connection.rs | 26 +--- 7 files changed, 165 insertions(+), 280 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c0b11c4..f87ecea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -408,7 +408,7 @@ dependencies = [ [[package]] name = "servicepoint" version = "0.13.2" -source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#971bee5065139f220022e8108cfaa9c263b8a8a0" +source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#531d4e6b4a368dc126cab9dc12b64d2ca8a81694" dependencies = [ "bitvec", "bzip2", diff --git a/example/Makefile b/example/Makefile index e7d858f..d3f346f 100644 --- a/example/Makefile +++ b/example/Makefile @@ -63,11 +63,19 @@ out/example_unstripped: dependencies main.c $(CCFLAGS) \ -o out/example_unstripped out/example: out/example_unstripped - strip -s -R .comment -R .gnu.version --strip-unneeded out/example_unstripped -o out/example -#strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag + strip -s --strip-unneeded \ + -R .comment -R .gnu.version -R .comment -R .note -R .note.gnu.build-id -R .note.ABI-tag \ + out/example_unstripped \ + -o out/example dependencies: FORCE mkdir -p include || true # generate servicepoint header and binary to link against ${CARGO} rustc $(CARGOFLAGS) -- $(RUSTFLAGS) + +analyze-size: out/example_unstripped + nm --print-size --size-sort --reverse-sort --radix=d --demangle out/example_unstripped \ + | awk '{size=$$2+0; print size "\t" $$4}' \ + | less + FORCE: ; diff --git a/example/main.c b/example/main.c index e3cfc8f..9c0ec9e 100644 --- a/example/main.c +++ b/example/main.c @@ -2,7 +2,7 @@ #include "servicepoint.h" int main(void) { - UdpConnection *connection = sp_connection_open_ipv4(127,0,0,1,2342); + UdpConnection *connection = sp_udp_open_ipv4(127, 0, 0, 1, 2342); if (connection == NULL) return 1; @@ -12,17 +12,17 @@ int main(void) { sp_bitmap_fill(pixels, true); - TypedCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, COMPRESSION_CODE_UNCOMPRESSED); + TypedCommand *command = sp_command_bitmap(0, 0, pixels, COMPRESSION_CODE_UNCOMPRESSED); if (command == NULL) return 1; Packet *packet = sp_packet_from_command(command); Header *header = sp_packet_get_header(packet); - printf("[%d, %d, %d, %d, %d]\n", header->command_code, header->a, header->b, header->c, header->d); + //printf("[%d, %d, %d, %d, %d]\n", header->command_code, header->a, header->b, header->c, header->d); - sp_connection_send_packet(connection, packet); + sp_udp_send_packet(connection, packet); - sp_connection_free(connection); + sp_udp_free(connection); return 0; } diff --git a/include/servicepoint.h b/include/servicepoint.h index 7c0c819..8f7ca75 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -66,6 +66,35 @@ */ #define TILE_WIDTH 56 +/** + * Binary operations for use with the [`BitVecCommand`] command. + */ +enum BinaryOperation +#ifdef __cplusplus + : uint8_t +#endif // __cplusplus + { + /** + * r := a + */ + BINARY_OPERATION_OVERWRITE, + /** + * r := a && b + */ + BINARY_OPERATION_AND, + /** + * r := a || b + */ + BINARY_OPERATION_OR, + /** + * r := (a || b) && (a != b) + */ + BINARY_OPERATION_XOR, +}; +#ifndef __cplusplus +typedef uint8_t BinaryOperation; +#endif // __cplusplus + /** * Specifies the kind of compression to use. Availability depends on features. * @@ -428,7 +457,7 @@ Bitmap *sp_bitmap_new(size_t width, size_t height); * * returns: [Bitmap] initialized to all pixels off. */ -Bitmap */*notnull*/ sp_bitmap_new_screen_sized(void); +Bitmap */*notnull*/ sp_bitmap_new_max_sized(void); /** * Sets the value of the specified position in the [Bitmap]. @@ -791,81 +820,36 @@ void sp_char_grid_set(CharGrid */*notnull*/ char_grid, */ size_t sp_char_grid_width(CharGrid */*notnull*/ char_grid); +/** + * Sets a window of pixels to the specified values. + * + * The passed [Bitmap] gets consumed. + * + * Returns: a new [servicepoint::BitmapCommand] instance. + */ +TypedCommand *sp_command_bitmap(size_t x, + size_t y, + Bitmap */*notnull*/ bitmap, + CompressionCode compression); + /** * Set pixel data starting at the pixel offset on screen. * * The screen will continuously overwrite more pixel data without regarding the offset, meaning * once the starting row is full, overwriting will continue on column 0. * - * The contained [SPBitVec] is always uncompressed. + * The [`BinaryOperation`] will be applied on the display comparing old and sent bit. * - * The passed [SPBitVec] gets consumed. + * `new_bit = old_bit op sent_bit` * - * Returns: a new [servicepoint::Command::BitmapLinear] instance. + * For example, [`BinaryOperation::Or`] can be used to turn on some pixels without affecting other pixels. + * + * The contained [`BitVecU8Msb0`] is always uncompressed. */ -TypedCommand *sp_command_bitmap_linear(size_t offset, - SPBitVec */*notnull*/ bit_vec, - CompressionCode compression); - -/** - * Set pixel data according to an and-mask starting at the offset. - * - * The screen will continuously overwrite more pixel data without regarding the offset, meaning - * once the starting row is full, overwriting will continue on column 0. - * - * The contained [SPBitVec] is always uncompressed. - * - * The passed [SPBitVec] gets consumed. - * - * Returns: a new [servicepoint::Command::BitmapLinearAnd] instance. - */ -TypedCommand *sp_command_bitmap_linear_and(size_t offset, - SPBitVec */*notnull*/ bit_vec, - CompressionCode compression); - -/** - * Set pixel data according to an or-mask starting at the offset. - * - * The screen will continuously overwrite more pixel data without regarding the offset, meaning - * once the starting row is full, overwriting will continue on column 0. - * - * The contained [SPBitVec] is always uncompressed. - * - * The passed [SPBitVec] gets consumed. - * - * Returns: a new [servicepoint::Command::BitmapLinearOr] instance. - */ -TypedCommand *sp_command_bitmap_linear_or(size_t offset, - SPBitVec */*notnull*/ bit_vec, - CompressionCode compression); - -/** - * Sets a window of pixels to the specified values. - * - * The passed [Bitmap] gets consumed. - * - * Returns: a new [servicepoint::Command::BitmapLinearWin] instance. - */ -TypedCommand *sp_command_bitmap_linear_win(size_t x, - size_t y, - Bitmap */*notnull*/ bitmap, - CompressionCode compression); - -/** - * Set pixel data according to a xor-mask starting at the offset. - * - * The screen will continuously overwrite more pixel data without regarding the offset, meaning - * once the starting row is full, overwriting will continue on column 0. - * - * The contained [SPBitVec] is always uncompressed. - * - * The passed [SPBitVec] gets consumed. - * - * Returns: a new [servicepoint::Command::BitmapLinearXor] instance. - */ -TypedCommand *sp_command_bitmap_linear_xor(size_t offset, - SPBitVec */*notnull*/ bit_vec, - CompressionCode compression); +TypedCommand *sp_command_bitvec(size_t offset, + SPBitVec */*notnull*/ bit_vec, + CompressionCode compression, + BinaryOperation operation); /** * Set the brightness of all tiles to the same value. @@ -885,6 +869,17 @@ TypedCommand */*notnull*/ sp_command_char_brightness(size_t x, size_t y, BrightnessGrid */*notnull*/ grid); +/** + * Show UTF-8 encoded text on the screen. + * + * The passed [CharGrid] gets consumed. + * + * Returns: a new [servicepoint::CharGridCommand] instance. + */ +TypedCommand */*notnull*/ sp_command_char_grid(size_t x, + size_t y, + CharGrid */*notnull*/ grid); + /** * Set all pixels to the off state. * @@ -912,9 +907,9 @@ TypedCommand */*notnull*/ sp_command_clone(TypedCommand */*notnull*/ command); * * The passed [Cp437Grid] gets consumed. * - * Returns: a new [servicepoint::Command::Cp437Data] instance. + * Returns: a new [servicepoint::Cp437GridCommand] instance. */ -TypedCommand */*notnull*/ sp_command_cp437_data(size_t x, +TypedCommand */*notnull*/ sp_command_cp437_grid(size_t x, size_t y, Cp437Grid */*notnull*/ grid); @@ -955,83 +950,6 @@ TypedCommand */*notnull*/ sp_command_hard_reset(void); */ TypedCommand *sp_command_try_from_packet(Packet */*notnull*/ packet); -/** - * Show UTF-8 encoded text on the screen. - * - * The passed [CharGrid] gets consumed. - * - * Returns: a new [servicepoint::Command::Utf8Data] instance. - */ -TypedCommand */*notnull*/ sp_command_utf8_data(size_t x, - size_t y, - CharGrid */*notnull*/ grid); - -/** - * Closes and deallocates a [UdpConnection]. - */ -void sp_connection_free(UdpConnection */*notnull*/ connection); - -/** - * Creates a new instance of [UdpConnection]. - * - * returns: NULL if connection fails, or connected instance - * - * # Examples - * - * ```C - * UdpConnection connection = sp_connection_open("172.23.42.29:2342"); - * if (connection != NULL) - * sp_connection_send_command(connection, sp_command_clear()); - * ``` - */ -UdpConnection *sp_connection_open(char */*notnull*/ host); - -/** - * Creates a new instance of [UdpConnection]. - * - * returns: NULL if connection fails, or connected instance - * - * # Examples - * - * ```C - * UdpConnection connection = sp_connection_open_ipv4(172, 23, 42, 29, 2342); - * if (connection != NULL) - * sp_connection_send_command(connection, sp_command_clear()); - * ``` - */ -UdpConnection *sp_connection_open_ipv4(uint8_t ip1, - uint8_t ip2, - uint8_t ip3, - uint8_t ip4, - uint16_t port); - -/** - * Sends a [TypedCommand] to the display using the [UdpConnection]. - * - * The passed `command` gets consumed. - * - * returns: true in case of success - * - * # Examples - * - * ```C - * sp_connection_send_command(connection, sp_command_clear()); - * sp_connection_send_command(connection, sp_command_brightness(5)); - * ``` - */ -bool sp_connection_send_command(UdpConnection */*notnull*/ connection, - TypedCommand */*notnull*/ command); - -/** - * Sends a [Packet] to the display using the [UdpConnection]. - * - * The passed `packet` gets consumed. - * - * returns: true in case of success - */ -bool sp_connection_send_packet(UdpConnection */*notnull*/ connection, - Packet */*notnull*/ packet); - /** * Clones a [Cp437Grid]. */ @@ -1188,6 +1106,72 @@ void sp_packet_set_payload(Packet */*notnull*/ packet, ByteSlice data); */ Packet *sp_packet_try_load(ByteSlice data); +/** + * Closes and deallocates a [UdpConnection]. + */ +void sp_udp_free(UdpConnection */*notnull*/ connection); + +/** + * Creates a new instance of [UdpConnection]. + * + * returns: NULL if connection fails, or connected instance + * + * # Examples + * + * ```C + * UdpConnection connection = sp_connection_open("172.23.42.29:2342"); + * if (connection != NULL) + * sp_connection_send_command(connection, sp_command_clear()); + * ``` + */ +UdpConnection *sp_udp_open(char */*notnull*/ host); + +/** + * Creates a new instance of [UdpConnection]. + * + * returns: NULL if connection fails, or connected instance + * + * # Examples + * + * ```C + * UdpConnection connection = sp_connection_open_ipv4(172, 23, 42, 29, 2342); + * if (connection != NULL) + * sp_connection_send_command(connection, sp_command_clear()); + * ``` + */ +UdpConnection *sp_udp_open_ipv4(uint8_t ip1, + uint8_t ip2, + uint8_t ip3, + uint8_t ip4, + uint16_t port); + +/** + * Sends a [TypedCommand] to the display using the [UdpConnection]. + * + * The passed `command` gets consumed. + * + * returns: true in case of success + * + * # Examples + * + * ```C + * sp_connection_send_command(connection, sp_command_clear()); + * sp_connection_send_command(connection, sp_command_brightness(5)); + * ``` + */ +bool sp_udp_send_command(UdpConnection */*notnull*/ connection, + TypedCommand */*notnull*/ command); + +/** + * Sends a [Packet] to the display using the [UdpConnection]. + * + * The passed `packet` gets consumed. + * + * returns: true in case of success + */ +bool sp_udp_send_packet(UdpConnection */*notnull*/ connection, + Packet */*notnull*/ packet); + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/src/bitmap.rs b/src/bitmap.rs index f9b6882..d1d8522 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -42,7 +42,7 @@ pub unsafe extern "C" fn sp_bitmap_new( /// /// returns: [Bitmap] initialized to all pixels off. #[no_mangle] -pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull { +pub unsafe extern "C" fn sp_bitmap_new_max_sized() -> NonNull { let result = Box::new(Bitmap::max_sized()); NonNull::from(Box::leak(result)) } diff --git a/src/command.rs b/src/command.rs index b867eba..80a2b22 100644 --- a/src/command.rs +++ b/src/command.rs @@ -104,106 +104,15 @@ pub unsafe extern "C" fn sp_command_char_brightness( /// The screen will continuously overwrite more pixel data without regarding the offset, meaning /// once the starting row is full, overwriting will continue on column 0. /// -/// The contained [SPBitVec] is always uncompressed. +/// The [`BinaryOperation`] will be applied on the display comparing old and sent bit. /// -/// The passed [SPBitVec] gets consumed. +/// `new_bit = old_bit op sent_bit` /// -/// Returns: a new [servicepoint::Command::BitmapLinear] instance. +/// For example, [`BinaryOperation::Or`] can be used to turn on some pixels without affecting other pixels. +/// +/// The contained [`BitVecU8Msb0`] is always uncompressed. #[no_mangle] -pub unsafe extern "C" fn sp_command_bitmap_linear( - offset: usize, - bit_vec: NonNull, - compression: CompressionCode, -) -> *mut TypedCommand { - unsafe { - sp_command_bitmap_linear_internal( - offset, - bit_vec, - compression, - BinaryOperation::Overwrite, - ) - } -} - -/// Set pixel data according to an and-mask starting at the offset. -/// -/// The screen will continuously overwrite more pixel data without regarding the offset, meaning -/// once the starting row is full, overwriting will continue on column 0. -/// -/// The contained [SPBitVec] is always uncompressed. -/// -/// The passed [SPBitVec] gets consumed. -/// -/// Returns: a new [servicepoint::Command::BitmapLinearAnd] instance. -#[no_mangle] -pub unsafe extern "C" fn sp_command_bitmap_linear_and( - offset: usize, - bit_vec: NonNull, - compression: CompressionCode, -) -> *mut TypedCommand { - unsafe { - sp_command_bitmap_linear_internal( - offset, - bit_vec, - compression, - BinaryOperation::Xor, - ) - } -} - -/// Set pixel data according to an or-mask starting at the offset. -/// -/// The screen will continuously overwrite more pixel data without regarding the offset, meaning -/// once the starting row is full, overwriting will continue on column 0. -/// -/// The contained [SPBitVec] is always uncompressed. -/// -/// The passed [SPBitVec] gets consumed. -/// -/// Returns: a new [servicepoint::Command::BitmapLinearOr] instance. -#[no_mangle] -pub unsafe extern "C" fn sp_command_bitmap_linear_or( - offset: usize, - bit_vec: NonNull, - compression: CompressionCode, -) -> *mut TypedCommand { - unsafe { - sp_command_bitmap_linear_internal( - offset, - bit_vec, - compression, - BinaryOperation::Or, - ) - } -} - -/// Set pixel data according to a xor-mask starting at the offset. -/// -/// The screen will continuously overwrite more pixel data without regarding the offset, meaning -/// once the starting row is full, overwriting will continue on column 0. -/// -/// The contained [SPBitVec] is always uncompressed. -/// -/// The passed [SPBitVec] gets consumed. -/// -/// Returns: a new [servicepoint::Command::BitmapLinearXor] instance. -#[no_mangle] -pub unsafe extern "C" fn sp_command_bitmap_linear_xor( - offset: usize, - bit_vec: NonNull, - compression: CompressionCode, -) -> *mut TypedCommand { - unsafe { - sp_command_bitmap_linear_internal( - offset, - bit_vec, - compression, - BinaryOperation::Xor, - ) - } -} - -unsafe fn sp_command_bitmap_linear_internal( +pub unsafe extern "C" fn sp_command_bitvec( offset: usize, bit_vec: NonNull, compression: CompressionCode, @@ -220,7 +129,7 @@ unsafe fn sp_command_bitmap_linear_internal( bitvec: bit_vec.0, compression, } - .into(); + .into(); Box::leak(Box::new(command)) } @@ -228,9 +137,9 @@ unsafe fn sp_command_bitmap_linear_internal( /// /// The passed [Cp437Grid] gets consumed. /// -/// Returns: a new [servicepoint::Command::Cp437Data] instance. +/// Returns: a new [servicepoint::Cp437GridCommand] instance. #[no_mangle] -pub unsafe extern "C" fn sp_command_cp437_data( +pub unsafe extern "C" fn sp_command_cp437_grid( x: usize, y: usize, grid: NonNull, @@ -250,9 +159,9 @@ pub unsafe extern "C" fn sp_command_cp437_data( /// /// The passed [CharGrid] gets consumed. /// -/// Returns: a new [servicepoint::Command::Utf8Data] instance. +/// Returns: a new [servicepoint::CharGridCommand] instance. #[no_mangle] -pub unsafe extern "C" fn sp_command_utf8_data( +pub unsafe extern "C" fn sp_command_char_grid( x: usize, y: usize, grid: NonNull, @@ -272,9 +181,9 @@ pub unsafe extern "C" fn sp_command_utf8_data( /// /// The passed [Bitmap] gets consumed. /// -/// Returns: a new [servicepoint::Command::BitmapLinearWin] instance. +/// Returns: a new [servicepoint::BitmapCommand] instance. #[no_mangle] -pub unsafe extern "C" fn sp_command_bitmap_linear_win( +pub unsafe extern "C" fn sp_command_bitmap( x: usize, y: usize, bitmap: NonNull, diff --git a/src/connection.rs b/src/connection.rs index d6ffb83..b49225d 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -15,7 +15,7 @@ use std::ptr::NonNull; /// sp_connection_send_command(connection, sp_command_clear()); /// ``` #[no_mangle] -pub unsafe extern "C" fn sp_connection_open( +pub unsafe extern "C" fn sp_udp_open( host: NonNull, ) -> *mut UdpConnection { let host = unsafe { CStr::from_ptr(host.as_ptr()) } @@ -41,7 +41,7 @@ pub unsafe extern "C" fn sp_connection_open( /// sp_connection_send_command(connection, sp_command_clear()); /// ``` #[no_mangle] -pub unsafe extern "C" fn sp_connection_open_ipv4( +pub unsafe extern "C" fn sp_udp_open_ipv4( ip1: u8, ip2: u8, ip3: u8, ip4: u8, port: u16, ) -> *mut UdpConnection { @@ -53,29 +53,13 @@ pub unsafe extern "C" fn sp_connection_open_ipv4( Box::into_raw(Box::new(connection)) } -// /// Creates a new instance of [SPUdpConnection] for testing that does not actually send anything. -// /// -// /// returns: a new instance. -// /// -// /// # 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`. -// #[no_mangle] -// pub unsafe extern "C" fn sp_connection_fake() -> NonNull { -// let result = Box::new(SPUdpConnection(servicepoint::Connection::Fake)); -// NonNull::from(Box::leak(result)) -// } - /// Sends a [Packet] to the display using the [UdpConnection]. /// /// The passed `packet` gets consumed. /// /// returns: true in case of success #[no_mangle] -pub unsafe extern "C" fn sp_connection_send_packet( +pub unsafe extern "C" fn sp_udp_send_packet( connection: NonNull, packet: NonNull, ) -> bool { @@ -96,7 +80,7 @@ pub unsafe extern "C" fn sp_connection_send_packet( /// sp_connection_send_command(connection, sp_command_brightness(5)); /// ``` #[no_mangle] -pub unsafe extern "C" fn sp_connection_send_command( +pub unsafe extern "C" fn sp_udp_send_command( connection: NonNull, command: NonNull, ) -> bool { @@ -106,7 +90,7 @@ pub unsafe extern "C" fn sp_connection_send_command( /// Closes and deallocates a [UdpConnection]. #[no_mangle] -pub unsafe extern "C" fn sp_connection_free( +pub unsafe extern "C" fn sp_udp_free( connection: NonNull, ) { _ = unsafe { Box::from_raw(connection.as_ptr()) }; -- 2.47.0 From f483b5a2d5e3deea2b43a11b86cf65a20968bcb5 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 18:05:01 +0200 Subject: [PATCH 17/25] unify heap allocation handling --- include/servicepoint.h | 16 ++++----- src/bitmap.rs | 16 ++++----- src/bitvec.rs | 20 ++++------- src/brightness_grid.rs | 12 +++---- src/char_grid.rs | 12 +++---- src/command.rs | 78 +++++++++++++++++++----------------------- src/connection.rs | 18 +++++----- src/cp437_grid.rs | 12 +++---- src/lib.rs | 13 +++++++ src/packet.rs | 14 ++++---- 10 files changed, 101 insertions(+), 110 deletions(-) diff --git a/include/servicepoint.h b/include/servicepoint.h index 8f7ca75..9edeaf9 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -851,13 +851,6 @@ TypedCommand *sp_command_bitvec(size_t offset, CompressionCode compression, BinaryOperation operation); -/** - * Set the brightness of all tiles to the same value. - * - * Returns: a new [servicepoint::Command::Brightness] instance. - */ -TypedCommand */*notnull*/ sp_command_brightness(Brightness brightness); - /** * Set the brightness of individual tiles in a rectangular area of the display. * @@ -865,7 +858,7 @@ TypedCommand */*notnull*/ sp_command_brightness(Brightness brightness); * * Returns: a new [servicepoint::Command::CharBrightness] instance. */ -TypedCommand */*notnull*/ sp_command_char_brightness(size_t x, +TypedCommand */*notnull*/ sp_command_brightness_grid(size_t x, size_t y, BrightnessGrid */*notnull*/ grid); @@ -932,6 +925,13 @@ TypedCommand */*notnull*/ sp_command_fade_out(void); */ void sp_command_free(TypedCommand */*notnull*/ command); +/** + * Set the brightness of all tiles to the same value. + * + * Returns: a new [servicepoint::Command::Brightness] instance. + */ +TypedCommand */*notnull*/ sp_command_global_brightness(Brightness brightness); + /** * Kills the udp daemon on the display, which usually results in a restart. * diff --git a/src/bitmap.rs b/src/bitmap.rs index d1d8522..c166881 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -1,8 +1,8 @@ +use crate::byte_slice::ByteSlice; +use crate::{heap_drop, heap_move, heap_move_nonnull}; use servicepoint::{Bitmap, DataRef, Grid}; use std::ptr::NonNull; -use crate::byte_slice::ByteSlice; - /// Creates a new [Bitmap] with the specified dimensions. /// /// # Arguments @@ -32,7 +32,7 @@ pub unsafe extern "C" fn sp_bitmap_new( height: usize, ) -> *mut Bitmap { if let Some(bitmap) = Bitmap::new(width, height) { - Box::leak(Box::new(bitmap)) + heap_move(bitmap) } else { std::ptr::null_mut() } @@ -43,8 +43,7 @@ pub unsafe extern "C" fn sp_bitmap_new( /// returns: [Bitmap] initialized to all pixels off. #[no_mangle] pub unsafe extern "C" fn sp_bitmap_new_max_sized() -> NonNull { - let result = Box::new(Bitmap::max_sized()); - NonNull::from(Box::leak(result)) + heap_move_nonnull(Bitmap::max_sized()) } /// Loads a [Bitmap] with the specified dimensions from the provided data. @@ -63,7 +62,7 @@ pub unsafe extern "C" fn sp_bitmap_load( ) -> *mut Bitmap { let data = unsafe { data.as_slice() }; if let Ok(bitmap) = Bitmap::load(width, height, data) { - Box::leak(Box::new(bitmap)) + heap_move(bitmap) } else { std::ptr::null_mut() } @@ -74,14 +73,13 @@ pub unsafe extern "C" fn sp_bitmap_load( pub unsafe extern "C" fn sp_bitmap_clone( bitmap: NonNull, ) -> NonNull { - let result = Box::new(unsafe { bitmap.as_ref().clone() }); - NonNull::from(Box::leak(result)) + heap_move_nonnull(unsafe { bitmap.as_ref().clone() }) } /// Deallocates a [Bitmap]. #[no_mangle] pub unsafe extern "C" fn sp_bitmap_free(bitmap: NonNull) { - _ = unsafe { Box::from_raw(bitmap.as_ptr()) }; + unsafe { heap_drop(bitmap) } } /// Gets the current value at the specified position in the [Bitmap]. diff --git a/src/bitvec.rs b/src/bitvec.rs index f87423d..e5ce720 100644 --- a/src/bitvec.rs +++ b/src/bitvec.rs @@ -1,6 +1,6 @@ -use crate::ByteSlice; -use std::ptr::NonNull; +use crate::{heap_drop, heap_move_nonnull, ByteSlice}; use servicepoint::BitVecU8Msb0; +use std::ptr::NonNull; /// A vector of bits /// @@ -31,21 +31,16 @@ impl Clone for SPBitVec { /// - when `size` is not divisible by 8. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_new(size: usize) -> NonNull { - let result = - Box::new(SPBitVec(BitVecU8Msb0::repeat(false, size))); - NonNull::from(Box::leak(result)) + heap_move_nonnull(SPBitVec(BitVecU8Msb0::repeat(false, size))) } /// Interpret the data as a series of bits and load then into a new [SPBitVec] instance. /// /// returns: [SPBitVec] instance containing data. #[no_mangle] -pub unsafe extern "C" fn sp_bitvec_load( - data: ByteSlice, -) -> NonNull { +pub unsafe extern "C" fn sp_bitvec_load(data: ByteSlice) -> NonNull { let data = unsafe { data.as_slice() }; - let result = Box::new(SPBitVec(BitVecU8Msb0::from_slice(data))); - NonNull::from(Box::leak(result)) + heap_move_nonnull(SPBitVec(BitVecU8Msb0::from_slice(data))) } /// Clones a [SPBitVec]. @@ -53,14 +48,13 @@ pub unsafe extern "C" fn sp_bitvec_load( pub unsafe extern "C" fn sp_bitvec_clone( bit_vec: NonNull, ) -> NonNull { - let result = Box::new(unsafe { bit_vec.as_ref().clone() }); - NonNull::from(Box::leak(result)) + heap_move_nonnull(unsafe { bit_vec.as_ref().clone() }) } /// Deallocates a [SPBitVec]. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_free(bit_vec: NonNull) { - _ = unsafe { Box::from_raw(bit_vec.as_ptr()) }; + unsafe { heap_drop(bit_vec) } } /// Gets the value of a bit from the [SPBitVec]. diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index 5cd7a16..a283d0a 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -1,4 +1,4 @@ -use crate::ByteSlice; +use crate::{heap_drop, heap_move, heap_move_nonnull, ByteSlice}; use servicepoint::{Brightness, BrightnessGrid, ByteGrid, DataRef, Grid}; use std::mem::transmute; use std::ptr::NonNull; @@ -25,8 +25,7 @@ pub unsafe extern "C" fn sp_brightness_grid_new( width: usize, height: usize, ) -> NonNull { - let result = Box::new(BrightnessGrid::new(width, height)); - NonNull::from(Box::leak(result)) + heap_move_nonnull(BrightnessGrid::new(width, height)) } /// Loads a [BrightnessGrid] with the specified dimensions from the provided data. @@ -44,7 +43,7 @@ pub unsafe extern "C" fn sp_brightness_grid_load( Some(grid) => grid, }; if let Ok(grid) = BrightnessGrid::try_from(grid) { - Box::leak(Box::new(grid)) + heap_move(grid) } else { std::ptr::null_mut() } @@ -55,8 +54,7 @@ pub unsafe extern "C" fn sp_brightness_grid_load( pub unsafe extern "C" fn sp_brightness_grid_clone( brightness_grid: NonNull, ) -> NonNull { - let result = Box::new(unsafe { brightness_grid.as_ref().clone() }); - NonNull::from(Box::leak(result)) + heap_move_nonnull(unsafe { brightness_grid.as_ref().clone() }) } /// Deallocates a [BrightnessGrid]. @@ -64,7 +62,7 @@ pub unsafe extern "C" fn sp_brightness_grid_clone( pub unsafe extern "C" fn sp_brightness_grid_free( brightness_grid: NonNull, ) { - _ = unsafe { Box::from_raw(brightness_grid.as_ptr()) }; + unsafe { heap_drop(brightness_grid) } } /// Gets the current value at the specified position. diff --git a/src/char_grid.rs b/src/char_grid.rs index a287d70..cdcc4b5 100644 --- a/src/char_grid.rs +++ b/src/char_grid.rs @@ -1,4 +1,4 @@ -use crate::ByteSlice; +use crate::{heap_drop, heap_move, heap_move_nonnull, ByteSlice}; use servicepoint::{CharGrid, Grid}; use std::ptr::NonNull; @@ -19,8 +19,7 @@ pub unsafe extern "C" fn sp_char_grid_new( width: usize, height: usize, ) -> NonNull { - let result = Box::new(CharGrid::new(width, height)); - NonNull::from(Box::leak(result)) + heap_move_nonnull(CharGrid::new(width, height)) } /// Loads a [CharGrid] with the specified dimensions from the provided data. @@ -34,7 +33,7 @@ pub unsafe extern "C" fn sp_char_grid_load( ) -> *mut CharGrid { let data = unsafe { data.as_slice() }; if let Ok(grid) = CharGrid::load_utf8(width, height, data.to_vec()) { - Box::leak(Box::new(grid)) + heap_move(grid) } else { std::ptr::null_mut() } @@ -45,14 +44,13 @@ pub unsafe extern "C" fn sp_char_grid_load( pub unsafe extern "C" fn sp_char_grid_clone( char_grid: NonNull, ) -> NonNull { - let result = unsafe { char_grid.as_ref().clone() }; - NonNull::from(Box::leak(Box::new(result))) + heap_move_nonnull(unsafe { char_grid.as_ref().clone() }) } /// Deallocates a [CharGrid]. #[no_mangle] pub unsafe extern "C" fn sp_char_grid_free(char_grid: NonNull) { - _ = unsafe { Box::from_raw(char_grid.as_ptr()) }; + unsafe { heap_drop(char_grid) } } /// Returns the current value at the specified position. diff --git a/src/command.rs b/src/command.rs index 80a2b22..32d5acd 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,5 +1,8 @@ -use crate::SPBitVec; -use servicepoint::{BinaryOperation, Bitmap, Brightness, BrightnessGrid, CharGrid, CompressionCode, Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand}; +use crate::{heap_drop, heap_move, heap_move_nonnull, SPBitVec}; +use servicepoint::{ + BinaryOperation, Bitmap, Brightness, BrightnessGrid, CharGrid, + CompressionCode, Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand, +}; use std::ptr::NonNull; /// Tries to turn a [Packet] into a [TypedCommand]. @@ -14,7 +17,7 @@ pub unsafe extern "C" fn sp_command_try_from_packet( let packet = *unsafe { Box::from_raw(packet.as_ptr()) }; match servicepoint::TypedCommand::try_from(packet) { Err(_) => std::ptr::null_mut(), - Ok(command) => Box::into_raw(Box::new(command)), + Ok(command) => heap_move(command), } } @@ -25,8 +28,7 @@ pub unsafe extern "C" fn sp_command_try_from_packet( pub unsafe extern "C" fn sp_command_clone( command: NonNull, ) -> NonNull { - let result = Box::new(unsafe { command.as_ref().clone() }); - NonNull::from(Box::leak(result)) + heap_move_nonnull(unsafe { command.as_ref().clone() }) } /// Set all pixels to the off state. @@ -42,8 +44,7 @@ pub unsafe extern "C" fn sp_command_clone( /// ``` #[no_mangle] pub unsafe extern "C" fn sp_command_clear() -> NonNull { - let result = Box::new(servicepoint::ClearCommand.into()); - NonNull::from(Box::leak(result)) + heap_move_nonnull(servicepoint::ClearCommand.into()) } /// Kills the udp daemon on the display, which usually results in a restart. @@ -53,8 +54,7 @@ pub unsafe extern "C" fn sp_command_clear() -> NonNull { /// Returns: a new [servicepoint::Command::HardReset] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull { - let result = Box::new(servicepoint::HardResetCommand.into()); - NonNull::from(Box::leak(result)) + heap_move_nonnull(servicepoint::HardResetCommand.into()) } /// A yet-to-be-tested command. @@ -62,19 +62,17 @@ pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull { /// Returns: a new [servicepoint::Command::FadeOut] instance. #[no_mangle] pub unsafe extern "C" fn sp_command_fade_out() -> NonNull { - let result = Box::new(servicepoint::FadeOutCommand.into()); - NonNull::from(Box::leak(result)) + heap_move_nonnull(servicepoint::FadeOutCommand.into()) } /// Set the brightness of all tiles to the same value. /// /// Returns: a new [servicepoint::Command::Brightness] instance. #[no_mangle] -pub unsafe extern "C" fn sp_command_brightness( +pub unsafe extern "C" fn sp_command_global_brightness( brightness: Brightness, ) -> NonNull { - let result = Box::new(GlobalBrightnessCommand::from(brightness).into()); - NonNull::from(Box::leak(result)) + heap_move_nonnull(GlobalBrightnessCommand::from(brightness).into()) } /// Set the brightness of individual tiles in a rectangular area of the display. @@ -83,20 +81,18 @@ pub unsafe extern "C" fn sp_command_brightness( /// /// Returns: a new [servicepoint::Command::CharBrightness] instance. #[no_mangle] -pub unsafe extern "C" fn sp_command_char_brightness( +pub unsafe extern "C" fn sp_command_brightness_grid( x: usize, y: usize, grid: NonNull, ) -> NonNull { let grid = unsafe { *Box::from_raw(grid.as_ptr()) }; - let result = Box::new( - servicepoint::BrightnessGridCommand { - origin: servicepoint::Origin::new(x, y), - grid, - } - .into(), - ); - NonNull::from(Box::leak(result)) + let result = servicepoint::BrightnessGridCommand { + origin: servicepoint::Origin::new(x, y), + grid, + } + .into(); + heap_move_nonnull(result) } /// Set pixel data starting at the pixel offset on screen. @@ -129,8 +125,8 @@ pub unsafe extern "C" fn sp_command_bitvec( bitvec: bit_vec.0, compression, } - .into(); - Box::leak(Box::new(command)) + .into(); + heap_move(command) } /// Show codepage 437 encoded text on the screen. @@ -145,14 +141,12 @@ pub unsafe extern "C" fn sp_command_cp437_grid( grid: NonNull, ) -> NonNull { let grid = *unsafe { Box::from_raw(grid.as_ptr()) }; - let result = Box::new( - servicepoint::Cp437GridCommand { - origin: servicepoint::Origin::new(x, y), - grid, - } - .into(), - ); - NonNull::from(Box::leak(result)) + let result = servicepoint::Cp437GridCommand { + origin: servicepoint::Origin::new(x, y), + grid, + } + .into(); + heap_move_nonnull(result) } /// Show UTF-8 encoded text on the screen. @@ -167,14 +161,12 @@ pub unsafe extern "C" fn sp_command_char_grid( grid: NonNull, ) -> NonNull { let grid = unsafe { *Box::from_raw(grid.as_ptr()) }; - let result = Box::new( - servicepoint::CharGridCommand { - origin: servicepoint::Origin::new(x, y), - grid, - } - .into(), - ); - NonNull::from(Box::leak(result)) + let result = servicepoint::CharGridCommand { + origin: servicepoint::Origin::new(x, y), + grid, + } + .into(); + heap_move_nonnull(result) } /// Sets a window of pixels to the specified values. @@ -200,7 +192,7 @@ pub unsafe extern "C" fn sp_command_bitmap( compression, } .into(); - Box::leak(Box::new(command)) + heap_move(command) } /// Deallocates a [TypedCommand]. @@ -213,5 +205,5 @@ pub unsafe extern "C" fn sp_command_bitmap( /// ``` #[no_mangle] pub unsafe extern "C" fn sp_command_free(command: NonNull) { - _ = unsafe { Box::from_raw(command.as_ptr()) }; + unsafe { heap_drop(command) } } diff --git a/src/connection.rs b/src/connection.rs index b49225d..7b29e29 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,3 +1,4 @@ +use crate::{heap_drop, heap_move}; use servicepoint::{Connection, Packet, TypedCommand, UdpConnection}; use std::ffi::{c_char, CStr}; use std::net::{Ipv4Addr, SocketAddrV4}; @@ -26,7 +27,7 @@ pub unsafe extern "C" fn sp_udp_open( Ok(value) => value, }; - Box::into_raw(Box::new(connection)) + heap_move(connection) } /// Creates a new instance of [UdpConnection]. @@ -42,15 +43,18 @@ pub unsafe extern "C" fn sp_udp_open( /// ``` #[no_mangle] pub unsafe extern "C" fn sp_udp_open_ipv4( - ip1: u8, ip2: u8, ip3: u8, ip4: u8, + ip1: u8, + ip2: u8, + ip3: u8, + ip4: u8, port: u16, ) -> *mut UdpConnection { - let addr = SocketAddrV4::new(Ipv4Addr::from( [ip1, ip2, ip3, ip4]), port); + let addr = SocketAddrV4::new(Ipv4Addr::from([ip1, ip2, ip3, ip4]), port); let connection = match UdpConnection::open(addr) { Err(_) => return std::ptr::null_mut(), Ok(value) => value, }; - Box::into_raw(Box::new(connection)) + heap_move(connection) } /// Sends a [Packet] to the display using the [UdpConnection]. @@ -90,8 +94,6 @@ pub unsafe extern "C" fn sp_udp_send_command( /// Closes and deallocates a [UdpConnection]. #[no_mangle] -pub unsafe extern "C" fn sp_udp_free( - connection: NonNull, -) { - _ = unsafe { Box::from_raw(connection.as_ptr()) }; +pub unsafe extern "C" fn sp_udp_free(connection: NonNull) { + unsafe { heap_drop(connection) } } diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index 3904354..e22a0ed 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -1,4 +1,4 @@ -use crate::ByteSlice; +use crate::{heap_drop, heap_move, heap_move_nonnull, ByteSlice}; use servicepoint::{Cp437Grid, DataRef, Grid}; use std::ptr::NonNull; @@ -10,8 +10,7 @@ pub unsafe extern "C" fn sp_cp437_grid_new( width: usize, height: usize, ) -> NonNull { - let result = Box::new(Cp437Grid::new(width, height)); - NonNull::from(Box::leak(result)) + heap_move_nonnull(Cp437Grid::new(width, height)) } /// Loads a [Cp437Grid] with the specified dimensions from the provided data. @@ -24,7 +23,7 @@ pub unsafe extern "C" fn sp_cp437_grid_load( let data = unsafe { data.as_slice() }; let grid = Cp437Grid::load(width, height, data); if let Some(grid) = grid { - Box::leak(Box::new(grid)) + heap_move(grid) } else { std::ptr::null_mut() } @@ -35,14 +34,13 @@ pub unsafe extern "C" fn sp_cp437_grid_load( pub unsafe extern "C" fn sp_cp437_grid_clone( cp437_grid: NonNull, ) -> NonNull { - let result = Box::new(unsafe { cp437_grid.as_ref().clone() }); - NonNull::from(Box::leak(result)) + heap_move_nonnull(unsafe { cp437_grid.as_ref().clone() }) } /// Deallocates a [Cp437Grid]. #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: NonNull) { - _ = unsafe { Box::from_raw(cp437_grid.as_ptr()) }; + unsafe { heap_drop(cp437_grid) } } /// Gets the current value at the specified position. diff --git a/src/lib.rs b/src/lib.rs index 4d4e386..f90e93d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,7 @@ pub use crate::command::*; pub use crate::connection::*; pub use crate::cp437_grid::*; pub use crate::packet::*; +use std::ptr::NonNull; mod bitmap; mod bitvec; @@ -49,3 +50,15 @@ use std::time::Duration; /// Actual hardware limit is around 28-29ms/frame. Rounded up for less dropped packets. pub const SP_FRAME_PACING_MS: u128 = Duration::from_millis(30).as_millis(); + +pub(crate) fn heap_move(x: T) -> *mut T { + Box::into_raw(Box::new(x)) +} + +pub(crate) fn heap_move_nonnull(x: T) -> NonNull { + NonNull::from(Box::leak(Box::new(x))) +} + +pub(crate) unsafe fn heap_drop(x: NonNull) { + drop(unsafe { Box::from_raw(x.as_ptr()) }); +} diff --git a/src/packet.rs b/src/packet.rs index 996c83d..a9def67 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,4 +1,4 @@ -use crate::ByteSlice; +use crate::{heap_drop, heap_move, heap_move_nonnull, ByteSlice}; use servicepoint::{Header, Packet, TypedCommand}; use std::ptr::NonNull; @@ -12,7 +12,7 @@ pub unsafe extern "C" fn sp_packet_from_command( ) -> *mut Packet { let command = unsafe { *Box::from_raw(command.as_ptr()) }; if let Ok(packet) = command.try_into() { - Box::leak(Box::new(packet)) + heap_move(packet) } else { std::ptr::null_mut() } @@ -26,7 +26,7 @@ pub unsafe extern "C" fn sp_packet_try_load(data: ByteSlice) -> *mut Packet { let data = unsafe { data.as_slice() }; match servicepoint::Packet::try_from(data) { Err(_) => std::ptr::null_mut(), - Ok(packet) => Box::into_raw(Box::new(packet)), + Ok(packet) => heap_move(packet), } } @@ -45,8 +45,7 @@ pub unsafe extern "C" fn sp_packet_from_parts( Vec::from(payload) }; - let packet = Box::new(Packet { header, payload }); - NonNull::from(Box::leak(packet)) + heap_move_nonnull(Packet { header, payload }) } /// Returns a pointer to the header field of the provided packet. @@ -100,12 +99,11 @@ pub unsafe extern "C" fn sp_packet_serialize_to( pub unsafe extern "C" fn sp_packet_clone( packet: NonNull, ) -> NonNull { - let result = Box::new(unsafe { packet.as_ref().clone() }); - NonNull::from(Box::leak(result)) + heap_move_nonnull(unsafe { packet.as_ref().clone() }) } /// Deallocates a [Packet]. #[no_mangle] pub unsafe extern "C" fn sp_packet_free(packet: NonNull) { - _ = unsafe { Box::from_raw(packet.as_ptr()) } + unsafe { heap_drop(packet) } } -- 2.47.0 From c797bb68942686d9c3cdfc9b2a886423fa738c5f Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 18:35:48 +0200 Subject: [PATCH 18/25] add sp_bitmap_into_bitvec --- include/servicepoint.h | 5 +++++ src/bitmap.rs | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/servicepoint.h b/include/servicepoint.h index 9edeaf9..2b9b07c 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -411,6 +411,11 @@ bool sp_bitmap_get(Bitmap */*notnull*/ bitmap, size_t x, size_t y); */ size_t sp_bitmap_height(Bitmap */*notnull*/ bitmap); +/** + * Consumes the Bitmap and returns the contained BitVec + */ +SPBitVec */*notnull*/ sp_bitmap_into_bitvec(Bitmap */*notnull*/ bitmap); + /** * Loads a [Bitmap] with the specified dimensions from the provided data. * diff --git a/src/bitmap.rs b/src/bitmap.rs index c166881..988a6ce 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -1,5 +1,5 @@ use crate::byte_slice::ByteSlice; -use crate::{heap_drop, heap_move, heap_move_nonnull}; +use crate::{heap_drop, heap_move, heap_move_nonnull, SPBitVec}; use servicepoint::{Bitmap, DataRef, Grid}; use std::ptr::NonNull; @@ -172,3 +172,12 @@ pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref( ) -> ByteSlice { unsafe { ByteSlice::from_slice(bitmap.as_mut().data_ref_mut()) } } + +/// Consumes the Bitmap and returns the contained BitVec +#[no_mangle] +pub unsafe extern "C" fn sp_bitmap_into_bitvec( + bitmap: NonNull, +) -> NonNull { + let bitmap = unsafe { *Box::from_raw(bitmap.as_ptr()) }; + heap_move_nonnull(SPBitVec(bitmap.into())) +} -- 2.47.0 From 2e468fb47ac58c2d5724b84d9b41c7a36fc4f299 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 18:41:43 +0200 Subject: [PATCH 19/25] add sp_bitmap_from_bitvec --- include/servicepoint.h | 9 +++++++++ src/bitmap.rs | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/servicepoint.h b/include/servicepoint.h index 2b9b07c..51b00ca 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -388,6 +388,15 @@ void sp_bitmap_fill(Bitmap */*notnull*/ bitmap, bool value); */ void sp_bitmap_free(Bitmap */*notnull*/ bitmap); +/** + * Tries to convert the BitVec to a Bitmap. + * + * The provided BitVec gets consumed. + * + * Returns NULL in case of error. + */ +Bitmap *sp_bitmap_from_bitvec(size_t width, SPBitVec */*notnull*/ bitvec); + /** * Gets the current value at the specified position in the [Bitmap]. * diff --git a/src/bitmap.rs b/src/bitmap.rs index 988a6ce..f203395 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -68,6 +68,24 @@ pub unsafe extern "C" fn sp_bitmap_load( } } +/// Tries to convert the BitVec to a Bitmap. +/// +/// The provided BitVec gets consumed. +/// +/// Returns NULL in case of error. +#[no_mangle] +pub unsafe extern "C" fn sp_bitmap_from_bitvec( + width: usize, + bitvec: NonNull, +) -> *mut Bitmap { + let bitvec = unsafe { *Box::from_raw(bitvec.as_ptr()) }; + if let Ok(bitmap) = Bitmap::from_bitvec(width, bitvec.0) { + heap_move(bitmap) + } else { + std::ptr::null_mut() + } +} + /// Clones a [Bitmap]. #[no_mangle] pub unsafe extern "C" fn sp_bitmap_clone( -- 2.47.0 From a418e4f0c3dcf3aaa26193bec72f016afc98d112 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 18:49:12 +0200 Subject: [PATCH 20/25] sp_brightness_grid_load ignore out of range --- cbindgen.toml | 2 +- src/brightness_grid.rs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cbindgen.toml b/cbindgen.toml index 363d001..221e915 100644 --- a/cbindgen.toml +++ b/cbindgen.toml @@ -24,7 +24,7 @@ sort_by = "Name" [parse] parse_deps = true -include = ["servicepoint"] +include = ["servicepoint", "std"] extra_bindings = ["servicepoint"] [parse.expand] diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index a283d0a..823a1fd 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -30,6 +30,8 @@ pub unsafe extern "C" fn sp_brightness_grid_new( /// Loads a [BrightnessGrid] with the specified dimensions from the provided data. /// +/// Any out of range values will be set to [Brightness::MAX] or [Brightness::MIN]. +/// /// returns: new [BrightnessGrid] instance, or NULL in case of an error. #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_load( @@ -38,14 +40,12 @@ pub unsafe extern "C" fn sp_brightness_grid_load( data: ByteSlice, ) -> *mut BrightnessGrid { let data = unsafe { data.as_slice() }; - let grid = match ByteGrid::load(width, height, data) { - None => return std::ptr::null_mut(), - Some(grid) => grid, - }; - if let Ok(grid) = BrightnessGrid::try_from(grid) { - heap_move(grid) - } else { - std::ptr::null_mut() + + match ByteGrid::load(width, height, data) + .map(move |grid| grid.map(Brightness::saturating_from)) + { + None => std::ptr::null_mut(), + Some(grid) => heap_move(grid), } } -- 2.47.0 From b4eab85b199bef044cc33cff20c9bf44ee9d8c53 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 19:29:10 +0200 Subject: [PATCH 21/25] translate announce example --- example/Makefile | 31 +++++++++++++++-------------- example/announce.c | 32 ++++++++++++++++++++++++++++++ example/{main.c => random_stuff.c} | 0 include/servicepoint.h | 2 ++ 4 files changed, 50 insertions(+), 15 deletions(-) create mode 100644 example/announce.c rename example/{main.c => random_stuff.c} (100%) diff --git a/example/Makefile b/example/Makefile index d3f346f..91083d4 100644 --- a/example/Makefile +++ b/example/Makefile @@ -4,6 +4,7 @@ CARGO := rustup run nightly cargo THIS_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) REPO_ROOT := $(THIS_DIR)/.. RUST_TARGET_DIR := $(REPO_ROOT)/target/x86_64-unknown-linux-musl/size-optimized +export SERVICEPOINT_HEADER_OUT := $(REPO_ROOT)/include RUSTFLAGS := -Zlocation-detail=none \ -Zfmt-debug=none \ @@ -41,34 +42,34 @@ CCFLAGS := -static -Os \ -fno-exceptions #-Wl,--icf=all \ -export SERVICEPOINT_HEADER_OUT := $(REPO_ROOT)/include +STRIPFLAGS := -s --strip-unneeded -R .comment -R .gnu.version -R .comment -R .note -R .note.gnu.build-id -R .note.ABI-tag -build: out/example +src := $(wildcard *.c) +programs := $(basename $(src)) +bins := $(addprefix out/, $(programs)) +unstripped_bins := $(addsuffix _unstripped, $(bins)) + +all: $(bins) clean: rm -r out || true rm include/servicepoint.h || true cargo clean -run: out/example - out/example +PHONY: all clean analyze-size -PHONY: build clean dependencies run - -out/example_unstripped: dependencies main.c +$(unstripped_bins): out/%_unstripped: %.c $(SERVICEPOINT_HEADER_OUT)/servicepoint.h mkdir -p out || true - ${CC} main.c \ + ${CC} $^ \ -I $(SERVICEPOINT_HEADER_OUT) \ -L $(RUST_TARGET_DIR)\ $(CCFLAGS) \ - -o out/example_unstripped -out/example: out/example_unstripped - strip -s --strip-unneeded \ - -R .comment -R .gnu.version -R .comment -R .note -R .note.gnu.build-id -R .note.ABI-tag \ - out/example_unstripped \ - -o out/example + -o $@ -dependencies: FORCE +$(bins): out/%: out/%_unstripped + strip $(STRIPFLAGS) $^ -o $@ + +$(SERVICEPOINT_HEADER_OUT)/servicepoint.h: FORCE mkdir -p include || true # generate servicepoint header and binary to link against ${CARGO} rustc $(CARGOFLAGS) -- $(RUSTFLAGS) diff --git a/example/announce.c b/example/announce.c new file mode 100644 index 0000000..6cf3dc4 --- /dev/null +++ b/example/announce.c @@ -0,0 +1,32 @@ +#include +#include "servicepoint.h" + +int main(void) { + UdpConnection *connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); + if (connection == NULL) + return 1; + + sp_udp_send_command(connection, sp_command_clear()); + + CharGrid *grid = sp_char_grid_new(5,2); + if (grid == NULL) + return 1; + + sp_char_grid_set(grid, 0, 0, 'H'); + sp_char_grid_set(grid, 1, 0, 'e'); + sp_char_grid_set(grid, 2, 0, 'l'); + sp_char_grid_set(grid, 3, 0, 'l'); + sp_char_grid_set(grid, 4, 0, 'o'); + sp_char_grid_set(grid, 0, 1, 'W'); + sp_char_grid_set(grid, 1, 1, 'o'); + sp_char_grid_set(grid, 2, 1, 'r'); + sp_char_grid_set(grid, 3, 1, 'l'); + sp_char_grid_set(grid, 4, 1, 'd'); + + + TypedCommand *command = sp_command_char_grid(0, 0, grid); + sp_udp_send_command(connection, command); + + sp_udp_free(connection); + return 0; +} diff --git a/example/main.c b/example/random_stuff.c similarity index 100% rename from example/main.c rename to example/random_stuff.c diff --git a/include/servicepoint.h b/include/servicepoint.h index 51b00ca..aa7893f 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -668,6 +668,8 @@ size_t sp_brightness_grid_height(BrightnessGrid */*notnull*/ brightness_grid); /** * Loads a [BrightnessGrid] with the specified dimensions from the provided data. * + * Any out of range values will be set to [Brightness::MAX] or [Brightness::MIN]. + * * returns: new [BrightnessGrid] instance, or NULL in case of an error. */ BrightnessGrid *sp_brightness_grid_load(size_t width, -- 2.47.0 From c509813aacfd56363a26aa5496f3fcacf9615ecb Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 21:07:05 +0200 Subject: [PATCH 22/25] translate brightness tester --- example/Makefile | 31 +++++++++++++++++++++---------- example/announce.c | 3 +-- example/brightness_tester.c | 29 +++++++++++++++++++++++++++++ example/random_stuff.c | 5 ++--- flake.nix | 1 - 5 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 example/brightness_tester.c diff --git a/example/Makefile b/example/Makefile index 91083d4..bb53fe1 100644 --- a/example/Makefile +++ b/example/Makefile @@ -37,17 +37,20 @@ CCFLAGS := -static -Os \ -fvisibility=hidden \ -Bsymbolic \ -Wl,--exclude-libs,ALL \ - -fno-ident + -fno-ident \ + -Wall #-fuse-ld=gold \ -fno-exceptions #-Wl,--icf=all \ STRIPFLAGS := -s --strip-unneeded -R .comment -R .gnu.version -R .comment -R .note -R .note.gnu.build-id -R .note.ABI-tag -src := $(wildcard *.c) -programs := $(basename $(src)) +c_src := $(wildcard *.c) +programs := $(basename $(c_src)) bins := $(addprefix out/, $(programs)) unstripped_bins := $(addsuffix _unstripped, $(bins)) +run_programs := $(addprefix run_, $(programs)) +rs_src := $(wildcard ../src/*.rs) ../Cargo.lock all: $(bins) @@ -56,9 +59,9 @@ clean: rm include/servicepoint.h || true cargo clean -PHONY: all clean analyze-size +PHONY: all clean sizes $(run_programs) -$(unstripped_bins): out/%_unstripped: %.c $(SERVICEPOINT_HEADER_OUT)/servicepoint.h +$(unstripped_bins): out/%_unstripped: %.c $(SERVICEPOINT_HEADER_OUT)/servicepoint.h $(RUST_TARGET_DIR)/libservicepoint_binding_c.a mkdir -p out || true ${CC} $^ \ -I $(SERVICEPOINT_HEADER_OUT) \ @@ -69,14 +72,22 @@ $(unstripped_bins): out/%_unstripped: %.c $(SERVICEPOINT_HEADER_OUT)/servicepoin $(bins): out/%: out/%_unstripped strip $(STRIPFLAGS) $^ -o $@ -$(SERVICEPOINT_HEADER_OUT)/servicepoint.h: FORCE +$(SERVICEPOINT_HEADER_OUT)/servicepoint.h $(RUST_TARGET_DIR)/libservicepoint_binding_c.a: $(rs_src) mkdir -p include || true # generate servicepoint header and binary to link against ${CARGO} rustc $(CARGOFLAGS) -- $(RUSTFLAGS) -analyze-size: out/example_unstripped - nm --print-size --size-sort --reverse-sort --radix=d --demangle out/example_unstripped \ - | awk '{size=$$2+0; print size "\t" $$4}' \ - | less +$(run_programs): run_%: out/% FORCE + ./$< + +sizes: $(bins) + ls -lB out + +#analyze-size: out/example_unstripped +# nm --print-size --size-sort --reverse-sort --radix=d --demangle out/example_unstripped \ +# | awk '{size=$$2+0; print size "\t" $$4}' \ +# | less + + FORCE: ; diff --git a/example/announce.c b/example/announce.c index 6cf3dc4..d7a55fb 100644 --- a/example/announce.c +++ b/example/announce.c @@ -1,4 +1,3 @@ -#include #include "servicepoint.h" int main(void) { @@ -8,7 +7,7 @@ int main(void) { sp_udp_send_command(connection, sp_command_clear()); - CharGrid *grid = sp_char_grid_new(5,2); + CharGrid *grid = sp_char_grid_new(5, 2); if (grid == NULL) return 1; diff --git a/example/brightness_tester.c b/example/brightness_tester.c new file mode 100644 index 0000000..93e64ce --- /dev/null +++ b/example/brightness_tester.c @@ -0,0 +1,29 @@ +#include "servicepoint.h" + +int main(void) { + // UdpConnection *connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); + UdpConnection *connection = sp_udp_open_ipv4(127, 0, 0, 1, 2342); + if (connection == NULL) + return -1; + + Bitmap *all_on = sp_bitmap_new_max_sized(); + sp_bitmap_fill(all_on, true); + TypedCommand *cmd = sp_command_bitmap(0, 0, all_on, COMPRESSION_CODE_UNCOMPRESSED); + if (cmd == NULL) + return -1; + + sp_udp_send_command(connection, cmd); + + BrightnessGrid *grid = sp_brightness_grid_new(TILE_WIDTH, TILE_HEIGHT); + + ByteSlice slice = sp_brightness_grid_unsafe_data_ref(grid); + for (size_t index = 0; index < slice.length; index++) { + slice.start[index] = (uint8_t) (index % ((size_t) Brightness_MAX)); + } + + TypedCommand *command = sp_command_brightness_grid(0, 0, grid); + sp_udp_send_command(connection, command); + + sp_udp_free(connection); + return 0; +} diff --git a/example/random_stuff.c b/example/random_stuff.c index 9c0ec9e..80c3847 100644 --- a/example/random_stuff.c +++ b/example/random_stuff.c @@ -1,4 +1,3 @@ -#include #include "servicepoint.h" int main(void) { @@ -8,13 +7,13 @@ int main(void) { Bitmap *pixels = sp_bitmap_new(PIXEL_WIDTH, PIXEL_HEIGHT); if (pixels == NULL) - return 1; + return 1; sp_bitmap_fill(pixels, true); TypedCommand *command = sp_command_bitmap(0, 0, pixels, COMPRESSION_CODE_UNCOMPRESSED); if (command == NULL) - return 1; + return 1; Packet *packet = sp_packet_from_command(command); diff --git a/flake.nix b/flake.nix index 1f0ac97..b4f874f 100644 --- a/flake.nix +++ b/flake.nix @@ -59,7 +59,6 @@ gcc gnumake pkg-config - ]; RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}"; -- 2.47.0 From a3e2dcb3c2159d642d7ea6952d191cbc98080f34 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 21:47:23 +0200 Subject: [PATCH 23/25] add command code constants, send header --- Cargo.lock | 2 +- Cargo.toml | 3 ++ example/Makefile | 37 ++++++++-------- example/announce.c | 8 ++-- include/servicepoint.h | 63 +++++++++++++++++++++++---- src/brightness_grid.rs | 6 +-- src/byte_slice.rs | 2 +- src/commands/mod.rs | 3 ++ src/{command.rs => commands/typed.rs} | 10 +---- src/connection.rs | 34 ++++++++++++--- src/lib.rs | 11 ++--- src/packet.rs | 22 ++++++++-- 12 files changed, 141 insertions(+), 60 deletions(-) create mode 100644 src/commands/mod.rs rename src/{command.rs => commands/typed.rs} (94%) diff --git a/Cargo.lock b/Cargo.lock index f87ecea..968bfeb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -408,7 +408,7 @@ dependencies = [ [[package]] name = "servicepoint" version = "0.13.2" -source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#531d4e6b4a368dc126cab9dc12b64d2ca8a81694" +source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#114385868af03f8cba7c87a630b501bb0106d140" dependencies = [ "bitvec", "bzip2", diff --git a/Cargo.toml b/Cargo.toml index 7e5ed5d..e92ceb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,9 @@ default = ["full"] missing-docs = "warn" unsafe_op_in_unsafe_fn = "warn" +[lints.clippy] +missing_safety_doc = "allow" + [package.metadata.docs.rs] all-features = true diff --git a/example/Makefile b/example/Makefile index bb53fe1..f69f385 100644 --- a/example/Makefile +++ b/example/Makefile @@ -1,9 +1,12 @@ CC := gcc CARGO := rustup run nightly cargo +TARGET := x86_64-unknown-linux-musl +PROFILE := size-optimized + THIS_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) REPO_ROOT := $(THIS_DIR)/.. -RUST_TARGET_DIR := $(REPO_ROOT)/target/x86_64-unknown-linux-musl/size-optimized +RUST_TARGET_DIR := $(REPO_ROOT)/target/$(TARGET)/$(PROFILE) export SERVICEPOINT_HEADER_OUT := $(REPO_ROOT)/include RUSTFLAGS := -Zlocation-detail=none \ @@ -17,9 +20,9 @@ RUSTFLAGS := -Zlocation-detail=none \ -C panic=abort CARGOFLAGS := --manifest-path=$(REPO_ROOT)/Cargo.toml \ - --profile=size-optimized \ + --profile=$(PROFILE) \ --no-default-features \ - --target=x86_64-unknown-linux-musl \ + --target=$(TARGET) \ -Zbuild-std="core,std,alloc,proc_macro,panic_abort" \ -Zbuild-std-features="panic_immediate_abort" \ @@ -45,23 +48,23 @@ CCFLAGS := -static -Os \ STRIPFLAGS := -s --strip-unneeded -R .comment -R .gnu.version -R .comment -R .note -R .note.gnu.build-id -R .note.ABI-tag -c_src := $(wildcard *.c) -programs := $(basename $(c_src)) -bins := $(addprefix out/, $(programs)) -unstripped_bins := $(addsuffix _unstripped, $(bins)) -run_programs := $(addprefix run_, $(programs)) -rs_src := $(wildcard ../src/*.rs) ../Cargo.lock +_c_src := $(wildcard *.c) +_programs := $(basename $(_c_src)) +_bins := $(addprefix out/, $(_programs)) +_unstripped_bins := $(addsuffix _unstripped, $(_bins)) +_run_programs := $(addprefix run_, $(_programs)) +_rs_src := $(wildcard ../src/**.rs) ../Cargo.lock -all: $(bins) +all: $(_bins) clean: rm -r out || true rm include/servicepoint.h || true cargo clean -PHONY: all clean sizes $(run_programs) +PHONY: all clean sizes $(_run_programs) -$(unstripped_bins): out/%_unstripped: %.c $(SERVICEPOINT_HEADER_OUT)/servicepoint.h $(RUST_TARGET_DIR)/libservicepoint_binding_c.a +$(_unstripped_bins): out/%_unstripped: %.c $(SERVICEPOINT_HEADER_OUT)/servicepoint.h $(RUST_TARGET_DIR)/libservicepoint_binding_c.a mkdir -p out || true ${CC} $^ \ -I $(SERVICEPOINT_HEADER_OUT) \ @@ -69,18 +72,18 @@ $(unstripped_bins): out/%_unstripped: %.c $(SERVICEPOINT_HEADER_OUT)/servicepoin $(CCFLAGS) \ -o $@ -$(bins): out/%: out/%_unstripped +$(_bins): out/%: out/%_unstripped strip $(STRIPFLAGS) $^ -o $@ -$(SERVICEPOINT_HEADER_OUT)/servicepoint.h $(RUST_TARGET_DIR)/libservicepoint_binding_c.a: $(rs_src) +$(SERVICEPOINT_HEADER_OUT)/servicepoint.h $(RUST_TARGET_DIR)/libservicepoint_binding_c.a: $(_rs_src) mkdir -p include || true # generate servicepoint header and binary to link against ${CARGO} rustc $(CARGOFLAGS) -- $(RUSTFLAGS) -$(run_programs): run_%: out/% FORCE +$(_run_programs): run_%: out/% FORCE ./$< -sizes: $(bins) +sizes: $(_bins) ls -lB out #analyze-size: out/example_unstripped @@ -88,6 +91,4 @@ sizes: $(bins) # | awk '{size=$$2+0; print size "\t" $$4}' \ # | less - - FORCE: ; diff --git a/example/announce.c b/example/announce.c index d7a55fb..9220242 100644 --- a/example/announce.c +++ b/example/announce.c @@ -1,16 +1,17 @@ #include "servicepoint.h" int main(void) { - UdpConnection *connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); + //UdpConnection *connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); + UdpConnection *connection = sp_udp_open_ipv4(127, 0, 0, 1, 2342); if (connection == NULL) return 1; - sp_udp_send_command(connection, sp_command_clear()); + sp_udp_send_header(connection, (Header) {.command_code = COMMAND_CODE_CLEAR}); CharGrid *grid = sp_char_grid_new(5, 2); if (grid == NULL) return 1; - + sp_char_grid_set(grid, 0, 0, 'H'); sp_char_grid_set(grid, 1, 0, 'e'); sp_char_grid_set(grid, 2, 0, 'l'); @@ -22,7 +23,6 @@ int main(void) { sp_char_grid_set(grid, 3, 1, 'l'); sp_char_grid_set(grid, 4, 1, 'd'); - TypedCommand *command = sp_command_char_grid(0, 0, grid); sp_udp_send_command(connection, command); diff --git a/include/servicepoint.h b/include/servicepoint.h index aa7893f..0a0d340 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -95,6 +95,36 @@ enum BinaryOperation typedef uint8_t BinaryOperation; #endif // __cplusplus +/** + * The u16 command codes used for the [Command]s. + */ +enum CommandCode +#ifdef __cplusplus + : uint16_t +#endif // __cplusplus + { + COMMAND_CODE_CLEAR = 2, + COMMAND_CODE_CP437_DATA = 3, + COMMAND_CODE_CHAR_BRIGHTNESS = 5, + COMMAND_CODE_BRIGHTNESS = 7, + COMMAND_CODE_HARD_RESET = 11, + COMMAND_CODE_FADE_OUT = 13, + COMMAND_CODE_BITMAP_LEGACY = 16, + COMMAND_CODE_BITMAP_LINEAR = 18, + COMMAND_CODE_BITMAP_LINEAR_WIN_UNCOMPRESSED = 19, + COMMAND_CODE_BITMAP_LINEAR_AND = 20, + COMMAND_CODE_BITMAP_LINEAR_OR = 21, + COMMAND_CODE_BITMAP_LINEAR_XOR = 22, + COMMAND_CODE_BITMAP_LINEAR_WIN_ZLIB = 23, + COMMAND_CODE_BITMAP_LINEAR_WIN_BZIP2 = 24, + COMMAND_CODE_BITMAP_LINEAR_WIN_LZMA = 25, + COMMAND_CODE_UTF8_DATA = 32, + COMMAND_CODE_BITMAP_LINEAR_WIN_ZSTD = 26, +}; +#ifndef __cplusplus +typedef uint16_t CommandCode; +#endif // __cplusplus + /** * Specifies the kind of compression to use. Availability depends on features. * @@ -683,7 +713,7 @@ BrightnessGrid *sp_brightness_grid_load(size_t width, * * # Examples * ```C - * UdpConnection connection = sp_connection_open("127.0.0.1:2342"); + * UdpConnection connection = sp_udp_open("127.0.0.1:2342"); * if (connection == NULL) * return 1; * @@ -692,7 +722,7 @@ BrightnessGrid *sp_brightness_grid_load(size_t width, * sp_brightness_grid_set(grid, 1, 1, 10); * * TypedCommand command = sp_command_char_brightness(grid); - * sp_connection_free(connection); + * sp_udp_free(connection); * ``` */ BrightnessGrid */*notnull*/ sp_brightness_grid_new(size_t width, size_t height); @@ -899,7 +929,7 @@ TypedCommand */*notnull*/ sp_command_char_grid(size_t x, * # Examples * * ```C - * sp_connection_send_command(connection, sp_command_clear()); + * sp_udp_send_command(connection, sp_command_clear()); * ``` */ TypedCommand */*notnull*/ sp_command_clear(void); @@ -1122,6 +1152,8 @@ void sp_packet_set_payload(Packet */*notnull*/ packet, ByteSlice data); */ Packet *sp_packet_try_load(ByteSlice data); +bool sp_u16_to_command_code(uint16_t code, CommandCode *result); + /** * Closes and deallocates a [UdpConnection]. */ @@ -1135,9 +1167,9 @@ void sp_udp_free(UdpConnection */*notnull*/ connection); * # Examples * * ```C - * UdpConnection connection = sp_connection_open("172.23.42.29:2342"); + * UdpConnection connection = sp_udp_open("172.23.42.29:2342"); * if (connection != NULL) - * sp_connection_send_command(connection, sp_command_clear()); + * sp_udp_send_command(connection, sp_command_clear()); * ``` */ UdpConnection *sp_udp_open(char */*notnull*/ host); @@ -1150,9 +1182,9 @@ UdpConnection *sp_udp_open(char */*notnull*/ host); * # Examples * * ```C - * UdpConnection connection = sp_connection_open_ipv4(172, 23, 42, 29, 2342); + * UdpConnection connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); * if (connection != NULL) - * sp_connection_send_command(connection, sp_command_clear()); + * sp_udp_send_command(connection, sp_command_clear()); * ``` */ UdpConnection *sp_udp_open_ipv4(uint8_t ip1, @@ -1171,13 +1203,26 @@ UdpConnection *sp_udp_open_ipv4(uint8_t ip1, * # Examples * * ```C - * sp_connection_send_command(connection, sp_command_clear()); - * sp_connection_send_command(connection, sp_command_brightness(5)); + * sp_udp_send_command(connection, sp_command_brightness(5)); * ``` */ bool sp_udp_send_command(UdpConnection */*notnull*/ connection, TypedCommand */*notnull*/ command); +/** + * Sends a [Header] to the display using the [UdpConnection]. + * + * returns: true in case of success + * + * # Examples + * + * ```C + * sp_udp_send_header(connection, sp_command_brightness(5)); + * ``` + */ +bool sp_udp_send_header(UdpConnection */*notnull*/ udp_connection, + Header header); + /** * Sends a [Packet] to the display using the [UdpConnection]. * diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index 823a1fd..dcde8cf 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -9,7 +9,7 @@ use std::ptr::NonNull; /// /// # Examples /// ```C -/// UdpConnection connection = sp_connection_open("127.0.0.1:2342"); +/// UdpConnection connection = sp_udp_open("127.0.0.1:2342"); /// if (connection == NULL) /// return 1; /// @@ -18,7 +18,7 @@ use std::ptr::NonNull; /// sp_brightness_grid_set(grid, 1, 1, 10); /// /// TypedCommand command = sp_command_char_brightness(grid); -/// sp_connection_free(connection); +/// sp_udp_free(connection); /// ``` #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_new( @@ -167,5 +167,5 @@ pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( const _: () = assert!(size_of::() == 1); let data = unsafe { (*brightness_grid.as_ptr()).data_ref_mut() }; - unsafe { ByteSlice::from_slice(transmute(data)) } + unsafe { ByteSlice::from_slice(transmute::<&mut [Brightness], &mut [u8]>(data)) } } diff --git a/src/byte_slice.rs b/src/byte_slice.rs index 001a616..de7d0df 100644 --- a/src/byte_slice.rs +++ b/src/byte_slice.rs @@ -24,7 +24,7 @@ impl ByteSlice { unsafe { std::slice::from_raw_parts(self.start.as_ptr(), self.length) } } - pub(crate) unsafe fn as_slice_mut(&self) -> &mut [u8] { + pub(crate) unsafe fn as_slice_mut(&mut self) -> &mut [u8] { unsafe { std::slice::from_raw_parts_mut(self.start.as_ptr(), self.length) } diff --git a/src/commands/mod.rs b/src/commands/mod.rs new file mode 100644 index 0000000..1ea03d5 --- /dev/null +++ b/src/commands/mod.rs @@ -0,0 +1,3 @@ +mod typed; + +pub use typed::*; diff --git a/src/command.rs b/src/commands/typed.rs similarity index 94% rename from src/command.rs rename to src/commands/typed.rs index 32d5acd..9e27540 100644 --- a/src/command.rs +++ b/src/commands/typed.rs @@ -40,7 +40,7 @@ pub unsafe extern "C" fn sp_command_clone( /// # Examples /// /// ```C -/// sp_connection_send_command(connection, sp_command_clear()); +/// sp_udp_send_command(connection, sp_command_clear()); /// ``` #[no_mangle] pub unsafe extern "C" fn sp_command_clear() -> NonNull { @@ -115,10 +115,6 @@ pub unsafe extern "C" fn sp_command_bitvec( operation: BinaryOperation, ) -> *mut TypedCommand { let bit_vec = unsafe { *Box::from_raw(bit_vec.as_ptr()) }; - let compression = match compression.try_into() { - Ok(compression) => compression, - Err(_) => return std::ptr::null_mut(), - }; let command = servicepoint::BitVecCommand { offset, operation, @@ -182,10 +178,6 @@ pub unsafe extern "C" fn sp_command_bitmap( compression: CompressionCode, ) -> *mut TypedCommand { let bitmap = unsafe { *Box::from_raw(bitmap.as_ptr()) }; - let compression = match compression.try_into() { - Ok(compression) => compression, - Err(_) => return std::ptr::null_mut(), - }; let command = servicepoint::BitmapCommand { origin: servicepoint::Origin::new(x, y), bitmap, diff --git a/src/connection.rs b/src/connection.rs index 7b29e29..eec1f43 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,5 +1,5 @@ use crate::{heap_drop, heap_move}; -use servicepoint::{Connection, Packet, TypedCommand, UdpConnection}; +use servicepoint::{Connection, Header, Packet, TypedCommand, UdpConnection}; use std::ffi::{c_char, CStr}; use std::net::{Ipv4Addr, SocketAddrV4}; use std::ptr::NonNull; @@ -11,9 +11,9 @@ use std::ptr::NonNull; /// # Examples /// /// ```C -/// UdpConnection connection = sp_connection_open("172.23.42.29:2342"); +/// UdpConnection connection = sp_udp_open("172.23.42.29:2342"); /// if (connection != NULL) -/// sp_connection_send_command(connection, sp_command_clear()); +/// sp_udp_send_command(connection, sp_command_clear()); /// ``` #[no_mangle] pub unsafe extern "C" fn sp_udp_open( @@ -37,9 +37,9 @@ pub unsafe extern "C" fn sp_udp_open( /// # Examples /// /// ```C -/// UdpConnection connection = sp_connection_open_ipv4(172, 23, 42, 29, 2342); +/// UdpConnection connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); /// if (connection != NULL) -/// sp_connection_send_command(connection, sp_command_clear()); +/// sp_udp_send_command(connection, sp_command_clear()); /// ``` #[no_mangle] pub unsafe extern "C" fn sp_udp_open_ipv4( @@ -80,8 +80,7 @@ pub unsafe extern "C" fn sp_udp_send_packet( /// # Examples /// /// ```C -/// sp_connection_send_command(connection, sp_command_clear()); -/// sp_connection_send_command(connection, sp_command_brightness(5)); +/// sp_udp_send_command(connection, sp_command_brightness(5)); /// ``` #[no_mangle] pub unsafe extern "C" fn sp_udp_send_command( @@ -92,6 +91,27 @@ pub unsafe extern "C" fn sp_udp_send_command( unsafe { connection.as_ref().send(command) }.is_ok() } +/// Sends a [Header] to the display using the [UdpConnection]. +/// +/// returns: true in case of success +/// +/// # Examples +/// +/// ```C +/// sp_udp_send_header(connection, sp_command_brightness(5)); +/// ``` +#[no_mangle] +pub unsafe extern "C" fn sp_udp_send_header( + udp_connection: NonNull, + header: Header, +) -> bool { + let packet = Packet { + header, + payload: vec![], + }; + unsafe { udp_connection.as_ref() }.send(packet).is_ok() +} + /// Closes and deallocates a [UdpConnection]. #[no_mangle] pub unsafe extern "C" fn sp_udp_free(connection: NonNull) { diff --git a/src/lib.rs b/src/lib.rs index f90e93d..c434ab1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ //! #include "servicepoint.h" //! //! int main(void) { -//! UdpConnection *connection = sp_connection_open("172.23.42.29:2342"); +//! UdpConnection *connection = sp_udp_open("172.23.42.29:2342"); //! if (connection == NULL) //! return 1; //! @@ -17,10 +17,10 @@ //! sp_bitmap_fill(pixels, true); //! //! TypedCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed); -//! while (sp_connection_send_command(connection, sp_command_clone(command))); +//! while (sp_udp_send_command(connection, sp_command_clone(command))); //! //! sp_command_free(command); -//! sp_connection_free(connection); +//! sp_udp_free(connection); //! return 0; //! } //! ``` @@ -30,10 +30,11 @@ pub use crate::bitvec::*; pub use crate::brightness_grid::*; pub use crate::byte_slice::*; pub use crate::char_grid::*; -pub use crate::command::*; +pub use crate::commands::*; pub use crate::connection::*; pub use crate::cp437_grid::*; pub use crate::packet::*; +pub use servicepoint::CommandCode; use std::ptr::NonNull; mod bitmap; @@ -41,7 +42,7 @@ mod bitvec; mod brightness_grid; mod byte_slice; mod char_grid; -mod command; +mod commands; mod connection; mod cp437_grid; mod packet; diff --git a/src/packet.rs b/src/packet.rs index a9def67..4a30b51 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,5 +1,5 @@ use crate::{heap_drop, heap_move, heap_move_nonnull, ByteSlice}; -use servicepoint::{Header, Packet, TypedCommand}; +use servicepoint::{CommandCode, Header, Packet, TypedCommand}; use std::ptr::NonNull; /// Turns a [TypedCommand] into a [Packet]. @@ -65,7 +65,7 @@ pub unsafe extern "C" fn sp_packet_get_header( pub unsafe extern "C" fn sp_packet_get_payload( packet: NonNull, ) -> ByteSlice { - unsafe { ByteSlice::from_slice(&mut *(*packet.as_ptr()).payload) } + unsafe { ByteSlice::from_slice(&mut (*packet.as_ptr()).payload) } } /// Sets the payload of the provided packet to the provided data. @@ -87,7 +87,7 @@ pub unsafe extern "C" fn sp_packet_set_payload( #[no_mangle] pub unsafe extern "C" fn sp_packet_serialize_to( packet: NonNull, - buffer: ByteSlice, + mut buffer: ByteSlice, ) { unsafe { packet.as_ref().serialize_to(buffer.as_slice_mut()); @@ -107,3 +107,19 @@ pub unsafe extern "C" fn sp_packet_clone( pub unsafe extern "C" fn sp_packet_free(packet: NonNull) { unsafe { heap_drop(packet) } } + +#[no_mangle] +pub unsafe extern "C" fn sp_u16_to_command_code( + code: u16, + result: *mut CommandCode, +) -> bool { + match CommandCode::try_from(code) { + Ok(code) => { + unsafe { + *result = code; + } + true + } + Err(_) => false, + } +} -- 2.47.0 From a87f228c32ea3bf3160cb1fc3a39c2ce0ecc9590 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 21:56:07 +0200 Subject: [PATCH 24/25] heap_remove, sp_brightness_grid_into_packet --- include/servicepoint.h | 4 ++++ src/bitmap.rs | 6 +++--- src/brightness_grid.rs | 27 ++++++++++++++++++++++++--- src/connection.rs | 8 ++++---- src/lib.rs | 6 +++++- src/packet.rs | 4 ++-- 6 files changed, 42 insertions(+), 13 deletions(-) diff --git a/include/servicepoint.h b/include/servicepoint.h index 0a0d340..1ece5e6 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -695,6 +695,10 @@ Brightness sp_brightness_grid_get(BrightnessGrid */*notnull*/ brightness_grid, */ size_t sp_brightness_grid_height(BrightnessGrid */*notnull*/ brightness_grid); +Packet *sp_brightness_grid_into_packet(BrightnessGrid */*notnull*/ grid, + size_t x, + size_t y); + /** * Loads a [BrightnessGrid] with the specified dimensions from the provided data. * diff --git a/src/bitmap.rs b/src/bitmap.rs index f203395..71753a5 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -1,5 +1,5 @@ use crate::byte_slice::ByteSlice; -use crate::{heap_drop, heap_move, heap_move_nonnull, SPBitVec}; +use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, SPBitVec}; use servicepoint::{Bitmap, DataRef, Grid}; use std::ptr::NonNull; @@ -78,7 +78,7 @@ pub unsafe extern "C" fn sp_bitmap_from_bitvec( width: usize, bitvec: NonNull, ) -> *mut Bitmap { - let bitvec = unsafe { *Box::from_raw(bitvec.as_ptr()) }; + let bitvec = unsafe { heap_remove(bitvec) }; if let Ok(bitmap) = Bitmap::from_bitvec(width, bitvec.0) { heap_move(bitmap) } else { @@ -196,6 +196,6 @@ pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref( pub unsafe extern "C" fn sp_bitmap_into_bitvec( bitmap: NonNull, ) -> NonNull { - let bitmap = unsafe { *Box::from_raw(bitmap.as_ptr()) }; + let bitmap = unsafe { heap_remove(bitmap) }; heap_move_nonnull(SPBitVec(bitmap.into())) } diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index dcde8cf..f85602a 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -1,5 +1,8 @@ -use crate::{heap_drop, heap_move, heap_move_nonnull, ByteSlice}; -use servicepoint::{Brightness, BrightnessGrid, ByteGrid, DataRef, Grid}; +use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, ByteSlice}; +use servicepoint::{ + Brightness, BrightnessGrid, BrightnessGridCommand, ByteGrid, DataRef, Grid, + Origin, Packet, +}; use std::mem::transmute; use std::ptr::NonNull; @@ -167,5 +170,23 @@ pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( const _: () = assert!(size_of::() == 1); let data = unsafe { (*brightness_grid.as_ptr()).data_ref_mut() }; - unsafe { ByteSlice::from_slice(transmute::<&mut [Brightness], &mut [u8]>(data)) } + unsafe { + ByteSlice::from_slice(transmute::<&mut [Brightness], &mut [u8]>(data)) + } +} + +#[no_mangle] +pub unsafe extern "C" fn sp_brightness_grid_into_packet( + grid: NonNull, + x: usize, + y: usize, +) -> *mut Packet { + let grid = unsafe { heap_remove(grid) }; + match Packet::try_from(BrightnessGridCommand { + grid, + origin: Origin::new(x, y), + }) { + Ok(packet) => heap_move(packet), + Err(_) => std::ptr::null_mut(), + } } diff --git a/src/connection.rs b/src/connection.rs index eec1f43..93e0a21 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,4 +1,4 @@ -use crate::{heap_drop, heap_move}; +use crate::{heap_drop, heap_move, heap_remove}; use servicepoint::{Connection, Header, Packet, TypedCommand, UdpConnection}; use std::ffi::{c_char, CStr}; use std::net::{Ipv4Addr, SocketAddrV4}; @@ -67,8 +67,8 @@ pub unsafe extern "C" fn sp_udp_send_packet( connection: NonNull, packet: NonNull, ) -> bool { - let packet = unsafe { Box::from_raw(packet.as_ptr()) }; - unsafe { connection.as_ref().send(*packet) }.is_ok() + let packet = unsafe { heap_remove(packet) }; + unsafe { connection.as_ref().send(packet) }.is_ok() } /// Sends a [TypedCommand] to the display using the [UdpConnection]. @@ -87,7 +87,7 @@ pub unsafe extern "C" fn sp_udp_send_command( connection: NonNull, command: NonNull, ) -> bool { - let command = *unsafe { Box::from_raw(command.as_ptr()) }; + let command = unsafe { heap_remove(command) }; unsafe { connection.as_ref().send(command) }.is_ok() } diff --git a/src/lib.rs b/src/lib.rs index c434ab1..05fb009 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,5 +61,9 @@ pub(crate) fn heap_move_nonnull(x: T) -> NonNull { } pub(crate) unsafe fn heap_drop(x: NonNull) { - drop(unsafe { Box::from_raw(x.as_ptr()) }); + drop(unsafe { heap_remove(x) }); +} + +pub(crate) unsafe fn heap_remove(x: NonNull) -> T { + unsafe { *Box::from_raw(x.as_ptr()) } } diff --git a/src/packet.rs b/src/packet.rs index 4a30b51..a891ee3 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,4 +1,4 @@ -use crate::{heap_drop, heap_move, heap_move_nonnull, ByteSlice}; +use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, ByteSlice}; use servicepoint::{CommandCode, Header, Packet, TypedCommand}; use std::ptr::NonNull; @@ -10,7 +10,7 @@ use std::ptr::NonNull; pub unsafe extern "C" fn sp_packet_from_command( command: NonNull, ) -> *mut Packet { - let command = unsafe { *Box::from_raw(command.as_ptr()) }; + let command = unsafe { heap_remove(command) }; if let Ok(packet) = command.try_into() { heap_move(packet) } else { -- 2.47.0 From 3589a90385b7bf33f165fe8fb663f2798bd523d7 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 22:13:29 +0200 Subject: [PATCH 25/25] add functions to convert containers directly into packet --- example/announce.c | 6 ++-- example/brightness_tester.c | 11 ++++--- example/random_stuff.c | 9 +++--- include/servicepoint.h | 61 ++++++++++++++++++++++++++++++++++++- src/bitmap.rs | 25 ++++++++++++++- src/bitvec.rs | 28 +++++++++++++++-- src/brightness_grid.rs | 5 +++ src/char_grid.rs | 25 +++++++++++++-- src/cp437_grid.rs | 25 +++++++++++++-- src/packet.rs | 3 ++ 10 files changed, 178 insertions(+), 20 deletions(-) diff --git a/example/announce.c b/example/announce.c index 9220242..737eff5 100644 --- a/example/announce.c +++ b/example/announce.c @@ -23,8 +23,10 @@ int main(void) { sp_char_grid_set(grid, 3, 1, 'l'); sp_char_grid_set(grid, 4, 1, 'd'); - TypedCommand *command = sp_command_char_grid(0, 0, grid); - sp_udp_send_command(connection, command); + Packet *packet = sp_char_grid_into_packet(grid, 0, 0); + if (packet == NULL) + return 1; + sp_udp_send_packet(connection, packet); sp_udp_free(connection); return 0; diff --git a/example/brightness_tester.c b/example/brightness_tester.c index 93e64ce..d06d30d 100644 --- a/example/brightness_tester.c +++ b/example/brightness_tester.c @@ -8,11 +8,12 @@ int main(void) { Bitmap *all_on = sp_bitmap_new_max_sized(); sp_bitmap_fill(all_on, true); - TypedCommand *cmd = sp_command_bitmap(0, 0, all_on, COMPRESSION_CODE_UNCOMPRESSED); - if (cmd == NULL) + + Packet *packet = sp_bitmap_into_packet(all_on, 0, 0, COMPRESSION_CODE_UNCOMPRESSED); + if (packet == NULL) return -1; - sp_udp_send_command(connection, cmd); + sp_udp_send_packet(connection, packet); BrightnessGrid *grid = sp_brightness_grid_new(TILE_WIDTH, TILE_HEIGHT); @@ -21,8 +22,8 @@ int main(void) { slice.start[index] = (uint8_t) (index % ((size_t) Brightness_MAX)); } - TypedCommand *command = sp_command_brightness_grid(0, 0, grid); - sp_udp_send_command(connection, command); + packet = sp_brightness_grid_into_packet(grid, 0, 0); + sp_udp_send_packet(connection, packet); sp_udp_free(connection); return 0; diff --git a/example/random_stuff.c b/example/random_stuff.c index 80c3847..ca5a14d 100644 --- a/example/random_stuff.c +++ b/example/random_stuff.c @@ -1,3 +1,4 @@ +#include #include "servicepoint.h" int main(void) { @@ -11,14 +12,12 @@ int main(void) { sp_bitmap_fill(pixels, true); - TypedCommand *command = sp_command_bitmap(0, 0, pixels, COMPRESSION_CODE_UNCOMPRESSED); - if (command == NULL) + Packet *packet = sp_bitmap_into_packet(pixels, 0, 0, COMPRESSION_CODE_UNCOMPRESSED); + if (packet == NULL) return 1; - Packet *packet = sp_packet_from_command(command); - Header *header = sp_packet_get_header(packet); - //printf("[%d, %d, %d, %d, %d]\n", header->command_code, header->a, header->b, header->c, header->d); + printf("[%d, %d, %d, %d, %d]\n", header->command_code, header->a, header->b, header->c, header->d); sp_udp_send_packet(connection, packet); diff --git a/include/servicepoint.h b/include/servicepoint.h index 1ece5e6..77d2e36 100644 --- a/include/servicepoint.h +++ b/include/servicepoint.h @@ -455,6 +455,18 @@ size_t sp_bitmap_height(Bitmap */*notnull*/ bitmap); */ SPBitVec */*notnull*/ sp_bitmap_into_bitvec(Bitmap */*notnull*/ bitmap); +/** + * Creates a [BitmapCommand] and immediately turns that into a [Packet]. + * + * The provided [Bitmap] gets consumed. + * + * Returns NULL in case of an error. + */ +Packet *sp_bitmap_into_packet(Bitmap */*notnull*/ bitmap, + size_t x, + size_t y, + CompressionCode compression); + /** * Loads a [Bitmap] with the specified dimensions from the provided data. * @@ -580,6 +592,18 @@ void sp_bitvec_free(SPBitVec */*notnull*/ bit_vec); */ bool sp_bitvec_get(SPBitVec */*notnull*/ bit_vec, size_t index); +/** + * Creates a [BitVecCommand] and immediately turns that into a [Packet]. + * + * The provided [SPBitVec] gets consumed. + * + * Returns NULL in case of an error. + */ +Packet *sp_bitvec_into_packet(SPBitVec */*notnull*/ bitvec, + size_t offset, + BinaryOperation operation, + CompressionCode compression); + /** * Returns true if length is 0. * @@ -695,6 +719,13 @@ Brightness sp_brightness_grid_get(BrightnessGrid */*notnull*/ brightness_grid, */ size_t sp_brightness_grid_height(BrightnessGrid */*notnull*/ brightness_grid); +/** + * Creates a [BrightnessGridCommand] and immediately turns that into a [Packet]. + * + * The provided [BrightnessGrid] gets consumed. + * + * Returns NULL in case of an error. + */ Packet *sp_brightness_grid_into_packet(BrightnessGrid */*notnull*/ grid, size_t x, size_t y); @@ -818,6 +849,17 @@ uint32_t sp_char_grid_get(CharGrid */*notnull*/ char_grid, size_t x, size_t y); */ size_t sp_char_grid_height(CharGrid */*notnull*/ char_grid); +/** + * Creates a [CharGridCommand] and immediately turns that into a [Packet]. + * + * The provided [CharGrid] gets consumed. + * + * Returns NULL in case of an error. + */ +Packet *sp_char_grid_into_packet(CharGrid */*notnull*/ grid, + size_t x, + size_t y); + /** * Loads a [CharGrid] with the specified dimensions from the provided data. * @@ -1045,6 +1087,17 @@ uint8_t sp_cp437_grid_get(Cp437Grid */*notnull*/ cp437_grid, */ size_t sp_cp437_grid_height(Cp437Grid */*notnull*/ cp437_grid); +/** + * Creates a [Cp437GridCommand] and immediately turns that into a [Packet]. + * + * The provided [Cp437Grid] gets consumed. + * + * Returns NULL in case of an error. + */ +Packet *sp_cp437_grid_into_packet(Cp437Grid */*notnull*/ grid, + size_t x, + size_t y); + /** * Loads a [Cp437Grid] with the specified dimensions from the provided data. */ @@ -1156,7 +1209,13 @@ void sp_packet_set_payload(Packet */*notnull*/ packet, ByteSlice data); */ Packet *sp_packet_try_load(ByteSlice data); -bool sp_u16_to_command_code(uint16_t code, CommandCode *result); +/** + * Converts u16 into [CommandCode]. + * + * If the provided value is not valid, false is returned and result is not changed. + */ +bool sp_u16_to_command_code(uint16_t code, + CommandCode *result); /** * Closes and deallocates a [UdpConnection]. diff --git a/src/bitmap.rs b/src/bitmap.rs index 71753a5..358be48 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -1,6 +1,6 @@ use crate::byte_slice::ByteSlice; use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, SPBitVec}; -use servicepoint::{Bitmap, DataRef, Grid}; +use servicepoint::{Bitmap, BitmapCommand, CompressionCode, DataRef, Grid, Origin, Packet}; use std::ptr::NonNull; /// Creates a new [Bitmap] with the specified dimensions. @@ -199,3 +199,26 @@ pub unsafe extern "C" fn sp_bitmap_into_bitvec( let bitmap = unsafe { heap_remove(bitmap) }; heap_move_nonnull(SPBitVec(bitmap.into())) } + +/// Creates a [BitmapCommand] and immediately turns that into a [Packet]. +/// +/// The provided [Bitmap] gets consumed. +/// +/// Returns NULL in case of an error. +#[no_mangle] +pub unsafe extern "C" fn sp_bitmap_into_packet( + bitmap: NonNull, + x: usize, + y: usize, + compression: CompressionCode +) -> *mut Packet { + let bitmap = unsafe { heap_remove(bitmap) }; + match Packet::try_from(BitmapCommand { + bitmap, + origin: Origin::new(x, y), + compression, + }) { + Ok(packet) => heap_move(packet), + Err(_) => std::ptr::null_mut(), + } +} diff --git a/src/bitvec.rs b/src/bitvec.rs index e5ce720..22f7545 100644 --- a/src/bitvec.rs +++ b/src/bitvec.rs @@ -1,5 +1,5 @@ -use crate::{heap_drop, heap_move_nonnull, ByteSlice}; -use servicepoint::BitVecU8Msb0; +use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, ByteSlice}; +use servicepoint::{BinaryOperation, BitVecCommand, BitVecU8Msb0, CompressionCode, Packet}; use std::ptr::NonNull; /// A vector of bits @@ -146,3 +146,27 @@ pub unsafe extern "C" fn sp_bitvec_unsafe_data_ref( ) -> ByteSlice { unsafe { ByteSlice::from_slice((*bit_vec.as_ptr()).0.as_raw_mut_slice()) } } + +/// Creates a [BitVecCommand] and immediately turns that into a [Packet]. +/// +/// The provided [SPBitVec] gets consumed. +/// +/// Returns NULL in case of an error. +#[no_mangle] +pub unsafe extern "C" fn sp_bitvec_into_packet( + bitvec: NonNull, + offset: usize, + operation: BinaryOperation, + compression: CompressionCode +) -> *mut Packet { + let bitvec = unsafe { heap_remove(bitvec) }.0; + match Packet::try_from(BitVecCommand { + bitvec, + offset, + operation, + compression, + }) { + Ok(packet) => heap_move(packet), + Err(_) => std::ptr::null_mut(), + } +} diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index f85602a..1099be0 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -175,6 +175,11 @@ pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( } } +/// Creates a [BrightnessGridCommand] and immediately turns that into a [Packet]. +/// +/// The provided [BrightnessGrid] gets consumed. +/// +/// Returns NULL in case of an error. #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_into_packet( grid: NonNull, diff --git a/src/char_grid.rs b/src/char_grid.rs index cdcc4b5..bfb2585 100644 --- a/src/char_grid.rs +++ b/src/char_grid.rs @@ -1,5 +1,5 @@ -use crate::{heap_drop, heap_move, heap_move_nonnull, ByteSlice}; -use servicepoint::{CharGrid, Grid}; +use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, ByteSlice}; +use servicepoint::{CharGrid, CharGridCommand, Grid, Origin, Packet}; use std::ptr::NonNull; /// Creates a new [CharGrid] with the specified dimensions. @@ -132,3 +132,24 @@ pub unsafe extern "C" fn sp_char_grid_height( ) -> usize { unsafe { char_grid.as_ref().height() } } + +/// Creates a [CharGridCommand] and immediately turns that into a [Packet]. +/// +/// The provided [CharGrid] gets consumed. +/// +/// Returns NULL in case of an error. +#[no_mangle] +pub unsafe extern "C" fn sp_char_grid_into_packet( + grid: NonNull, + x: usize, + y: usize, +) -> *mut Packet { + let grid = unsafe { heap_remove(grid) }; + match Packet::try_from(CharGridCommand { + grid, + origin: Origin::new(x, y), + }) { + Ok(packet) => heap_move(packet), + Err(_) => std::ptr::null_mut(), + } +} diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index e22a0ed..01aeb1e 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -1,5 +1,5 @@ -use crate::{heap_drop, heap_move, heap_move_nonnull, ByteSlice}; -use servicepoint::{Cp437Grid, DataRef, Grid}; +use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, ByteSlice}; +use servicepoint::{Cp437Grid, Cp437GridCommand, DataRef, Grid, Origin, Packet}; use std::ptr::NonNull; /// Creates a new [Cp437Grid] with the specified dimensions. @@ -132,3 +132,24 @@ pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref( ) -> ByteSlice { unsafe { ByteSlice::from_slice((*cp437_grid.as_ptr()).data_ref_mut()) } } + +/// Creates a [Cp437GridCommand] and immediately turns that into a [Packet]. +/// +/// The provided [Cp437Grid] gets consumed. +/// +/// Returns NULL in case of an error. +#[no_mangle] +pub unsafe extern "C" fn sp_cp437_grid_into_packet( + grid: NonNull, + x: usize, + y: usize, +) -> *mut Packet { + let grid = unsafe { heap_remove(grid) }; + match Packet::try_from(Cp437GridCommand { + grid, + origin: Origin::new(x, y), + }) { + Ok(packet) => heap_move(packet), + Err(_) => std::ptr::null_mut(), + } +} diff --git a/src/packet.rs b/src/packet.rs index a891ee3..d8b1579 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -108,6 +108,9 @@ pub unsafe extern "C" fn sp_packet_free(packet: NonNull) { unsafe { heap_drop(packet) } } +/// Converts u16 into [CommandCode]. +/// +/// If the provided value is not valid, false is returned and result is not changed. #[no_mangle] pub unsafe extern "C" fn sp_u16_to_command_code( code: u16, -- 2.47.0