use crate::{heap_drop, heap_move_nonnull, ByteSlice}; use servicepoint::BitVecU8Msb0; use std::ptr::NonNull; /// A vector of bits /// /// # Examples /// ```C /// SPBitVec vec = sp_bitvec_new(8); /// sp_bitvec_set(vec, 5, true); /// sp_bitvec_free(vec); /// ``` pub struct SPBitVec(pub(crate) BitVecU8Msb0); impl Clone for SPBitVec { fn clone(&self) -> Self { SPBitVec(self.0.clone()) } } /// Creates a new [SPBitVec] instance. /// /// # Arguments /// /// - `size`: size in bits. /// /// returns: [SPBitVec] with all bits set to false. /// /// # Panics /// /// - when `size` is not divisible by 8. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_new(size: usize) -> NonNull { heap_move_nonnull(SPBitVec(BitVecU8Msb0::repeat(false, size))) } /// Interpret the data as a series of bits and load then into a new [SPBitVec] instance. /// /// returns: [SPBitVec] instance containing data. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_load(data: ByteSlice) -> NonNull { let data = unsafe { data.as_slice() }; heap_move_nonnull(SPBitVec(BitVecU8Msb0::from_slice(data))) } /// Clones a [SPBitVec]. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_clone( bit_vec: NonNull, ) -> NonNull { heap_move_nonnull(unsafe { bit_vec.as_ref().clone() }) } /// Deallocates a [SPBitVec]. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_free(bit_vec: NonNull) { unsafe { heap_drop(bit_vec) } } /// Gets the value of a bit from the [SPBitVec]. /// /// # Arguments /// /// - `bit_vec`: instance to read from /// - `index`: the bit index to read /// /// returns: value of the bit /// /// # Panics /// /// - when accessing `index` out of bounds #[no_mangle] pub unsafe extern "C" fn sp_bitvec_get( bit_vec: NonNull, index: usize, ) -> bool { unsafe { *bit_vec.as_ref().0.get(index).unwrap() } } /// Sets the value of a bit in the [SPBitVec]. /// /// # Arguments /// /// - `bit_vec`: instance to write to /// - `index`: the bit index to edit /// - `value`: the value to set the bit to /// /// # Panics /// /// - when accessing `index` out of bounds #[no_mangle] pub unsafe extern "C" fn sp_bitvec_set( bit_vec: NonNull, index: usize, value: bool, ) { unsafe { (*bit_vec.as_ptr()).0.set(index, value) } } /// Sets the value of all bits in the [SPBitVec]. /// /// # Arguments /// /// - `bit_vec`: instance to write to /// - `value`: the value to set all bits to #[no_mangle] pub unsafe extern "C" fn sp_bitvec_fill( bit_vec: NonNull, value: bool, ) { unsafe { (*bit_vec.as_ptr()).0.fill(value) } } /// Gets the length of the [SPBitVec] in bits. /// /// # Arguments /// /// - `bit_vec`: instance to write to #[no_mangle] pub unsafe extern "C" fn sp_bitvec_len(bit_vec: NonNull) -> usize { unsafe { bit_vec.as_ref().0.len() } } /// Returns true if length is 0. /// /// # Arguments /// /// - `bit_vec`: instance to write to #[no_mangle] pub unsafe extern "C" fn sp_bitvec_is_empty( bit_vec: NonNull, ) -> bool { unsafe { bit_vec.as_ref().0.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 #[no_mangle] pub unsafe extern "C" fn sp_bitvec_unsafe_data_ref( bit_vec: NonNull, ) -> ByteSlice { unsafe { ByteSlice::from_slice((*bit_vec.as_ptr()).0.as_raw_mut_slice()) } }