From d351eef6fac49910e9abc34de09d92d06ad8e65a Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Tue, 28 May 2024 20:37:55 +0200 Subject: [PATCH] more documentation --- crates/servicepoint/src/bit_vec.rs | 18 ++- crates/servicepoint/src/byte_grid.rs | 21 +++ crates/servicepoint_binding_c/src/bit_vec.rs | 42 +++++- .../servicepoint_binding_c/src/byte_grid.rs | 125 ++++++++++++++++-- crates/servicepoint_binding_c/src/c_slice.rs | 8 +- crates/servicepoint_binding_cs/src/lib.rs | 2 +- 6 files changed, 194 insertions(+), 22 deletions(-) diff --git a/crates/servicepoint/src/bit_vec.rs b/crates/servicepoint/src/bit_vec.rs index 0f3e262..7b2d5c1 100644 --- a/crates/servicepoint/src/bit_vec.rs +++ b/crates/servicepoint/src/bit_vec.rs @@ -1,6 +1,6 @@ use crate::DataRef; -/// A vector of bits +/// A fixed-size vector of bits #[derive(Debug, Clone, PartialEq)] pub struct BitVec { size: usize, @@ -8,17 +8,17 @@ pub struct BitVec { } impl BitVec { - /// Create a new bit vector. + /// Create a new `BitVec`. /// /// # Arguments /// - /// * `size`: size in bits. Must be dividable by 8. + /// * `size`: size in bits. /// - /// returns: bit vector with all bits set to false. + /// returns: `BitVec` with all bits set to false. /// /// # Panics /// - /// When size is not a multiple of 8. + /// When `size` is not divisible by 8. #[must_use] pub fn new(size: usize) -> BitVec { assert_eq!(size % 8, 0); @@ -36,6 +36,10 @@ impl BitVec { /// * `value`: the value to set the bit to /// /// returns: old value of the bit + /// + /// # Panics + /// + /// When accessing `index` out of bounds. pub fn set(&mut self, index: usize, value: bool) -> bool { let (byte_index, bit_mask) = self.get_indexes(index); @@ -58,6 +62,10 @@ impl BitVec { /// * `index`: the bit index to read /// /// returns: value of the bit + /// + /// # Panics + /// + /// When accessing `index` out of bounds. #[must_use] pub fn get(&self, index: usize) -> bool { let (byte_index, bit_mask) = self.get_indexes(index); diff --git a/crates/servicepoint/src/byte_grid.rs b/crates/servicepoint/src/byte_grid.rs index 9a17ead..d9b515c 100644 --- a/crates/servicepoint/src/byte_grid.rs +++ b/crates/servicepoint/src/byte_grid.rs @@ -52,6 +52,18 @@ impl Grid for ByteGrid { } } + /// Sets the value of the cell at the specified position in the `ByteGrid. + /// + /// # Arguments + /// + /// * `x` and `y`: position of the cell + /// * `value`: the value to write to the cell + /// + /// returns: old value of the cell. + /// + /// # Panics + /// + /// When accessing `x` or `y` out of bounds. fn set(&mut self, x: usize, y: usize, value: u8) -> u8 { self.check_indexes(x, y); let pos = &mut self.data[x + y * self.width]; @@ -60,6 +72,15 @@ impl Grid for ByteGrid { old_val } + /// Gets the current value at the specified position. + /// + /// # Arguments + /// + /// * `x` and `y`: position of the cell to read + /// + /// # Panics + /// + /// When accessing `x` or `y` out of bounds. fn get(&self, x: usize, y: usize) -> u8 { self.check_indexes(x, y); self.data[x + y * self.width] diff --git a/crates/servicepoint_binding_c/src/bit_vec.rs b/crates/servicepoint_binding_c/src/bit_vec.rs index 58423cd..582e97d 100644 --- a/crates/servicepoint_binding_c/src/bit_vec.rs +++ b/crates/servicepoint_binding_c/src/bit_vec.rs @@ -4,11 +4,20 @@ use servicepoint::DataRef; use crate::c_slice::CByteSlice; /// Creates a new `BitVec` instance. -/// The returned instance has to be freed with `bit_vec_dealloc`. +/// +/// # Arguments +/// +/// * `size`: size in bits. +/// +/// returns: `BitVec` with all bits set to false. +/// +/// # Panics +/// +/// When `size` is not divisible by 8. /// /// # Safety /// -/// The caller has to make sure that:7 +/// 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_bit_vec_dealloc`. @@ -17,7 +26,7 @@ pub unsafe extern "C" fn sp_bit_vec_new(size: usize) -> *mut BitVec { Box::into_raw(Box::new(BitVec::new(size))) } -/// Loads a `BitVec` from the provided data. +/// Interpret the data as a series of bits and load then into a new `BitVec` instance. /// /// # Safety /// @@ -67,6 +76,17 @@ pub unsafe extern "C" fn sp_bit_vec_dealloc(this: *mut BitVec) { /// Gets the value of a bit from the `BitVec`. /// +/// # Arguments +/// +/// * `this`: instance to read from +/// * `index`: the bit index to read +/// +/// returns: value of the bit +/// +/// # Panics +/// +/// When accessing `index` out of bounds. +/// /// # Safety /// /// The caller has to make sure that: @@ -83,6 +103,18 @@ pub unsafe extern "C" fn sp_bit_vec_get( /// Sets the value of a bit in the `BitVec`. /// +/// # Arguments +/// +/// * `this`: instance to write to +/// * `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. +/// /// # Safety /// /// The caller has to make sure that: @@ -100,6 +132,10 @@ pub unsafe extern "C" fn sp_bit_vec_set( /// Sets the value of all bits in the `BitVec`. /// +/// # Arguments +/// +/// * `value`: the value to set all bits to +/// /// # Safety /// /// The caller has to make sure that: diff --git a/crates/servicepoint_binding_c/src/byte_grid.rs b/crates/servicepoint_binding_c/src/byte_grid.rs index 124420f..c77654a 100644 --- a/crates/servicepoint_binding_c/src/byte_grid.rs +++ b/crates/servicepoint_binding_c/src/byte_grid.rs @@ -3,8 +3,16 @@ use servicepoint::{DataRef, Grid}; use crate::c_slice::CByteSlice; -/// Creates a new `ByteGrid` instance. -/// The returned instance has to be freed with `byte_grid_dealloc`. +/// Creates a new `ByteGrid` with the specified dimensions. +/// +/// returns: `ByteGrid` initialized to 0. +/// +/// # 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_byte_grid_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_byte_grid_new( width: usize, @@ -14,7 +22,19 @@ pub unsafe extern "C" fn sp_byte_grid_new( } /// Loads a `ByteGrid` with the specified dimensions from the provided data. -/// The returned instance has to be freed with `byte_grid_dealloc`. +/// +/// # Panics +/// +/// When the provided `data_length` is not sufficient for the `height` and `width` +/// +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - `data` points to a valid memory location of at least `data_length` +/// bytes in size. +/// - the returned instance is freed in some way, either by using a consuming function or +/// by explicitly calling `sp_byte_grid_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_byte_grid_load( width: usize, @@ -27,7 +47,15 @@ pub unsafe extern "C" fn sp_byte_grid_load( } /// Clones a `ByteGrid`. -/// The returned instance has to be freed with `byte_grid_dealloc`. +/// +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - `this` points to a valid `ByteGrid` +/// - `this` is not written to concurrently +/// - the returned instance is freed in some way, either by using a consuming function or +/// by explicitly calling `sp_byte_grid_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_byte_grid_clone( this: *const ByteGrid, @@ -37,13 +65,35 @@ pub unsafe extern "C" fn sp_byte_grid_clone( /// Deallocates a `ByteGrid`. /// -/// Note: do not call this if the grid has been consumed in another way, e.g. to create a command. +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - `this` points to a valid `ByteGrid` +/// - `this` is not used concurrently or after this call +/// - `this` was not passed to another consuming function, e.g. to create a `Command` #[no_mangle] pub unsafe extern "C" fn sp_byte_grid_dealloc(this: *mut ByteGrid) { _ = Box::from_raw(this); } -/// Get the current value at the specified position +/// Gets the current value at the specified position. +/// +/// # Arguments +/// +/// * `this`: instance to read from +/// * `x` and `y`: position of the cell to read +/// +/// # Panics +/// +/// When accessing `x` or `y` out of bounds. +/// +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - `this` points to a valid `ByteGrid` +/// - `this` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_byte_grid_get( this: *const ByteGrid, @@ -53,7 +103,26 @@ pub unsafe extern "C" fn sp_byte_grid_get( (*this).get(x, y) } -/// Sets the current value at the specified position +/// Sets the value of the specified position in the `ByteGrid`. +/// +/// # Arguments +/// +/// * `this`: instance to write to +/// * `x` and `y`: position of the cell +/// * `value`: the value to write to the cell +/// +/// returns: old value of the cell +/// +/// # Panics +/// +/// When accessing `x` or `y` out of bounds. +/// +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - `this` points to a valid `BitVec` +/// - `this` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_byte_grid_set( this: *mut ByteGrid, @@ -64,19 +133,51 @@ pub unsafe extern "C" fn sp_byte_grid_set( (*this).set(x, y, value); } -/// Fills the whole `ByteGrid` with the specified value +/// Sets the value of all cells in the `ByteGrid`. +/// +/// # Arguments +/// +/// * `this`: instance to write to +/// * `value`: the value to set all cells to +/// +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - `this` points to a valid `ByteGrid` +/// - `this` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_byte_grid_fill(this: *mut ByteGrid, value: u8) { (*this).fill(value); } /// Gets the width in pixels of the `ByteGrid` instance. +/// +/// # Arguments +/// +/// * `this`: instance to read from +/// +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - `this` points to a valid `ByteGrid` #[no_mangle] pub unsafe extern "C" fn sp_byte_grid_width(this: *const ByteGrid) -> usize { (*this).width() } /// Gets the height in pixels of the `ByteGrid` instance. +/// +/// # Arguments +/// +/// * `this`: instance to read from +/// +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - `this` points to a valid `ByteGrid` #[no_mangle] pub unsafe extern "C" fn sp_byte_grid_height(this: *const ByteGrid) -> usize { (*this).height() @@ -86,11 +187,11 @@ pub unsafe extern "C" fn sp_byte_grid_height(this: *const ByteGrid) -> usize { /// /// ## Safety /// -/// The caller has to make sure to never access the returned memory after the `ByteGrid` -/// instance has been consumed or manually deallocated. +/// The caller has to make sure that: /// -/// Reading and writing concurrently to either the original instance or the returned data will -/// result in undefined behavior. +/// - `this` points to a valid `ByteGrid` +/// - the returned memory range is never accessed after the passed `ByteGrid` has been freed +/// - the returned memory range is never accessed concurrently, either via the `ByteGrid` or directly #[no_mangle] pub unsafe extern "C" fn sp_byte_grid_unsafe_data_ref( this: *mut ByteGrid, diff --git a/crates/servicepoint_binding_c/src/c_slice.rs b/crates/servicepoint_binding_c/src/c_slice.rs index 9609906..b255c1b 100644 --- a/crates/servicepoint_binding_c/src/c_slice.rs +++ b/crates/servicepoint_binding_c/src/c_slice.rs @@ -1,7 +1,13 @@ #[repr(C)] /// Represents a span of memory (`&mut [u8]` ) as a struct usable by C code. /// -/// Usage of this type is inherently unsafe. +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - accesses to the memory pointed to with `start` is never accessed outside `length` +/// - the lifetime of the `CByteSlice` does not outlive the memory it points to, as described in +/// the function returning this type. pub struct CByteSlice { /// The start address of the memory pub start: *mut u8, diff --git a/crates/servicepoint_binding_cs/src/lib.rs b/crates/servicepoint_binding_cs/src/lib.rs index 8b13789..c7bcac6 100644 --- a/crates/servicepoint_binding_cs/src/lib.rs +++ b/crates/servicepoint_binding_cs/src/lib.rs @@ -1 +1 @@ - +//! This crate is intentionally left empty. Only the build script is relevant here.