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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

@ -1,43 +1,12 @@
//! C functions for interacting with [TypedCommand]s
//!
//! prefix `sp_command_`
use crate::SPBitVec;
use servicepoint::{BinaryOperation, Bitmap, Brightness, BrightnessGrid, CharGrid, CompressionCode, Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand};
use std::ptr::NonNull;
/// A low-level display command.
///
/// This struct and associated functions implement the UDP protocol for the display.
///
/// To send a [TypedCommand], use a [UdpConnection].
///
/// # Examples
///
/// ```C
/// sp_connection_send_command(connection, sp_command_clear());
/// sp_connection_send_command(connection, sp_command_brightness(5));
/// ```
/// Tries to turn a [Packet] into a [TypedCommand].
///
/// The packet is deallocated in the process.
///
/// Returns: pointer to new [TypedCommand] instance or NULL if parsing failed.
///
/// # Panics
///
/// - when `packet` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - [Packet] points to a valid instance of [Packet]
/// - [Packet] is not used concurrently or after this call
/// - the result is checked for NULL
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_try_from_packet(
packet: NonNull<Packet>,
@ -51,20 +20,7 @@ pub unsafe extern "C" fn sp_command_try_from_packet(
/// Clones a [TypedCommand] instance.
///
/// returns: new [TypedCommand] instance. Will never return NULL.
///
/// # Panics
///
/// - when `command` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `command` points to a valid instance of [TypedCommand]
/// - `command` is not written to concurrently
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// returns: new [TypedCommand] instance.
#[no_mangle]
pub unsafe extern "C" fn sp_command_clone(
command: NonNull<TypedCommand>,
@ -77,20 +33,13 @@ pub unsafe extern "C" fn sp_command_clone(
///
/// Does not affect brightness.
///
/// Returns: a new [servicepoint::Command::Clear] instance. Will never return NULL.
/// Returns: a new [servicepoint::Command::Clear] instance.
///
/// # Examples
///
/// ```C
/// sp_connection_send_command(connection, sp_command_clear());
/// ```
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_clear() -> NonNull<TypedCommand> {
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.
///
/// Returns: a new [servicepoint::Command::HardReset] instance. Will never return NULL.
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// Returns: a new [servicepoint::Command::HardReset] instance.
#[no_mangle]
pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull<TypedCommand> {
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.
///
/// Returns: a new [servicepoint::Command::FadeOut] instance. Will never return NULL.
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// Returns: a new [servicepoint::Command::FadeOut] instance.
#[no_mangle]
pub unsafe extern "C" fn sp_command_fade_out() -> NonNull<TypedCommand> {
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.
///
/// Returns: a new [servicepoint::Command::Brightness] instance. Will never return NULL.
///
/// # Panics
///
/// - When the provided brightness value is out of range (0-11).
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// Returns: a new [servicepoint::Command::Brightness] instance.
#[no_mangle]
pub unsafe extern "C" fn sp_command_brightness(
brightness: Brightness,
@ -157,20 +81,7 @@ pub unsafe extern "C" fn sp_command_brightness(
///
/// The passed [BrightnessGrid] gets consumed.
///
/// Returns: a new [servicepoint::Command::CharBrightness] instance. Will never return NULL.
///
/// # Panics
///
/// - when `grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `grid` points to a valid instance of [BrightnessGrid]
/// - `grid` is not used concurrently or after this call
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// Returns: a new [servicepoint::Command::CharBrightness] instance.
#[no_mangle]
pub unsafe extern "C" fn sp_command_char_brightness(
x: usize,
@ -197,22 +108,7 @@ pub unsafe extern "C" fn sp_command_char_brightness(
///
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new [servicepoint::Command::BitmapLinear] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// Returns: a new [servicepoint::Command::BitmapLinear] instance.
#[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear(
offset: usize,
@ -238,22 +134,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear(
///
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new [servicepoint::Command::BitmapLinearAnd] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// Returns: a new [servicepoint::Command::BitmapLinearAnd] instance.
#[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_and(
offset: usize,
@ -279,22 +160,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and(
///
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new [servicepoint::Command::BitmapLinearOr] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// Returns: a new [servicepoint::Command::BitmapLinearOr] instance.
#[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_or(
offset: usize,
@ -320,22 +186,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or(
///
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new [servicepoint::Command::BitmapLinearXor] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// Returns: a new [servicepoint::Command::BitmapLinearXor] instance.
#[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
offset: usize,
@ -352,7 +203,6 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
}
}
#[inline]
unsafe fn sp_command_bitmap_linear_internal(
offset: usize,
bit_vec: NonNull<SPBitVec>,
@ -378,20 +228,7 @@ unsafe fn sp_command_bitmap_linear_internal(
///
/// The passed [Cp437Grid] gets consumed.
///
/// Returns: a new [servicepoint::Command::Cp437Data] instance. Will never return NULL.
///
/// # Panics
///
/// - when `grid` is null
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `grid` points to a valid instance of [Cp437Grid]
/// - `grid` is not used concurrently or after this call
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// Returns: a new [servicepoint::Command::Cp437Data] instance.
#[no_mangle]
pub unsafe extern "C" fn sp_command_cp437_data(
x: usize,
@ -413,20 +250,7 @@ pub unsafe extern "C" fn sp_command_cp437_data(
///
/// The passed [CharGrid] gets consumed.
///
/// Returns: a new [servicepoint::Command::Utf8Data] instance. Will never return NULL.
///
/// # Panics
///
/// - when `grid` is null
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `grid` points to a valid instance of [CharGrid]
/// - `grid` is not used concurrently or after this call
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// Returns: a new [servicepoint::Command::Utf8Data] instance.
#[no_mangle]
pub unsafe extern "C" fn sp_command_utf8_data(
x: usize,
@ -448,22 +272,7 @@ pub unsafe extern "C" fn sp_command_utf8_data(
///
/// The passed [Bitmap] gets consumed.
///
/// Returns: a new [servicepoint::Command::BitmapLinearWin] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bitmap` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid instance of [Bitmap]
/// - `bitmap` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [TypedCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// Returns: a new [servicepoint::Command::BitmapLinearWin] instance.
#[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_win(
x: usize,
@ -493,18 +302,6 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win(
/// TypedCommand c = sp_command_clear();
/// sp_command_free(c);
/// ```
///
/// # Panics
///
/// - when `command` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `command` points to a valid [TypedCommand]
/// - `command` is not used concurrently or after this call
/// - `command` was not passed to another consuming function, e.g. to create a [Packet]
#[no_mangle]
pub unsafe extern "C" fn sp_command_free(command: NonNull<TypedCommand>) {
_ = 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 std::ffi::{c_char, CStr};
use std::ptr::NonNull;
@ -20,16 +6,13 @@ use std::ptr::NonNull;
///
/// returns: NULL if connection fails, or connected instance
///
/// # Panics
/// # Examples
///
/// - when `host` is null or an invalid host
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_connection_free`.
/// ```C
/// CConnection connection = sp_connection_open("172.23.42.29:2342");
/// if (connection != NULL)
/// sp_connection_send_command(connection, sp_command_clear());
/// ```
#[no_mangle]
pub unsafe extern "C" fn sp_connection_open(
host: NonNull<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.
// ///
// /// returns: a new instance. Will never return NULL.
// /// returns: a new instance.
// ///
// /// # Safety
// ///
@ -78,19 +61,6 @@ pub unsafe extern "C" fn sp_connection_open(
/// The passed `packet` gets consumed.
///
/// returns: true in case of success
///
/// # Panics
///
/// - when `connection` is NULL
/// - when `packet` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `connection` points to a valid instance of [UdpConnection]
/// - `packet` points to a valid instance of [Packet]
/// - `packet` is not used concurrently or after this call
#[no_mangle]
pub unsafe extern "C" fn sp_connection_send_packet(
connection: NonNull<UdpConnection>,
@ -106,18 +76,12 @@ pub unsafe extern "C" fn sp_connection_send_packet(
///
/// returns: true in case of success
///
/// # Panics
/// # Examples
///
/// - when `connection` is NULL
/// - when `command` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `connection` points to a valid instance of [UdpConnection]
/// - `command` points to a valid instance of [Packet]
/// - `command` is not used concurrently or after this call
/// ```C
/// sp_connection_send_command(connection, sp_command_clear());
/// sp_connection_send_command(connection, sp_command_brightness(5));
/// ```
#[no_mangle]
pub unsafe extern "C" fn sp_connection_send_command(
connection: NonNull<UdpConnection>,
@ -128,17 +92,6 @@ pub unsafe extern "C" fn sp_connection_send_command(
}
/// Closes and deallocates a [UdpConnection].
///
/// # Panics
///
/// - when `connection` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `connection` points to a valid [UdpConnection]
/// - `connection` is not used concurrently or after this call
#[no_mangle]
pub unsafe extern "C" fn sp_connection_free(
connection: NonNull<UdpConnection>,

View file

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

View file

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