Merge pull request 'update safety notes' (#1) from update-safety-notes into main
ci / Check build (macos-latest) (push) Has been cancelled
ci / Check build (ubuntu-latest) (push) Has been cancelled
ci / Check build (windows-latest) (push) Has been cancelled
ci / Run Tests (push) Has been cancelled
ci / Check MSRV (push) Has been cancelled
ci / Check Cross-Compilation (armv7-unknown-linux-gnueabihf) (push) Has been cancelled
ci / Check Cross-Compilation (thumbv7em-none-eabihf) (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled

Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
muellerr committed 2026-06-08 17:19:03 +02:00
commit 5f7ff2fc5d
3 files changed
+62 -17

No files matched your search

+11
View File
@@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased]
# [v0.1.2] 2026-06-08
- Released with new name `raw-buffer`.
- Added more safety notes.
# [v0.1.1]
Badge fix, points to wrong crate.
@@ -16,5 +21,11 @@ Badge fix, points to wrong crate.
Initial release
# Release with new name
[v0.1.2]: https://egit.irs.uni-stuttgart.de/rust/raw-buffer/releases/tag/v0.1.2
# Release with old name `raw-slicee`
[v0.1.1]: https://egit.irs.uni-stuttgart.de/rust/raw-slice/compare/v0.1.0...v0.1.1
[v0.1.0]: https://egit.irs.uni-stuttgart.de/rust/raw-slice/releases/tag/v0.1.0
+4 -8
View File
@@ -1,19 +1,15 @@
[package]
name = "raw-slicee"
version = "0.1.1"
name = "raw-buffer"
version = "0.1.2"
edition = "2024"
rust-version = "1.85.1"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
description = "Generic low-level raw slice types"
homepage = "https://egit.irs.uni-stuttgart.de/rust/raw-slice"
repository = "https://egit.irs.uni-stuttgart.de/rust/raw-slice"
homepage = "https://egit.irs.uni-stuttgart.de/rust/raw-buffer"
repository = "https://egit.irs.uni-stuttgart.de/rust/raw-buffer"
license = "Apache-2.0 OR MIT"
keywords = ["no-std", "slice", "embedded", "dma", "pointer"]
categories = ["no-std", "no-std::no-alloc", "hardware-support", "embedded", "data-structures"]
# Name was hogged.
[lib]
name = "raw_slice"
[dependencies]
embedded-dma = "0.2"
+47 -9
View File
@@ -12,7 +12,7 @@
//! This data structure is particularly useful in embedded systems, where data may be
//! passed to asynchronous peripherals such as serial TX drivers using interrupts or DMA.
//! The data may be static, but it could also reside on the stack. By using a shared [RawBufSlice],
//! you can pass borrowed data to a driver **without** needing to explicitly manage lifetimes.
//! you can pass borrowed data to a driver without needing to explicitly manage lifetimes.
//!
//! ## Safety Considerations
//!
@@ -22,6 +22,12 @@
//! (e.g., an ISR and a task) requires proper synchronization.
//! - **Immutability:** [RawSlice] provides a **read-only view** of the data. If you need
//! mutability, [RawSliceMut] can be used.
//! - If the raw slice wrapper is used with stack allocated slices: Higher-level APIs
//! oftentimes rely on `Drop` implementations to allow cancelling
//! transfers on non-blocking APIs. Using `core::mem::forget` on such implementations
//! can leak the underlying memory. HAL and firmware authors *MUST* either use this
//! abstraction combined with `'static` slices or ensure that the `Drop`
//! implementations always runs properly.
//!
//! ## Usage Example
//!
@@ -30,7 +36,9 @@
//!
//! static DATA: &[u8] = &[1, 2, 3, 4];
//!
//! let raw_buf = unsafe { RawBufSlice::new(DATA) };
//! // Safety: Your safety note here. We are using static data, your DMA might have other
//! // requirements to the buffer used, e.g. buffer in correct RAM, with certain alignment etc.
//! let raw_buf = unsafe { RawSlice::new(DATA) };
//!
//! // Later, in an ISR or different context
//! unsafe {
@@ -68,9 +76,9 @@ impl<T> RawSlice<T> {
///
/// # Safety
///
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`.
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`. This is especially
/// important if the original slice is stack allocated.
/// - The original slice **must not** be mutated while this `RawSlice<T>` is used.
#[allow(dead_code)]
pub const unsafe fn new(data: &[T]) -> Self {
Self {
data: data.as_ptr(),
@@ -90,7 +98,8 @@ impl<T> RawSlice<T> {
///
/// # Safety
///
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`.
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`. This is especially
/// important if the original slice is stack allocated.
/// - The original slice **must not** be mutated while this `RawSlice<T>` is used.
pub const unsafe fn set(&mut self, data: &[T]) {
self.data = data.as_ptr();
@@ -153,11 +162,25 @@ pub type RawU32Slice = RawSlice<u32>;
macro_rules! impl_dma_read_buf {
($slice_type:ident, $ty:ident) => {
/// This allows using [Self] in DMA APIs which expect a [embedded_dma::ReadBuffer].
/// This allows using [Self] in DMA based APIs which expect a [embedded_dma::ReadBuffer].
///
/// However, the user still must ensure that any alignment rules for DMA buffers required by
/// the hardware are met and than any MPU/MMU configuration necessary is also performed for this
/// to work properly.
///
/// # Safety
///
/// - The raw slice type erases the lifetime of slice. The caller *MUST* ensure that the
/// lifetime of the slice is valid as long as the buffer is in-use by the DMA.
/// - It is also imperitive that the DMA system you're using returns the pointer
/// *only after a DMA transfer is complete*. If you're unsure check the docs and if nothing
/// is mentioned in the docs please clarify it with a project maintainer.
/// - If the raw slice wrapper is used on a stack allocated slice: Higher-level APIs
/// oftentimes rely on `Drop` implementations to allow cancelling
/// transfers on non-blocking APIs. Using `core::mem::forget` on such implementations
/// can leak the underlying memory. HAL and firmware authors *MUST* either use this
/// abstraction combined with `'static` slices or ensure that the `Drop`
/// implementations always runs properly.
unsafe impl embedded_dma::ReadBuffer for $slice_type {
type Word = $ty;
@@ -186,9 +209,9 @@ impl<T> RawSliceMut<T> {
///
/// # Safety
///
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`.
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`. This is especially
/// important if the original slice is stack allocated.
/// - The original slice **must not** be mutated while this `RawSlice<T>` is used.
#[allow(dead_code)]
pub const unsafe fn new(data: &mut [T]) -> Self {
Self {
data: data.as_mut_ptr(),
@@ -208,7 +231,8 @@ impl<T> RawSliceMut<T> {
///
/// # Safety
///
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`.
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`. This is especially
/// important if the original slice is stack allocated.
/// - The original slice **must not** be mutated while this `RawSlice<T>` is used.
pub const unsafe fn set(&mut self, data: &mut [T]) {
self.data = data.as_mut_ptr();
@@ -288,6 +312,20 @@ macro_rules! impl_dma_write_buf {
///
/// However, the user still must ensure that any alignment rules for DMA buffers required by
/// the hardware are met and than any MPU/MMU configuration necessary was also performed.
///
/// # Safety
///
/// - The raw slice type erases the lifetime of slice. The caller *MUST* ensure that the
/// lifetime of the slice is valid as long as the buffer is in-use by the DMA.
/// - It is also imperitive that the DMA system you're using returns the pointer
/// *only after a DMA transfer is complete*. If you're unsure check the docs and if nothing
/// is mentioned in the docs please clarify it with a project maintainer.
/// - If the raw slice wrapper is used on a stack allocated slice: Higher-level APIs
/// oftentimes rely on `Drop` implementations to allow cancelling
/// transfers on non-blocking APIs. Using `core::mem::forget` on such implementations
/// can leak the underlying memory, allowing hardware to write to invalid memory
/// locations. HAL and firmware authors *MUST* either use this abstraction combined with
/// `'static` slices or ensure that the `Drop` implementations always runs properly.
unsafe impl embedded_dma::WriteBuffer for $slice_type {
type Word = $ty;