diff --git a/crates/servicepoint_binding_c/src/bitmap.rs b/crates/servicepoint_binding_c/src/bitmap.rs index a7ae48a..2956de3 100644 --- a/crates/servicepoint_binding_c/src/bitmap.rs +++ b/crates/servicepoint_binding_c/src/bitmap.rs @@ -49,6 +49,22 @@ pub unsafe extern "C" fn sp_bitmap_new( NonNull::from(Box::leak(result)) } +/// Creates a new [SPBitmap] with a size matching the screen. +/// +/// returns: [SPBitmap] 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]. +#[no_mangle] +pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull { + let result = Box::new(SPBitmap(servicepoint::Bitmap::max_sized())); + NonNull::from(Box::leak(result)) +} + /// Loads a [SPBitmap] with the specified dimensions from the provided data. /// /// # Arguments diff --git a/crates/servicepoint_binding_c/src/packet.rs b/crates/servicepoint_binding_c/src/packet.rs index e44c23f..1f7082a 100644 --- a/crates/servicepoint_binding_c/src/packet.rs +++ b/crates/servicepoint_binding_c/src/packet.rs @@ -65,6 +65,63 @@ pub unsafe extern "C" fn sp_packet_try_load( } } +/// Creates a raw [SPPacket] 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 [SPPacket] 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( + command_code: u16, + a: u16, + b: u16, + c: u16, + d: u16, + payload: *const u8, + payload_len: usize, +) -> NonNull { + assert_eq!(payload.is_null(), payload_len == 0); + + let payload = if payload.is_null() { + vec![] + } else { + let payload = std::slice::from_raw_parts(payload, payload_len); + Vec::from(payload) + }; + + let packet = servicepoint::packet::Packet { + header: servicepoint::packet::Header { + command_code, + a, + b, + c, + d, + }, + payload, + }; + let result = Box::new(SPPacket(packet)); + NonNull::from(Box::leak(result)) +} + /// Clones a [SPPacket]. /// /// Will never return NULL. @@ -94,7 +151,7 @@ pub unsafe extern "C" fn sp_packet_clone( /// /// # Panics /// -/// - when `sp_packet_free` is NULL +/// - when `packet` is NULL /// /// # Safety ///