Skip to content

Commit 8fedf6f

Browse files
committed
Removes static {read,write} buffers
- Fixes rust-embedded#17 - Fixes rust-embedded#10 - This is essentially a copy of rust-embedded#13 but with the documentation change requirements that were never made. Since the PR has been stale since March, I found it fair to make another PR.
1 parent 24f7f09 commit 8fedf6f

File tree

1 file changed

+14
-25
lines changed

1 file changed

+14
-25
lines changed

src/lib.rs

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Traits to aid the correct use of buffers in DMA abstractions.
22
//!
3-
//! This library provides the `ReadBuffer` and `WriteBuffer` unsafe traits to be used as bounds to
3+
//! This library provides the [ReadBuffer] and [WriteBuffer] unsafe traits to be used as bounds to
44
//! buffers types used in DMA operations.
55
//!
66
//! There are some subtleties to the extent of the guarantees provided by these traits, all of these
@@ -11,27 +11,19 @@
1111
//! `Self` (with the exception of [`write_buffer`](trait.WriteBuffer.html#tymethod.write_buffer) in
1212
//! our case). This is to allow types like `Vec`, this restriction doesn't apply to `Self::Target`.
1313
//!
14-
//! * The location is only guaranteed to be stable for the duration of `Self`, that means that
15-
//! `Self` doesn't need to be `'static`, i.e. `&'a [u8]` is valid. This can be a bit subtle for
16-
//! most DMA abstractions, because they almost always require `'static`, given the intrinsics of
17-
//! `mem::forget` and the Rust language itself. Those APIs must also bound to `'static` and not only
18-
//! `WriteBuffer`/`ReadBuffer`. The reason we don't require `'static` in the traits themselves is
19-
//! because it would block implementations that can deal with stack allocated buffers, like APIs
20-
//! that use closures to prevent memory corruption.
14+
//! * [ReadBuffer] and [WriteBuffer] guarantee a stable location for as long as the DMA transfer
15+
//! occurs. Given the intrinsics of `mem::forget` and the Rust language itself, a
16+
//! 'static lifetime is usually required.
2117
//!
22-
//! If your API also needs a `'static` bound, prefer the use of [StaticReadBuffer] and
23-
//! [StaticWriteBuffer]. They are a stricter version that requires a `'static` lifetime invariant,
24-
//! while also allowing end users to __unsafely__ bypass it.
25-
//!
26-
//! If you are not sure which version of the traits you should be bounding to in your DMA
27-
//! implementations, prefer the "Static" versions, they are sound for a bigger number of techniques
28-
//! that deal with DMA.
18+
//! * The end-user can add their custom implementations of [ReadBuffer] and [WriteBuffer] which do
19+
//! not need to be 'static. This can be useful when DMA transfers use memory on the stack.
20+
//! Implementing either trait is unsafe, and end-user will need to verify that invariants are
21+
//! upheld each time the trait is used. This usually means `mem::forget` is not called on the struct
22+
//! representing the DMA transfer before the DMA transfer is finished. Since the invariants must be
23+
//! upheld locally, any implemented traits should not be exported.
2924
//!
3025
//! The above list is not exhaustive, for a complete set of requirements and guarantees, the
3126
//! documentation of each trait and method should be analyzed.
32-
//!
33-
//! [StaticReadBuffer]: trait.StaticReadBuffer.html
34-
//! [StaticWriteBuffer]: trait.StaticWriteBuffer.html
3527
#![no_std]
3628

3729
use core::{
@@ -51,7 +43,7 @@ use stable_deref_trait::StableDeref;
5143
/// - `read_buffer` must always return the same value, if called multiple
5244
/// times.
5345
/// - The memory specified by the pointer and size returned by `read_buffer`
54-
/// must not be freed as long as `self` is not dropped.
46+
/// must not be freed during the transfer it is used in as long as `self` is not dropped.
5547
pub unsafe trait ReadBuffer {
5648
type Word;
5749

@@ -82,7 +74,7 @@ pub unsafe trait ReadBuffer {
8274
/// - `write_buffer` must always return the same value, if called multiple
8375
/// times.
8476
/// - The memory specified by the pointer and size returned by `write_buffer`
85-
/// must not be freed as long as `self` is not dropped.
77+
/// must not be freed during the transfer as long as `self` is not dropped.
8678
pub unsafe trait WriteBuffer {
8779
type Word;
8880

@@ -279,22 +271,19 @@ mod tests {
279271
fn read_api() {
280272
const SIZE: usize = 128;
281273
static BUF: [u8; SIZE] = [0u8; SIZE];
282-
let local_buf = [0u8; SIZE];
283274

284275
let (ptr, size_local) = api_read(&BUF);
285276
assert!(unsafe { (&*ptr as &dyn Any).is::<u8>() });
286-
assert!(size_local == SIZE);
287-
277+
assert_eq!(size_local, SIZE);
288278
}
289279

290280
#[test]
291281
fn write_api() {
292282
const SIZE: usize = 128;
293283
static mut BUF: [u8; SIZE] = [0u8; SIZE];
294-
let mut local_buf = [0u8; SIZE];
295284

296285
let (ptr, size_local) = api_write(unsafe { &mut BUF });
297286
assert!(unsafe { (&*ptr as &dyn Any).is::<u8>() });
298-
assert!(size_local == SIZE);
287+
assert_eq!(size_local, SIZE);
299288
}
300289
}

0 commit comments

Comments
 (0)