add ability to send commands directly in C code, annotate which functions may return null

This commit is contained in:
Vinzenz Schroeter 2024-09-07 14:35:16 +02:00
parent 53f05efb3d
commit acc35b6727
13 changed files with 138 additions and 29 deletions

View file

@ -25,8 +25,7 @@ int main(void) {
sp_pixel_grid_fill(pixels, true); sp_pixel_grid_fill(pixels, true);
SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed); SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed);
SPPacket *packet = sp_packet_from_command(command); while (sp_connection_send(connection, sp_command_clone(command)));
while (sp_connection_send(connection, sp_packet_clone(packet)));
sp_packet_free(packet); sp_packet_free(packet);
sp_connection_free(connection); sp_connection_free(connection);

View file

@ -306,7 +306,7 @@ struct SPBitVec *sp_bit_vec_load(const uint8_t *data,
* *
* - `size`: size in bits. * - `size`: size in bits.
* *
* returns: `SPBitVec` with all bits set to false. * returns: `SPBitVec` with all bits set to false. Will never return NULL.
* *
* # Panics * # Panics
* *
@ -468,7 +468,7 @@ struct SPBrightnessGrid *sp_brightness_grid_load(size_t width,
/** /**
* Creates a new `SPBrightnessGrid` with the specified dimensions. * Creates a new `SPBrightnessGrid` with the specified dimensions.
* *
* returns: `SPBrightnessGrid` initialized to 0. * returns: `SPBrightnessGrid` initialized to 0. Will never return NULL.
* *
* # Safety * # Safety
* *
@ -615,7 +615,9 @@ struct SPCommand *sp_command_bitmap_linear_or(size_t offset,
* Allocates a new `Command::BitmapLinearWin` instance. * Allocates a new `Command::BitmapLinearWin` instance.
* The passed `SPPixelGrid` gets consumed. * The passed `SPPixelGrid` gets consumed.
* *
* Sets a window of pixels to the specified values * Sets a window of pixels to the specified values.
*
* Will never return NULL.
* *
* # Safety * # Safety
* *
@ -738,6 +740,8 @@ struct SPCommand *sp_command_clone(const struct SPCommand *original);
* Because Rust expects UTF-8 strings, it might be necessary to only send ASCII for now. * Because Rust expects UTF-8 strings, it might be necessary to only send ASCII for now.
* </div> * </div>
* *
* Will never return NULL.
*
* # Safety * # Safety
* *
* The caller has to make sure that: * The caller has to make sure that:
@ -845,6 +849,23 @@ void sp_connection_free(struct SPConnection *ptr);
*/ */
struct SPConnection *sp_connection_open(const char *host); struct SPConnection *sp_connection_open(const char *host);
/**
* Sends a `SPCommand` to the display using the `SPConnection`.
* The passed `SPCommand` gets consumed.
*
* returns: true in case of success
*
* # Safety
*
* The caller has to make sure that:
*
* - `connection` points to a valid instance of `SPConnection`
* - `command` points to a valid instance of `SPPacket`
* - `command` is not used concurrently or after this call
*/
bool sp_connection_send_command(const struct SPConnection *connection,
struct SPCommand *command);
/** /**
* Sends a `SPPacket` to the display using the `SPConnection`. * Sends a `SPPacket` to the display using the `SPConnection`.
* The passed `SPPacket` gets consumed. * The passed `SPPacket` gets consumed.
@ -859,12 +880,14 @@ struct SPConnection *sp_connection_open(const char *host);
* - `SPPacket` points to a valid instance of `SPPacket` * - `SPPacket` points to a valid instance of `SPPacket`
* - `SPPacket` is not used concurrently or after this call * - `SPPacket` is not used concurrently or after this call
*/ */
bool sp_connection_send(const struct SPConnection *connection, bool sp_connection_send_packet(const struct SPConnection *connection,
struct SPPacket *packet); struct SPPacket *packet);
/** /**
* Clones a `SPCp437Grid`. * Clones a `SPCp437Grid`.
* *
* Will never return NULL.
*
* # Safety * # Safety
* *
* The caller has to make sure that: * The caller has to make sure that:
@ -945,6 +968,8 @@ size_t sp_cp437_grid_height(const struct SPCp437Grid *this_);
/** /**
* Loads a `SPCp437Grid` with the specified dimensions from the provided data. * Loads a `SPCp437Grid` with the specified dimensions from the provided data.
* *
* Will never return NULL.
*
* # Panics * # Panics
* *
* When the provided `data_length` is not sufficient for the `height` and `width` * When the provided `data_length` is not sufficient for the `height` and `width`
@ -1008,6 +1033,8 @@ void sp_cp437_grid_set(struct SPCp437Grid *this_,
/** /**
* Gets an unsafe reference to the data of the `SPCp437Grid` instance. * Gets an unsafe reference to the data of the `SPCp437Grid` instance.
* *
* Will never return NULL.
*
* ## Safety * ## Safety
* *
* The caller has to make sure that: * The caller has to make sure that:
@ -1036,6 +1063,8 @@ size_t sp_cp437_grid_width(const struct SPCp437Grid *this_);
/** /**
* Clones a `SPPacket`. * Clones a `SPPacket`.
* *
* Will never return NULL.
*
* # Safety * # Safety
* *
* The caller has to make sure that: * The caller has to make sure that:
@ -1063,6 +1092,8 @@ void sp_packet_free(struct SPPacket *this_);
* Turns a `SPCommand` into a `SPPacket`. * Turns a `SPCommand` into a `SPPacket`.
* The `SPCommand` gets consumed. * The `SPCommand` gets consumed.
* *
* Will never return NULL.
*
* # Safety * # Safety
* *
* The caller has to make sure that: * The caller has to make sure that:
@ -1094,6 +1125,8 @@ struct SPPacket *sp_packet_try_load(const uint8_t *data,
/** /**
* Clones a `SPPixelGrid`. * Clones a `SPPixelGrid`.
* *
* Will never return NULL.
*
* # Safety * # Safety
* *
* The caller has to make sure that: * The caller has to make sure that:
@ -1179,7 +1212,7 @@ size_t sp_pixel_grid_height(const struct SPPixelGrid *this_);
* - `width`: size in pixels in x-direction * - `width`: size in pixels in x-direction
* - `height`: size in pixels in y-direction * - `height`: size in pixels in y-direction
* *
* returns: `SPPixelGrid` that contains a copy of the provided data * returns: `SPPixelGrid` that contains a copy of the provided data. Will never return NULL.
* *
* # Panics * # Panics
* *
@ -1207,7 +1240,7 @@ struct SPPixelGrid *sp_pixel_grid_load(size_t width,
* - `width`: size in pixels in x-direction * - `width`: size in pixels in x-direction
* - `height`: size in pixels in y-direction * - `height`: size in pixels in y-direction
* *
* returns: `SPPixelGrid` initialized to all pixels off * returns: `SPPixelGrid` initialized to all pixels off. Will never return NULL.
* *
* # Panics * # Panics
* *

View file

@ -10,10 +10,9 @@ int main(void) {
sp_pixel_grid_fill(pixels, true); sp_pixel_grid_fill(pixels, true);
SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed); SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed);
SPPacket *packet = sp_packet_from_command(command); while (sp_connection_send_command(connection, sp_command_clone(command)));
while (sp_connection_send(connection, sp_packet_clone(packet)));
sp_packet_free(packet); sp_command_free(command);
sp_connection_free(connection); sp_connection_free(connection);
return 0; return 0;
} }

View file

@ -39,7 +39,7 @@ impl Clone for SPBitVec {
/// ///
/// - `size`: size in bits. /// - `size`: size in bits.
/// ///
/// returns: `SPBitVec` with all bits set to false. /// returns: `SPBitVec` with all bits set to false. Will never return NULL.
/// ///
/// # Panics /// # Panics
/// ///

View file

@ -35,7 +35,7 @@ impl Clone for SPBrightnessGrid {
/// Creates a new `SPBrightnessGrid` with the specified dimensions. /// Creates a new `SPBrightnessGrid` with the specified dimensions.
/// ///
/// returns: `SPBrightnessGrid` initialized to 0. /// returns: `SPBrightnessGrid` initialized to 0. Will never return NULL.
/// ///
/// # Safety /// # Safety
/// ///

View file

@ -314,6 +314,8 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
/// Because Rust expects UTF-8 strings, it might be necessary to only send ASCII for now. /// Because Rust expects UTF-8 strings, it might be necessary to only send ASCII for now.
/// </div> /// </div>
/// ///
/// Will never return NULL.
///
/// # Safety /// # Safety
/// ///
/// The caller has to make sure that: /// The caller has to make sure that:
@ -338,7 +340,9 @@ pub unsafe extern "C" fn sp_command_cp437_data(
/// Allocates a new `Command::BitmapLinearWin` instance. /// Allocates a new `Command::BitmapLinearWin` instance.
/// The passed `SPPixelGrid` gets consumed. /// The passed `SPPixelGrid` gets consumed.
/// ///
/// Sets a window of pixels to the specified values /// Sets a window of pixels to the specified values.
///
/// Will never return NULL.
/// ///
/// # Safety /// # Safety
/// ///

View file

@ -5,7 +5,7 @@
use std::ffi::{c_char, CStr}; use std::ffi::{c_char, CStr};
use std::ptr::null_mut; use std::ptr::null_mut;
use crate::SPPacket; use crate::{SPCommand, SPPacket};
/// A connection to the display. /// A connection to the display.
/// ///
@ -58,7 +58,7 @@ pub unsafe extern "C" fn sp_connection_open(
/// - `SPPacket` points to a valid instance of `SPPacket` /// - `SPPacket` points to a valid instance of `SPPacket`
/// - `SPPacket` is not used concurrently or after this call /// - `SPPacket` is not used concurrently or after this call
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_connection_send( pub unsafe extern "C" fn sp_connection_send_packet(
connection: *const SPConnection, connection: *const SPConnection,
packet: *mut SPPacket, packet: *mut SPPacket,
) -> bool { ) -> bool {
@ -66,6 +66,27 @@ pub unsafe extern "C" fn sp_connection_send(
(*connection).0.send((*packet).0).is_ok() (*connection).0.send((*packet).0).is_ok()
} }
/// Sends a `SPCommand` to the display using the `SPConnection`.
/// The passed `SPCommand` gets consumed.
///
/// returns: true in case of success
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `connection` points to a valid instance of `SPConnection`
/// - `command` points to a valid instance of `SPPacket`
/// - `command` is not used concurrently or after this call
#[no_mangle]
pub unsafe extern "C" fn sp_connection_send_command(
connection: *const SPConnection,
command: *mut SPCommand,
) -> bool {
let command = (*Box::from_raw(command)).0;
(*connection).0.send(command).is_ok()
}
/// Closes and deallocates a `SPConnection`. /// Closes and deallocates a `SPConnection`.
/// ///
/// # Safety /// # Safety

View file

@ -51,6 +51,8 @@ pub unsafe extern "C" fn sp_cp437_grid_new(
/// Loads a `SPCp437Grid` with the specified dimensions from the provided data. /// Loads a `SPCp437Grid` with the specified dimensions from the provided data.
/// ///
/// Will never return NULL.
///
/// # Panics /// # Panics
/// ///
/// When the provided `data_length` is not sufficient for the `height` and `width` /// When the provided `data_length` is not sufficient for the `height` and `width`
@ -78,6 +80,8 @@ pub unsafe extern "C" fn sp_cp437_grid_load(
/// Clones a `SPCp437Grid`. /// Clones a `SPCp437Grid`.
/// ///
/// Will never return NULL.
///
/// # Safety /// # Safety
/// ///
/// The caller has to make sure that: /// The caller has to make sure that:
@ -219,6 +223,8 @@ pub unsafe extern "C" fn sp_cp437_grid_height(
/// Gets an unsafe reference to the data of the `SPCp437Grid` instance. /// Gets an unsafe reference to the data of the `SPCp437Grid` instance.
/// ///
/// Will never return NULL.
///
/// ## Safety /// ## Safety
/// ///
/// The caller has to make sure that: /// The caller has to make sure that:

View file

@ -17,8 +17,7 @@
//! sp_pixel_grid_fill(pixels, true); //! sp_pixel_grid_fill(pixels, true);
//! //!
//! SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed); //! SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed);
//! SPPacket *packet = sp_packet_from_command(command); //! while (sp_connection_send(connection, sp_command_clone(command)));
//! while (sp_connection_send(connection, sp_packet_clone(packet)));
//! //!
//! sp_packet_free(packet); //! sp_packet_free(packet);
//! sp_connection_free(connection); //! sp_connection_free(connection);

View file

@ -12,6 +12,8 @@ pub struct SPPacket(pub(crate) servicepoint::Packet);
/// Turns a `SPCommand` into a `SPPacket`. /// Turns a `SPCommand` into a `SPPacket`.
/// The `SPCommand` gets consumed. /// The `SPCommand` gets consumed.
/// ///
/// Will never return NULL.
///
/// # Safety /// # Safety
/// ///
/// The caller has to make sure that: /// The caller has to make sure that:
@ -55,6 +57,8 @@ pub unsafe extern "C" fn sp_packet_try_load(
/// Clones a `SPPacket`. /// Clones a `SPPacket`.
/// ///
/// Will never return NULL.
///
/// # Safety /// # Safety
/// ///
/// The caller has to make sure that: /// The caller has to make sure that:

View file

@ -25,7 +25,7 @@ pub struct SPPixelGrid(pub(crate) servicepoint::PixelGrid);
/// - `width`: size in pixels in x-direction /// - `width`: size in pixels in x-direction
/// - `height`: size in pixels in y-direction /// - `height`: size in pixels in y-direction
/// ///
/// returns: `SPPixelGrid` initialized to all pixels off /// returns: `SPPixelGrid` initialized to all pixels off. Will never return NULL.
/// ///
/// # Panics /// # Panics
/// ///
@ -54,7 +54,7 @@ pub unsafe extern "C" fn sp_pixel_grid_new(
/// - `width`: size in pixels in x-direction /// - `width`: size in pixels in x-direction
/// - `height`: size in pixels in y-direction /// - `height`: size in pixels in y-direction
/// ///
/// returns: `SPPixelGrid` that contains a copy of the provided data /// returns: `SPPixelGrid` that contains a copy of the provided data. Will never return NULL.
/// ///
/// # Panics /// # Panics
/// ///
@ -83,6 +83,8 @@ pub unsafe extern "C" fn sp_pixel_grid_load(
/// Clones a `SPPixelGrid`. /// Clones a `SPPixelGrid`.
/// ///
/// Will never return NULL.
///
/// # Safety /// # Safety
/// ///
/// The caller has to make sure that: /// The caller has to make sure that:

View file

@ -26,7 +26,7 @@ namespace ServicePoint.BindGen
/// ///
/// - `size`: size in bits. /// - `size`: size in bits.
/// ///
/// returns: `SPBitVec` with all bits set to false. /// returns: `SPBitVec` with all bits set to false. Will never return NULL.
/// ///
/// # Panics /// # Panics
/// ///
@ -195,7 +195,7 @@ namespace ServicePoint.BindGen
/// <summary> /// <summary>
/// Creates a new `SPBrightnessGrid` with the specified dimensions. /// Creates a new `SPBrightnessGrid` with the specified dimensions.
/// ///
/// returns: `SPBrightnessGrid` initialized to 0. /// returns: `SPBrightnessGrid` initialized to 0. Will never return NULL.
/// ///
/// # Safety /// # Safety
/// ///
@ -597,6 +597,8 @@ namespace ServicePoint.BindGen
/// Because Rust expects UTF-8 strings, it might be necessary to only send ASCII for now. /// Because Rust expects UTF-8 strings, it might be necessary to only send ASCII for now.
/// &lt;/div&gt; /// &lt;/div&gt;
/// ///
/// Will never return NULL.
///
/// # Safety /// # Safety
/// ///
/// The caller has to make sure that: /// The caller has to make sure that:
@ -613,7 +615,9 @@ namespace ServicePoint.BindGen
/// Allocates a new `Command::BitmapLinearWin` instance. /// Allocates a new `Command::BitmapLinearWin` instance.
/// The passed `SPPixelGrid` gets consumed. /// The passed `SPPixelGrid` gets consumed.
/// ///
/// Sets a window of pixels to the specified values /// Sets a window of pixels to the specified values.
///
/// Will never return NULL.
/// ///
/// # Safety /// # Safety
/// ///
@ -682,9 +686,27 @@ namespace ServicePoint.BindGen
/// - `SPPacket` points to a valid instance of `SPPacket` /// - `SPPacket` points to a valid instance of `SPPacket`
/// - `SPPacket` is not used concurrently or after this call /// - `SPPacket` is not used concurrently or after this call
/// </summary> /// </summary>
[DllImport(__DllName, EntryPoint = "sp_connection_send", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_connection_send_packet", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)] [return: MarshalAs(UnmanagedType.U1)]
public static extern bool sp_connection_send(Connection* connection, Packet* packet); public static extern bool sp_connection_send_packet(Connection* connection, Packet* packet);
/// <summary>
/// Sends a `SPCommand` to the display using the `SPConnection`.
/// The passed `SPCommand` gets consumed.
///
/// returns: true in case of success
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `connection` points to a valid instance of `SPConnection`
/// - `command` points to a valid instance of `SPPacket`
/// - `command` is not used concurrently or after this call
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_connection_send_command", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool sp_connection_send_command(Connection* connection, Command* command);
/// <summary> /// <summary>
/// Closes and deallocates a `SPConnection`. /// Closes and deallocates a `SPConnection`.
@ -717,6 +739,8 @@ namespace ServicePoint.BindGen
/// <summary> /// <summary>
/// Loads a `SPCp437Grid` with the specified dimensions from the provided data. /// Loads a `SPCp437Grid` with the specified dimensions from the provided data.
/// ///
/// Will never return NULL.
///
/// # Panics /// # Panics
/// ///
/// When the provided `data_length` is not sufficient for the `height` and `width` /// When the provided `data_length` is not sufficient for the `height` and `width`
@ -736,6 +760,8 @@ namespace ServicePoint.BindGen
/// <summary> /// <summary>
/// Clones a `SPCp437Grid`. /// Clones a `SPCp437Grid`.
/// ///
/// Will never return NULL.
///
/// # Safety /// # Safety
/// ///
/// The caller has to make sure that: /// The caller has to make sure that:
@ -862,6 +888,8 @@ namespace ServicePoint.BindGen
/// <summary> /// <summary>
/// Gets an unsafe reference to the data of the `SPCp437Grid` instance. /// Gets an unsafe reference to the data of the `SPCp437Grid` instance.
/// ///
/// Will never return NULL.
///
/// ## Safety /// ## Safety
/// ///
/// The caller has to make sure that: /// The caller has to make sure that:
@ -877,6 +905,8 @@ namespace ServicePoint.BindGen
/// Turns a `SPCommand` into a `SPPacket`. /// Turns a `SPCommand` into a `SPPacket`.
/// The `SPCommand` gets consumed. /// The `SPCommand` gets consumed.
/// ///
/// Will never return NULL.
///
/// # Safety /// # Safety
/// ///
/// The caller has to make sure that: /// The caller has to make sure that:
@ -909,6 +939,8 @@ namespace ServicePoint.BindGen
/// <summary> /// <summary>
/// Clones a `SPPacket`. /// Clones a `SPPacket`.
/// ///
/// Will never return NULL.
///
/// # Safety /// # Safety
/// ///
/// The caller has to make sure that: /// The caller has to make sure that:
@ -942,7 +974,7 @@ namespace ServicePoint.BindGen
/// - `width`: size in pixels in x-direction /// - `width`: size in pixels in x-direction
/// - `height`: size in pixels in y-direction /// - `height`: size in pixels in y-direction
/// ///
/// returns: `SPPixelGrid` initialized to all pixels off /// returns: `SPPixelGrid` initialized to all pixels off. Will never return NULL.
/// ///
/// # Panics /// # Panics
/// ///
@ -966,7 +998,7 @@ namespace ServicePoint.BindGen
/// - `width`: size in pixels in x-direction /// - `width`: size in pixels in x-direction
/// - `height`: size in pixels in y-direction /// - `height`: size in pixels in y-direction
/// ///
/// returns: `SPPixelGrid` that contains a copy of the provided data /// returns: `SPPixelGrid` that contains a copy of the provided data. Will never return NULL.
/// ///
/// # Panics /// # Panics
/// ///
@ -987,6 +1019,8 @@ namespace ServicePoint.BindGen
/// <summary> /// <summary>
/// Clones a `SPPixelGrid`. /// Clones a `SPPixelGrid`.
/// ///
/// Will never return NULL.
///
/// # Safety /// # Safety
/// ///
/// The caller has to make sure that: /// The caller has to make sure that:

View file

@ -20,7 +20,15 @@ public sealed class Connection : SpNativeInstance<BindGen.Connection>
{ {
unsafe unsafe
{ {
return NativeMethods.sp_connection_send(Instance, packet.Into()); return NativeMethods.sp_connection_send_packet(Instance, packet.Into());
}
}
public bool Send(Command command)
{
unsafe
{
return NativeMethods.sp_connection_send_command(Instance, command.Into());
} }
} }