use NonNull as return type in C API

This commit is contained in:
Vinzenz Schroeter 2024-10-15 22:23:52 +02:00
parent c6450d7759
commit 590b21d433
7 changed files with 105 additions and 128 deletions

View file

@ -2,6 +2,7 @@
//! //!
//! prefix `sp_bitmap_` //! prefix `sp_bitmap_`
use std::ptr::NonNull;
use servicepoint::{DataRef, Grid}; use servicepoint::{DataRef, Grid};
use crate::byte_slice::SPByteSlice; use crate::byte_slice::SPByteSlice;
@ -41,12 +42,11 @@ pub struct SPBitmap(pub(crate) servicepoint::Bitmap);
pub unsafe extern "C" fn sp_bitmap_new( pub unsafe extern "C" fn sp_bitmap_new(
width: usize, width: usize,
height: usize, height: usize,
) -> *mut SPBitmap { ) -> NonNull<SPBitmap> {
let result = Box::into_raw(Box::new(SPBitmap(servicepoint::Bitmap::new( let result = Box::new(SPBitmap(servicepoint::Bitmap::new(
width, height, width, height,
)))); )));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Loads a [SPBitmap] with the specified dimensions from the provided data. /// Loads a [SPBitmap] with the specified dimensions from the provided data.
@ -77,14 +77,13 @@ pub unsafe extern "C" fn sp_bitmap_load(
height: usize, height: usize,
data: *const u8, data: *const u8,
data_length: usize, data_length: usize,
) -> *mut SPBitmap { ) -> NonNull<SPBitmap> {
assert!(!data.is_null()); assert!(!data.is_null());
let data = std::slice::from_raw_parts(data, data_length); let data = std::slice::from_raw_parts(data, data_length);
let result = Box::into_raw(Box::new(SPBitmap(servicepoint::Bitmap::load( let result = Box::new(SPBitmap(servicepoint::Bitmap::load(
width, height, data, width, height, data,
)))); )));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Clones a [SPBitmap]. /// Clones a [SPBitmap].
@ -106,11 +105,10 @@ pub unsafe extern "C" fn sp_bitmap_load(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitmap_clone( pub unsafe extern "C" fn sp_bitmap_clone(
bitmap: *const SPBitmap, bitmap: *const SPBitmap,
) -> *mut SPBitmap { ) -> NonNull<SPBitmap> {
assert!(!bitmap.is_null()); assert!(!bitmap.is_null());
let result = Box::into_raw(Box::new(SPBitmap((*bitmap).0.clone()))); let result = Box::new(SPBitmap((*bitmap).0.clone()));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Deallocates a [SPBitmap]. /// Deallocates a [SPBitmap].
@ -277,7 +275,7 @@ pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref(
assert!(!bitmap.is_null()); assert!(!bitmap.is_null());
let data = (*bitmap).0.data_ref_mut(); let data = (*bitmap).0.data_ref_mut();
SPByteSlice { SPByteSlice {
start: data.as_mut_ptr_range().start, start: NonNull::new(data.as_mut_ptr_range().start).unwrap(),
length: data.len(), length: data.len(),
} }
} }

View file

@ -2,6 +2,7 @@
//! //!
//! prefix `sp_bitvec_` //! prefix `sp_bitvec_`
use std::ptr::NonNull;
use crate::SPByteSlice; use crate::SPByteSlice;
use servicepoint::bitvec::prelude::{BitVec, Msb0}; use servicepoint::bitvec::prelude::{BitVec, Msb0};
@ -52,10 +53,9 @@ impl Clone for SPBitVec {
/// - the returned instance is freed in some way, either by using a consuming function or /// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_bitvec_free`. /// by explicitly calling `sp_bitvec_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_new(size: usize) -> *mut SPBitVec { pub unsafe extern "C" fn sp_bitvec_new(size: usize) -> NonNull<SPBitVec> {
let result = Box::into_raw(Box::new(SPBitVec(BitVec::repeat(false, size)))); let result = Box::new(SPBitVec(BitVec::repeat(false, size)));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
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.
@ -78,12 +78,11 @@ pub unsafe extern "C" fn sp_bitvec_new(size: usize) -> *mut SPBitVec {
pub unsafe extern "C" fn sp_bitvec_load( pub unsafe extern "C" fn sp_bitvec_load(
data: *const u8, data: *const u8,
data_length: usize, data_length: usize,
) -> *mut SPBitVec { ) -> NonNull<SPBitVec> {
assert!(!data.is_null()); assert!(!data.is_null());
let data = std::slice::from_raw_parts(data, data_length); let data = std::slice::from_raw_parts(data, data_length);
let result = Box::into_raw(Box::new(SPBitVec(BitVec::from_slice(data)))); let result = Box::new(SPBitVec(BitVec::from_slice(data)));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Clones a [SPBitVec]. /// Clones a [SPBitVec].
@ -105,11 +104,10 @@ pub unsafe extern "C" fn sp_bitvec_load(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bitvec_clone( pub unsafe extern "C" fn sp_bitvec_clone(
bit_vec: *const SPBitVec, bit_vec: *const SPBitVec,
) -> *mut SPBitVec { ) -> NonNull<SPBitVec> {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
let result = Box::into_raw(Box::new((*bit_vec).clone())); let result = Box::new((*bit_vec).clone());
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Deallocates a [SPBitVec]. /// Deallocates a [SPBitVec].
@ -278,7 +276,7 @@ pub unsafe extern "C" fn sp_bitvec_unsafe_data_ref(
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
let data = (*bit_vec).0.as_raw_mut_slice(); let data = (*bit_vec).0.as_raw_mut_slice();
SPByteSlice { SPByteSlice {
start: data.as_mut_ptr_range().start, start: NonNull::new(data.as_mut_ptr_range().start).unwrap(),
length: data.len(), length: data.len(),
} }
} }

View file

@ -5,6 +5,7 @@
use crate::SPByteSlice; use crate::SPByteSlice;
use servicepoint::{Brightness, DataRef, Grid, PrimitiveGrid}; use servicepoint::{Brightness, DataRef, Grid, PrimitiveGrid};
use std::intrinsics::transmute; use std::intrinsics::transmute;
use std::ptr::NonNull;
/// A grid containing brightness values. /// A grid containing brightness values.
/// ///
@ -38,12 +39,11 @@ pub struct SPBrightnessGrid(pub(crate) servicepoint::BrightnessGrid);
pub unsafe extern "C" fn sp_brightness_grid_new( pub unsafe extern "C" fn sp_brightness_grid_new(
width: usize, width: usize,
height: usize, height: usize,
) -> *mut SPBrightnessGrid { ) -> NonNull<SPBrightnessGrid> {
let result = Box::into_raw(Box::new(SPBrightnessGrid( let result = Box::new(SPBrightnessGrid(
servicepoint::BrightnessGrid::new(width, height), servicepoint::BrightnessGrid::new(width, height),
))); ));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Loads a [SPBrightnessGrid] with the specified dimensions from the provided data. /// Loads a [SPBrightnessGrid] with the specified dimensions from the provided data.
@ -69,15 +69,14 @@ pub unsafe extern "C" fn sp_brightness_grid_load(
height: usize, height: usize,
data: *const u8, data: *const u8,
data_length: usize, data_length: usize,
) -> *mut SPBrightnessGrid { ) -> NonNull<SPBrightnessGrid> {
assert!(!data.is_null()); assert!(!data.is_null());
let data = std::slice::from_raw_parts(data, data_length); let data = std::slice::from_raw_parts(data, data_length);
let grid = PrimitiveGrid::load(width, height, data); let grid = PrimitiveGrid::load(width, height, data);
let grid = servicepoint::BrightnessGrid::try_from(grid) let grid = servicepoint::BrightnessGrid::try_from(grid)
.expect("invalid brightness value"); .expect("invalid brightness value");
let result = Box::into_raw(Box::new(SPBrightnessGrid(grid))); let result = Box::new(SPBrightnessGrid(grid));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Clones a [SPBrightnessGrid]. /// Clones a [SPBrightnessGrid].
@ -103,11 +102,10 @@ pub unsafe extern "C" fn sp_brightness_grid_load(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_clone( pub unsafe extern "C" fn sp_brightness_grid_clone(
brightness_grid: *const SPBrightnessGrid, brightness_grid: *const SPBrightnessGrid,
) -> *mut SPBrightnessGrid { ) -> NonNull<SPBrightnessGrid> {
assert!(!brightness_grid.is_null()); assert!(!brightness_grid.is_null());
let result = Box::into_raw(Box::new((*brightness_grid).clone())); let result = Box::new((*brightness_grid).clone());
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Deallocates a [SPBrightnessGrid]. /// Deallocates a [SPBrightnessGrid].
@ -305,9 +303,10 @@ pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref(
assert!(!brightness_grid.is_null()); assert!(!brightness_grid.is_null());
assert_eq!(core::mem::size_of::<Brightness>(), 1); assert_eq!(core::mem::size_of::<Brightness>(), 1);
let data = (*brightness_grid).0.data_ref_mut(); let data = (*brightness_grid).0.data_ref_mut();
// this assumes more about the memory layout than rust guarantees. yikes!
let data: &mut [u8] = transmute(data); let data: &mut [u8] = transmute(data);
SPByteSlice { SPByteSlice {
start: data.as_mut_ptr_range().start, start: NonNull::new(data.as_mut_ptr_range().start).unwrap(),
length: data.len(), length: data.len(),
} }
} }

View file

@ -1,5 +1,7 @@
//! FFI slice helper //! FFI slice helper
use std::ptr::NonNull;
#[repr(C)] #[repr(C)]
/// Represents a span of memory (`&mut [u8]` ) as a struct usable by C code. /// Represents a span of memory (`&mut [u8]` ) as a struct usable by C code.
/// ///
@ -16,7 +18,7 @@
/// will try to free the memory of a potentially separate allocator. /// will try to free the memory of a potentially separate allocator.
pub struct SPByteSlice { pub struct SPByteSlice {
/// The start address of the memory /// The start address of the memory
pub start: *mut u8, pub start: NonNull<u8>,
/// The amount of memory in bytes /// The amount of memory in bytes
pub length: usize, pub length: usize,
} }

View file

@ -2,7 +2,7 @@
//! //!
//! prefix `sp_command_` //! prefix `sp_command_`
use std::ptr::null_mut; use std::ptr::{null_mut, NonNull};
use servicepoint::{Brightness, Origin}; use servicepoint::{Brightness, Origin};
@ -80,11 +80,10 @@ pub unsafe extern "C" fn sp_command_try_from_packet(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_clone( pub unsafe extern "C" fn sp_command_clone(
command: *const SPCommand, command: *const SPCommand,
) -> *mut SPCommand { ) -> NonNull<SPCommand> {
assert!(!command.is_null()); assert!(!command.is_null());
let result = Box::into_raw(Box::new((*command).clone())); let result = Box::new((*command).clone());
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Set all pixels to the off state. /// Set all pixels to the off state.
@ -106,11 +105,9 @@ pub unsafe extern "C" fn sp_command_clone(
/// - 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`. /// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_clear() -> *mut SPCommand { pub unsafe extern "C" fn sp_command_clear() -> NonNull<SPCommand> {
let result = let result = Box::new(SPCommand(servicepoint::Command::Clear));
Box::into_raw(Box::new(SPCommand(servicepoint::Command::Clear))); NonNull::from(Box::leak(result))
assert!(!result.is_null());
result
} }
/// Kills the udp daemon on the display, which usually results in a restart. /// Kills the udp daemon on the display, which usually results in a restart.
@ -126,11 +123,9 @@ pub unsafe extern "C" fn sp_command_clear() -> *mut SPCommand {
/// - 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`. /// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_hard_reset() -> *mut SPCommand { pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull<SPCommand> {
let result = let result = Box::new(SPCommand(servicepoint::Command::HardReset));
Box::into_raw(Box::new(SPCommand(servicepoint::Command::HardReset))); NonNull::from(Box::leak(result))
assert!(!result.is_null());
result
} }
/// A yet-to-be-tested command. /// A yet-to-be-tested command.
@ -144,11 +139,9 @@ pub unsafe extern "C" fn sp_command_hard_reset() -> *mut SPCommand {
/// - 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`. /// by explicitly calling `sp_command_free`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_fade_out() -> *mut SPCommand { pub unsafe extern "C" fn sp_command_fade_out() -> NonNull<SPCommand> {
let result = let result = Box::new(SPCommand(servicepoint::Command::FadeOut));
Box::into_raw(Box::new(SPCommand(servicepoint::Command::FadeOut))); NonNull::from(Box::leak(result))
assert!(!result.is_null());
result
} }
/// Set the brightness of all tiles to the same value. /// Set the brightness of all tiles to the same value.
@ -168,14 +161,13 @@ pub unsafe extern "C" fn sp_command_fade_out() -> *mut SPCommand {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_brightness( pub unsafe extern "C" fn sp_command_brightness(
brightness: u8, brightness: u8,
) -> *mut SPCommand { ) -> NonNull<SPCommand> {
let brightness = let brightness =
Brightness::try_from(brightness).expect("invalid brightness"); Brightness::try_from(brightness).expect("invalid brightness");
let result = Box::into_raw(Box::new(SPCommand( let result = Box::new(SPCommand(
servicepoint::Command::Brightness(brightness), servicepoint::Command::Brightness(brightness),
))); ));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Set the brightness of individual tiles in a rectangular area of the display. /// Set the brightness of individual tiles in a rectangular area of the display.
@ -201,14 +193,13 @@ pub unsafe extern "C" fn sp_command_char_brightness(
x: usize, x: usize,
y: usize, y: usize,
grid: *mut SPBrightnessGrid, grid: *mut SPBrightnessGrid,
) -> *mut SPCommand { ) -> NonNull<SPCommand> {
assert!(!grid.is_null()); assert!(!grid.is_null());
let byte_grid = *Box::from_raw(grid); let byte_grid = *Box::from_raw(grid);
let result = Box::into_raw(Box::new(SPCommand( let result = Box::new(SPCommand(
servicepoint::Command::CharBrightness(Origin::new(x, y), byte_grid.0), servicepoint::Command::CharBrightness(Origin::new(x, y), byte_grid.0),
))); ));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Set pixel data starting at the pixel offset on screen. /// Set pixel data starting at the pixel offset on screen.
@ -241,18 +232,17 @@ pub unsafe extern "C" fn sp_command_bitmap_linear(
offset: usize, offset: usize,
bit_vec: *mut SPBitVec, bit_vec: *mut SPBitVec,
compression: SPCompressionCode, compression: SPCompressionCode,
) -> *mut SPCommand { ) -> NonNull<SPCommand> {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
let bit_vec = *Box::from_raw(bit_vec); let bit_vec = *Box::from_raw(bit_vec);
let result = Box::into_raw(Box::new(SPCommand( let result = Box::new(SPCommand(
servicepoint::Command::BitmapLinear( servicepoint::Command::BitmapLinear(
offset, offset,
bit_vec.into(), bit_vec.into(),
compression.try_into().expect("invalid compression code"), compression.try_into().expect("invalid compression code"),
), ),
))); ));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Set pixel data according to an and-mask starting at the offset. /// Set pixel data according to an and-mask starting at the offset.
@ -285,18 +275,17 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and(
offset: usize, offset: usize,
bit_vec: *mut SPBitVec, bit_vec: *mut SPBitVec,
compression: SPCompressionCode, compression: SPCompressionCode,
) -> *mut SPCommand { ) -> NonNull<SPCommand> {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
let bit_vec = *Box::from_raw(bit_vec); let bit_vec = *Box::from_raw(bit_vec);
let result = Box::into_raw(Box::new(SPCommand( let result = Box::new(SPCommand(
servicepoint::Command::BitmapLinearAnd( servicepoint::Command::BitmapLinearAnd(
offset, offset,
bit_vec.into(), bit_vec.into(),
compression.try_into().expect("invalid compression code"), compression.try_into().expect("invalid compression code"),
), ),
))); ));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Set pixel data according to an or-mask starting at the offset. /// Set pixel data according to an or-mask starting at the offset.
@ -329,18 +318,17 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or(
offset: usize, offset: usize,
bit_vec: *mut SPBitVec, bit_vec: *mut SPBitVec,
compression: SPCompressionCode, compression: SPCompressionCode,
) -> *mut SPCommand { ) -> NonNull<SPCommand> {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
let bit_vec = *Box::from_raw(bit_vec); let bit_vec = *Box::from_raw(bit_vec);
let result = Box::into_raw(Box::new(SPCommand( let result = Box::new(SPCommand(
servicepoint::Command::BitmapLinearOr( servicepoint::Command::BitmapLinearOr(
offset, offset,
bit_vec.into(), bit_vec.into(),
compression.try_into().expect("invalid compression code"), compression.try_into().expect("invalid compression code"),
), ),
))); ));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Set pixel data according to a xor-mask starting at the offset. /// Set pixel data according to a xor-mask starting at the offset.
@ -373,18 +361,17 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
offset: usize, offset: usize,
bit_vec: *mut SPBitVec, bit_vec: *mut SPBitVec,
compression: SPCompressionCode, compression: SPCompressionCode,
) -> *mut SPCommand { ) -> NonNull<SPCommand> {
assert!(!bit_vec.is_null()); assert!(!bit_vec.is_null());
let bit_vec = *Box::from_raw(bit_vec); let bit_vec = *Box::from_raw(bit_vec);
let result = Box::into_raw(Box::new(SPCommand( let result = Box::new(SPCommand(
servicepoint::Command::BitmapLinearXor( servicepoint::Command::BitmapLinearXor(
offset, offset,
bit_vec.into(), bit_vec.into(),
compression.try_into().expect("invalid compression code"), compression.try_into().expect("invalid compression code"),
), ),
))); ));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Show text on the screen. /// Show text on the screen.
@ -410,14 +397,13 @@ pub unsafe extern "C" fn sp_command_cp437_data(
x: usize, x: usize,
y: usize, y: usize,
grid: *mut SPCp437Grid, grid: *mut SPCp437Grid,
) -> *mut SPCommand { ) -> NonNull<SPCommand> {
assert!(!grid.is_null()); assert!(!grid.is_null());
let grid = *Box::from_raw(grid); let grid = *Box::from_raw(grid);
let result = Box::into_raw(Box::new(SPCommand( let result = Box::new(SPCommand(
servicepoint::Command::Cp437Data(Origin::new(x, y), grid.0), servicepoint::Command::Cp437Data(Origin::new(x, y), grid.0),
))); ));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Sets a window of pixels to the specified values. /// Sets a window of pixels to the specified values.
@ -446,10 +432,10 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win(
y: usize, y: usize,
bitmap: *mut SPBitmap, bitmap: *mut SPBitmap,
compression_code: SPCompressionCode, compression_code: SPCompressionCode,
) -> *mut SPCommand { ) -> NonNull<SPCommand> {
assert!(!bitmap.is_null()); assert!(!bitmap.is_null());
let byte_grid = (*Box::from_raw(bitmap)).0; let byte_grid = (*Box::from_raw(bitmap)).0;
let result = Box::into_raw(Box::new(SPCommand( let result = Box::new(SPCommand(
servicepoint::Command::BitmapLinearWin( servicepoint::Command::BitmapLinearWin(
Origin::new(x, y), Origin::new(x, y),
byte_grid, byte_grid,
@ -457,9 +443,8 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win(
.try_into() .try_into()
.expect("invalid compression code"), .expect("invalid compression code"),
), ),
))); ));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Deallocates a [SPCommand]. /// Deallocates a [SPCommand].

View file

@ -2,6 +2,7 @@
//! //!
//! prefix `sp_cp437_grid_` //! prefix `sp_cp437_grid_`
use std::ptr::NonNull;
use crate::SPByteSlice; use crate::SPByteSlice;
use servicepoint::{DataRef, Grid}; use servicepoint::{DataRef, Grid};
@ -39,12 +40,11 @@ impl Clone for SPCp437Grid {
pub unsafe extern "C" fn sp_cp437_grid_new( pub unsafe extern "C" fn sp_cp437_grid_new(
width: usize, width: usize,
height: usize, height: usize,
) -> *mut SPCp437Grid { ) -> NonNull<SPCp437Grid> {
let result = Box::into_raw(Box::new(SPCp437Grid( let result = Box::new(SPCp437Grid(
servicepoint::Cp437Grid::new(width, height), servicepoint::Cp437Grid::new(width, height),
))); ));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Loads a [SPCp437Grid] with the specified dimensions from the provided data. /// Loads a [SPCp437Grid] with the specified dimensions from the provided data.
@ -70,14 +70,13 @@ pub unsafe extern "C" fn sp_cp437_grid_load(
height: usize, height: usize,
data: *const u8, data: *const u8,
data_length: usize, data_length: usize,
) -> *mut SPCp437Grid { ) -> NonNull<SPCp437Grid> {
assert!(data.is_null()); assert!(data.is_null());
let data = std::slice::from_raw_parts(data, data_length); let data = std::slice::from_raw_parts(data, data_length);
let result = Box::into_raw(Box::new(SPCp437Grid( let result = Box::new(SPCp437Grid(
servicepoint::Cp437Grid::load(width, height, data), servicepoint::Cp437Grid::load(width, height, data),
))); ));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Clones a [SPCp437Grid]. /// Clones a [SPCp437Grid].
@ -99,11 +98,10 @@ pub unsafe extern "C" fn sp_cp437_grid_load(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_clone( pub unsafe extern "C" fn sp_cp437_grid_clone(
cp437_grid: *const SPCp437Grid, cp437_grid: *const SPCp437Grid,
) -> *mut SPCp437Grid { ) -> NonNull<SPCp437Grid> {
assert!(!cp437_grid.is_null()); assert!(!cp437_grid.is_null());
let result = Box::into_raw(Box::new((*cp437_grid).clone())); let result = Box::new((*cp437_grid).clone());
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Deallocates a [SPCp437Grid]. /// Deallocates a [SPCp437Grid].
@ -278,7 +276,7 @@ pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref(
) -> SPByteSlice { ) -> SPByteSlice {
let data = (*cp437_grid).0.data_ref_mut(); let data = (*cp437_grid).0.data_ref_mut();
SPByteSlice { SPByteSlice {
start: data.as_mut_ptr_range().start, start: NonNull::new(data.as_mut_ptr_range().start).unwrap(),
length: data.len(), length: data.len(),
} }
} }

View file

@ -2,7 +2,7 @@
//! //!
//! prefix `sp_packet_` //! prefix `sp_packet_`
use std::ptr::null_mut; use std::ptr::{null_mut, NonNull};
use crate::SPCommand; use crate::SPCommand;
@ -29,13 +29,11 @@ pub struct SPPacket(pub(crate) servicepoint::packet::Packet);
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_packet_from_command( pub unsafe extern "C" fn sp_packet_from_command(
command: *mut SPCommand, command: *mut SPCommand,
) -> *mut SPPacket { ) -> NonNull<SPPacket> {
assert!(!command.is_null()); assert!(!command.is_null());
let command = *Box::from_raw(command); let command = *Box::from_raw(command);
let packet = SPPacket(command.0.into()); let result = Box::new(SPPacket(command.0.into()));
let result = Box::into_raw(Box::new(packet)); NonNull::from(Box::leak(result))
assert!(!result.is_null());
result
} }
/// Tries to load a [SPPacket] from the passed array with the specified length. /// Tries to load a [SPPacket] from the passed array with the specified length.
@ -86,11 +84,10 @@ pub unsafe extern "C" fn sp_packet_try_load(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_packet_clone( pub unsafe extern "C" fn sp_packet_clone(
packet: *const SPPacket, packet: *const SPPacket,
) -> *mut SPPacket { ) -> NonNull<SPPacket> {
assert!(!packet.is_null()); assert!(!packet.is_null());
let result = Box::into_raw(Box::new(SPPacket((*packet).0.clone()))); let result = Box::new(SPPacket((*packet).0.clone()));
assert!(!result.is_null()); NonNull::from(Box::leak(result))
result
} }
/// Deallocates a [SPPacket]. /// Deallocates a [SPPacket].