From 6f40441dfe304fbdcb3ed3289a97e0ccff9e8d50 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 10:54:47 +0200 Subject: [PATCH 1/6] wip remove newtypes --- Cargo.lock | 4 +- build.rs | 28 +- cbindgen.toml | 8 +- examples/lang_c/Cargo.lock | 4 +- examples/lang_c/Makefile | 2 +- examples/lang_c/include/servicepoint.h | 426 +++++++++++++++---------- examples/lang_c/src/main.c | 6 +- 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 ++-- 15 files changed, 499 insertions(+), 432 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/examples/lang_c/Cargo.lock b/examples/lang_c/Cargo.lock index 9435574..a03ba46 100644 --- a/examples/lang_c/Cargo.lock +++ b/examples/lang_c/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" @@ -423,7 +423,7 @@ dependencies = [ [[package]] name = "servicepoint" version = "0.13.2" -source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#75d24f658764dea251e28c7067446f3ccfbb89b0" +source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#aafa2bc9f91c3ae7d88607bf545d9665d50fc0db" dependencies = [ "bitvec", "bzip2", 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/examples/lang_c/include/servicepoint.h b/examples/lang_c/include/servicepoint.h index ca235ca..46fe3b8 100644 --- a/examples/lang_c/include/servicepoint.h +++ b/examples/lang_c/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/examples/lang_c/src/main.c b/examples/lang_c/src/main.c index 6a4b30e..73f4726 100644 --- a/examples/lang_c/src/main.c +++ b/examples/lang_c/src/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/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) } } From fed12a4c1200c873130e1280245af407212e045b Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 12:05:19 +0200 Subject: [PATCH 2/6] functions for manipulating packets --- Cargo.lock | 2 +- examples/lang_c/Cargo.lock | 2 +- examples/lang_c/include/servicepoint.h | 8 +++++- examples/lang_c/src/main.c | 7 ++++- 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 ++++++++++++++++++++------ 10 files changed, 82 insertions(+), 38 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/examples/lang_c/Cargo.lock b/examples/lang_c/Cargo.lock index a03ba46..1cd1a29 100644 --- a/examples/lang_c/Cargo.lock +++ b/examples/lang_c/Cargo.lock @@ -423,7 +423,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/examples/lang_c/include/servicepoint.h b/examples/lang_c/include/servicepoint.h index 46fe3b8..1de6cc5 100644 --- a/examples/lang_c/include/servicepoint.h +++ b/examples/lang_c/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/examples/lang_c/src/main.c b/examples/lang_c/src/main.c index 73f4726..388218e 100644 --- a/examples/lang_c/src/main.c +++ b/examples/lang_c/src/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/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]. From 99c1884ddcc1a40dfaa9d47c7ca964063acdd89e Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 12:08:49 +0200 Subject: [PATCH 3/6] wip remove newtypes --- examples/lang_c/include/servicepoint.h | 46 +++++---------- src/command.rs | 8 +-- src/cp437_grid.rs | 78 ++++++++++++-------------- 3 files changed, 54 insertions(+), 78 deletions(-) diff --git a/examples/lang_c/include/servicepoint.h b/examples/lang_c/include/servicepoint.h index 1de6cc5..691fffe 100644 --- a/examples/lang_c/include/servicepoint.h +++ b/examples/lang_c/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()) } } From 992c30b2bce11e9063d651e317ef27f1e156c3aa Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 12:12:51 +0200 Subject: [PATCH 4/6] re-export constants from base lib --- cbindgen.toml | 1 + examples/lang_c/include/servicepoint.h | 111 ++++++++++++++++++------- examples/lang_c/src/main.c | 4 +- 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/examples/lang_c/include/servicepoint.h b/examples/lang_c/include/servicepoint.h index 691fffe..63c1179 100644 --- a/examples/lang_c/include/servicepoint.h +++ b/examples/lang_c/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/examples/lang_c/src/main.c b/examples/lang_c/src/main.c index 388218e..80a1756 100644 --- a/examples/lang_c/src/main.c +++ b/examples/lang_c/src/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/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(); From df9c04939ddb5b35751775dd2b743d3f44c6f60c Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 12:19:10 +0200 Subject: [PATCH 5/6] add /*notnull*/ comments in header --- cbindgen.toml | 3 + examples/lang_c/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/examples/lang_c/include/servicepoint.h b/examples/lang_c/include/servicepoint.h index 63c1179..4e7843f 100644 --- a/examples/lang_c/include/servicepoint.h +++ b/examples/lang_c/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); From 6dcd26d1c1ddf4b87d687209efbb491cc1d26074 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sat, 12 Apr 2025 12:33:36 +0200 Subject: [PATCH 6/6] use NotNull for parameters --- build.rs | 4 +- examples/lang_c/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/examples/lang_c/include/servicepoint.h b/examples/lang_c/include/servicepoint.h index 4e7843f..4a0af95 100644 --- a/examples/lang_c/include/servicepoint.h +++ b/examples/lang_c/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()) } }