diff --git a/crates/servicepoint/src/connection.rs b/crates/servicepoint/src/connection.rs index 76945c3..9237006 100644 --- a/crates/servicepoint/src/connection.rs +++ b/crates/servicepoint/src/connection.rs @@ -9,38 +9,24 @@ use crate::Packet; /// /// # Examples /// ```rust -/// # use servicepoint::{Command, Connection}; -/// let connection = servicepoint::UdpConnection::open("172.23.42.29:2342") +/// let connection = servicepoint::Connection::open("172.23.42.29:2342") /// .expect("connection failed"); -/// connection.send(Command::Clear); +/// connection.send(servicepoint::Command::Clear) +/// .expect("send failed"); /// ``` -pub trait Connection { - /// Send something packet-like to the display. Usually this is in the form of a Command. - /// - /// # Arguments - /// - /// - `packet`: the packet-like to send - /// - /// returns: true if packet was sent, otherwise false - /// - /// # Examples - /// - /// ```rust - /// # use servicepoint::{Command, Connection }; - /// # let connection = servicepoint::UdpConnection::open("172.23.42.29:2342") - /// # .expect("connection failed"); - /// // turn off all pixels on display - /// connection.send(Command::Clear); - /// ``` - fn send(&self, packet: impl Into) -> bool; +pub enum Connection { + /// A real connection using the UDP protocol + Udp(UdpSocket), + /// A fake connection for testing that does not actually send anything + Fake, } -/// A real connection using the UDP protocol -pub struct UdpConnection { - socket: UdpSocket, +#[derive(Debug)] +pub enum SendError { + IoError(std::io::Error), } -impl UdpConnection { +impl Connection { /// Open a new UDP socket and connect to the provided host. /// /// Note that this is UDP, which means that the open call can succeed even if the display is unreachable. @@ -58,24 +44,37 @@ impl UdpConnection { info!("connecting to {addr:?}"); let socket = UdpSocket::bind("0.0.0.0:0")?; socket.connect(addr)?; - Ok(Self { socket }) + Ok(Self::Udp(socket)) } -} -impl Connection for UdpConnection { - fn send(&self, packet: impl Into) -> bool { + /// Send something packet-like to the display. Usually this is in the form of a Command. + /// + /// # Arguments + /// + /// - `packet`: the packet-like to send + /// + /// returns: true if packet was sent, otherwise false + /// + /// # Examples + /// + /// ```rust + /// # let connection = servicepoint::Connection::Fake; + /// // turn off all pixels on display + /// connection.send(servicepoint::Command::Clear) + /// .expect("send failed"); + /// ``` + pub fn send(&self, packet: impl Into) -> Result<(), SendError> { let packet = packet.into(); debug!("sending {packet:?}"); let data: Vec = packet.into(); - self.socket.send(&data).is_err() - } -} - -/// A fake connection for testing that does not actually send anything -pub struct NoopConnection; - -impl Connection for NoopConnection { - fn send(&self, packet: impl Into) -> bool { - true + match self { + Connection::Udp(socket) => { + socket + .send(&data) + .map_err(move |io_err| SendError::IoError(io_err)) + .map(move |_| ()) // ignore Ok value + } + Connection::Fake => Ok(()), + } } } diff --git a/crates/servicepoint/src/lib.rs b/crates/servicepoint/src/lib.rs index a8956bb..d71e1fa 100644 --- a/crates/servicepoint/src/lib.rs +++ b/crates/servicepoint/src/lib.rs @@ -39,7 +39,7 @@ use bitvec::prelude::{BitVec, Msb0}; pub use crate::brightness::{Brightness, BrightnessGrid}; pub use crate::command::{Command, Cp437Grid, Offset}; pub use crate::compression_code::CompressionCode; -pub use crate::connection::{Connection, UdpConnection}; +pub use crate::connection::Connection; pub use crate::data_ref::DataRef; pub use crate::grid::Grid; pub use crate::origin::{Origin, Pixels, Tiles}; diff --git a/crates/servicepoint_binding_c/cbindgen.toml b/crates/servicepoint_binding_c/cbindgen.toml index c65f551..1c363cf 100644 --- a/crates/servicepoint_binding_c/cbindgen.toml +++ b/crates/servicepoint_binding_c/cbindgen.toml @@ -18,19 +18,8 @@ style = "both" sort_by = "Name" usize_is_size_t = true -[defines] -#"feature = compression_zlib" = "SP_FEATURE_compression_zlib" -#"feature = compression_bzip2" = "SP_FEATURE_compression_bzip2" -#"feature = compression_lzma" = "SP_FEATURE_compression_lzma" -#"feature = compression_zstd" = "SP_FEATURE_compression_zstd" - -[export] -prefix = "sp_" - [parse] -parse_deps = true -include = ["servicepoint"] -extra_bindings = ["servicepoint"] +parse_deps = false [parse.expand] all_features = true diff --git a/crates/servicepoint_binding_c/examples/lang_c/Makefile b/crates/servicepoint_binding_c/examples/lang_c/Makefile index 86cf49c..6b15722 100644 --- a/crates/servicepoint_binding_c/examples/lang_c/Makefile +++ b/crates/servicepoint_binding_c/examples/lang_c/Makefile @@ -6,8 +6,9 @@ REPO_ROOT := $(THIS_DIR)/../../../.. build: out/lang_c clean: - rm -r out - rm include/servicepoint.h + rm -r out || true + rm include/servicepoint.h || true + cargo clean run: out/lang_c out/lang_c diff --git a/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h b/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h index eaf2e40..960353e 100644 --- a/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h +++ b/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h @@ -9,78 +9,37 @@ /** * pixel count on whole screen */ -#define sp_PIXEL_COUNT (sp_PIXEL_WIDTH * sp_PIXEL_HEIGHT) +#define SP_PIXEL_COUNT (SP_PIXEL_WIDTH * SP_PIXEL_HEIGHT) /** * Display height in pixels - * - * # Examples - * - * ```rust - * # use servicepoint::{PIXEL_HEIGHT, PIXEL_WIDTH, PixelGrid}; - * let grid = PixelGrid::new(PIXEL_WIDTH, PIXEL_HEIGHT); - * ``` */ -#define sp_PIXEL_HEIGHT (sp_TILE_HEIGHT * sp_TILE_SIZE) +#define SP_PIXEL_HEIGHT (SP_TILE_HEIGHT * SP_TILE_SIZE) /** * Display width in pixels - * - * # Examples - * - * ```rust - * # use servicepoint::{PIXEL_HEIGHT, PIXEL_WIDTH, PixelGrid}; - * let grid = PixelGrid::new(PIXEL_WIDTH, PIXEL_HEIGHT); - * ``` */ -#define sp_PIXEL_WIDTH (sp_TILE_WIDTH * sp_TILE_SIZE) +#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 SP_TILE_HEIGHT 20 /** * size of a single tile in one dimension */ -#define sp_TILE_SIZE 8 +#define SP_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 SP_TILE_WIDTH 56 /** - * Specifies the kind of compression to use. Availability depends on features. - * - * # Examples - * - * ```rust - * # use servicepoint::{Command, CompressionCode, Origin, PixelGrid}; - * // create command without payload compression - * # let pixels = PixelGrid::max_sized(); - * _ = Command::BitmapLinearWin(Origin::new(0, 0), pixels, CompressionCode::Uncompressed); - * - * // create command with payload compressed with lzma and appropriate header flags - * # let pixels = PixelGrid::max_sized(); - * _ = Command::BitmapLinearWin(Origin::new(0, 0), pixels, CompressionCode::Lzma); - * ``` + * Specifies the kind of compression to use. */ -enum sp_CompressionCode +enum SPCompressionCode #ifdef __cplusplus : uint16_t #endif // __cplusplus @@ -107,75 +66,103 @@ enum sp_CompressionCode Zstd = 31347, }; #ifndef __cplusplus -typedef uint16_t sp_CompressionCode; +typedef uint16_t SPCompressionCode; #endif // __cplusplus /** - * A display brightness value, checked for correct value range + * A vector of bits * * # Examples - * - * ``` - * # use servicepoint::{Brightness, Command, Connection}; - * let b = Brightness::MAX; - * let val: u8 = b.into(); - * - * let b = Brightness::try_from(7).unwrap(); - * # let connection = Connection::open("127.0.0.1:2342").unwrap(); - * let result = connection.send(Command::Brightness(b)); + * ```C + * SPBitVec vec = sp_bit_vec_new(8); + * sp_bit_vec_set(vec, 5, true); + * sp_bit_vec_dealloc(vec); * ``` */ -typedef struct sp_Brightness sp_Brightness; +typedef struct SPBitVec SPBitVec; /** - * A vector of bits + * 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_dealloc(connection); + * ``` */ -typedef struct sp_CBitVec sp_CBitVec; - -/** - * C-wrapper for grid containing brightness values. - */ -typedef struct sp_CBrightnessGrid sp_CBrightnessGrid; +typedef struct SPBrightnessGrid SPBrightnessGrid; /** * A low-level display command. * * This struct and associated functions implement the UDP protocol for the display. * - * To send a `CCommand`, use a `Connection`. - */ -typedef struct sp_CCommand sp_CCommand; - -/** - * A C-wrapper for grid containing codepage 437 characters. + * To send a `CCommand`, use a `CConnection`. * - * The encoding is currently not enforced. + * # Examples + * + * ```C + * sp_connection_send(connection, sp_command_clear()); + * sp_connection_send(connection, sp_command_brightness(5)); + * ``` */ -typedef struct sp_CCp437Grid sp_CCp437Grid; +typedef struct SPCommand SPCommand; /** * A connection to the display. * * # Examples - * ```rust - * # use servicepoint::Command; - * let connection = servicepoint::Connection::open("172.23.42.29:2342") - * .expect("connection failed"); - * connection.send(Command::Clear) - * .expect("send failed"); + * + * ```C + * CConnection connection = sp_connection_open("172.23.42.29:2342"); + * if (connection != NULL) + * sp_connection_send(connection, sp_command_clear()); * ``` */ -typedef struct sp_Connection sp_Connection; +typedef struct SPConnection SPConnection; /** - * The raw packet. Should probably not be used directly. + * 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_dealloc(grid); + * ``` */ -typedef struct sp_Packet sp_Packet; +typedef struct SPCp437Grid SPCp437Grid; /** - * A grid of pixels stored in packed bytes. + * The raw packet */ -typedef struct sp_PixelGrid sp_PixelGrid; +typedef struct SPPacket SPPacket; + +/** + * A grid of pixels. + * + * # Examples + * + * ```C + * Cp437Grid grid = sp_pixel_grid_new(8, 3); + * sp_pixel_grid_fill(grid, true); + * sp_pixel_grid_set(grid, 0, 0, false); + * sp_pixel_grid_dealloc(grid); + * ``` + */ +typedef struct SPPixelGrid SPPixelGrid; /** * Represents a span of memory (`&mut [u8]` ) as a struct usable by C code. @@ -188,7 +175,7 @@ typedef struct sp_PixelGrid sp_PixelGrid; * - the lifetime of the `CByteSlice` does not outlive the memory it points to, as described in * the function returning this type. */ -typedef struct sp_CByteSlice { +typedef struct SPByteSlice { /** * The start address of the memory */ @@ -197,16 +184,12 @@ typedef struct sp_CByteSlice { * The amount of memory in bytes */ size_t length; -} sp_CByteSlice; +} SPByteSlice; /** - * Type alias for documenting the meaning of the u16 in enum values + * Type alias for documenting the meaning of the variable in enum values */ -typedef size_t sp_Offset; - - - - +typedef size_t SPOffset; #ifdef __cplusplus extern "C" { @@ -224,7 +207,7 @@ extern "C" { * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bit_vec_dealloc`. */ -struct sp_CBitVec *sp_bit_vec_clone(const struct sp_CBitVec *this_); +struct SPBitVec *sp_bit_vec_clone(const struct SPBitVec *this_); /** * Deallocates a `BitVec`. @@ -237,7 +220,7 @@ struct sp_CBitVec *sp_bit_vec_clone(const struct sp_CBitVec *this_); * - `this` is not used concurrently or after this call * - `this` was not passed to another consuming function, e.g. to create a `Command` */ -void sp_bit_vec_dealloc(struct sp_CBitVec *this_); +void sp_bit_vec_dealloc(struct SPBitVec *this_); /** * Sets the value of all bits in the `BitVec`. @@ -253,7 +236,7 @@ void sp_bit_vec_dealloc(struct sp_CBitVec *this_); * - `this` points to a valid `BitVec` * - `this` is not written to or read from concurrently */ -void sp_bit_vec_fill(struct sp_CBitVec *this_, bool value); +void sp_bit_vec_fill(struct SPBitVec *this_, bool value); /** * Gets the value of a bit from the `BitVec`. @@ -276,7 +259,7 @@ void sp_bit_vec_fill(struct sp_CBitVec *this_, bool value); * - `this` points to a valid `BitVec` * - `this` is not written to concurrently */ -bool sp_bit_vec_get(const struct sp_CBitVec *this_, size_t index); +bool sp_bit_vec_get(const struct SPBitVec *this_, size_t index); /** * Returns true if length is 0. @@ -287,7 +270,7 @@ bool sp_bit_vec_get(const struct sp_CBitVec *this_, size_t index); * * - `this` points to a valid `BitVec` */ -bool sp_bit_vec_is_empty(const struct sp_CBitVec *this_); +bool sp_bit_vec_is_empty(const struct SPBitVec *this_); /** * Gets the length of the `BitVec` in bits. @@ -298,7 +281,7 @@ bool sp_bit_vec_is_empty(const struct sp_CBitVec *this_); * * - `this` points to a valid `BitVec` */ -size_t sp_bit_vec_len(const struct sp_CBitVec *this_); +size_t sp_bit_vec_len(const struct SPBitVec *this_); /** * Interpret the data as a series of bits and load then into a new `BitVec` instance. @@ -312,8 +295,8 @@ size_t sp_bit_vec_len(const struct sp_CBitVec *this_); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bit_vec_dealloc`. */ -struct sp_CBitVec *sp_bit_vec_load(const uint8_t *data, - size_t data_length); +struct SPBitVec *sp_bit_vec_load(const uint8_t *data, + size_t data_length); /** * Creates a new `BitVec` instance. @@ -335,7 +318,7 @@ struct sp_CBitVec *sp_bit_vec_load(const uint8_t *data, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_bit_vec_dealloc`. */ -struct sp_CBitVec *sp_bit_vec_new(size_t size); +struct SPBitVec *sp_bit_vec_new(size_t size); /** * Sets the value of a bit in the `BitVec`. @@ -359,7 +342,7 @@ struct sp_CBitVec *sp_bit_vec_new(size_t size); * - `this` points to a valid `BitVec` * - `this` is not written to or read from concurrently */ -void sp_bit_vec_set(struct sp_CBitVec *this_, size_t index, bool value); +void sp_bit_vec_set(struct SPBitVec *this_, size_t index, bool value); /** * Gets an unsafe reference to the data of the `BitVec` instance. @@ -372,7 +355,7 @@ void sp_bit_vec_set(struct sp_CBitVec *this_, size_t index, bool value); * - the returned memory range is never accessed after the passed `BitVec` has been freed * - the returned memory range is never accessed concurrently, either via the `BitVec` or directly */ -struct sp_CByteSlice sp_bit_vec_unsafe_data_ref(struct sp_CBitVec *this_); +struct SPByteSlice sp_bit_vec_unsafe_data_ref(struct SPBitVec *this_); /** * Clones a `BrightnessGrid`. @@ -386,7 +369,7 @@ struct sp_CByteSlice sp_bit_vec_unsafe_data_ref(struct sp_CBitVec *this_); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_brightness_grid_dealloc`. */ -struct sp_CBrightnessGrid *sp_brightness_grid_clone(const struct sp_CBrightnessGrid *this_); +struct SPBrightnessGrid *sp_brightness_grid_clone(const struct SPBrightnessGrid *this_); /** * Deallocates a `BrightnessGrid`. @@ -399,7 +382,7 @@ struct sp_CBrightnessGrid *sp_brightness_grid_clone(const struct sp_CBrightnessG * - `this` is not used concurrently or after this call * - `this` was not passed to another consuming function, e.g. to create a `Command` */ -void sp_brightness_grid_dealloc(struct sp_CBrightnessGrid *this_); +void sp_brightness_grid_dealloc(struct SPBrightnessGrid *this_); /** * Sets the value of all cells in the `BrightnessGrid`. @@ -420,7 +403,7 @@ void sp_brightness_grid_dealloc(struct sp_CBrightnessGrid *this_); * - `this` points to a valid `BrightnessGrid` * - `this` is not written to or read from concurrently */ -void sp_brightness_grid_fill(struct sp_CBrightnessGrid *this_, uint8_t value); +void sp_brightness_grid_fill(struct SPBrightnessGrid *this_, uint8_t value); /** * Gets the current value at the specified position. @@ -441,7 +424,7 @@ void sp_brightness_grid_fill(struct sp_CBrightnessGrid *this_, uint8_t value); * - `this` points to a valid `BrightnessGrid` * - `this` is not written to concurrently */ -uint8_t sp_brightness_grid_get(const struct sp_CBrightnessGrid *this_, +uint8_t sp_brightness_grid_get(const struct SPBrightnessGrid *this_, size_t x, size_t y); @@ -458,7 +441,7 @@ uint8_t sp_brightness_grid_get(const struct sp_CBrightnessGrid *this_, * * - `this` points to a valid `BrightnessGrid` */ -size_t sp_brightness_grid_height(const struct sp_CBrightnessGrid *this_); +size_t sp_brightness_grid_height(const struct SPBrightnessGrid *this_); /** * Loads a `BrightnessGrid` with the specified dimensions from the provided data. @@ -476,10 +459,10 @@ size_t sp_brightness_grid_height(const struct sp_CBrightnessGrid *this_); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_brightness_grid_dealloc`. */ -struct sp_CBrightnessGrid *sp_brightness_grid_load(size_t width, - size_t height, - const uint8_t *data, - size_t data_length); +struct SPBrightnessGrid *sp_brightness_grid_load(size_t width, + size_t height, + const uint8_t *data, + size_t data_length); /** * Creates a new `BrightnessGrid` with the specified dimensions. @@ -493,8 +476,8 @@ struct sp_CBrightnessGrid *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_dealloc`. */ -struct sp_CBrightnessGrid *sp_brightness_grid_new(size_t width, - size_t height); +struct SPBrightnessGrid *sp_brightness_grid_new(size_t width, + size_t height); /** * Sets the value of the specified position in the `BrightnessGrid`. @@ -519,7 +502,7 @@ struct sp_CBrightnessGrid *sp_brightness_grid_new(size_t width, * - `this` points to a valid `BitVec` * - `this` is not written to or read from concurrently */ -void sp_brightness_grid_set(struct sp_CBrightnessGrid *this_, +void sp_brightness_grid_set(struct SPBrightnessGrid *this_, size_t x, size_t y, uint8_t value); @@ -535,7 +518,7 @@ void sp_brightness_grid_set(struct sp_CBrightnessGrid *this_, * - the returned memory range is never accessed after the passed `BrightnessGrid` has been freed * - the returned memory range is never accessed concurrently, either via the `BrightnessGrid` or directly */ -struct sp_CByteSlice sp_brightness_grid_unsafe_data_ref(struct sp_CBrightnessGrid *this_); +struct SPByteSlice sp_brightness_grid_unsafe_data_ref(struct SPBrightnessGrid *this_); /** * Gets the width of the `BrightnessGrid` instance. @@ -550,7 +533,7 @@ struct sp_CByteSlice sp_brightness_grid_unsafe_data_ref(struct sp_CBrightnessGri * * - `this` points to a valid `BrightnessGrid` */ -size_t sp_brightness_grid_width(const struct sp_CBrightnessGrid *this_); +size_t sp_brightness_grid_width(const struct SPBrightnessGrid *this_); /** * Allocates a new `Command::BitmapLinear` instance. @@ -566,9 +549,9 @@ size_t sp_brightness_grid_width(const struct sp_CBrightnessGrid *this_); * - the returned `Command` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ -struct sp_CCommand *sp_command_bitmap_linear(sp_Offset offset, - struct sp_CBitVec *bit_vec, - sp_CompressionCode compression); +struct SPCommand *sp_command_bitmap_linear(SPOffset offset, + struct SPBitVec *bit_vec, + SPCompressionCode compression); /** * Allocates a new `Command::BitmapLinearAnd` instance. @@ -584,9 +567,9 @@ struct sp_CCommand *sp_command_bitmap_linear(sp_Offset offset, * - the returned `Command` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ -struct sp_CCommand *sp_command_bitmap_linear_and(sp_Offset offset, - struct sp_CBitVec *bit_vec, - sp_CompressionCode compression); +struct SPCommand *sp_command_bitmap_linear_and(SPOffset offset, + struct SPBitVec *bit_vec, + SPCompressionCode compression); /** * Allocates a new `Command::BitmapLinearOr` instance. @@ -602,9 +585,9 @@ struct sp_CCommand *sp_command_bitmap_linear_and(sp_Offset offset, * - the returned `Command` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ -struct sp_CCommand *sp_command_bitmap_linear_or(sp_Offset offset, - struct sp_CBitVec *bit_vec, - sp_CompressionCode compression); +struct SPCommand *sp_command_bitmap_linear_or(SPOffset offset, + struct SPBitVec *bit_vec, + SPCompressionCode compression); /** * Allocates a new `Command::BitmapLinearWin` instance. @@ -620,10 +603,10 @@ struct sp_CCommand *sp_command_bitmap_linear_or(sp_Offset offset, * - the returned `Command` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ -struct sp_CCommand *sp_command_bitmap_linear_win(size_t x, - size_t y, - struct sp_PixelGrid *pixel_grid, - sp_CompressionCode compression_code); +struct SPCommand *sp_command_bitmap_linear_win(size_t x, + size_t y, + struct SPPixelGrid *pixel_grid, + SPCompressionCode compression_code); /** * Allocates a new `Command::BitmapLinearXor` instance. @@ -639,9 +622,9 @@ struct sp_CCommand *sp_command_bitmap_linear_win(size_t x, * - the returned `Command` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ -struct sp_CCommand *sp_command_bitmap_linear_xor(sp_Offset offset, - struct sp_CBitVec *bit_vec, - sp_CompressionCode compression); +struct SPCommand *sp_command_bitmap_linear_xor(SPOffset offset, + struct SPBitVec *bit_vec, + SPCompressionCode compression); /** * Allocates a new `Command::Brightness` instance for setting the brightness of all tiles to the @@ -655,27 +638,27 @@ struct sp_CCommand *sp_command_bitmap_linear_xor(sp_Offset offset, * * The caller has to make sure that: * - * - the returned `Command` instance is freed in some way, either by using a consuming function or + * - the returned `SPCommand` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ -struct sp_CCommand *sp_command_brightness(uint8_t brightness); +struct SPCommand *sp_command_brightness(uint8_t brightness); /** * Allocates a new `Command::CharBrightness` instance. - * The passed `ByteGrid` gets consumed. + * The passed `SPBrightnessGrid` gets consumed. * * # Safety * * The caller has to make sure that: * - * - `byte_grid` points to a valid instance of `ByteGrid` - * - `byte_grid` is not used concurrently or after this call + * - `grid` points to a valid instance of `SPBrightnessGrid` + * - `grid` is not used concurrently or after this call * - the returned `Command` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ -struct sp_CCommand *sp_command_char_brightness(size_t x, - size_t y, - struct sp_CBrightnessGrid *byte_grid); +struct SPCommand *sp_command_char_brightness(size_t x, + size_t y, + struct SPBrightnessGrid *grid); /** * Allocates a new `Command::Clear` instance. @@ -687,7 +670,7 @@ struct sp_CCommand *sp_command_char_brightness(size_t x, * - the returned `Command` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ -struct sp_CCommand *sp_command_clear(void); +struct SPCommand *sp_command_clear(void); /** * Clones a `Command` instance. @@ -701,7 +684,7 @@ struct sp_CCommand *sp_command_clear(void); * - the returned `Command` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ -struct sp_CCommand *sp_command_clone(const struct sp_CCommand *original); +struct SPCommand *sp_command_clone(const struct SPCommand *original); /** * Allocates a new `Command::Cp437Data` instance. @@ -716,9 +699,9 @@ struct sp_CCommand *sp_command_clone(const struct sp_CCommand *original); * - the returned `Command` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ -struct sp_CCommand *sp_command_cp437_data(size_t x, - size_t y, - struct sp_CCp437Grid *byte_grid); +struct SPCommand *sp_command_cp437_data(size_t x, + size_t y, + struct SPCp437Grid *byte_grid); /** * Deallocates a `Command`. @@ -731,7 +714,7 @@ struct sp_CCommand *sp_command_cp437_data(size_t x, * - `this` is not used concurrently or after this call * - `this` was not passed to another consuming function, e.g. to create a `Packet` */ -void sp_command_dealloc(struct sp_CCommand *ptr); +void sp_command_dealloc(struct SPCommand *ptr); /** * Allocates a new `Command::FadeOut` instance. @@ -743,7 +726,7 @@ void sp_command_dealloc(struct sp_CCommand *ptr); * - the returned `Command` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ -struct sp_CCommand *sp_command_fade_out(void); +struct SPCommand *sp_command_fade_out(void); /** * Allocates a new `Command::HardReset` instance. @@ -755,7 +738,7 @@ struct sp_CCommand *sp_command_fade_out(void); * - the returned `Command` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ -struct sp_CCommand *sp_command_hard_reset(void); +struct SPCommand *sp_command_hard_reset(void); /** * Tries to turn a `Packet` into a `Command`. The packet is deallocated in the process. @@ -772,7 +755,7 @@ struct sp_CCommand *sp_command_hard_reset(void); * - the returned `Command` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ -struct sp_CCommand *sp_command_try_from_packet(struct sp_Packet *packet); +struct SPCommand *sp_command_try_from_packet(struct SPPacket *packet); /** * Closes and deallocates a `Connection`. @@ -784,7 +767,7 @@ struct sp_CCommand *sp_command_try_from_packet(struct sp_Packet *packet); * - `this` points to a valid `Connection` * - `this` is not used concurrently or after this call */ -void sp_connection_dealloc(struct sp_Connection *ptr); +void sp_connection_dealloc(struct SPConnection *ptr); /** * Creates a new instance of `Connection`. @@ -802,7 +785,7 @@ void sp_connection_dealloc(struct sp_Connection *ptr); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_connection_dealloc`. */ -struct sp_Connection *sp_connection_open(const char *host); +struct SPConnection *sp_connection_open(const char *host); /** * Sends a `Packet` to the display using the `Connection`. @@ -818,8 +801,8 @@ struct sp_Connection *sp_connection_open(const char *host); * - `packet` points to a valid instance of `Packet` * - `packet` is not used concurrently or after this call */ -bool sp_connection_send(const struct sp_Connection *connection, - struct sp_Packet *packet); +bool sp_connection_send(const struct SPConnection *connection, + struct SPPacket *packet); /** * Clones a `Cp437Grid`. @@ -833,7 +816,7 @@ bool sp_connection_send(const struct sp_Connection *connection, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_cp437_grid_dealloc`. */ -struct sp_CCp437Grid *sp_cp437_grid_clone(const struct sp_CCp437Grid *this_); +struct SPCp437Grid *sp_cp437_grid_clone(const struct SPCp437Grid *this_); /** * Deallocates a `Cp437Grid`. @@ -846,7 +829,7 @@ struct sp_CCp437Grid *sp_cp437_grid_clone(const struct sp_CCp437Grid *this_); * - `this` is not used concurrently or after this call * - `this` was not passed to another consuming function, e.g. to create a `Command` */ -void sp_cp437_grid_dealloc(struct sp_CCp437Grid *this_); +void sp_cp437_grid_dealloc(struct SPCp437Grid *this_); /** * Sets the value of all cells in the `Cp437Grid`. @@ -863,7 +846,7 @@ void sp_cp437_grid_dealloc(struct sp_CCp437Grid *this_); * - `this` points to a valid `Cp437Grid` * - `this` is not written to or read from concurrently */ -void sp_cp437_grid_fill(struct sp_CCp437Grid *this_, uint8_t value); +void sp_cp437_grid_fill(struct SPCp437Grid *this_, uint8_t value); /** * Gets the current value at the specified position. @@ -884,9 +867,7 @@ void sp_cp437_grid_fill(struct sp_CCp437Grid *this_, uint8_t value); * - `this` points to a valid `Cp437Grid` * - `this` is not written to concurrently */ -uint8_t sp_cp437_grid_get(const struct sp_CCp437Grid *this_, - size_t x, - size_t y); +uint8_t sp_cp437_grid_get(const struct SPCp437Grid *this_, size_t x, size_t y); /** * Gets the height of the `Cp437Grid` instance. @@ -901,7 +882,7 @@ uint8_t sp_cp437_grid_get(const struct sp_CCp437Grid *this_, * * - `this` points to a valid `Cp437Grid` */ -size_t sp_cp437_grid_height(const struct sp_CCp437Grid *this_); +size_t sp_cp437_grid_height(const struct SPCp437Grid *this_); /** * Loads a `Cp437Grid` with the specified dimensions from the provided data. @@ -919,10 +900,10 @@ size_t sp_cp437_grid_height(const struct sp_CCp437Grid *this_); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_cp437_grid_dealloc`. */ -struct sp_CCp437Grid *sp_cp437_grid_load(size_t width, - size_t height, - const uint8_t *data, - size_t data_length); +struct SPCp437Grid *sp_cp437_grid_load(size_t width, + size_t height, + const uint8_t *data, + size_t data_length); /** * Creates a new `Cp437Grid` with the specified dimensions. @@ -936,8 +917,8 @@ struct sp_CCp437Grid *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_dealloc`. */ -struct sp_CCp437Grid *sp_cp437_grid_new(size_t width, - size_t height); +struct SPCp437Grid *sp_cp437_grid_new(size_t width, + size_t height); /** * Sets the value of the specified position in the `Cp437Grid`. @@ -961,7 +942,7 @@ struct sp_CCp437Grid *sp_cp437_grid_new(size_t width, * - `this` points to a valid `BitVec` * - `this` is not written to or read from concurrently */ -void sp_cp437_grid_set(struct sp_CCp437Grid *this_, +void sp_cp437_grid_set(struct SPCp437Grid *this_, size_t x, size_t y, uint8_t value); @@ -977,7 +958,7 @@ void sp_cp437_grid_set(struct sp_CCp437Grid *this_, * - the returned memory range is never accessed after the passed `Cp437Grid` has been freed * - the returned memory range is never accessed concurrently, either via the `Cp437Grid` or directly */ -struct sp_CByteSlice sp_cp437_grid_unsafe_data_ref(struct sp_CCp437Grid *this_); +struct SPByteSlice sp_cp437_grid_unsafe_data_ref(struct SPCp437Grid *this_); /** * Gets the width of the `Cp437Grid` instance. @@ -992,7 +973,7 @@ struct sp_CByteSlice sp_cp437_grid_unsafe_data_ref(struct sp_CCp437Grid *this_); * * - `this` points to a valid `Cp437Grid` */ -size_t sp_cp437_grid_width(const struct sp_CCp437Grid *this_); +size_t sp_cp437_grid_width(const struct SPCp437Grid *this_); /** * Clones a `Packet`. @@ -1006,7 +987,7 @@ size_t sp_cp437_grid_width(const struct sp_CCp437Grid *this_); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_packet_dealloc`. */ -struct sp_Packet *sp_packet_clone(const struct sp_Packet *this_); +struct SPPacket *sp_packet_clone(const struct SPPacket *this_); /** * Deallocates a `Packet`. @@ -1018,7 +999,7 @@ struct sp_Packet *sp_packet_clone(const struct sp_Packet *this_); * - `this` points to a valid `Packet` * - `this` is not used concurrently or after this call */ -void sp_packet_dealloc(struct sp_Packet *this_); +void sp_packet_dealloc(struct SPPacket *this_); /** * Turns a `Command` into a `Packet`. @@ -1033,7 +1014,7 @@ void sp_packet_dealloc(struct sp_Packet *this_); * - the returned `Packet` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_packet_dealloc`. */ -struct sp_Packet *sp_packet_from_command(struct sp_CCommand *command); +struct SPPacket *sp_packet_from_command(struct SPCommand *command); /** * Tries to load a `Packet` from the passed array with the specified length. @@ -1049,8 +1030,8 @@ struct sp_Packet *sp_packet_from_command(struct sp_CCommand *command); * - the returned `Packet` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_packet_dealloc`. */ -struct sp_Packet *sp_packet_try_load(const uint8_t *data, - size_t length); +struct SPPacket *sp_packet_try_load(const uint8_t *data, + size_t length); /** * Clones a `PixelGrid`. @@ -1064,7 +1045,7 @@ struct sp_Packet *sp_packet_try_load(const uint8_t *data, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_pixel_grid_dealloc`. */ -struct sp_PixelGrid *sp_pixel_grid_clone(const struct sp_PixelGrid *this_); +struct SPPixelGrid *sp_pixel_grid_clone(const struct SPPixelGrid *this_); /** * Deallocates a `PixelGrid`. @@ -1077,7 +1058,7 @@ struct sp_PixelGrid *sp_pixel_grid_clone(const struct sp_PixelGrid *this_); * - `this` is not used concurrently or after this call * - `this` was not passed to another consuming function, e.g. to create a `Command` */ -void sp_pixel_grid_dealloc(struct sp_PixelGrid *this_); +void sp_pixel_grid_dealloc(struct SPPixelGrid *this_); /** * Sets the state of all pixels in the `PixelGrid`. @@ -1094,7 +1075,7 @@ void sp_pixel_grid_dealloc(struct sp_PixelGrid *this_); * - `this` points to a valid `PixelGrid` * - `this` is not written to or read from concurrently */ -void sp_pixel_grid_fill(struct sp_PixelGrid *this_, bool value); +void sp_pixel_grid_fill(struct SPPixelGrid *this_, bool value); /** * Gets the current value at the specified position in the `PixelGrid`. @@ -1115,7 +1096,7 @@ void sp_pixel_grid_fill(struct sp_PixelGrid *this_, bool value); * - `this` points to a valid `PixelGrid` * - `this` is not written to concurrently */ -bool sp_pixel_grid_get(const struct sp_PixelGrid *this_, size_t x, size_t y); +bool sp_pixel_grid_get(const struct SPPixelGrid *this_, size_t x, size_t y); /** * Gets the height in pixels of the `PixelGrid` instance. @@ -1130,7 +1111,7 @@ bool sp_pixel_grid_get(const struct sp_PixelGrid *this_, size_t x, size_t y); * * - `this` points to a valid `PixelGrid` */ -size_t sp_pixel_grid_height(const struct sp_PixelGrid *this_); +size_t sp_pixel_grid_height(const struct SPPixelGrid *this_); /** * Loads a `PixelGrid` with the specified dimensions from the provided data. @@ -1155,10 +1136,10 @@ size_t sp_pixel_grid_height(const struct sp_PixelGrid *this_); * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_pixel_grid_dealloc`. */ -struct sp_PixelGrid *sp_pixel_grid_load(size_t width, - size_t height, - const uint8_t *data, - size_t data_length); +struct SPPixelGrid *sp_pixel_grid_load(size_t width, + size_t height, + const uint8_t *data, + size_t data_length); /** * Creates a new `PixelGrid` with the specified dimensions. @@ -1181,8 +1162,8 @@ struct sp_PixelGrid *sp_pixel_grid_load(size_t width, * - the returned instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_pixel_grid_dealloc`. */ -struct sp_PixelGrid *sp_pixel_grid_new(size_t width, - size_t height); +struct SPPixelGrid *sp_pixel_grid_new(size_t width, + size_t height); /** * Sets the value of the specified position in the `PixelGrid`. @@ -1206,7 +1187,7 @@ struct sp_PixelGrid *sp_pixel_grid_new(size_t width, * - `this` points to a valid `PixelGrid` * - `this` is not written to or read from concurrently */ -void sp_pixel_grid_set(struct sp_PixelGrid *this_, +void sp_pixel_grid_set(struct SPPixelGrid *this_, size_t x, size_t y, bool value); @@ -1222,7 +1203,7 @@ void sp_pixel_grid_set(struct sp_PixelGrid *this_, * - the returned memory range is never accessed after the passed `PixelGrid` has been freed * - the returned memory range is never accessed concurrently, either via the `PixelGrid` or directly */ -struct sp_CByteSlice sp_pixel_grid_unsafe_data_ref(struct sp_PixelGrid *this_); +struct SPByteSlice sp_pixel_grid_unsafe_data_ref(struct SPPixelGrid *this_); /** * Gets the width in pixels of the `PixelGrid` instance. @@ -1237,7 +1218,7 @@ struct sp_CByteSlice sp_pixel_grid_unsafe_data_ref(struct sp_PixelGrid *this_); * * - `this` points to a valid `PixelGrid` */ -size_t sp_pixel_grid_width(const struct sp_PixelGrid *this_); +size_t sp_pixel_grid_width(const struct SPPixelGrid *this_); #ifdef __cplusplus } // extern "C" diff --git a/crates/servicepoint_binding_c/examples/lang_c/src/main.c b/crates/servicepoint_binding_c/examples/lang_c/src/main.c index 451abe7..738cdfe 100644 --- a/crates/servicepoint_binding_c/examples/lang_c/src/main.c +++ b/crates/servicepoint_binding_c/examples/lang_c/src/main.c @@ -2,15 +2,15 @@ #include "servicepoint.h" int main(void) { - sp_Connection *connection = sp_connection_open("172.23.42.29:2342"); + SPConnection *connection = sp_connection_open("172.23.42.29:2342"); if (connection == NULL) return 1; - sp_PixelGrid *pixels = sp_pixel_grid_new(sp_PIXEL_WIDTH, sp_PIXEL_HEIGHT); + SPPixelGrid *pixels = sp_pixel_grid_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT); sp_pixel_grid_fill(pixels, true); - sp_CCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed); - sp_Packet *packet = sp_packet_from_command(command); + SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed); + SPPacket *packet = sp_packet_from_command(command); while (sp_connection_send(connection, sp_packet_clone(packet))); sp_packet_dealloc(packet); diff --git a/crates/servicepoint_binding_c/src/bit_vec.rs b/crates/servicepoint_binding_c/src/bit_vec.rs index 6a52a63..d53792e 100644 --- a/crates/servicepoint_binding_c/src/bit_vec.rs +++ b/crates/servicepoint_binding_c/src/bit_vec.rs @@ -2,34 +2,34 @@ //! //! prefix `sp_bit_vec_` -use crate::c_slice::CByteSlice; +use crate::c_slice::SPByteSlice; use servicepoint::bitvec::prelude::{BitVec, Msb0}; -/// cbindgen:no-export -type SpBitVec = BitVec; - /// A vector of bits -pub struct CBitVec { - actual: SpBitVec, -} +/// +/// # Examples +/// ```C +/// SPBitVec vec = sp_bit_vec_new(8); +/// sp_bit_vec_set(vec, 5, true); +/// sp_bit_vec_dealloc(vec); +/// ``` +pub struct SPBitVec(BitVec); -impl From for CBitVec { - fn from(actual: SpBitVec) -> Self { - Self { actual } +impl From> for SPBitVec { + fn from(actual: BitVec) -> Self { + Self(actual) } } -impl From for SpBitVec { - fn from(value: CBitVec) -> Self { - value.actual +impl From for BitVec { + fn from(value: SPBitVec) -> Self { + value.0 } } -impl Clone for CBitVec { +impl Clone for SPBitVec { fn clone(&self) -> Self { - CBitVec { - actual: self.actual.clone(), - } + SPBitVec(self.0.clone()) } } @@ -52,10 +52,8 @@ impl Clone for CBitVec { /// - the returned instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_bit_vec_dealloc`. #[no_mangle] -pub unsafe extern "C" fn sp_bit_vec_new(size: usize) -> *mut CBitVec { - Box::into_raw(Box::new(CBitVec { - actual: SpBitVec::repeat(false, size), - })) +pub unsafe extern "C" fn sp_bit_vec_new(size: usize) -> *mut SPBitVec { + Box::into_raw(Box::new(SPBitVec(BitVec::repeat(false, size)))) } /// Interpret the data as a series of bits and load then into a new `BitVec` instance. @@ -72,11 +70,9 @@ pub unsafe extern "C" fn sp_bit_vec_new(size: usize) -> *mut CBitVec { pub unsafe extern "C" fn sp_bit_vec_load( data: *const u8, data_length: usize, -) -> *mut CBitVec { +) -> *mut SPBitVec { let data = std::slice::from_raw_parts(data, data_length); - Box::into_raw(Box::new(CBitVec { - actual: SpBitVec::from_slice(data), - })) + Box::into_raw(Box::new(SPBitVec(BitVec::from_slice(data)))) } /// Clones a `BitVec`. @@ -91,8 +87,8 @@ pub unsafe extern "C" fn sp_bit_vec_load( /// by explicitly calling `sp_bit_vec_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_clone( - this: *const CBitVec, -) -> *mut CBitVec { + this: *const SPBitVec, +) -> *mut SPBitVec { Box::into_raw(Box::new((*this).clone())) } @@ -106,7 +102,7 @@ pub unsafe extern "C" fn sp_bit_vec_clone( /// - `this` is not used concurrently or after this call /// - `this` was not passed to another consuming function, e.g. to create a `Command` #[no_mangle] -pub unsafe extern "C" fn sp_bit_vec_dealloc(this: *mut CBitVec) { +pub unsafe extern "C" fn sp_bit_vec_dealloc(this: *mut SPBitVec) { _ = Box::from_raw(this); } @@ -131,10 +127,10 @@ pub unsafe extern "C" fn sp_bit_vec_dealloc(this: *mut CBitVec) { /// - `this` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_get( - this: *const CBitVec, + this: *const SPBitVec, index: usize, ) -> bool { - *(*this).actual.get(index).unwrap() + *(*this).0.get(index).unwrap() } /// Sets the value of a bit in the `BitVec`. @@ -159,11 +155,11 @@ pub unsafe extern "C" fn sp_bit_vec_get( /// - `this` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_set( - this: *mut CBitVec, + this: *mut SPBitVec, index: usize, value: bool, ) { - (*this).actual.set(index, value) + (*this).0.set(index, value) } /// Sets the value of all bits in the `BitVec`. @@ -179,8 +175,8 @@ pub unsafe extern "C" fn sp_bit_vec_set( /// - `this` points to a valid `BitVec` /// - `this` is not written to or read from concurrently #[no_mangle] -pub unsafe extern "C" fn sp_bit_vec_fill(this: *mut CBitVec, value: bool) { - (*this).actual.fill(value) +pub unsafe extern "C" fn sp_bit_vec_fill(this: *mut SPBitVec, value: bool) { + (*this).0.fill(value) } /// Gets the length of the `BitVec` in bits. @@ -191,8 +187,8 @@ pub unsafe extern "C" fn sp_bit_vec_fill(this: *mut CBitVec, value: bool) { /// /// - `this` points to a valid `BitVec` #[no_mangle] -pub unsafe extern "C" fn sp_bit_vec_len(this: *const CBitVec) -> usize { - (*this).actual.len() +pub unsafe extern "C" fn sp_bit_vec_len(this: *const SPBitVec) -> usize { + (*this).0.len() } /// Returns true if length is 0. @@ -203,8 +199,8 @@ pub unsafe extern "C" fn sp_bit_vec_len(this: *const CBitVec) -> usize { /// /// - `this` points to a valid `BitVec` #[no_mangle] -pub unsafe extern "C" fn sp_bit_vec_is_empty(this: *const CBitVec) -> bool { - (*this).actual.is_empty() +pub unsafe extern "C" fn sp_bit_vec_is_empty(this: *const SPBitVec) -> bool { + (*this).0.is_empty() } /// Gets an unsafe reference to the data of the `BitVec` instance. @@ -218,10 +214,10 @@ pub unsafe extern "C" fn sp_bit_vec_is_empty(this: *const CBitVec) -> bool { /// - the returned memory range is never accessed concurrently, either via the `BitVec` or directly #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_unsafe_data_ref( - this: *mut CBitVec, -) -> CByteSlice { - let data = (*this).actual.as_raw_mut_slice(); - CByteSlice { + this: *mut SPBitVec, +) -> SPByteSlice { + let data = (*this).0.as_raw_mut_slice(); + SPByteSlice { start: data.as_mut_ptr_range().start, length: data.len(), } diff --git a/crates/servicepoint_binding_c/src/brightness_grid.rs b/crates/servicepoint_binding_c/src/brightness_grid.rs index 0ca0ec6..e4af777 100644 --- a/crates/servicepoint_binding_c/src/brightness_grid.rs +++ b/crates/servicepoint_binding_c/src/brightness_grid.rs @@ -2,18 +2,32 @@ //! //! prefix `sp_brightness_grid_` -use crate::c_slice::CByteSlice; -use servicepoint::{Brightness, BrightnessGrid, DataRef, Grid, PrimitiveGrid}; +use crate::c_slice::SPByteSlice; +use servicepoint::{Brightness, DataRef, Grid, PrimitiveGrid}; use std::intrinsics::transmute; -/// C-wrapper for grid containing brightness values. -pub struct CBrightnessGrid { - pub(crate) actual: BrightnessGrid, +/// 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_dealloc(connection); +/// ``` +pub struct SPBrightnessGrid { + pub(crate) actual: servicepoint::BrightnessGrid, } -impl Clone for CBrightnessGrid { +impl Clone for SPBrightnessGrid { fn clone(&self) -> Self { - CBrightnessGrid { + SPBrightnessGrid { actual: self.actual.clone(), } } @@ -33,9 +47,9 @@ impl Clone for CBrightnessGrid { pub unsafe extern "C" fn sp_brightness_grid_new( width: usize, height: usize, -) -> *mut CBrightnessGrid { - Box::into_raw(Box::new(CBrightnessGrid { - actual: BrightnessGrid::new(width, height), +) -> *mut SPBrightnessGrid { + Box::into_raw(Box::new(SPBrightnessGrid { + actual: servicepoint::BrightnessGrid::new(width, height), })) } @@ -59,12 +73,12 @@ pub unsafe extern "C" fn sp_brightness_grid_load( height: usize, data: *const u8, data_length: usize, -) -> *mut CBrightnessGrid { +) -> *mut SPBrightnessGrid { let data = std::slice::from_raw_parts(data, data_length); let grid = PrimitiveGrid::load(width, height, data); - let grid = - BrightnessGrid::try_from(grid).expect("invalid brightness value"); - Box::into_raw(Box::new(CBrightnessGrid { actual: grid })) + let grid = servicepoint::BrightnessGrid::try_from(grid) + .expect("invalid brightness value"); + Box::into_raw(Box::new(SPBrightnessGrid { actual: grid })) } /// Clones a `BrightnessGrid`. @@ -79,8 +93,8 @@ pub unsafe extern "C" fn sp_brightness_grid_load( /// by explicitly calling `sp_brightness_grid_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_clone( - this: *const CBrightnessGrid, -) -> *mut CBrightnessGrid { + this: *const SPBrightnessGrid, +) -> *mut SPBrightnessGrid { Box::into_raw(Box::new((*this).clone())) } @@ -95,7 +109,7 @@ pub unsafe extern "C" fn sp_brightness_grid_clone( /// - `this` was not passed to another consuming function, e.g. to create a `Command` #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_dealloc( - this: *mut CBrightnessGrid, + this: *mut SPBrightnessGrid, ) { _ = Box::from_raw(this); } @@ -119,7 +133,7 @@ pub unsafe extern "C" fn sp_brightness_grid_dealloc( /// - `this` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_get( - this: *const CBrightnessGrid, + this: *const SPBrightnessGrid, x: usize, y: usize, ) -> u8 { @@ -149,7 +163,7 @@ pub unsafe extern "C" fn sp_brightness_grid_get( /// - `this` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_set( - this: *mut CBrightnessGrid, + this: *mut SPBrightnessGrid, x: usize, y: usize, value: u8, @@ -178,7 +192,7 @@ pub unsafe extern "C" fn sp_brightness_grid_set( /// - `this` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_fill( - this: *mut CBrightnessGrid, + this: *mut SPBrightnessGrid, value: u8, ) { let brightness = @@ -199,7 +213,7 @@ pub unsafe extern "C" fn sp_brightness_grid_fill( /// - `this` points to a valid `BrightnessGrid` #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_width( - this: *const CBrightnessGrid, + this: *const SPBrightnessGrid, ) -> usize { (*this).actual.width() } @@ -217,7 +231,7 @@ pub unsafe extern "C" fn sp_brightness_grid_width( /// - `this` points to a valid `BrightnessGrid` #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_height( - this: *const CBrightnessGrid, + this: *const SPBrightnessGrid, ) -> usize { (*this).actual.height() } @@ -233,13 +247,13 @@ pub unsafe extern "C" fn sp_brightness_grid_height( /// - the returned memory range is never accessed concurrently, either via the `BrightnessGrid` or directly #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( - this: *mut CBrightnessGrid, -) -> CByteSlice { + this: *mut SPBrightnessGrid, +) -> SPByteSlice { assert_eq!(std::mem::size_of::(), 1); let data = (*this).actual.data_ref_mut(); let data: &mut [u8] = transmute(data); - CByteSlice { + SPByteSlice { start: data.as_mut_ptr_range().start, length: data.len(), } diff --git a/crates/servicepoint_binding_c/src/c_slice.rs b/crates/servicepoint_binding_c/src/c_slice.rs index 566213d..9962511 100644 --- a/crates/servicepoint_binding_c/src/c_slice.rs +++ b/crates/servicepoint_binding_c/src/c_slice.rs @@ -10,7 +10,7 @@ /// - accesses to the memory pointed to with `start` is never accessed outside `length` /// - the lifetime of the `CByteSlice` does not outlive the memory it points to, as described in /// the function returning this type. -pub struct CByteSlice { +pub struct SPByteSlice { /// The start address of the memory pub start: *mut u8, /// The amount of memory in bytes diff --git a/crates/servicepoint_binding_c/src/command.rs b/crates/servicepoint_binding_c/src/command.rs index 6126284..ec8a033 100644 --- a/crates/servicepoint_binding_c/src/command.rs +++ b/crates/servicepoint_binding_c/src/command.rs @@ -4,24 +4,33 @@ use std::ptr::null_mut; -use servicepoint::{ - Brightness, Command, CompressionCode, Offset, Origin, Packet, PixelGrid, -}; +use servicepoint::{Brightness, Origin}; -use crate::bit_vec::CBitVec; -use crate::brightness_grid::CBrightnessGrid; -use crate::cp437_grid::CCp437Grid; +use crate::bit_vec::SPBitVec; +use crate::brightness_grid::SPBrightnessGrid; +use crate::constants::SPCompressionCode; +use crate::cp437_grid::SPCp437Grid; +use crate::packet::SPPacket; +use crate::pixel_grid::SPPixelGrid; +use crate::SPOffset; /// A low-level display command. /// /// This struct and associated functions implement the UDP protocol for the display. /// -/// To send a `CCommand`, use a `Connection`. -pub struct CCommand(pub(crate) Command); +/// To send a `CCommand`, use a `CConnection`. +/// +/// # Examples +/// +/// ```C +/// sp_connection_send(connection, sp_command_clear()); +/// sp_connection_send(connection, sp_command_brightness(5)); +/// ``` +pub struct SPCommand(pub(crate) servicepoint::Command); -impl Clone for CCommand { +impl Clone for SPCommand { fn clone(&self) -> Self { - CCommand(self.0.clone()) + SPCommand(self.0.clone()) } } @@ -40,12 +49,12 @@ impl Clone for CCommand { /// by explicitly calling `sp_command_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_command_try_from_packet( - packet: *mut Packet, -) -> *mut CCommand { + packet: *mut SPPacket, +) -> *mut SPCommand { let packet = *Box::from_raw(packet); - match Command::try_from(packet) { + match servicepoint::Command::try_from(packet.0) { Err(_) => null_mut(), - Ok(command) => Box::into_raw(Box::new(CCommand(command))), + Ok(command) => Box::into_raw(Box::new(SPCommand(command))), } } @@ -61,8 +70,8 @@ pub unsafe extern "C" fn sp_command_try_from_packet( /// by explicitly calling `sp_command_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_command_clone( - original: *const CCommand, -) -> *mut CCommand { + original: *const SPCommand, +) -> *mut SPCommand { Box::into_raw(Box::new((*original).clone())) } @@ -75,8 +84,8 @@ pub unsafe extern "C" fn sp_command_clone( /// - the returned `Command` instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_dealloc`. #[no_mangle] -pub unsafe extern "C" fn sp_command_clear() -> *mut CCommand { - Box::into_raw(Box::new(CCommand(Command::Clear))) +pub unsafe extern "C" fn sp_command_clear() -> *mut SPCommand { + Box::into_raw(Box::new(SPCommand(servicepoint::Command::Clear))) } /// Allocates a new `Command::HardReset` instance. @@ -88,8 +97,8 @@ pub unsafe extern "C" fn sp_command_clear() -> *mut CCommand { /// - the returned `Command` instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_dealloc`. #[no_mangle] -pub unsafe extern "C" fn sp_command_hard_reset() -> *mut CCommand { - Box::into_raw(Box::new(CCommand(Command::HardReset))) +pub unsafe extern "C" fn sp_command_hard_reset() -> *mut SPCommand { + Box::into_raw(Box::new(SPCommand(servicepoint::Command::HardReset))) } /// Allocates a new `Command::FadeOut` instance. @@ -101,8 +110,8 @@ pub unsafe extern "C" fn sp_command_hard_reset() -> *mut CCommand { /// - the returned `Command` instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_dealloc`. #[no_mangle] -pub unsafe extern "C" fn sp_command_fade_out() -> *mut CCommand { - Box::into_raw(Box::new(CCommand(Command::FadeOut))) +pub unsafe extern "C" fn sp_command_fade_out() -> *mut SPCommand { + Box::into_raw(Box::new(SPCommand(servicepoint::Command::FadeOut))) } /// Allocates a new `Command::Brightness` instance for setting the brightness of all tiles to the @@ -116,36 +125,38 @@ pub unsafe extern "C" fn sp_command_fade_out() -> *mut CCommand { /// /// The caller has to make sure that: /// -/// - the returned `Command` instance is freed in some way, either by using a consuming function or +/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_command_brightness( brightness: u8, -) -> *mut CCommand { +) -> *mut SPCommand { let brightness = Brightness::try_from(brightness).expect("invalid brightness"); - Box::into_raw(Box::new(CCommand(Command::Brightness(brightness)))) + Box::into_raw(Box::new(SPCommand(servicepoint::Command::Brightness( + brightness, + )))) } /// Allocates a new `Command::CharBrightness` instance. -/// The passed `ByteGrid` gets consumed. +/// The passed `SPBrightnessGrid` gets consumed. /// /// # Safety /// /// The caller has to make sure that: /// -/// - `byte_grid` points to a valid instance of `ByteGrid` -/// - `byte_grid` is not used concurrently or after this call +/// - `grid` points to a valid instance of `SPBrightnessGrid` +/// - `grid` is not used concurrently or after this call /// - the returned `Command` instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_command_char_brightness( x: usize, y: usize, - byte_grid: *mut CBrightnessGrid, -) -> *mut CCommand { - let byte_grid = *Box::from_raw(byte_grid); - Box::into_raw(Box::new(CCommand(Command::CharBrightness( + grid: *mut SPBrightnessGrid, +) -> *mut SPCommand { + let byte_grid = *Box::from_raw(grid); + Box::into_raw(Box::new(SPCommand(servicepoint::Command::CharBrightness( Origin::new(x, y), byte_grid.actual, )))) @@ -165,15 +176,15 @@ pub unsafe extern "C" fn sp_command_char_brightness( /// by explicitly calling `sp_command_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear( - offset: Offset, - bit_vec: *mut CBitVec, - compression: CompressionCode, -) -> *mut CCommand { + offset: SPOffset, + bit_vec: *mut SPBitVec, + compression: SPCompressionCode, +) -> *mut SPCommand { let bit_vec = *Box::from_raw(bit_vec); - Box::into_raw(Box::new(CCommand(Command::BitmapLinear( + Box::into_raw(Box::new(SPCommand(servicepoint::Command::BitmapLinear( offset, bit_vec.into(), - compression, + compression.try_into().expect("invalid compression code"), )))) } @@ -191,15 +202,15 @@ pub unsafe extern "C" fn sp_command_bitmap_linear( /// by explicitly calling `sp_command_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_and( - offset: Offset, - bit_vec: *mut CBitVec, - compression: CompressionCode, -) -> *mut CCommand { + offset: SPOffset, + bit_vec: *mut SPBitVec, + compression: SPCompressionCode, +) -> *mut SPCommand { let bit_vec = *Box::from_raw(bit_vec); - Box::into_raw(Box::new(CCommand(Command::BitmapLinearAnd( + Box::into_raw(Box::new(SPCommand(servicepoint::Command::BitmapLinearAnd( offset, bit_vec.into(), - compression, + compression.try_into().expect("invalid compression code"), )))) } @@ -217,15 +228,15 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and( /// by explicitly calling `sp_command_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_or( - offset: Offset, - bit_vec: *mut CBitVec, - compression: CompressionCode, -) -> *mut CCommand { + offset: SPOffset, + bit_vec: *mut SPBitVec, + compression: SPCompressionCode, +) -> *mut SPCommand { let bit_vec = *Box::from_raw(bit_vec); - Box::into_raw(Box::new(CCommand(Command::BitmapLinearOr( + Box::into_raw(Box::new(SPCommand(servicepoint::Command::BitmapLinearOr( offset, bit_vec.into(), - compression, + compression.try_into().expect("invalid compression code"), )))) } @@ -243,15 +254,15 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or( /// by explicitly calling `sp_command_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_xor( - offset: Offset, - bit_vec: *mut CBitVec, - compression: CompressionCode, -) -> *mut CCommand { + offset: SPOffset, + bit_vec: *mut SPBitVec, + compression: SPCompressionCode, +) -> *mut SPCommand { let bit_vec = *Box::from_raw(bit_vec); - Box::into_raw(Box::new(CCommand(Command::BitmapLinearXor( + Box::into_raw(Box::new(SPCommand(servicepoint::Command::BitmapLinearXor( offset, bit_vec.into(), - compression, + compression.try_into().expect("invalid compression code"), )))) } @@ -270,10 +281,10 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor( pub unsafe extern "C" fn sp_command_cp437_data( x: usize, y: usize, - byte_grid: *mut CCp437Grid, -) -> *mut CCommand { + byte_grid: *mut SPCp437Grid, +) -> *mut SPCommand { let byte_grid = *Box::from_raw(byte_grid); - Box::into_raw(Box::new(CCommand(Command::Cp437Data( + Box::into_raw(Box::new(SPCommand(servicepoint::Command::Cp437Data( Origin::new(x, y), byte_grid.actual, )))) @@ -295,14 +306,16 @@ pub unsafe extern "C" fn sp_command_cp437_data( pub unsafe extern "C" fn sp_command_bitmap_linear_win( x: usize, y: usize, - pixel_grid: *mut PixelGrid, - compression_code: CompressionCode, -) -> *mut CCommand { - let byte_grid = *Box::from_raw(pixel_grid); - Box::into_raw(Box::new(CCommand(Command::BitmapLinearWin( + pixel_grid: *mut SPPixelGrid, + compression_code: SPCompressionCode, +) -> *mut SPCommand { + let byte_grid = (*Box::from_raw(pixel_grid)).0; + Box::into_raw(Box::new(SPCommand(servicepoint::Command::BitmapLinearWin( Origin::new(x, y), byte_grid, - compression_code, + compression_code + .try_into() + .expect("invalid compression code"), )))) } @@ -316,6 +329,6 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win( /// - `this` is not used concurrently or after this call /// - `this` was not passed to another consuming function, e.g. to create a `Packet` #[no_mangle] -pub unsafe extern "C" fn sp_command_dealloc(ptr: *mut CCommand) { +pub unsafe extern "C" fn sp_command_dealloc(ptr: *mut SPCommand) { _ = Box::from_raw(ptr); } diff --git a/crates/servicepoint_binding_c/src/connection.rs b/crates/servicepoint_binding_c/src/connection.rs index 25b9cf7..e0556e3 100644 --- a/crates/servicepoint_binding_c/src/connection.rs +++ b/crates/servicepoint_binding_c/src/connection.rs @@ -5,7 +5,18 @@ use std::ffi::{c_char, CStr}; use std::ptr::null_mut; -use servicepoint::{Connection, Packet}; +use crate::packet::SPPacket; + +/// A connection to the display. +/// +/// # Examples +/// +/// ```C +/// CConnection connection = sp_connection_open("172.23.42.29:2342"); +/// if (connection != NULL) +/// sp_connection_send(connection, sp_command_clear()); +/// ``` +pub struct SPConnection(pub(crate) servicepoint::Connection); /// Creates a new instance of `Connection`. /// @@ -24,14 +35,14 @@ use servicepoint::{Connection, Packet}; #[no_mangle] pub unsafe extern "C" fn sp_connection_open( host: *const c_char, -) -> *mut Connection { +) -> *mut SPConnection { let host = CStr::from_ptr(host).to_str().expect("Bad encoding"); - let connection = match Connection::open(host) { + let connection = match servicepoint::Connection::open(host) { Err(_) => return null_mut(), Ok(value) => value, }; - Box::into_raw(Box::new(connection)) + Box::into_raw(Box::new(SPConnection(connection))) } /// Sends a `Packet` to the display using the `Connection`. @@ -48,11 +59,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( - connection: *const Connection, - packet: *mut Packet, + connection: *const SPConnection, + packet: *mut SPPacket, ) -> bool { let packet = Box::from_raw(packet); - (*connection).send(*packet).is_ok() + (*connection).0.send((*packet).0).is_ok() } /// Closes and deallocates a `Connection`. @@ -64,6 +75,6 @@ pub unsafe extern "C" fn sp_connection_send( /// - `this` points to a valid `Connection` /// - `this` is not used concurrently or after this call #[no_mangle] -pub unsafe extern "C" fn sp_connection_dealloc(ptr: *mut Connection) { +pub unsafe extern "C" fn sp_connection_dealloc(ptr: *mut SPConnection) { _ = Box::from_raw(ptr); } diff --git a/crates/servicepoint_binding_c/src/constants.rs b/crates/servicepoint_binding_c/src/constants.rs new file mode 100644 index 0000000..1a268f4 --- /dev/null +++ b/crates/servicepoint_binding_c/src/constants.rs @@ -0,0 +1,48 @@ +//! 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) + } +} diff --git a/crates/servicepoint_binding_c/src/cp437_grid.rs b/crates/servicepoint_binding_c/src/cp437_grid.rs index 79651bf..f181fdf 100644 --- a/crates/servicepoint_binding_c/src/cp437_grid.rs +++ b/crates/servicepoint_binding_c/src/cp437_grid.rs @@ -2,19 +2,28 @@ //! //! prefix `sp_cp437_grid_` -use crate::c_slice::CByteSlice; +use crate::c_slice::SPByteSlice; use servicepoint::{Cp437Grid, DataRef, Grid}; /// A C-wrapper for grid containing codepage 437 characters. /// /// The encoding is currently not enforced. -pub struct CCp437Grid { +/// +/// # 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_dealloc(grid); +/// ``` +pub struct SPCp437Grid { pub(crate) actual: Cp437Grid, } -impl Clone for CCp437Grid { +impl Clone for SPCp437Grid { fn clone(&self) -> Self { - CCp437Grid { + SPCp437Grid { actual: self.actual.clone(), } } @@ -34,8 +43,8 @@ impl Clone for CCp437Grid { pub unsafe extern "C" fn sp_cp437_grid_new( width: usize, height: usize, -) -> *mut CCp437Grid { - Box::into_raw(Box::new(CCp437Grid { +) -> *mut SPCp437Grid { + Box::into_raw(Box::new(SPCp437Grid { actual: Cp437Grid::new(width, height), })) } @@ -60,9 +69,9 @@ pub unsafe extern "C" fn sp_cp437_grid_load( height: usize, data: *const u8, data_length: usize, -) -> *mut CCp437Grid { +) -> *mut SPCp437Grid { let data = std::slice::from_raw_parts(data, data_length); - Box::into_raw(Box::new(CCp437Grid { + Box::into_raw(Box::new(SPCp437Grid { actual: Cp437Grid::load(width, height, data), })) } @@ -79,8 +88,8 @@ pub unsafe extern "C" fn sp_cp437_grid_load( /// by explicitly calling `sp_cp437_grid_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_clone( - this: *const CCp437Grid, -) -> *mut CCp437Grid { + this: *const SPCp437Grid, +) -> *mut SPCp437Grid { Box::into_raw(Box::new((*this).clone())) } @@ -94,7 +103,7 @@ pub unsafe extern "C" fn sp_cp437_grid_clone( /// - `this` is not used concurrently or after this call /// - `this` was not passed to another consuming function, e.g. to create a `Command` #[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_dealloc(this: *mut CCp437Grid) { +pub unsafe extern "C" fn sp_cp437_grid_dealloc(this: *mut SPCp437Grid) { _ = Box::from_raw(this); } @@ -117,7 +126,7 @@ pub unsafe extern "C" fn sp_cp437_grid_dealloc(this: *mut CCp437Grid) { /// - `this` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_get( - this: *const CCp437Grid, + this: *const SPCp437Grid, x: usize, y: usize, ) -> u8 { @@ -146,7 +155,7 @@ pub unsafe extern "C" fn sp_cp437_grid_get( /// - `this` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_set( - this: *mut CCp437Grid, + this: *mut SPCp437Grid, x: usize, y: usize, value: u8, @@ -168,7 +177,7 @@ pub unsafe extern "C" fn sp_cp437_grid_set( /// - `this` points to a valid `Cp437Grid` /// - `this` is not written to or read from concurrently #[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_fill(this: *mut CCp437Grid, value: u8) { +pub unsafe extern "C" fn sp_cp437_grid_fill(this: *mut SPCp437Grid, value: u8) { (*this).actual.fill(value); } @@ -184,7 +193,9 @@ pub unsafe extern "C" fn sp_cp437_grid_fill(this: *mut CCp437Grid, value: u8) { /// /// - `this` points to a valid `Cp437Grid` #[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_width(this: *const CCp437Grid) -> usize { +pub unsafe extern "C" fn sp_cp437_grid_width( + this: *const SPCp437Grid, +) -> usize { (*this).actual.width() } @@ -201,7 +212,7 @@ pub unsafe extern "C" fn sp_cp437_grid_width(this: *const CCp437Grid) -> usize { /// - `this` points to a valid `Cp437Grid` #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_height( - this: *const CCp437Grid, + this: *const SPCp437Grid, ) -> usize { (*this).actual.height() } @@ -217,10 +228,10 @@ pub unsafe extern "C" fn sp_cp437_grid_height( /// - the returned memory range is never accessed concurrently, either via the `Cp437Grid` or directly #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref( - this: *mut CCp437Grid, -) -> CByteSlice { + this: *mut SPCp437Grid, +) -> SPByteSlice { let data = (*this).actual.data_ref_mut(); - CByteSlice { + SPByteSlice { start: data.as_mut_ptr_range().start, length: data.len(), } diff --git a/crates/servicepoint_binding_c/src/lib.rs b/crates/servicepoint_binding_c/src/lib.rs index 0939b66..c2d2877 100644 --- a/crates/servicepoint_binding_c/src/lib.rs +++ b/crates/servicepoint_binding_c/src/lib.rs @@ -1,11 +1,6 @@ //! C API wrapper for the `servicepoint` crate. -pub use servicepoint::{ - CompressionCode, PIXEL_COUNT, PIXEL_HEIGHT, PIXEL_WIDTH, TILE_HEIGHT, - TILE_SIZE, TILE_WIDTH, -}; - -pub use crate::c_slice::CByteSlice; +pub use crate::c_slice::SPByteSlice; pub mod bit_vec; @@ -23,5 +18,7 @@ pub mod c_slice; pub mod cp437_grid; -/// The minimum time needed for the display to refresh the screen in ms. -pub const FRAME_PACING_MS: u32 = servicepoint::FRAME_PACING.as_millis() as u32; +pub mod constants; + +/// Type alias for documenting the meaning of the variable in enum values +pub type SPOffset = usize; diff --git a/crates/servicepoint_binding_c/src/packet.rs b/crates/servicepoint_binding_c/src/packet.rs index 8c69410..c3304b8 100644 --- a/crates/servicepoint_binding_c/src/packet.rs +++ b/crates/servicepoint_binding_c/src/packet.rs @@ -4,8 +4,10 @@ use std::ptr::null_mut; -use crate::command::CCommand; -use servicepoint::Packet; +use crate::command::SPCommand; + +/// The raw packet +pub struct SPPacket(pub(crate) servicepoint::Packet); /// Turns a `Command` into a `Packet`. /// The `Command` gets consumed. @@ -20,10 +22,10 @@ use servicepoint::Packet; /// by explicitly calling `sp_packet_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_packet_from_command( - command: *mut CCommand, -) -> *mut Packet { + command: *mut SPCommand, +) -> *mut SPPacket { let command = *Box::from_raw(command); - let packet = command.0.into(); + let packet = SPPacket(command.0.into()); Box::into_raw(Box::new(packet)) } @@ -43,11 +45,11 @@ pub unsafe extern "C" fn sp_packet_from_command( pub unsafe extern "C" fn sp_packet_try_load( data: *const u8, length: usize, -) -> *mut Packet { +) -> *mut SPPacket { let data = std::slice::from_raw_parts(data, length); - match Packet::try_from(data) { + match servicepoint::Packet::try_from(data) { Err(_) => null_mut(), - Ok(packet) => Box::into_raw(Box::new(packet)), + Ok(packet) => Box::into_raw(Box::new(SPPacket(packet))), } } @@ -62,8 +64,10 @@ pub unsafe extern "C" fn sp_packet_try_load( /// - the returned instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_packet_dealloc`. #[no_mangle] -pub unsafe extern "C" fn sp_packet_clone(this: *const Packet) -> *mut Packet { - Box::into_raw(Box::new((*this).clone())) +pub unsafe extern "C" fn sp_packet_clone( + this: *const SPPacket, +) -> *mut SPPacket { + Box::into_raw(Box::new(SPPacket((*this).0.clone()))) } /// Deallocates a `Packet`. @@ -75,6 +79,6 @@ pub unsafe extern "C" fn sp_packet_clone(this: *const Packet) -> *mut Packet { /// - `this` points to a valid `Packet` /// - `this` is not used concurrently or after this call #[no_mangle] -pub unsafe extern "C" fn sp_packet_dealloc(this: *mut Packet) { +pub unsafe extern "C" fn sp_packet_dealloc(this: *mut SPPacket) { _ = Box::from_raw(this) } diff --git a/crates/servicepoint_binding_c/src/pixel_grid.rs b/crates/servicepoint_binding_c/src/pixel_grid.rs index 185017c..585fda3 100644 --- a/crates/servicepoint_binding_c/src/pixel_grid.rs +++ b/crates/servicepoint_binding_c/src/pixel_grid.rs @@ -2,9 +2,21 @@ //! //! prefix `sp_pixel_grid_` -use servicepoint::{DataRef, Grid, PixelGrid}; +use servicepoint::{DataRef, Grid}; -use crate::c_slice::CByteSlice; +use crate::c_slice::SPByteSlice; + +/// A grid of pixels. +/// +/// # Examples +/// +/// ```C +/// Cp437Grid grid = sp_pixel_grid_new(8, 3); +/// sp_pixel_grid_fill(grid, true); +/// sp_pixel_grid_set(grid, 0, 0, false); +/// sp_pixel_grid_dealloc(grid); +/// ``` +pub struct SPPixelGrid(pub(crate) servicepoint::PixelGrid); /// Creates a new `PixelGrid` with the specified dimensions. /// @@ -29,8 +41,10 @@ use crate::c_slice::CByteSlice; pub unsafe extern "C" fn sp_pixel_grid_new( width: usize, height: usize, -) -> *mut PixelGrid { - Box::into_raw(Box::new(PixelGrid::new(width, height))) +) -> *mut SPPixelGrid { + Box::into_raw(Box::new(SPPixelGrid(servicepoint::PixelGrid::new( + width, height, + )))) } /// Loads a `PixelGrid` with the specified dimensions from the provided data. @@ -60,9 +74,11 @@ pub unsafe extern "C" fn sp_pixel_grid_load( height: usize, data: *const u8, data_length: usize, -) -> *mut PixelGrid { +) -> *mut SPPixelGrid { let data = std::slice::from_raw_parts(data, data_length); - Box::into_raw(Box::new(PixelGrid::load(width, height, data))) + Box::into_raw(Box::new(SPPixelGrid(servicepoint::PixelGrid::load( + width, height, data, + )))) } /// Clones a `PixelGrid`. @@ -77,9 +93,9 @@ pub unsafe extern "C" fn sp_pixel_grid_load( /// by explicitly calling `sp_pixel_grid_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_pixel_grid_clone( - this: *const PixelGrid, -) -> *mut PixelGrid { - Box::into_raw(Box::new((*this).clone())) + this: *const SPPixelGrid, +) -> *mut SPPixelGrid { + Box::into_raw(Box::new(SPPixelGrid((*this).0.clone()))) } /// Deallocates a `PixelGrid`. @@ -92,7 +108,7 @@ pub unsafe extern "C" fn sp_pixel_grid_clone( /// - `this` is not used concurrently or after this call /// - `this` was not passed to another consuming function, e.g. to create a `Command` #[no_mangle] -pub unsafe extern "C" fn sp_pixel_grid_dealloc(this: *mut PixelGrid) { +pub unsafe extern "C" fn sp_pixel_grid_dealloc(this: *mut SPPixelGrid) { _ = Box::from_raw(this); } @@ -115,11 +131,11 @@ pub unsafe extern "C" fn sp_pixel_grid_dealloc(this: *mut PixelGrid) { /// - `this` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_pixel_grid_get( - this: *const PixelGrid, + this: *const SPPixelGrid, x: usize, y: usize, ) -> bool { - (*this).get(x, y) + (*this).0.get(x, y) } /// Sets the value of the specified position in the `PixelGrid`. @@ -144,12 +160,12 @@ pub unsafe extern "C" fn sp_pixel_grid_get( /// - `this` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_pixel_grid_set( - this: *mut PixelGrid, + this: *mut SPPixelGrid, x: usize, y: usize, value: bool, ) { - (*this).set(x, y, value); + (*this).0.set(x, y, value); } /// Sets the state of all pixels in the `PixelGrid`. @@ -166,8 +182,11 @@ pub unsafe extern "C" fn sp_pixel_grid_set( /// - `this` points to a valid `PixelGrid` /// - `this` is not written to or read from concurrently #[no_mangle] -pub unsafe extern "C" fn sp_pixel_grid_fill(this: *mut PixelGrid, value: bool) { - (*this).fill(value); +pub unsafe extern "C" fn sp_pixel_grid_fill( + this: *mut SPPixelGrid, + value: bool, +) { + (*this).0.fill(value); } /// Gets the width in pixels of the `PixelGrid` instance. @@ -182,8 +201,10 @@ pub unsafe extern "C" fn sp_pixel_grid_fill(this: *mut PixelGrid, value: bool) { /// /// - `this` points to a valid `PixelGrid` #[no_mangle] -pub unsafe extern "C" fn sp_pixel_grid_width(this: *const PixelGrid) -> usize { - (*this).width() +pub unsafe extern "C" fn sp_pixel_grid_width( + this: *const SPPixelGrid, +) -> usize { + (*this).0.width() } /// Gets the height in pixels of the `PixelGrid` instance. @@ -198,8 +219,10 @@ pub unsafe extern "C" fn sp_pixel_grid_width(this: *const PixelGrid) -> usize { /// /// - `this` points to a valid `PixelGrid` #[no_mangle] -pub unsafe extern "C" fn sp_pixel_grid_height(this: *const PixelGrid) -> usize { - (*this).height() +pub unsafe extern "C" fn sp_pixel_grid_height( + this: *const SPPixelGrid, +) -> usize { + (*this).0.height() } /// Gets an unsafe reference to the data of the `PixelGrid` instance. @@ -213,10 +236,10 @@ pub unsafe extern "C" fn sp_pixel_grid_height(this: *const PixelGrid) -> usize { /// - the returned memory range is never accessed concurrently, either via the `PixelGrid` or directly #[no_mangle] pub unsafe extern "C" fn sp_pixel_grid_unsafe_data_ref( - this: *mut PixelGrid, -) -> CByteSlice { - let data = (*this).data_ref_mut(); - CByteSlice { + this: *mut SPPixelGrid, +) -> SPByteSlice { + let data = (*this).0.data_ref_mut(); + SPByteSlice { start: data.as_mut_ptr_range().start, length: data.len(), } diff --git a/crates/servicepoint_binding_cs/ServicePoint/BindGen/ServicePoint.g.cs b/crates/servicepoint_binding_cs/ServicePoint/BindGen/ServicePoint.g.cs index 6545319..49c4d25 100644 --- a/crates/servicepoint_binding_cs/ServicePoint/BindGen/ServicePoint.g.cs +++ b/crates/servicepoint_binding_cs/ServicePoint/BindGen/ServicePoint.g.cs @@ -14,9 +14,9 @@ namespace ServicePoint.BindGen { const string __DllName = "servicepoint_binding_c"; - public const nuint TILE_SIZE = 8; - public const nuint TILE_WIDTH = 56; - public const nuint TILE_HEIGHT = 20; + public const nuint SP_TILE_SIZE = 8; + public const nuint SP_TILE_WIDTH = 56; + public const nuint SP_TILE_HEIGHT = 20; /// @@ -629,7 +629,7 @@ namespace ServicePoint.BindGen /// /// The caller has to make sure that: /// - /// - the returned `Command` instance is freed in some way, either by using a consuming function or + /// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_dealloc`. /// [DllImport(__DllName, EntryPoint = "sp_command_brightness", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] @@ -637,19 +637,19 @@ namespace ServicePoint.BindGen /// /// Allocates a new `Command::CharBrightness` instance. - /// The passed `ByteGrid` gets consumed. + /// The passed `SPBrightnessGrid` gets consumed. /// /// # Safety /// /// The caller has to make sure that: /// - /// - `byte_grid` points to a valid instance of `ByteGrid` - /// - `byte_grid` is not used concurrently or after this call + /// - `grid` points to a valid instance of `SPBrightnessGrid` + /// - `grid` is not used concurrently or after this call /// - the returned `Command` instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_dealloc`. /// [DllImport(__DllName, EntryPoint = "sp_command_char_brightness", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern Command* sp_command_char_brightness(nuint x, nuint y, BrightnessGrid* byte_grid); + public static extern Command* sp_command_char_brightness(nuint x, nuint y, BrightnessGrid* grid); /// /// Allocates a new `Command::BitmapLinear` instance. @@ -1040,6 +1040,21 @@ namespace ServicePoint.BindGen [DllImport(__DllName, EntryPoint = "sp_packet_try_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] public static extern Packet* sp_packet_try_load(byte* data, nuint length); + /// + /// Clones a `Packet`. + /// + /// # Safety + /// + /// The caller has to make sure that: + /// + /// - `this` points to a valid `Packet` + /// - `this` is not written to concurrently + /// - the returned instance is freed in some way, either by using a consuming function or + /// by explicitly calling `sp_packet_dealloc`. + /// + [DllImport(__DllName, EntryPoint = "sp_packet_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern Packet* sp_packet_clone(Packet* @this); + /// /// Deallocates a `Packet`. /// @@ -1076,13 +1091,6 @@ namespace ServicePoint.BindGen { } - [StructLayout(LayoutKind.Sequential)] - public unsafe partial struct ByteSlice - { - public byte* start; - public nuint length; - } - [StructLayout(LayoutKind.Sequential)] public unsafe partial struct Connection { @@ -1093,6 +1101,13 @@ namespace ServicePoint.BindGen { } + [StructLayout(LayoutKind.Sequential)] + public unsafe partial struct ByteSlice + { + public byte* start; + public nuint length; + } + [StructLayout(LayoutKind.Sequential)] public unsafe partial struct Packet { diff --git a/crates/servicepoint_binding_cs/build.rs b/crates/servicepoint_binding_cs/build.rs index 648324d..a74e7ff 100644 --- a/crates/servicepoint_binding_cs/build.rs +++ b/crates/servicepoint_binding_cs/build.rs @@ -13,23 +13,18 @@ fn main() { .input_extern_file("../servicepoint_binding_c/src/lib.rs") .input_extern_file("../servicepoint_binding_c/src/c_slice.rs") .input_extern_file("../servicepoint_binding_c/src/packet.rs") - .input_extern_file("../servicepoint/src/command.rs") - .input_extern_file("../servicepoint/src/connection.rs") - .input_extern_file("../servicepoint/src/pixel_grid.rs") - .input_extern_file("../servicepoint/src/lib.rs") - .input_extern_file("../servicepoint/src/packet.rs") - .input_extern_file("../servicepoint/src/compression_code.rs") + .input_extern_file("../servicepoint_binding_c/src/constants.rs") .csharp_dll_name("servicepoint_binding_c") .csharp_namespace("ServicePoint.BindGen") .csharp_use_nint_types(true) .csharp_class_accessibility("public") .csharp_generate_const_filter(|_| true) .csharp_type_rename(move |name| { - if name.len() > 1 - && name.starts_with("C") - && name.chars().nth(1).unwrap().is_uppercase() + if name.len() > 2 + && name.starts_with("SP") + && name.chars().nth(2).unwrap().is_uppercase() { - name[1..].to_string() + name[2..].to_string() } else { name }