1
1
//! Traits to aid the correct use of buffers in DMA abstractions.
2
2
//!
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
4
4
//! buffers types used in DMA operations.
5
5
//!
6
6
//! There are some subtleties to the extent of the guarantees provided by these traits, all of these
11
11
//! `Self` (with the exception of [`write_buffer`](trait.WriteBuffer.html#tymethod.write_buffer) in
12
12
//! our case). This is to allow types like `Vec`, this restriction doesn't apply to `Self::Target`.
13
13
//!
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.
21
17
//!
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.
29
24
//!
30
25
//! The above list is not exhaustive, for a complete set of requirements and guarantees, the
31
26
//! documentation of each trait and method should be analyzed.
32
- //!
33
- //! [StaticReadBuffer]: trait.StaticReadBuffer.html
34
- //! [StaticWriteBuffer]: trait.StaticWriteBuffer.html
35
27
#![ no_std]
36
28
37
29
use core:: {
@@ -51,7 +43,7 @@ use stable_deref_trait::StableDeref;
51
43
/// - `read_buffer` must always return the same value, if called multiple
52
44
/// times.
53
45
/// - 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.
55
47
pub unsafe trait ReadBuffer {
56
48
type Word ;
57
49
@@ -82,7 +74,7 @@ pub unsafe trait ReadBuffer {
82
74
/// - `write_buffer` must always return the same value, if called multiple
83
75
/// times.
84
76
/// - 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.
86
78
pub unsafe trait WriteBuffer {
87
79
type Word ;
88
80
@@ -279,22 +271,19 @@ mod tests {
279
271
fn read_api ( ) {
280
272
const SIZE : usize = 128 ;
281
273
static BUF : [ u8 ; SIZE ] = [ 0u8 ; SIZE ] ;
282
- let local_buf = [ 0u8 ; SIZE ] ;
283
274
284
275
let ( ptr, size_local) = api_read ( & BUF ) ;
285
276
assert ! ( unsafe { ( & * ptr as & dyn Any ) . is:: <u8 >( ) } ) ;
286
- assert ! ( size_local == SIZE ) ;
287
-
277
+ assert_eq ! ( size_local, SIZE ) ;
288
278
}
289
279
290
280
#[ test]
291
281
fn write_api ( ) {
292
282
const SIZE : usize = 128 ;
293
283
static mut BUF : [ u8 ; SIZE ] = [ 0u8 ; SIZE ] ;
294
- let mut local_buf = [ 0u8 ; SIZE ] ;
295
284
296
285
let ( ptr, size_local) = api_write ( unsafe { & mut BUF } ) ;
297
286
assert ! ( unsafe { ( & * ptr as & dyn Any ) . is:: <u8 >( ) } ) ;
298
- assert ! ( size_local == SIZE ) ;
287
+ assert_eq ! ( size_local, SIZE ) ;
299
288
}
300
289
}
0 commit comments