add NULL checks - bit_vec

This commit is contained in:
Vinzenz Schroeter 2024-10-13 18:12:55 +02:00
parent 68d809c714
commit 03becf19b5
7 changed files with 120 additions and 73 deletions

View file

@ -1,4 +1,4 @@
//! C functions for interacting with `SPBitVec`s
//! C functions for interacting with [SPBitVec]s
//!
//! prefix `sp_bit_vec_`
@ -33,17 +33,17 @@ impl Clone for SPBitVec {
}
}
/// Creates a new `SPBitVec` instance.
/// Creates a new [SPBitVec] instance.
///
/// # Arguments
///
/// - `size`: size in bits.
///
/// returns: `SPBitVec` with all bits set to false. Will never return NULL.
/// returns: [SPBitVec] with all bits set to false. Will never return NULL.
///
/// # Panics
///
/// When `size` is not divisible by 8.
/// - when `size` is not divisible by 8.
///
/// # Safety
///
@ -53,10 +53,18 @@ impl Clone for SPBitVec {
/// by explicitly calling `sp_bit_vec_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_new(size: usize) -> *mut SPBitVec {
Box::into_raw(Box::new(SPBitVec(BitVec::repeat(false, size))))
let result = Box::into_raw(Box::new(SPBitVec(BitVec::repeat(false, size))));
assert!(!result.is_null());
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.
///
/// # Panics
///
/// - when `data` is NULL
///
/// # Safety
///
@ -71,17 +79,26 @@ pub unsafe extern "C" fn sp_bit_vec_load(
data: *const u8,
data_length: usize,
) -> *mut SPBitVec {
assert!(!data.is_null());
let data = std::slice::from_raw_parts(data, data_length);
Box::into_raw(Box::new(SPBitVec(BitVec::from_slice(data))))
let result = Box::into_raw(Box::new(SPBitVec(BitVec::from_slice(data))));
assert!(!result.is_null());
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` 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_bit_vec_free`.
@ -89,24 +106,32 @@ pub unsafe extern "C" fn sp_bit_vec_load(
pub unsafe extern "C" fn sp_bit_vec_clone(
bit_vec: *const SPBitVec,
) -> *mut SPBitVec {
Box::into_raw(Box::new((*bit_vec).clone()))
assert!(!bit_vec.is_null());
let result = Box::into_raw(Box::new((*bit_vec).clone()));
assert!(!result.is_null());
result
}
/// 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` 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 `SPCommand`
/// - `bit_vec` was not passed to another consuming function, e.g. to create a [SPCommand]
#[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_free(bit_vec: *mut SPBitVec) {
assert!(!bit_vec.is_null());
_ = Box::from_raw(bit_vec);
}
/// Gets the value of a bit from the `SPBitVec`.
/// Gets the value of a bit from the [SPBitVec].
///
/// # Arguments
///
@ -117,23 +142,25 @@ pub unsafe extern "C" fn sp_bit_vec_free(bit_vec: *mut SPBitVec) {
///
/// # Panics
///
/// When accessing `index` out of bounds.
/// - 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` points to a valid [SPBitVec]
/// - `bit_vec` is not written to concurrently
#[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_get(
bit_vec: *const SPBitVec,
index: usize,
) -> bool {
assert!(!bit_vec.is_null());
*(*bit_vec).0.get(index).unwrap()
}
/// Sets the value of a bit in the `SPBitVec`.
/// Sets the value of a bit in the [SPBitVec].
///
/// # Arguments
///
@ -141,17 +168,16 @@ pub unsafe extern "C" fn sp_bit_vec_get(
/// - `index`: the bit index to edit
/// - `value`: the value to set the bit to
///
/// returns: old value of the bit
///
/// # Panics
///
/// When accessing `index` out of bounds.
/// - 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` points to a valid [SPBitVec]
/// - `bit_vec` is not written to or read from concurrently
#[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_set(
@ -159,40 +185,51 @@ pub unsafe extern "C" fn sp_bit_vec_set(
index: usize,
value: bool,
) {
assert!(!bit_vec.is_null());
(*bit_vec).0.set(index, value)
}
/// Sets the value of all bits in the `SPBitVec`.
/// Sets the value of all bits in the [SPBitVec].
///
/// # Arguments
///
/// - `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` points to a valid [SPBitVec]
/// - `bit_vec` is not written to or read from concurrently
#[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_fill(bit_vec: *mut SPBitVec, value: bool) {
assert!(!bit_vec.is_null());
(*bit_vec).0.fill(value)
}
/// Gets the length of the `SPBitVec` in bits.
/// Gets the length of the [SPBitVec] in bits.
///
/// # 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`
/// - `bit_vec` points to a valid [SPBitVec]
#[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_len(bit_vec: *const SPBitVec) -> usize {
assert!(!bit_vec.is_null());
(*bit_vec).0.len()
}
@ -202,33 +239,43 @@ pub unsafe extern "C" fn sp_bit_vec_len(bit_vec: *const SPBitVec) -> usize {
///
/// - `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`
/// - `bit_vec` points to a valid [SPBitVec]
#[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_is_empty(bit_vec: *const SPBitVec) -> bool {
assert!(!bit_vec.is_null());
(*bit_vec).0.is_empty()
}
/// Gets an unsafe reference to the data of the `SPBitVec` instance.
/// Gets an unsafe reference to the data of the [SPBitVec] instance.
///
/// # 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
/// - `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_bit_vec_unsafe_data_ref(
bit_vec: *mut SPBitVec,
) -> SPByteSlice {
assert!(!bit_vec.is_null());
let data = (*bit_vec).0.as_raw_mut_slice();
SPByteSlice {
start: data.as_mut_ptr_range().start,

View file

@ -110,7 +110,7 @@ pub unsafe extern "C" fn sp_brightness_grid_clone(
///
/// - `brightness_grid` points to a valid `SPBrightnessGrid`
/// - `brightness_grid` is not used concurrently or after this call
/// - `brightness_grid` was not passed to another consuming function, e.g. to create a `SPCommand`
/// - `brightness_grid` was not passed to another consuming function, e.g. to create a [SPCommand]
#[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_free(
brightness_grid: *mut SPBrightnessGrid,
@ -163,7 +163,7 @@ pub unsafe extern "C" fn sp_brightness_grid_get(
///
/// The caller has to make sure that:
///
/// - `brightness_grid` points to a valid `SPBitVec`
/// - `brightness_grid` points to a valid [SPBitVec]
/// - `brightness_grid` is not written to or read from concurrently
#[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_set(

View file

@ -1,4 +1,4 @@
//! C functions for interacting with `SPCommand`s
//! C functions for interacting with [SPCommand]s
//!
//! prefix `sp_command_`
@ -15,7 +15,7 @@ use crate::{
///
/// This struct and associated functions implement the UDP protocol for the display.
///
/// To send a `SPCommand`, use a `SPConnection`.
/// To send a [SPCommand], use a `SPConnection`.
///
/// # Examples
///
@ -31,11 +31,11 @@ impl Clone for SPCommand {
}
}
/// Tries to turn a `SPPacket` into a `SPCommand`.
/// Tries to turn a `SPPacket` into a [SPCommand].
///
/// The packet is deallocated in the process.
///
/// Returns: pointer to new `SPCommand` instance or NULL
/// Returns: pointer to new [SPCommand] instance or NULL
///
/// # Safety
///
@ -44,7 +44,7 @@ impl Clone for SPCommand {
/// - `SPPacket` points to a valid instance of `SPPacket`
/// - `SPPacket` is not used concurrently or after this call
/// - the result is checked for NULL
/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_try_from_packet(
@ -57,15 +57,15 @@ pub unsafe extern "C" fn sp_command_try_from_packet(
}
}
/// Clones a `SPCommand` instance.
/// Clones a [SPCommand] instance.
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `command` points to a valid instance of `SPCommand`
/// - `command` points to a valid instance of [SPCommand]
/// - `command` is not written to concurrently
/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_clone(
@ -90,7 +90,7 @@ pub unsafe extern "C" fn sp_command_clone(
///
/// The caller has to make sure that:
///
/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_clear() -> *mut SPCommand {
@ -107,7 +107,7 @@ pub unsafe extern "C" fn sp_command_clear() -> *mut SPCommand {
///
/// The caller has to make sure that:
///
/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_hard_reset() -> *mut SPCommand {
@ -122,7 +122,7 @@ pub unsafe extern "C" fn sp_command_hard_reset() -> *mut SPCommand {
///
/// The caller has to make sure that:
///
/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_fade_out() -> *mut SPCommand {
@ -141,7 +141,7 @@ pub unsafe extern "C" fn sp_command_fade_out() -> *mut SPCommand {
///
/// The caller has to make sure that:
///
/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_brightness(
@ -166,7 +166,7 @@ pub unsafe extern "C" fn sp_command_brightness(
///
/// - `grid` points to a valid instance of `SPBrightnessGrid`
/// - `grid` is not used concurrently or after this call
/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_char_brightness(
@ -186,9 +186,9 @@ pub unsafe extern "C" fn sp_command_char_brightness(
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
/// once the starting row is full, overwriting will continue on column 0.
///
/// The contained `SPBitVec` is always uncompressed.
/// The contained [SPBitVec] is always uncompressed.
///
/// The passed `SPBitVec` gets consumed.
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new `Command::BitmapLinear` instance. Will never return NULL.
///
@ -196,10 +196,10 @@ pub unsafe extern "C" fn sp_command_char_brightness(
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of `SPBitVec`
/// - `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 `SPCommand` instance is freed in some way, either by using a consuming function or
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear(
@ -220,9 +220,9 @@ pub unsafe extern "C" fn sp_command_bitmap_linear(
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
/// once the starting row is full, overwriting will continue on column 0.
///
/// The contained `SPBitVec` is always uncompressed.
/// The contained [SPBitVec] is always uncompressed.
///
/// The passed `SPBitVec` gets consumed.
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new `Command::BitmapLinearAnd` instance. Will never return NULL.
///
@ -230,10 +230,10 @@ pub unsafe extern "C" fn sp_command_bitmap_linear(
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of `SPBitVec`
/// - `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 `SPCommand` instance is freed in some way, either by using a consuming function or
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_and(
@ -254,9 +254,9 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and(
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
/// once the starting row is full, overwriting will continue on column 0.
///
/// The contained `SPBitVec` is always uncompressed.
/// The contained [SPBitVec] is always uncompressed.
///
/// The passed `SPBitVec` gets consumed.
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new `Command::BitmapLinearOr` instance. Will never return NULL.
///
@ -264,10 +264,10 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and(
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of `SPBitVec`
/// - `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 `SPCommand` instance is freed in some way, either by using a consuming function or
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_or(
@ -288,9 +288,9 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or(
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
/// once the starting row is full, overwriting will continue on column 0.
///
/// The contained `SPBitVec` is always uncompressed.
/// The contained [SPBitVec] is always uncompressed.
///
/// The passed `SPBitVec` gets consumed.
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new `Command::BitmapLinearXor` instance. Will never return NULL.
///
@ -298,10 +298,10 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or(
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of `SPBitVec`
/// - `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 `SPCommand` instance is freed in some way, either by using a consuming function or
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
@ -334,7 +334,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
///
/// - `grid` points to a valid instance of `SPCp437Grid`
/// - `grid` is not used concurrently or after this call
/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_cp437_data(
@ -362,7 +362,7 @@ pub unsafe extern "C" fn sp_command_cp437_data(
/// - `pixel_grid` points to a valid instance of `SPPixelGrid`
/// - `pixel_grid` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_win(
@ -381,7 +381,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win(
))))
}
/// Deallocates a `SPCommand`.
/// Deallocates a [SPCommand].
///
/// # Examples
///
@ -394,7 +394,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win(
///
/// The caller has to make sure that:
///
/// - `command` points to a valid `SPCommand`
/// - `command` points to a valid [SPCommand]
/// - `command` is not used concurrently or after this call
/// - `command` was not passed to another consuming function, e.g. to create a `SPPacket`
#[no_mangle]

View file

@ -67,7 +67,7 @@ pub unsafe extern "C" fn sp_connection_send_packet(
(*connection).0.send((*packet).0).is_ok()
}
/// Sends a `SPCommand` to the display using the `SPConnection`.
/// Sends a [SPCommand] to the display using the `SPConnection`.
///
/// The passed `command` gets consumed.
///

View file

@ -101,7 +101,7 @@ pub unsafe extern "C" fn sp_cp437_grid_clone(
///
/// - `cp437_grid` points to a valid `SPCp437Grid`
/// - `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 `SPCommand`
/// - `cp437_grid` was not passed to another consuming function, e.g. to create a [SPCommand]
#[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: *mut SPCp437Grid) {
_ = Box::from_raw(cp437_grid);
@ -151,7 +151,7 @@ pub unsafe extern "C" fn sp_cp437_grid_get(
///
/// The caller has to make sure that:
///
/// - `cp437_grid` points to a valid `SPBitVec`
/// - `cp437_grid` points to a valid [SPBitVec]
/// - `cp437_grid` is not written to or read from concurrently
#[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_set(

View file

@ -9,8 +9,8 @@ use crate::SPCommand;
/// The raw packet
pub struct SPPacket(pub(crate) servicepoint::packet::Packet);
/// Turns a `SPCommand` into a `SPPacket`.
/// The `SPCommand` gets consumed.
/// Turns a [SPCommand] into a `SPPacket`.
/// The [SPCommand] gets consumed.
///
/// Will never return NULL.
///
@ -18,8 +18,8 @@ pub struct SPPacket(pub(crate) servicepoint::packet::Packet);
///
/// The caller has to make sure that:
///
/// - `SPCommand` points to a valid instance of `SPCommand`
/// - `SPCommand` is not used concurrently or after this call
/// - [SPCommand] points to a valid instance of [SPCommand]
/// - [SPCommand] is not used concurrently or after this call
/// - the returned `SPPacket` instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_packet_free`.
#[no_mangle]

View file

@ -108,7 +108,7 @@ pub unsafe extern "C" fn sp_pixel_grid_clone(
///
/// - `pixel_grid` points to a valid `SPPixelGrid`
/// - `pixel_grid` is not used concurrently or after pixel_grid call
/// - `pixel_grid` was not passed to another consuming function, e.g. to create a `SPCommand`
/// - `pixel_grid` was not passed to another consuming function, e.g. to create a [SPCommand]
#[no_mangle]
pub unsafe extern "C" fn sp_pixel_grid_free(pixel_grid: *mut SPPixelGrid) {
_ = Box::from_raw(pixel_grid);