use crate::{ containers::ByteSlice, mem::{ heap_clone, heap_drop, heap_move_nonnull, heap_move_ok, heap_remove, }, }; use servicepoint::{ BinaryOperation, BitVecCommand, CompressionCode, DisplayBitVec, Packet, }; use std::ptr::NonNull; /// Creates a new [DisplayBitVec] instance. /// /// # Arguments /// /// - `size`: size in bits. /// /// returns: [DisplayBitVec] 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(DisplayBitVec::repeat(false, size)) } /// Interpret the data as a series of bits and load then into a new [DisplayBitVec] instance. /// /// returns: [DisplayBitVec] 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(DisplayBitVec::from_slice(data)) } /// Clones a [DisplayBitVec]. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_clone( bit_vec: NonNull, ) -> NonNull { unsafe { heap_clone(bit_vec) } } /// Deallocates a [DisplayBitVec]. #[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 [DisplayBitVec]. /// /// # 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().get(index).unwrap() } } /// Sets the value of a bit in the [DisplayBitVec]. /// /// # 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()).set(index, value) } } /// Sets the value of all bits in the [DisplayBitVec]. /// /// # 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()).fill(value) } } /// Gets the length of the [DisplayBitVec] 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().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().is_empty() } } /// Gets an unsafe reference to the data of the [DisplayBitVec] 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()).as_raw_mut_slice()) } } /// Creates a [BitVecCommand] and immediately turns that into a [Packet]. /// /// The provided [DisplayBitVec] gets consumed. /// /// Returns NULL in case of an error. #[no_mangle] pub unsafe extern "C" fn sp_bitvec_into_packet( bitvec: NonNull, offset: usize, operation: BinaryOperation, compression: CompressionCode, ) -> *mut Packet { let bitvec = unsafe { heap_remove(bitvec) }; heap_move_ok(Packet::try_from(BitVecCommand { bitvec, offset, operation, compression, })) }