Skip to content

Commit d0bcea2

Browse files
committed
Add methods for working with volatile slices
These methods are only available on nightly since the required functions of `core::intrinsics` are still unstable.
1 parent b469f42 commit d0bcea2

File tree

2 files changed

+80
-11
lines changed

2 files changed

+80
-11
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ repository = "https://github.com/phil-opp/volatile"
1010

1111
[dependencies]
1212

13+
[features]
14+
nightly = []
15+
1316
[package.metadata.release]
1417
no-dev-version = true
1518
pre-release-replacements = [

src/lib.rs

Lines changed: 77 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88
//! These wrappers do not depend on the standard library and never panic.
99
1010
#![no_std]
11+
#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
1112

1213
use access::{ReadOnly, ReadWrite, Readable, Writable, WriteOnly};
14+
#[cfg(feature = "nightly")]
15+
use core::intrinsics;
1316
use core::{
1417
marker::PhantomData,
1518
ops::Deref,
@@ -158,36 +161,99 @@ where
158161
}
159162
}
160163

161-
impl<T, A> Volatile<&[T], A> {
162-
pub fn index<I>(&self, index: I) -> Volatile<&I::Output, A>
164+
/// Methods for volatile slices
165+
impl<T, R, A> Volatile<R, A>
166+
where
167+
R: Deref<Target = [T]>,
168+
{
169+
pub fn index<'a, I>(&'a self, index: I) -> Volatile<&'a I::Output, A>
163170
where
164171
I: SliceIndex<[T]>,
172+
T: 'a,
165173
{
166174
Volatile {
167175
reference: self.reference.index(index),
168176
access: self.access,
169177
}
170178
}
171-
}
172179

173-
impl<T, A> Volatile<&mut [T], A> {
174-
pub fn index<I>(&self, index: I) -> Volatile<&I::Output, A>
180+
pub fn index_mut<'a, I>(&'a mut self, index: I) -> Volatile<&mut I::Output, A>
175181
where
176182
I: SliceIndex<[T]>,
183+
R: DerefMut,
184+
T: 'a,
177185
{
178186
Volatile {
179-
reference: self.reference.index(index),
187+
reference: self.reference.index_mut(index),
180188
access: self.access,
181189
}
182190
}
183191

184-
pub fn index_mut<I>(&mut self, index: I) -> Volatile<&mut I::Output, A>
192+
#[cfg(feature = "nightly")]
193+
pub fn copy_into_slice(&self, dst: &mut [T])
185194
where
186-
I: SliceIndex<[T]>,
195+
T: Copy,
187196
{
188-
Volatile {
189-
reference: self.reference.index_mut(index),
190-
access: self.access,
197+
assert_eq!(
198+
self.reference.len(),
199+
dst.len(),
200+
"destination and source slices have different lengths"
201+
);
202+
unsafe {
203+
intrinsics::volatile_copy_nonoverlapping_memory(
204+
dst.as_mut_ptr(),
205+
self.reference.as_ptr(),
206+
self.reference.len(),
207+
);
208+
}
209+
}
210+
211+
/// Copies all elements from `src` into `self`, using a volatile memcpy.
212+
///
213+
/// The length of `src` must be the same as `self`.
214+
///
215+
/// ## Panics
216+
///
217+
/// This function will panic if the two slices have different lengths.
218+
///
219+
/// ## Examples
220+
///
221+
/// Copying two elements from a slice into another:
222+
///
223+
/// ```
224+
/// use volatile::Volatile;
225+
///
226+
/// let src = [1, 2, 3, 4];
227+
/// let mut dst = [0, 0];
228+
/// // the `Volatile` type does not work with arrays, so convert `dst` to a slice
229+
/// let slice = &mut dst[..];
230+
/// let mut volatile = Volatile::new(slice);
231+
///
232+
/// // Because the slices have to be the same length,
233+
/// // we slice the source slice from four elements
234+
/// // to two. It will panic if we don't do this.
235+
/// volatile.copy_from_slice(&src[2..]);
236+
///
237+
/// assert_eq!(src, [1, 2, 3, 4]);
238+
/// assert_eq!(dst, [3, 4]);
239+
/// ```
240+
#[cfg(feature = "nightly")]
241+
pub fn copy_from_slice(&mut self, src: &[T])
242+
where
243+
T: Copy,
244+
R: DerefMut,
245+
{
246+
assert_eq!(
247+
self.reference.len(),
248+
src.len(),
249+
"destination and source slices have different lengths"
250+
);
251+
unsafe {
252+
intrinsics::volatile_copy_nonoverlapping_memory(
253+
self.reference.as_mut_ptr(),
254+
src.as_ptr(),
255+
self.reference.len(),
256+
);
191257
}
192258
}
193259
}

0 commit comments

Comments
 (0)