diff --git a/Cargo.toml b/Cargo.toml index 6379c5c..017c224 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,7 @@ members = [ [workspace.package] version = "0.5.0" + +[workspace.lints.rust] +missing-docs = "warn" +missing-docs-in-crate-items = "warn" diff --git a/crates/servicepoint/Cargo.toml b/crates/servicepoint/Cargo.toml index 6ae0b0e..5e748e3 100644 --- a/crates/servicepoint/Cargo.toml +++ b/crates/servicepoint/Cargo.toml @@ -30,4 +30,7 @@ all_compressions = ["compression_zlib", "compression_bzip2", "compression_lzma", [dev-dependencies] # for examples clap = { version = "4.5", features = ["derive"] } -rand = "0.8" \ No newline at end of file +rand = "0.8" + +[lints] +workspace = true diff --git a/crates/servicepoint/src/compression_code.rs b/crates/servicepoint/src/compression_code.rs index 19984ad..44bed3c 100644 --- a/crates/servicepoint/src/compression_code.rs +++ b/crates/servicepoint/src/compression_code.rs @@ -2,14 +2,19 @@ #[repr(u16)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum CompressionCode { + /// no compression Uncompressed = 0x0, #[cfg(feature = "compression_zlib")] + /// compress using flate2 with zlib header Zlib = 0x677a, #[cfg(feature = "compression_bzip2")] + /// compress using bzip2 Bzip2 = 0x627a, #[cfg(feature = "compression_lzma")] + /// compress using lzma Lzma = 0x6c7a, #[cfg(feature = "compression_zstd")] + /// compress using Zstandard Zstd = 0x7a73, } diff --git a/crates/servicepoint/src/grid.rs b/crates/servicepoint/src/grid.rs index 55cab90..1a53f77 100644 --- a/crates/servicepoint/src/grid.rs +++ b/crates/servicepoint/src/grid.rs @@ -1,5 +1,14 @@ +/// A two-dimensional grid of `T` pub trait Grid { #[must_use] + /// Creates a new Grid with the specified dimensions. + /// + /// # Arguments + /// + /// - width: size in x-direction + /// - height: size in y-direction + /// + /// returns: Grid with all cells initialized to default state. fn new(width: usize, height: usize) -> Self; /// Sets the value at the specified position diff --git a/crates/servicepoint/src/lib.rs b/crates/servicepoint/src/lib.rs index 7263a6c..d68801c 100644 --- a/crates/servicepoint/src/lib.rs +++ b/crates/servicepoint/src/lib.rs @@ -1,3 +1,5 @@ +//! Abstractions for the UDP protocol of the CCCB servicepoint display. + use std::time::Duration; pub use crate::bit_vec::BitVec; diff --git a/crates/servicepoint_binding_c/Cargo.toml b/crates/servicepoint_binding_c/Cargo.toml index 4146255..364fbe2 100644 --- a/crates/servicepoint_binding_c/Cargo.toml +++ b/crates/servicepoint_binding_c/Cargo.toml @@ -20,3 +20,6 @@ cbindgen = "0.26.0" version = "0.5.0" path = "../servicepoint" features = ["all_compressions"] + +[lints] +workspace = true diff --git a/crates/servicepoint_binding_c/build.rs b/crates/servicepoint_binding_c/build.rs index 10505b0..93bf703 100644 --- a/crates/servicepoint_binding_c/build.rs +++ b/crates/servicepoint_binding_c/build.rs @@ -1,3 +1,9 @@ +//! Build script generating the header for the `servicepoint` C library. +//! +//! When the environment variable `SERVICEPOINT_HEADER_OUT` is set, the header is copied there from +//! the out directory. This can be used to use the build script as a command line tool from other +//! build tools. + use std::{env, fs::copy}; use cbindgen::{generate_with_config, Config}; diff --git a/crates/servicepoint_binding_c/src/bit_vec.rs b/crates/servicepoint_binding_c/src/bit_vec.rs index dfeb5d4..58423cd 100644 --- a/crates/servicepoint_binding_c/src/bit_vec.rs +++ b/crates/servicepoint_binding_c/src/bit_vec.rs @@ -5,13 +5,28 @@ use crate::c_slice::CByteSlice; /// Creates a new `BitVec` instance. /// The returned instance has to be freed with `bit_vec_dealloc`. +/// +/// # Safety +/// +/// The caller has to make sure that:7 +/// +/// - the returned instance is freed in some way, either by using a consuming function or +/// by explicitly calling `sp_bit_vec_dealloc`. #[no_mangle] 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. -/// The returned instance has to be freed with `bit_vec_dealloc`. +/// +/// # 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_bit_vec_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_load( data: *const u8, @@ -22,7 +37,15 @@ pub unsafe extern "C" fn sp_bit_vec_load( } /// Clones a `BitVec`. -/// The returned instance has to be freed with `bit_vec_dealloc`. +/// +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - `this` points to a valid `BitVec` +/// - `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_bit_vec_dealloc`. #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_clone(this: *const BitVec) -> *mut BitVec { Box::into_raw(Box::new((*this).clone())) @@ -30,13 +53,26 @@ pub unsafe extern "C" fn sp_bit_vec_clone(this: *const BitVec) -> *mut BitVec { /// Deallocates a `BitVec`. /// -/// 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 `BitVec` +/// - `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_bit_vec_dealloc(this: *mut BitVec) { _ = Box::from_raw(this); } /// Gets the value of a bit from the `BitVec`. +/// +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - `this` points to a valid `BitVec` +/// - `this` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_get( this: *const BitVec, @@ -46,6 +82,13 @@ pub unsafe extern "C" fn sp_bit_vec_get( } /// Sets the value of a bit in the `BitVec`. +/// +/// # 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_bit_vec_set( this: *mut BitVec, @@ -56,18 +99,37 @@ pub unsafe extern "C" fn sp_bit_vec_set( } /// Sets the value of all bits in the `BitVec`. +/// +/// # 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_bit_vec_fill(this: *mut BitVec, value: bool) { (*this).fill(value) } /// Gets the length of the `BitVec` in bits. +/// +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - `this` points to a valid `BitVec` #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_len(this: *const BitVec) -> usize { (*this).len() } /// Returns true if length is 0. +/// +/// # Safety +/// +/// The caller has to make sure that: +/// +/// - `this` points to a valid `BitVec` #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_is_empty(this: *const BitVec) -> bool { (*this).is_empty() @@ -77,11 +139,11 @@ pub unsafe extern "C" fn sp_bit_vec_is_empty(this: *const BitVec) -> bool { /// /// ## Safety /// -/// The caller has to make sure to never access the returned memory after the `BitVec` -/// 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 `BitVec` +/// - the returned memory range is never accessed after the passed `BitVec` has been freed +/// - the returned memory range is never accessed concurrently, either via the `BitVec` or directly #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_unsafe_data_ref( this: *mut BitVec, diff --git a/crates/servicepoint_binding_c/src/lib.rs b/crates/servicepoint_binding_c/src/lib.rs index 4ecbd5d..286ebce 100644 --- a/crates/servicepoint_binding_c/src/lib.rs +++ b/crates/servicepoint_binding_c/src/lib.rs @@ -1,14 +1,41 @@ +//! C API wrapper for the `servicepoint` crate. + pub use servicepoint::{ CompressionCode, PIXEL_COUNT, PIXEL_HEIGHT, PIXEL_WIDTH, TILE_HEIGHT, TILE_SIZE, TILE_WIDTH, }; +/// C functions for interacting with `BitVec`s pub mod bit_vec; + +/// C functions for interacting with `ByteGrid`s pub mod byte_grid; + +/// C functions for interacting with `BitVec`s pub mod c_slice; + +/// C functions for interacting with `Command`s pub mod command; + +/// C functions for interacting with `Connection`s pub mod connection; + +/// C functions for interacting with `Packet`s pub mod packet; + +/// C functions for interacting with `PixelGrid`s pub mod pixel_grid; +/// The minimum time needed for the display to refresh the screen in ms. pub const FRAME_PACING_MS: u32 = servicepoint::FRAME_PACING.as_millis() as u32; + +#[repr(C)] +/// Represents a span of memory (`&mut [u8]` ) as a struct usable by C code. +/// +/// Usage of this type is inherently unsafe. +pub struct CByteSlice { + /// The start address of the memory + pub start: *mut u8, + /// The amount of memory in bytes + pub length: usize, +} diff --git a/crates/servicepoint_binding_cs/Cargo.toml b/crates/servicepoint_binding_cs/Cargo.toml index 7282c1d..6a894e0 100644 --- a/crates/servicepoint_binding_cs/Cargo.toml +++ b/crates/servicepoint_binding_cs/Cargo.toml @@ -15,3 +15,6 @@ csbindgen = "1.8.0" [dependencies] servicepoint_binding_c = { version = "0.5.0", path = "../servicepoint_binding_c" } servicepoint = { version = "0.5.0", path = "../servicepoint" } + +[lints] +workspace = true diff --git a/crates/servicepoint_binding_cs/build.rs b/crates/servicepoint_binding_cs/build.rs index ec5aa81..7f64dcf 100644 --- a/crates/servicepoint_binding_cs/build.rs +++ b/crates/servicepoint_binding_cs/build.rs @@ -1,3 +1,5 @@ +//! Build script generating the C# code needed to call methods from the `servicepoint` C library. + fn main() { println!("cargo:rerun-if-changed=../servicepoint_binding_c/src"); println!("cargo:rerun-if-changed=build.rs");