WIP: next #1

Draft
vinzenz wants to merge 25 commits from next into main
11 changed files with 196 additions and 1938 deletions
Showing only changes of commit 7c8ede61b0 - Show all commits

View file

@ -82,6 +82,21 @@ You have the choice of linking statically (recommended) or dynamically.
- documentation is included in the header and - documentation is included in the header and
available [online](https://docs.rs/servicepoint_binding_c/latest/servicepoint_binding_c/) available [online](https://docs.rs/servicepoint_binding_c/latest/servicepoint_binding_c/)
## Safety
Functions expect that C code honors NonNull annotations.
Any created instances have to be freed in some way.
Pointers to those instances cannot be used anymore after that.
Instances cannot be shared between threads and need to be locked in the using code.
Enum values have to be used as-is. Do not pass values that are not part of the enum.
UTF-8 or UTF-32 encoding has to be used properly.
Brightness values provided as u8 parameters must be in range.
## Everything else ## Everything else
Look at the main project [README](https://git.berlin.ccc.de/servicepoint/servicepoint/src/branch/main/README.md) for Look at the main project [README](https://git.berlin.ccc.de/servicepoint/servicepoint/src/branch/main/README.md) for

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
use servicepoint::{Bitmap, DataRef, Grid}; use servicepoint::{Bitmap, DataRef, Grid};
use std::ptr::NonNull; use std::ptr::NonNull;
use crate::byte_slice::SPByteSlice; use crate::byte_slice::ByteSlice;
/// Creates a new [Bitmap] with the specified dimensions. /// Creates a new [Bitmap] with the specified dimensions.
/// ///
@ -18,13 +18,6 @@ use crate::byte_slice::SPByteSlice;
/// ///
/// - when the width is not dividable by 8 /// - when the width is not dividable by 8
/// ///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_bitmap_free`.
///
/// # Examples /// # Examples
/// ///
/// ```C /// ```C
@ -47,14 +40,7 @@ pub unsafe extern "C" fn sp_bitmap_new(
/// Creates a new [Bitmap] with a size matching the screen. /// Creates a new [Bitmap] with a size matching the screen.
/// ///
/// returns: [Bitmap] initialized to all pixels off. Will never return NULL. /// returns: [Bitmap] initialized to all pixels off.
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling [sp_bitmap_free].
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull<Bitmap> { pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull<Bitmap> {
let result = Box::new(Bitmap::max_sized()); let result = Box::new(Bitmap::max_sized());
@ -69,30 +55,11 @@ pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull<Bitmap> {
/// - `height`: size in pixels in y-direction /// - `height`: size in pixels in y-direction
/// ///
/// returns: [Bitmap] that contains a copy of the provided data, or NULL in case of an error. /// returns: [Bitmap] that contains a copy of the provided data, or NULL in case of an error.
///
/// # Errors
///
/// In the following cases, this function will return NULL:
///
/// - when the dimensions and data size do not match exactly.
/// - when the width is not dividable by 8
///
/// # Panics
///
/// - when `data` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `data` points to a valid memory location of at least `data_length` bytes in size.
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_bitmap_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_load( pub unsafe extern "C" fn sp_bitmap_load(
width: usize, width: usize,
height: usize, height: usize,
data: SPByteSlice, data: ByteSlice,
) -> *mut Bitmap { ) -> *mut Bitmap {
let data = unsafe { data.as_slice() }; let data = unsafe { data.as_slice() };
if let Ok(bitmap) = Bitmap::load(width, height, data) { if let Ok(bitmap) = Bitmap::load(width, height, data) {
@ -103,21 +70,6 @@ pub unsafe extern "C" fn sp_bitmap_load(
} }
/// Clones a [Bitmap]. /// Clones a [Bitmap].
///
/// Will never return NULL.
///
/// # Panics
///
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [Bitmap]
/// - `bitmap` is not written to concurrently
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_bitmap_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_clone( pub unsafe extern "C" fn sp_bitmap_clone(
bitmap: NonNull<Bitmap>, bitmap: NonNull<Bitmap>,
@ -127,18 +79,6 @@ pub unsafe extern "C" fn sp_bitmap_clone(
} }
/// Deallocates a [Bitmap]. /// Deallocates a [Bitmap].
///
/// # Panics
///
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [Bitmap]
///
/// [TypedCommand]: [crate::TypedCommand]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_free(bitmap: NonNull<Bitmap>) { pub unsafe extern "C" fn sp_bitmap_free(bitmap: NonNull<Bitmap>) {
_ = unsafe { Box::from_raw(bitmap.as_ptr()) }; _ = unsafe { Box::from_raw(bitmap.as_ptr()) };
@ -153,15 +93,7 @@ pub unsafe extern "C" fn sp_bitmap_free(bitmap: NonNull<Bitmap>) {
/// ///
/// # Panics /// # Panics
/// ///
/// - when `bitmap` is NULL
/// - when accessing `x` or `y` out of bounds /// - when accessing `x` or `y` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [Bitmap]
/// - `bitmap` is not written to concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_get( pub unsafe extern "C" fn sp_bitmap_get(
bitmap: NonNull<Bitmap>, bitmap: NonNull<Bitmap>,
@ -179,19 +111,9 @@ pub unsafe extern "C" fn sp_bitmap_get(
/// - `x` and `y`: position of the cell /// - `x` and `y`: position of the cell
/// - `value`: the value to write to the cell /// - `value`: the value to write to the cell
/// ///
/// returns: old value of the cell
///
/// # Panics /// # Panics
/// ///
/// - when `bitmap` is NULL
/// - when accessing `x` or `y` out of bounds /// - when accessing `x` or `y` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [Bitmap]
/// - `bitmap` is not written to or read from concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_set( pub unsafe extern "C" fn sp_bitmap_set(
bitmap: NonNull<Bitmap>, bitmap: NonNull<Bitmap>,
@ -208,17 +130,6 @@ pub unsafe extern "C" fn sp_bitmap_set(
/// ///
/// - `bitmap`: instance to write to /// - `bitmap`: instance to write to
/// - `value`: the value to set all pixels to /// - `value`: the value to set all pixels to
///
/// # Panics
///
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [Bitmap]
/// - `bitmap` is not written to or read from concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_fill(bitmap: NonNull<Bitmap>, value: bool) { pub unsafe extern "C" fn sp_bitmap_fill(bitmap: NonNull<Bitmap>, value: bool) {
unsafe { (*bitmap.as_ptr()).fill(value) }; unsafe { (*bitmap.as_ptr()).fill(value) };
@ -249,16 +160,6 @@ pub unsafe extern "C" fn sp_bitmap_width(bitmap: NonNull<Bitmap>) -> usize {
/// # Arguments /// # Arguments
/// ///
/// - `bitmap`: instance to read from /// - `bitmap`: instance to read from
///
/// # Panics
///
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [Bitmap]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_height(bitmap: NonNull<Bitmap>) -> usize { pub unsafe extern "C" fn sp_bitmap_height(bitmap: NonNull<Bitmap>) -> usize {
unsafe { bitmap.as_ref().height() } unsafe { bitmap.as_ref().height() }
@ -266,20 +167,10 @@ pub unsafe extern "C" fn sp_bitmap_height(bitmap: NonNull<Bitmap>) -> usize {
/// Gets an unsafe reference to the data of the [Bitmap] instance. /// Gets an unsafe reference to the data of the [Bitmap] instance.
/// ///
/// # Panics /// The returned memory is valid for the lifetime of the bitmap.
///
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [Bitmap]
/// - the returned memory range is never accessed after the passed [Bitmap] has been freed
/// - the returned memory range is never accessed concurrently, either via the [Bitmap] or directly
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref( pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref(
mut bitmap: NonNull<Bitmap>, mut bitmap: NonNull<Bitmap>,
) -> SPByteSlice { ) -> ByteSlice {
unsafe { SPByteSlice::from_slice(bitmap.as_mut().data_ref_mut()) } unsafe { ByteSlice::from_slice(bitmap.as_mut().data_ref_mut()) }
} }

View file

@ -1,9 +1,6 @@
//! C functions for interacting with [SPBitVec]s use crate::ByteSlice;
//!
//! prefix `sp_bitvec_`
use crate::SPByteSlice;
use std::ptr::NonNull; use std::ptr::NonNull;
use servicepoint::BitVecU8Msb0;
/// A vector of bits /// A vector of bits
/// ///
@ -13,7 +10,7 @@ use std::ptr::NonNull;
/// sp_bitvec_set(vec, 5, true); /// sp_bitvec_set(vec, 5, true);
/// sp_bitvec_free(vec); /// sp_bitvec_free(vec);
/// ``` /// ```
pub struct SPBitVec(pub(crate) servicepoint::BitVecU8Msb0); pub struct SPBitVec(pub(crate) BitVecU8Msb0);
impl Clone for SPBitVec { impl Clone for SPBitVec {
fn clone(&self) -> Self { fn clone(&self) -> Self {
@ -27,67 +24,31 @@ impl Clone for SPBitVec {
/// ///
/// - `size`: size in bits. /// - `size`: size in bits.
/// ///
/// returns: [SPBitVec] with all bits set to false. Will never return NULL. /// returns: [SPBitVec] with all bits set to false.
/// ///
/// # Panics /// # Panics
/// ///
/// - when `size` is not divisible by 8. /// - when `size` is not divisible by 8.
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_bitvec_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_new(size: usize) -> NonNull<SPBitVec> { pub unsafe extern "C" fn sp_bitvec_new(size: usize) -> NonNull<SPBitVec> {
let result = let result =
Box::new(SPBitVec(servicepoint::BitVecU8Msb0::repeat(false, size))); Box::new(SPBitVec(BitVecU8Msb0::repeat(false, size)));
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
/// Interpret the data as a series of bits and load then into a new [SPBitVec] instance. /// Interpret the data as a series of bits and load then into a new [SPBitVec] instance.
/// ///
/// returns: [SPBitVec] instance containing data. Will never return NULL. /// returns: [SPBitVec] instance containing data.
///
/// # Panics
///
/// - when `data` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `data` points to a valid memory location of at least `data_length`
/// bytes in size.
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_bitvec_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_load( pub unsafe extern "C" fn sp_bitvec_load(
data: SPByteSlice, data: ByteSlice,
) -> NonNull<SPBitVec> { ) -> NonNull<SPBitVec> {
let data = unsafe { data.as_slice() }; let data = unsafe { data.as_slice() };
let result = let result = Box::new(SPBitVec(BitVecU8Msb0::from_slice(data)));
Box::new(SPBitVec(servicepoint::BitVecU8Msb0::from_slice(data)));
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(result))
} }
/// Clones a [SPBitVec]. /// Clones a [SPBitVec].
///
/// returns: new [SPBitVec] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bit_vec` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid [SPBitVec]
/// - `bit_vec` is not written to concurrently
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_bitvec_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_clone( pub unsafe extern "C" fn sp_bitvec_clone(
bit_vec: NonNull<SPBitVec>, bit_vec: NonNull<SPBitVec>,
@ -97,20 +58,6 @@ pub unsafe extern "C" fn sp_bitvec_clone(
} }
/// Deallocates a [SPBitVec]. /// Deallocates a [SPBitVec].
///
/// # Panics
///
/// - when `but_vec` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `bit_vec` was not passed to another consuming function, e.g. to create a [TypedCommand]
///
/// [TypedCommand]: [crate::TypedCommand]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_free(bit_vec: NonNull<SPBitVec>) { pub unsafe extern "C" fn sp_bitvec_free(bit_vec: NonNull<SPBitVec>) {
_ = unsafe { Box::from_raw(bit_vec.as_ptr()) }; _ = unsafe { Box::from_raw(bit_vec.as_ptr()) };
@ -127,15 +74,7 @@ pub unsafe extern "C" fn sp_bitvec_free(bit_vec: NonNull<SPBitVec>) {
/// ///
/// # Panics /// # Panics
/// ///
/// - when `bit_vec` is NULL
/// - when accessing `index` out of bounds /// - when accessing `index` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid [SPBitVec]
/// - `bit_vec` is not written to concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_get( pub unsafe extern "C" fn sp_bitvec_get(
bit_vec: NonNull<SPBitVec>, bit_vec: NonNull<SPBitVec>,
@ -154,15 +93,7 @@ pub unsafe extern "C" fn sp_bitvec_get(
/// ///
/// # Panics /// # Panics
/// ///
/// - when `bit_vec` is NULL
/// - when accessing `index` out of bounds /// - when accessing `index` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid [SPBitVec]
/// - `bit_vec` is not written to or read from concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_set( pub unsafe extern "C" fn sp_bitvec_set(
bit_vec: NonNull<SPBitVec>, bit_vec: NonNull<SPBitVec>,
@ -178,17 +109,6 @@ pub unsafe extern "C" fn sp_bitvec_set(
/// ///
/// - `bit_vec`: instance to write to /// - `bit_vec`: instance to write to
/// - `value`: the value to set all bits to /// - `value`: the value to set all bits to
///
/// # Panics
///
/// - when `bit_vec` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid [SPBitVec]
/// - `bit_vec` is not written to or read from concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_fill( pub unsafe extern "C" fn sp_bitvec_fill(
bit_vec: NonNull<SPBitVec>, bit_vec: NonNull<SPBitVec>,
@ -202,16 +122,6 @@ pub unsafe extern "C" fn sp_bitvec_fill(
/// # Arguments /// # Arguments
/// ///
/// - `bit_vec`: instance to write to /// - `bit_vec`: instance to write to
///
/// # Panics
///
/// - when `bit_vec` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid [SPBitVec]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_len(bit_vec: NonNull<SPBitVec>) -> usize { pub unsafe extern "C" fn sp_bitvec_len(bit_vec: NonNull<SPBitVec>) -> usize {
unsafe { bit_vec.as_ref().0.len() } unsafe { bit_vec.as_ref().0.len() }
@ -222,16 +132,6 @@ pub unsafe extern "C" fn sp_bitvec_len(bit_vec: NonNull<SPBitVec>) -> usize {
/// # Arguments /// # Arguments
/// ///
/// - `bit_vec`: instance to write to /// - `bit_vec`: instance to write to
///
/// # Panics
///
/// - when `bit_vec` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid [SPBitVec]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_is_empty( pub unsafe extern "C" fn sp_bitvec_is_empty(
bit_vec: NonNull<SPBitVec>, bit_vec: NonNull<SPBitVec>,
@ -241,24 +141,14 @@ pub unsafe extern "C" fn sp_bitvec_is_empty(
/// Gets an unsafe reference to the data of the [SPBitVec] instance. /// Gets an unsafe reference to the data of the [SPBitVec] instance.
/// ///
/// The returned memory is valid for the lifetime of the bitvec.
///
/// # Arguments /// # Arguments
/// ///
/// - `bit_vec`: instance to write to /// - `bit_vec`: instance to write to
///
/// # Panics
///
/// - when `bit_vec` is NULL
///
/// ## Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid [SPBitVec]
/// - the returned memory range is never accessed after the passed [SPBitVec] has been freed
/// - the returned memory range is never accessed concurrently, either via the [SPBitVec] or directly
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_unsafe_data_ref( pub unsafe extern "C" fn sp_bitvec_unsafe_data_ref(
bit_vec: NonNull<SPBitVec>, bit_vec: NonNull<SPBitVec>,
) -> SPByteSlice { ) -> ByteSlice {
unsafe { SPByteSlice::from_slice((*bit_vec.as_ptr()).0.as_raw_mut_slice()) } unsafe { ByteSlice::from_slice((*bit_vec.as_ptr()).0.as_raw_mut_slice()) }
} }

View file

@ -1,39 +1,25 @@
//! C functions for interacting with [BrightnessGrid]s use crate::ByteSlice;
//! use servicepoint::{Brightness, BrightnessGrid, ByteGrid, DataRef, Grid};
//! prefix `sp_brightness_grid_`
//!
//!
//! A grid containing brightness values.
//!
//! # Examples
//! ```C
//! UdpConnection connection = sp_connection_open("127.0.0.1:2342");
//! if (connection == NULL)
//! return 1;
//!
//! BrightnessGrid grid = sp_brightness_grid_new(2, 2);
//! sp_brightness_grid_set(grid, 0, 0, 0);
//! sp_brightness_grid_set(grid, 1, 1, 10);
//!
//! TypedCommand command = sp_command_char_brightness(grid);
//! sp_connection_free(connection);
//! ```
use crate::SPByteSlice;
use servicepoint::{Brightness, BrightnessGrid, DataRef, Grid};
use std::mem::transmute; use std::mem::transmute;
use std::ptr::NonNull; use std::ptr::NonNull;
/// Creates a new [BrightnessGrid] with the specified dimensions. /// Creates a new [BrightnessGrid] with the specified dimensions.
/// ///
/// returns: [BrightnessGrid] initialized to 0. Will never return NULL. /// returns: [BrightnessGrid] initialized to 0.
/// ///
/// # Safety /// # Examples
/// ```C
/// UdpConnection connection = sp_connection_open("127.0.0.1:2342");
/// if (connection == NULL)
/// return 1;
/// ///
/// The caller has to make sure that: /// BrightnessGrid grid = sp_brightness_grid_new(2, 2);
/// sp_brightness_grid_set(grid, 0, 0, 0);
/// sp_brightness_grid_set(grid, 1, 1, 10);
/// ///
/// - the returned instance is freed in some way, either by using a consuming function or /// TypedCommand command = sp_command_char_brightness(grid);
/// by explicitly calling `sp_brightness_grid_free`. /// sp_connection_free(connection);
/// ```
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_new( pub unsafe extern "C" fn sp_brightness_grid_new(
width: usize, width: usize,
@ -45,29 +31,15 @@ pub unsafe extern "C" fn sp_brightness_grid_new(
/// Loads a [BrightnessGrid] with the specified dimensions from the provided data. /// Loads a [BrightnessGrid] with the specified dimensions from the provided data.
/// ///
/// returns: new [BrightnessGrid] instance. Will never return NULL. /// returns: new [BrightnessGrid] instance, or NULL in case of an error.
///
/// # Panics
///
/// - when `data` is NULL
/// - when the provided `data_length` does not match `height` and `width`
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `data` points to a valid memory location of at least `data_length`
/// bytes in size.
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_brightness_grid_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_load( pub unsafe extern "C" fn sp_brightness_grid_load(
width: usize, width: usize,
height: usize, height: usize,
data: SPByteSlice, data: ByteSlice,
) -> *mut BrightnessGrid { ) -> *mut BrightnessGrid {
let data = unsafe { data.as_slice() }; let data = unsafe { data.as_slice() };
let grid = match servicepoint::ByteGrid::load(width, height, data) { let grid = match ByteGrid::load(width, height, data) {
None => return std::ptr::null_mut(), None => return std::ptr::null_mut(),
Some(grid) => grid, Some(grid) => grid,
}; };
@ -79,25 +51,6 @@ pub unsafe extern "C" fn sp_brightness_grid_load(
} }
/// Clones a [BrightnessGrid]. /// Clones a [BrightnessGrid].
///
/// # Arguments
///
/// - `brightness_grid`: instance to read from
///
/// returns: new [BrightnessGrid] instance. Will never return NULL.
///
/// # Panics
///
/// - when `brightness_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `brightness_grid` points to a valid [BrightnessGrid]
/// - `brightness_grid` is not written to concurrently
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_brightness_grid_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_clone( pub unsafe extern "C" fn sp_brightness_grid_clone(
brightness_grid: NonNull<BrightnessGrid>, brightness_grid: NonNull<BrightnessGrid>,
@ -107,24 +60,6 @@ pub unsafe extern "C" fn sp_brightness_grid_clone(
} }
/// Deallocates a [BrightnessGrid]. /// Deallocates a [BrightnessGrid].
///
/// # Arguments
///
/// - `brightness_grid`: instance to read from
///
/// # Panics
///
/// - when `brightness_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `brightness_grid` points to a valid [BrightnessGrid]
/// - `brightness_grid` is not used concurrently or after this call
/// - `brightness_grid` was not passed to another consuming function, e.g. to create a [TypedCommand]
///
/// [TypedCommand]: [crate::TypedCommand]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_free( pub unsafe extern "C" fn sp_brightness_grid_free(
brightness_grid: NonNull<BrightnessGrid>, brightness_grid: NonNull<BrightnessGrid>,
@ -142,16 +77,7 @@ pub unsafe extern "C" fn sp_brightness_grid_free(
/// returns: value at position /// returns: value at position
/// ///
/// # Panics /// # Panics
///
/// - when `brightness_grid` is NULL
/// - When accessing `x` or `y` out of bounds. /// - When accessing `x` or `y` out of bounds.
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `brightness_grid` points to a valid [BrightnessGrid]
/// - `brightness_grid` is not written to concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_get( pub unsafe extern "C" fn sp_brightness_grid_get(
brightness_grid: NonNull<BrightnessGrid>, brightness_grid: NonNull<BrightnessGrid>,
@ -173,16 +99,7 @@ pub unsafe extern "C" fn sp_brightness_grid_get(
/// ///
/// # Panics /// # Panics
/// ///
/// - when `brightness_grid` is NULL
/// - When accessing `x` or `y` out of bounds. /// - When accessing `x` or `y` out of bounds.
/// - When providing an invalid brightness value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `brightness_grid` points to a valid [BrightnessGrid]
/// - `brightness_grid` is not written to or read from concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_set( pub unsafe extern "C" fn sp_brightness_grid_set(
brightness_grid: NonNull<BrightnessGrid>, brightness_grid: NonNull<BrightnessGrid>,
@ -199,18 +116,6 @@ pub unsafe extern "C" fn sp_brightness_grid_set(
/// ///
/// - `brightness_grid`: instance to write to /// - `brightness_grid`: instance to write to
/// - `value`: the value to set all cells to /// - `value`: the value to set all cells to
///
/// # Panics
///
/// - when `brightness_grid` is NULL
/// - When providing an invalid brightness value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `brightness_grid` points to a valid [BrightnessGrid]
/// - `brightness_grid` is not written to or read from concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_fill( pub unsafe extern "C" fn sp_brightness_grid_fill(
brightness_grid: NonNull<BrightnessGrid>, brightness_grid: NonNull<BrightnessGrid>,
@ -226,16 +131,6 @@ pub unsafe extern "C" fn sp_brightness_grid_fill(
/// - `brightness_grid`: instance to read from /// - `brightness_grid`: instance to read from
/// ///
/// returns: width /// returns: width
///
/// # Panics
///
/// - when `brightness_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `brightness_grid` points to a valid [BrightnessGrid]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_width( pub unsafe extern "C" fn sp_brightness_grid_width(
brightness_grid: NonNull<BrightnessGrid>, brightness_grid: NonNull<BrightnessGrid>,
@ -250,16 +145,6 @@ pub unsafe extern "C" fn sp_brightness_grid_width(
/// - `brightness_grid`: instance to read from /// - `brightness_grid`: instance to read from
/// ///
/// returns: height /// returns: height
///
/// # Panics
///
/// - when `brightness_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `brightness_grid` points to a valid [BrightnessGrid]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_height( pub unsafe extern "C" fn sp_brightness_grid_height(
brightness_grid: NonNull<BrightnessGrid>, brightness_grid: NonNull<BrightnessGrid>,
@ -269,30 +154,20 @@ pub unsafe extern "C" fn sp_brightness_grid_height(
/// Gets an unsafe reference to the data of the [BrightnessGrid] instance. /// Gets an unsafe reference to the data of the [BrightnessGrid] instance.
/// ///
/// The returned memory is valid for the lifetime of the brightness grid.
///
/// # Arguments /// # Arguments
/// ///
/// - `brightness_grid`: instance to read from /// - `brightness_grid`: instance to read from
/// ///
/// returns: slice of bytes underlying the `brightness_grid`. /// returns: slice of bytes underlying the `brightness_grid`.
///
/// # Panics
///
/// - when `brightness_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `brightness_grid` points to a valid [BrightnessGrid]
/// - the returned memory range is never accessed after the passed [BrightnessGrid] has been freed
/// - the returned memory range is never accessed concurrently, either via the [BrightnessGrid] or directly
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref(
brightness_grid: NonNull<BrightnessGrid>, brightness_grid: NonNull<BrightnessGrid>,
) -> SPByteSlice { ) -> ByteSlice {
//noinspection RsAssertEqual //noinspection RsAssertEqual
const _: () = assert!(size_of::<Brightness>() == 1); const _: () = assert!(size_of::<Brightness>() == 1);
let data = unsafe { (*brightness_grid.as_ptr()).data_ref_mut() }; let data = unsafe { (*brightness_grid.as_ptr()).data_ref_mut() };
unsafe { SPByteSlice::from_slice(transmute(data)) } unsafe { ByteSlice::from_slice(transmute(data)) }
} }

View file

@ -2,9 +2,7 @@
use std::ptr::NonNull; use std::ptr::NonNull;
/// Represents a span of memory (`&mut [u8]` ) as a struct usable by C code. /// Represents a span of memory (`&mut [u8]` ) as a struct.
///
/// You should not create an instance of this type in your C code.
/// ///
/// # Safety /// # Safety
/// ///
@ -13,17 +11,15 @@ use std::ptr::NonNull;
/// - accesses to the memory pointed to with `start` is never accessed outside `length` /// - 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 lifetime of the `CByteSlice` does not outlive the memory it points to, as described in
/// the function returning this type. /// the function returning this type.
/// - an instance of this created from C is never passed to a consuming function, as the rust code
/// will try to free the memory of a potentially separate allocator.
#[repr(C)] #[repr(C)]
pub struct SPByteSlice { pub struct ByteSlice {
/// The start address of the memory /// The start address of the memory.
pub start: NonNull<u8>, pub start: NonNull<u8>,
/// The amount of memory in bytes /// The amount of memory in bytes.
pub length: usize, pub length: usize,
} }
impl SPByteSlice { impl ByteSlice {
pub(crate) unsafe fn as_slice(&self) -> &[u8] { pub(crate) unsafe fn as_slice(&self) -> &[u8] {
unsafe { std::slice::from_raw_parts(self.start.as_ptr(), self.length) } unsafe { std::slice::from_raw_parts(self.start.as_ptr(), self.length) }
} }

View file

@ -1,37 +1,19 @@
//! C functions for interacting with [CharGrid]s use crate::ByteSlice;
//!
//! prefix `sp_char_grid_`
//!
//! A C-wrapper for grid containing UTF-8 characters.
//!
//! As the rust [char] type is not FFI-safe, characters are passed in their UTF-32 form as 32bit unsigned integers.
//!
//! The encoding is enforced in most cases by the rust standard library
//! and will panic when provided with illegal characters.
//!
//! # Examples
//!
//! ```C
//! CharGrid grid = sp_char_grid_new(4, 3);
//! sp_char_grid_fill(grid, '?');
//! sp_char_grid_set(grid, 0, 0, '!');
//! sp_char_grid_free(grid);
//! ```
use crate::SPByteSlice;
use servicepoint::{CharGrid, Grid}; use servicepoint::{CharGrid, Grid};
use std::ptr::NonNull; use std::ptr::NonNull;
/// Creates a new [CharGrid] with the specified dimensions. /// Creates a new [CharGrid] with the specified dimensions.
/// ///
/// returns: [CharGrid] initialized to 0. Will never return NULL. /// returns: [CharGrid] initialized to 0.
/// ///
/// # Safety /// # Examples
/// ///
/// The caller has to make sure that: /// ```C
/// /// CharGrid grid = sp_char_grid_new(4, 3);
/// - the returned instance is freed in some way, either by using a consuming function or /// sp_char_grid_fill(grid, '?');
/// by explicitly calling `sp_char_grid_free`. /// sp_char_grid_set(grid, 0, 0, '!');
/// sp_char_grid_free(grid);
/// ```
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_char_grid_new( pub unsafe extern "C" fn sp_char_grid_new(
width: usize, width: usize,
@ -43,80 +25,37 @@ pub unsafe extern "C" fn sp_char_grid_new(
/// Loads a [CharGrid] with the specified dimensions from the provided data. /// Loads a [CharGrid] with the specified dimensions from the provided data.
/// ///
/// Will never return NULL. /// returns: new CharGrid or NULL in case of an error
///
/// # Panics
///
/// - when `data` is NULL
/// - when the provided `data_length` does not match `height` and `width`
/// - when `data` is not valid UTF-8
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `data` points to a valid memory location of at least `data_length`
/// bytes in size.
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_char_grid_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_char_grid_load( pub unsafe extern "C" fn sp_char_grid_load(
width: usize, width: usize,
height: usize, height: usize,
data: SPByteSlice, data: ByteSlice,
) -> NonNull<CharGrid> { ) -> *mut CharGrid {
let data = unsafe { data.as_slice() }; let data = unsafe { data.as_slice() };
// TODO remove unwrap if let Ok(grid) = CharGrid::load_utf8(width, height, data.to_vec()) {
let result = Box::leak(Box::new(grid))
Box::new(CharGrid::load_utf8(width, height, data.to_vec()).unwrap()); } else {
NonNull::from(Box::leak(result)) std::ptr::null_mut()
}
} }
/// Clones a [CharGrid]. /// Clones a [CharGrid].
///
/// Will never return NULL.
///
/// # Panics
///
/// - when `char_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `char_grid` points to a valid [CharGrid]
/// - `char_grid` is not written to concurrently
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_char_grid_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_char_grid_clone( pub unsafe extern "C" fn sp_char_grid_clone(
char_grid: NonNull<CharGrid>, char_grid: NonNull<CharGrid>,
) -> NonNull<CharGrid> { ) -> NonNull<CharGrid> {
let result = Box::new(unsafe { char_grid.as_ref().clone() }); let result = unsafe { char_grid.as_ref().clone() };
NonNull::from(Box::leak(result)) NonNull::from(Box::leak(Box::new(result)))
} }
/// Deallocates a [CharGrid]. /// Deallocates a [CharGrid].
///
/// # Panics
///
/// - when `char_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `char_grid` points to a valid [CharGrid]
/// - `char_grid` is not used concurrently or after char_grid call
/// - `char_grid` was not passed to another consuming function, e.g. to create a [TypedCommand]
///
/// [TypedCommand]: [crate::TypedCommand]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_char_grid_free(char_grid: NonNull<CharGrid>) { pub unsafe extern "C" fn sp_char_grid_free(char_grid: NonNull<CharGrid>) {
_ = unsafe { Box::from_raw(char_grid.as_ptr()) }; _ = unsafe { Box::from_raw(char_grid.as_ptr()) };
} }
/// Gets the current value at the specified position. /// Returns the current value at the specified position.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -125,15 +64,7 @@ pub unsafe extern "C" fn sp_char_grid_free(char_grid: NonNull<CharGrid>) {
/// ///
/// # Panics /// # Panics
/// ///
/// - when `char_grid` is NULL
/// - when accessing `x` or `y` out of bounds /// - when accessing `x` or `y` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `char_grid` points to a valid [CharGrid]
/// - `char_grid` is not written to concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_char_grid_get( pub unsafe extern "C" fn sp_char_grid_get(
char_grid: NonNull<CharGrid>, char_grid: NonNull<CharGrid>,
@ -155,17 +86,7 @@ pub unsafe extern "C" fn sp_char_grid_get(
/// ///
/// # Panics /// # Panics
/// ///
/// - when `char_grid` is NULL
/// - when accessing `x` or `y` out of bounds /// - when accessing `x` or `y` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `char_grid` points to a valid [SPBitVec]
/// - `char_grid` is not written to or read from concurrently
///
/// [SPBitVec]: [crate::SPBitVec]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_char_grid_set( pub unsafe extern "C" fn sp_char_grid_set(
char_grid: NonNull<CharGrid>, char_grid: NonNull<CharGrid>,
@ -182,17 +103,6 @@ pub unsafe extern "C" fn sp_char_grid_set(
/// ///
/// - `char_grid`: instance to write to /// - `char_grid`: instance to write to
/// - `value`: the value to set all cells to /// - `value`: the value to set all cells to
///
/// # Panics
///
/// - when `char_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `char_grid` points to a valid [CharGrid]
/// - `char_grid` is not written to or read from concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_char_grid_fill( pub unsafe extern "C" fn sp_char_grid_fill(
char_grid: NonNull<CharGrid>, char_grid: NonNull<CharGrid>,
@ -206,16 +116,6 @@ pub unsafe extern "C" fn sp_char_grid_fill(
/// # Arguments /// # Arguments
/// ///
/// - `char_grid`: instance to read from /// - `char_grid`: instance to read from
///
/// # Panics
///
/// - when `char_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `char_grid` points to a valid [CharGrid]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_char_grid_width( pub unsafe extern "C" fn sp_char_grid_width(
char_grid: NonNull<CharGrid>, char_grid: NonNull<CharGrid>,
@ -228,16 +128,6 @@ pub unsafe extern "C" fn sp_char_grid_width(
/// # Arguments /// # Arguments
/// ///
/// - `char_grid`: instance to read from /// - `char_grid`: instance to read from
///
/// # Panics
///
/// - when `char_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `char_grid` points to a valid [CharGrid]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_char_grid_height( pub unsafe extern "C" fn sp_char_grid_height(
char_grid: NonNull<CharGrid>, char_grid: NonNull<CharGrid>,

View file

@ -1,43 +1,12 @@
//! C functions for interacting with [TypedCommand]s
//!
//! prefix `sp_command_`
use crate::SPBitVec; use crate::SPBitVec;
use servicepoint::{BinaryOperation, Bitmap, Brightness, BrightnessGrid, CharGrid, CompressionCode, Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand}; use servicepoint::{BinaryOperation, Bitmap, Brightness, BrightnessGrid, CharGrid, CompressionCode, Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand};
use std::ptr::NonNull; use std::ptr::NonNull;
/// A low-level display command.
///
/// This struct and associated functions implement the UDP protocol for the display.
///
/// To send a [TypedCommand], use a [UdpConnection].
///
/// # Examples
///
/// ```C
/// sp_connection_send_command(connection, sp_command_clear());
/// sp_connection_send_command(connection, sp_command_brightness(5));
/// ```
/// Tries to turn a [Packet] into a [TypedCommand]. /// Tries to turn a [Packet] into a [TypedCommand].
/// ///
/// The packet is deallocated in the process. /// The packet is deallocated in the process.
/// ///
/// Returns: pointer to new [TypedCommand] instance or NULL if parsing failed. /// Returns: pointer to new [TypedCommand] instance or NULL if parsing failed.
///
/// # Panics
///
/// - when `packet` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - [Packet] points to a valid instance of [Packet]
/// - [Packet] is not used concurrently or after this call
/// - the result is checked for NULL
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_try_from_packet( pub unsafe extern "C" fn sp_command_try_from_packet(
packet: NonNull<Packet>, packet: NonNull<Packet>,
@ -51,20 +20,7 @@ pub unsafe extern "C" fn sp_command_try_from_packet(
/// Clones a [TypedCommand] instance. /// Clones a [TypedCommand] instance.
/// ///
/// returns: new [TypedCommand] instance. Will never return NULL. /// returns: new [TypedCommand] instance.
///
/// # Panics
///
/// - when `command` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `command` points to a valid instance of [TypedCommand]
/// - `command` is not written to concurrently
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_clone( pub unsafe extern "C" fn sp_command_clone(
command: NonNull<TypedCommand>, command: NonNull<TypedCommand>,
@ -77,20 +33,13 @@ pub unsafe extern "C" fn sp_command_clone(
/// ///
/// Does not affect brightness. /// Does not affect brightness.
/// ///
/// Returns: a new [servicepoint::Command::Clear] instance. Will never return NULL. /// Returns: a new [servicepoint::Command::Clear] instance.
/// ///
/// # Examples /// # Examples
/// ///
/// ```C /// ```C
/// sp_connection_send_command(connection, sp_command_clear()); /// sp_connection_send_command(connection, sp_command_clear());
/// ``` /// ```
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_clear() -> NonNull<TypedCommand> { pub unsafe extern "C" fn sp_command_clear() -> NonNull<TypedCommand> {
let result = Box::new(servicepoint::ClearCommand.into()); let result = Box::new(servicepoint::ClearCommand.into());
@ -101,14 +50,7 @@ pub unsafe extern "C" fn sp_command_clear() -> NonNull<TypedCommand> {
/// ///
/// Please do not send this in your normal program flow. /// Please do not send this in your normal program flow.
/// ///
/// Returns: a new [servicepoint::Command::HardReset] instance. Will never return NULL. /// Returns: a new [servicepoint::Command::HardReset] instance.
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull<TypedCommand> { pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull<TypedCommand> {
let result = Box::new(servicepoint::HardResetCommand.into()); let result = Box::new(servicepoint::HardResetCommand.into());
@ -117,14 +59,7 @@ pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull<TypedCommand> {
/// A yet-to-be-tested command. /// A yet-to-be-tested command.
/// ///
/// Returns: a new [servicepoint::Command::FadeOut] instance. Will never return NULL. /// Returns: a new [servicepoint::Command::FadeOut] instance.
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_fade_out() -> NonNull<TypedCommand> { pub unsafe extern "C" fn sp_command_fade_out() -> NonNull<TypedCommand> {
let result = Box::new(servicepoint::FadeOutCommand.into()); let result = Box::new(servicepoint::FadeOutCommand.into());
@ -133,18 +68,7 @@ pub unsafe extern "C" fn sp_command_fade_out() -> NonNull<TypedCommand> {
/// Set the brightness of all tiles to the same value. /// Set the brightness of all tiles to the same value.
/// ///
/// Returns: a new [servicepoint::Command::Brightness] instance. Will never return NULL. /// Returns: a new [servicepoint::Command::Brightness] instance.
///
/// # Panics
///
/// - When the provided brightness value is out of range (0-11).
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_brightness( pub unsafe extern "C" fn sp_command_brightness(
brightness: Brightness, brightness: Brightness,
@ -157,20 +81,7 @@ pub unsafe extern "C" fn sp_command_brightness(
/// ///
/// The passed [BrightnessGrid] gets consumed. /// The passed [BrightnessGrid] gets consumed.
/// ///
/// Returns: a new [servicepoint::Command::CharBrightness] instance. Will never return NULL. /// Returns: a new [servicepoint::Command::CharBrightness] instance.
///
/// # Panics
///
/// - when `grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `grid` points to a valid instance of [BrightnessGrid]
/// - `grid` is not used concurrently or after this call
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_char_brightness( pub unsafe extern "C" fn sp_command_char_brightness(
x: usize, x: usize,
@ -197,22 +108,7 @@ pub unsafe extern "C" fn sp_command_char_brightness(
/// ///
/// The passed [SPBitVec] gets consumed. /// The passed [SPBitVec] gets consumed.
/// ///
/// Returns: a new [servicepoint::Command::BitmapLinear] instance. Will never return NULL. /// Returns: a new [servicepoint::Command::BitmapLinear] instance.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear( pub unsafe extern "C" fn sp_command_bitmap_linear(
offset: usize, offset: usize,
@ -238,22 +134,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear(
/// ///
/// The passed [SPBitVec] gets consumed. /// The passed [SPBitVec] gets consumed.
/// ///
/// Returns: a new [servicepoint::Command::BitmapLinearAnd] instance. Will never return NULL. /// Returns: a new [servicepoint::Command::BitmapLinearAnd] instance.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_and( pub unsafe extern "C" fn sp_command_bitmap_linear_and(
offset: usize, offset: usize,
@ -279,22 +160,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and(
/// ///
/// The passed [SPBitVec] gets consumed. /// The passed [SPBitVec] gets consumed.
/// ///
/// Returns: a new [servicepoint::Command::BitmapLinearOr] instance. Will never return NULL. /// Returns: a new [servicepoint::Command::BitmapLinearOr] instance.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_or( pub unsafe extern "C" fn sp_command_bitmap_linear_or(
offset: usize, offset: usize,
@ -320,22 +186,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or(
/// ///
/// The passed [SPBitVec] gets consumed. /// The passed [SPBitVec] gets consumed.
/// ///
/// Returns: a new [servicepoint::Command::BitmapLinearXor] instance. Will never return NULL. /// Returns: a new [servicepoint::Command::BitmapLinearXor] instance.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_xor( pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
offset: usize, offset: usize,
@ -352,7 +203,6 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
} }
} }
#[inline]
unsafe fn sp_command_bitmap_linear_internal( unsafe fn sp_command_bitmap_linear_internal(
offset: usize, offset: usize,
bit_vec: NonNull<SPBitVec>, bit_vec: NonNull<SPBitVec>,
@ -378,20 +228,7 @@ unsafe fn sp_command_bitmap_linear_internal(
/// ///
/// The passed [Cp437Grid] gets consumed. /// The passed [Cp437Grid] gets consumed.
/// ///
/// Returns: a new [servicepoint::Command::Cp437Data] instance. Will never return NULL. /// Returns: a new [servicepoint::Command::Cp437Data] instance.
///
/// # Panics
///
/// - when `grid` is null
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `grid` points to a valid instance of [Cp437Grid]
/// - `grid` is not used concurrently or after this call
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_cp437_data( pub unsafe extern "C" fn sp_command_cp437_data(
x: usize, x: usize,
@ -413,20 +250,7 @@ pub unsafe extern "C" fn sp_command_cp437_data(
/// ///
/// The passed [CharGrid] gets consumed. /// The passed [CharGrid] gets consumed.
/// ///
/// Returns: a new [servicepoint::Command::Utf8Data] instance. Will never return NULL. /// Returns: a new [servicepoint::Command::Utf8Data] instance.
///
/// # Panics
///
/// - when `grid` is null
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `grid` points to a valid instance of [CharGrid]
/// - `grid` is not used concurrently or after this call
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_utf8_data( pub unsafe extern "C" fn sp_command_utf8_data(
x: usize, x: usize,
@ -448,22 +272,7 @@ pub unsafe extern "C" fn sp_command_utf8_data(
/// ///
/// The passed [Bitmap] gets consumed. /// The passed [Bitmap] gets consumed.
/// ///
/// Returns: a new [servicepoint::Command::BitmapLinearWin] instance. Will never return NULL. /// Returns: a new [servicepoint::Command::BitmapLinearWin] instance.
///
/// # Panics
///
/// - when `bitmap` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid instance of [Bitmap]
/// - `bitmap` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_win( pub unsafe extern "C" fn sp_command_bitmap_linear_win(
x: usize, x: usize,
@ -493,18 +302,6 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win(
/// TypedCommand c = sp_command_clear(); /// TypedCommand c = sp_command_clear();
/// sp_command_free(c); /// sp_command_free(c);
/// ``` /// ```
///
/// # Panics
///
/// - when `command` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `command` points to a valid [TypedCommand]
/// - `command` is not used concurrently or after this call
/// - `command` was not passed to another consuming function, e.g. to create a [Packet]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_free(command: NonNull<TypedCommand>) { pub unsafe extern "C" fn sp_command_free(command: NonNull<TypedCommand>) {
_ = unsafe { Box::from_raw(command.as_ptr()) }; _ = unsafe { Box::from_raw(command.as_ptr()) };

View file

@ -1,17 +1,3 @@
//! C functions for interacting with [UdpConnection]s
//!
//! prefix `sp_connection_`
//!
//! A connection to the display.
//!
//! # Examples
//!
//! ```C
//! CConnection connection = sp_connection_open("172.23.42.29:2342");
//! if (connection != NULL)
//! sp_connection_send_command(connection, sp_command_clear());
//! ```
use servicepoint::{Connection, Packet, TypedCommand, UdpConnection}; use servicepoint::{Connection, Packet, TypedCommand, UdpConnection};
use std::ffi::{c_char, CStr}; use std::ffi::{c_char, CStr};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -20,16 +6,13 @@ use std::ptr::NonNull;
/// ///
/// returns: NULL if connection fails, or connected instance /// returns: NULL if connection fails, or connected instance
/// ///
/// # Panics /// # Examples
/// ///
/// - when `host` is null or an invalid host /// ```C
/// /// CConnection connection = sp_connection_open("172.23.42.29:2342");
/// # Safety /// if (connection != NULL)
/// /// sp_connection_send_command(connection, sp_command_clear());
/// The caller has to make sure that: /// ```
///
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_connection_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_connection_open( pub unsafe extern "C" fn sp_connection_open(
host: NonNull<c_char>, host: NonNull<c_char>,
@ -59,7 +42,7 @@ pub unsafe extern "C" fn sp_connection_open(
// /// Creates a new instance of [SPUdpConnection] for testing that does not actually send anything. // /// Creates a new instance of [SPUdpConnection] for testing that does not actually send anything.
// /// // ///
// /// returns: a new instance. Will never return NULL. // /// returns: a new instance.
// /// // ///
// /// # Safety // /// # Safety
// /// // ///
@ -78,19 +61,6 @@ pub unsafe extern "C" fn sp_connection_open(
/// The passed `packet` gets consumed. /// The passed `packet` gets consumed.
/// ///
/// returns: true in case of success /// returns: true in case of success
///
/// # Panics
///
/// - when `connection` is NULL
/// - when `packet` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `connection` points to a valid instance of [UdpConnection]
/// - `packet` points to a valid instance of [Packet]
/// - `packet` is not used concurrently or after this call
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_connection_send_packet( pub unsafe extern "C" fn sp_connection_send_packet(
connection: NonNull<UdpConnection>, connection: NonNull<UdpConnection>,
@ -106,18 +76,12 @@ pub unsafe extern "C" fn sp_connection_send_packet(
/// ///
/// returns: true in case of success /// returns: true in case of success
/// ///
/// # Panics /// # Examples
/// ///
/// - when `connection` is NULL /// ```C
/// - when `command` is NULL /// sp_connection_send_command(connection, sp_command_clear());
/// /// sp_connection_send_command(connection, sp_command_brightness(5));
/// # Safety /// ```
///
/// The caller has to make sure that:
///
/// - `connection` points to a valid instance of [UdpConnection]
/// - `command` points to a valid instance of [Packet]
/// - `command` is not used concurrently or after this call
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_connection_send_command( pub unsafe extern "C" fn sp_connection_send_command(
connection: NonNull<UdpConnection>, connection: NonNull<UdpConnection>,
@ -128,17 +92,6 @@ pub unsafe extern "C" fn sp_connection_send_command(
} }
/// Closes and deallocates a [UdpConnection]. /// Closes and deallocates a [UdpConnection].
///
/// # Panics
///
/// - when `connection` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `connection` points to a valid [UdpConnection]
/// - `connection` is not used concurrently or after this call
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_connection_free( pub unsafe extern "C" fn sp_connection_free(
connection: NonNull<UdpConnection>, connection: NonNull<UdpConnection>,

View file

@ -1,35 +1,10 @@
//! C functions for interacting with [Cp437Grid]s use crate::ByteSlice;
//!
//! prefix `sp_cp437_grid_`
//!
//!
//! A C-wrapper for grid containing codepage 437 characters.
//!
//! The encoding is currently not enforced.
//!
//! # Examples
//!
//! ```C
//! Cp437Grid grid = sp_cp437_grid_new(4, 3);
//! sp_cp437_grid_fill(grid, '?');
//! sp_cp437_grid_set(grid, 0, 0, '!');
//! sp_cp437_grid_free(grid);
//! ```
use crate::SPByteSlice;
use servicepoint::{Cp437Grid, DataRef, Grid}; use servicepoint::{Cp437Grid, DataRef, Grid};
use std::ptr::NonNull; use std::ptr::NonNull;
/// Creates a new [Cp437Grid] with the specified dimensions. /// Creates a new [Cp437Grid] with the specified dimensions.
/// ///
/// returns: [Cp437Grid] initialized to 0. Will never return NULL. /// returns: [Cp437Grid] initialized to 0.
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_cp437_grid_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_new( pub unsafe extern "C" fn sp_cp437_grid_new(
width: usize, width: usize,
@ -40,27 +15,11 @@ pub unsafe extern "C" fn sp_cp437_grid_new(
} }
/// Loads a [Cp437Grid] with the specified dimensions from the provided data. /// Loads a [Cp437Grid] with the specified dimensions from the provided data.
///
/// Will never return NULL.
///
/// # Panics
///
/// - when `data` is NULL
/// - when the provided `data_length` does not match `height` and `width`
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `data` points to a valid memory location of at least `data_length`
/// bytes in size.
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_cp437_grid_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_load( pub unsafe extern "C" fn sp_cp437_grid_load(
width: usize, width: usize,
height: usize, height: usize,
data: SPByteSlice, data: ByteSlice,
) -> *mut Cp437Grid { ) -> *mut Cp437Grid {
let data = unsafe { data.as_slice() }; let data = unsafe { data.as_slice() };
let grid = Cp437Grid::load(width, height, data); let grid = Cp437Grid::load(width, height, data);
@ -72,21 +31,6 @@ pub unsafe extern "C" fn sp_cp437_grid_load(
} }
/// Clones a [Cp437Grid]. /// Clones a [Cp437Grid].
///
/// Will never return NULL.
///
/// # Panics
///
/// - when `cp437_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `cp437_grid` points to a valid [Cp437Grid]
/// - `cp437_grid` is not written to concurrently
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_cp437_grid_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_clone( pub unsafe extern "C" fn sp_cp437_grid_clone(
cp437_grid: NonNull<Cp437Grid>, cp437_grid: NonNull<Cp437Grid>,
@ -96,20 +40,6 @@ pub unsafe extern "C" fn sp_cp437_grid_clone(
} }
/// Deallocates a [Cp437Grid]. /// Deallocates a [Cp437Grid].
///
/// # Panics
///
/// - when `cp437_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `cp437_grid` points to a valid [Cp437Grid]
/// - `cp437_grid` is not used concurrently or after cp437_grid call
/// - `cp437_grid` was not passed to another consuming function, e.g. to create a [TypedCommand]
///
/// [TypedCommand]: [crate::TypedCommand]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: NonNull<Cp437Grid>) { pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: NonNull<Cp437Grid>) {
_ = unsafe { Box::from_raw(cp437_grid.as_ptr()) }; _ = unsafe { Box::from_raw(cp437_grid.as_ptr()) };
@ -124,15 +54,7 @@ pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: NonNull<Cp437Grid>) {
/// ///
/// # Panics /// # Panics
/// ///
/// - when `cp437_grid` is NULL
/// - when accessing `x` or `y` out of bounds /// - when accessing `x` or `y` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `cp437_grid` points to a valid [Cp437Grid]
/// - `cp437_grid` is not written to concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_get( pub unsafe extern "C" fn sp_cp437_grid_get(
cp437_grid: NonNull<Cp437Grid>, cp437_grid: NonNull<Cp437Grid>,
@ -154,17 +76,7 @@ pub unsafe extern "C" fn sp_cp437_grid_get(
/// ///
/// # Panics /// # Panics
/// ///
/// - when `cp437_grid` is NULL
/// - when accessing `x` or `y` out of bounds /// - when accessing `x` or `y` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `cp437_grid` points to a valid [SPBitVec]
/// - `cp437_grid` is not written to or read from concurrently
///
/// [SPBitVec]: [crate::SPBitVec]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_set( pub unsafe extern "C" fn sp_cp437_grid_set(
cp437_grid: NonNull<Cp437Grid>, cp437_grid: NonNull<Cp437Grid>,
@ -181,17 +93,6 @@ pub unsafe extern "C" fn sp_cp437_grid_set(
/// ///
/// - `cp437_grid`: instance to write to /// - `cp437_grid`: instance to write to
/// - `value`: the value to set all cells to /// - `value`: the value to set all cells to
///
/// # Panics
///
/// - when `cp437_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `cp437_grid` points to a valid [Cp437Grid]
/// - `cp437_grid` is not written to or read from concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_fill( pub unsafe extern "C" fn sp_cp437_grid_fill(
cp437_grid: NonNull<Cp437Grid>, cp437_grid: NonNull<Cp437Grid>,
@ -205,16 +106,6 @@ pub unsafe extern "C" fn sp_cp437_grid_fill(
/// # Arguments /// # Arguments
/// ///
/// - `cp437_grid`: instance to read from /// - `cp437_grid`: instance to read from
///
/// # Panics
///
/// - when `cp437_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `cp437_grid` points to a valid [Cp437Grid]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_width( pub unsafe extern "C" fn sp_cp437_grid_width(
cp437_grid: NonNull<Cp437Grid>, cp437_grid: NonNull<Cp437Grid>,
@ -227,16 +118,6 @@ pub unsafe extern "C" fn sp_cp437_grid_width(
/// # Arguments /// # Arguments
/// ///
/// - `cp437_grid`: instance to read from /// - `cp437_grid`: instance to read from
///
/// # Panics
///
/// - when `cp437_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `cp437_grid` points to a valid [Cp437Grid]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_height( pub unsafe extern "C" fn sp_cp437_grid_height(
cp437_grid: NonNull<Cp437Grid>, cp437_grid: NonNull<Cp437Grid>,
@ -246,22 +127,10 @@ pub unsafe extern "C" fn sp_cp437_grid_height(
/// Gets an unsafe reference to the data of the [Cp437Grid] instance. /// Gets an unsafe reference to the data of the [Cp437Grid] instance.
/// ///
/// Will never return NULL. /// The returned memory is valid for the lifetime of the grid.
///
/// # Panics
///
/// - when `cp437_grid` is NULL
///
/// ## Safety
///
/// The caller has to make sure that:
///
/// - `cp437_grid` points to a valid [Cp437Grid]
/// - the returned memory range is never accessed after the passed [Cp437Grid] has been freed
/// - the returned memory range is never accessed concurrently, either via the [Cp437Grid] or directly
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref( pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref(
cp437_grid: NonNull<Cp437Grid>, cp437_grid: NonNull<Cp437Grid>,
) -> SPByteSlice { ) -> ByteSlice {
unsafe { SPByteSlice::from_slice((*cp437_grid.as_ptr()).data_ref_mut()) } unsafe { ByteSlice::from_slice((*cp437_grid.as_ptr()).data_ref_mut()) }
} }

View file

@ -1,11 +1,4 @@
//! C functions for interacting with [Packet]s use crate::ByteSlice;
//!
//! prefix `sp_packet_`
//!
//!
//! The raw packet
use crate::SPByteSlice;
use servicepoint::{Header, Packet, TypedCommand}; use servicepoint::{Header, Packet, TypedCommand};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -13,19 +6,6 @@ use std::ptr::NonNull;
/// The [TypedCommand] gets consumed. /// The [TypedCommand] gets consumed.
/// ///
/// Returns NULL in case of an error. /// Returns NULL in case of an error.
///
/// # Panics
///
/// - when `command` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - [TypedCommand] points to a valid instance of [TypedCommand]
/// - [TypedCommand] is not used concurrently or after this call
/// - the returned [Packet] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_packet_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_packet_from_command( pub unsafe extern "C" fn sp_packet_from_command(
command: NonNull<TypedCommand>, command: NonNull<TypedCommand>,
@ -41,21 +21,8 @@ pub unsafe extern "C" fn sp_packet_from_command(
/// Tries to load a [Packet] from the passed array with the specified length. /// Tries to load a [Packet] from the passed array with the specified length.
/// ///
/// returns: NULL in case of an error, pointer to the allocated packet otherwise /// returns: NULL in case of an error, pointer to the allocated packet otherwise
///
/// # Panics
///
/// - when `data` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `data` points to a valid memory region of at least `length` bytes
/// - `data` is not written to concurrently
/// - the returned [Packet] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_packet_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_packet_try_load(data: SPByteSlice) -> *mut Packet { pub unsafe extern "C" fn sp_packet_try_load(data: ByteSlice) -> *mut Packet {
let data = unsafe { data.as_slice() }; let data = unsafe { data.as_slice() };
match servicepoint::Packet::try_from(data) { match servicepoint::Packet::try_from(data) {
Err(_) => std::ptr::null_mut(), Err(_) => std::ptr::null_mut(),
@ -65,32 +32,11 @@ pub unsafe extern "C" fn sp_packet_try_load(data: SPByteSlice) -> *mut Packet {
/// Creates a raw [Packet] from parts. /// Creates a raw [Packet] from parts.
/// ///
/// # Arguments
///
/// - `command_code` specifies which command this packet contains
/// - `a`, `b`, `c` and `d` are command-specific header values
/// - `payload` is the optional data that is part of the command
/// - `payload_len` is the size of the payload
///
/// returns: new instance. Will never return null. /// returns: new instance. Will never return null.
///
/// # Panics
///
/// - when `payload` is null, but `payload_len` is not zero
/// - when `payload_len` is zero, but `payload` is nonnull
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `payload` points to a valid memory region of at least `payload_len` bytes
/// - `payload` is not written to concurrently
/// - the returned [Packet] instance is freed in some way, either by using a consuming function or
/// by explicitly calling [sp_packet_free].
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_packet_from_parts( pub unsafe extern "C" fn sp_packet_from_parts(
header: Header, header: Header,
payload: *const SPByteSlice, payload: *const ByteSlice,
) -> NonNull<Packet> { ) -> NonNull<Packet> {
let payload = if payload.is_null() { let payload = if payload.is_null() {
vec![] vec![]
@ -119,8 +65,8 @@ pub unsafe extern "C" fn sp_packet_get_header(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_packet_get_payload( pub unsafe extern "C" fn sp_packet_get_payload(
packet: NonNull<Packet>, packet: NonNull<Packet>,
) -> SPByteSlice { ) -> ByteSlice {
unsafe { SPByteSlice::from_slice(&mut *(*packet.as_ptr()).payload) } unsafe { ByteSlice::from_slice(&mut *(*packet.as_ptr()).payload) }
} }
/// Sets the payload of the provided packet to the provided data. /// Sets the payload of the provided packet to the provided data.
@ -129,7 +75,7 @@ pub unsafe extern "C" fn sp_packet_get_payload(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_packet_set_payload( pub unsafe extern "C" fn sp_packet_set_payload(
packet: NonNull<Packet>, packet: NonNull<Packet>,
data: SPByteSlice, data: ByteSlice,
) { ) {
unsafe { (*packet.as_ptr()).payload = data.as_slice().to_vec() } unsafe { (*packet.as_ptr()).payload = data.as_slice().to_vec() }
} }
@ -142,7 +88,7 @@ pub unsafe extern "C" fn sp_packet_set_payload(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_packet_serialize_to( pub unsafe extern "C" fn sp_packet_serialize_to(
packet: NonNull<Packet>, packet: NonNull<Packet>,
buffer: SPByteSlice, buffer: ByteSlice,
) { ) {
unsafe { unsafe {
packet.as_ref().serialize_to(buffer.as_slice_mut()); packet.as_ref().serialize_to(buffer.as_slice_mut());
@ -150,21 +96,6 @@ pub unsafe extern "C" fn sp_packet_serialize_to(
} }
/// Clones a [Packet]. /// Clones a [Packet].
///
/// Will never return NULL.
///
/// # Panics
///
/// - when `packet` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `packet` points to a valid [Packet]
/// - `packet` is not written to concurrently
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_packet_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_packet_clone( pub unsafe extern "C" fn sp_packet_clone(
packet: NonNull<Packet>, packet: NonNull<Packet>,
@ -174,17 +105,6 @@ pub unsafe extern "C" fn sp_packet_clone(
} }
/// Deallocates a [Packet]. /// Deallocates a [Packet].
///
/// # Panics
///
/// - when `packet` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `packet` points to a valid [Packet]
/// - `packet` is not used concurrently or after this call
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_packet_free(packet: NonNull<Packet>) { pub unsafe extern "C" fn sp_packet_free(packet: NonNull<Packet>) {
_ = unsafe { Box::from_raw(packet.as_ptr()) } _ = unsafe { Box::from_raw(packet.as_ptr()) }