Struct volatile::VolatilePtr
source · pub struct VolatilePtr<'a, T, A = ReadWrite>where
T: ?Sized,{ /* private fields */ }Expand description
Wraps a pointer to make accesses to the referenced value volatile.
Allows volatile reads and writes on the referenced value. The referenced value needs to
be Copy for reading and writing, as volatile reads and writes take and return copies
of the value.
Since not all volatile resources (e.g. memory mapped device registers) are both readable
and writable, this type supports limiting the allowed access types through an optional second
generic parameter A that can be one of ReadWrite, ReadOnly, or WriteOnly. It defaults
to ReadWrite, which allows all operations.
The size of this struct is the same as the size of the contained reference.
Implementations§
source§impl<'a, T> VolatilePtr<'a, T>where
T: ?Sized,
impl<'a, T> VolatilePtr<'a, T>where
T: ?Sized,
Constructor functions.
These functions construct new VolatilePtr values. While the new
function creates a VolatilePtr instance with unrestricted access, there
are also functions for creating read-only or write-only instances.
sourcepub unsafe fn new(pointer: NonNull<T>) -> VolatilePtr<'a, T, ReadWrite>
pub unsafe fn new(pointer: NonNull<T>) -> VolatilePtr<'a, T, ReadWrite>
Turns the given pointer into a VolatilePtr.
§Safety
- The given pointer must be valid.
- No other thread must have access to the given pointer. This must remain true
for the whole lifetime of the
VolatilePtr.
sourcepub const unsafe fn new_read_only(
pointer: NonNull<T>,
) -> VolatilePtr<'a, T, ReadOnly>
pub const unsafe fn new_read_only( pointer: NonNull<T>, ) -> VolatilePtr<'a, T, ReadOnly>
sourcepub const unsafe fn new_restricted<A>(
access: A,
pointer: NonNull<T>,
) -> VolatilePtr<'a, T, A>where
A: Access,
pub const unsafe fn new_restricted<A>(
access: A,
pointer: NonNull<T>,
) -> VolatilePtr<'a, T, A>where
A: Access,
source§impl<'a, T, A> VolatilePtr<'a, T, A>where
T: ?Sized,
impl<'a, T, A> VolatilePtr<'a, T, A>where
T: ?Sized,
sourcepub fn read(self) -> T
pub fn read(self) -> T
Performs a volatile read of the contained value.
Returns a copy of the read value. Volatile reads are guaranteed not to be optimized
away by the compiler, but by themselves do not have atomic ordering
guarantees. To also get atomicity, consider looking at the Atomic wrapper types of
the standard/core library.
§Examples
use volatile::{VolatilePtr, access};
use core::ptr::NonNull;
let value = 42;
let pointer = unsafe {
VolatilePtr::new_restricted(access::ReadOnly, NonNull::from(&value))
};
assert_eq!(pointer.read(), 42);sourcepub fn write(self, value: T)
pub fn write(self, value: T)
Performs a volatile write, setting the contained value to the given value.
Volatile writes are guaranteed to not be optimized away by the compiler, but by
themselves do not have atomic ordering guarantees. To also get atomicity, consider
looking at the Atomic wrapper types of the standard/core library.
§Example
use volatile::VolatilePtr;
let mut value = 42;
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
volatile.write(50);
assert_eq!(volatile.read(), 50);sourcepub fn update<F>(self, f: F)
pub fn update<F>(self, f: F)
Updates the contained value using the given closure and volatile instructions.
Performs a volatile read of the contained value, passes it to the
function f, and then performs a volatile write of the returned value back to
the target.
use volatile::VolatilePtr;
let mut value = 42;
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
volatile.update(|val| val + 1);
assert_eq!(volatile.read(), 43);sourcepub fn as_raw_ptr(self) -> NonNull<T>
pub fn as_raw_ptr(self) -> NonNull<T>
Extracts the wrapped raw pointer.
§Example
use volatile::VolatilePtr;
let mut value = 42;
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
volatile.write(50);
let unwrapped: *mut i32 = volatile.as_raw_ptr().as_ptr();
assert_eq!(unsafe { *unwrapped }, 50); // non volatile access, be careful!sourcepub unsafe fn map<F, U>(self, f: F) -> VolatilePtr<'a, U, A>
pub unsafe fn map<F, U>(self, f: F) -> VolatilePtr<'a, U, A>
Constructs a new VolatilePtr by mapping the wrapped pointer.
This method is useful for accessing only a part of a volatile value, e.g. a subslice or
a struct field. For struct field access, there is also the safe
map_field macro that wraps this function.
§Examples
Accessing a struct field:
use volatile::VolatilePtr;
use core::ptr::NonNull;
struct Example { field_1: u32, field_2: u8, }
let mut value = Example { field_1: 15, field_2: 255 };
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
// construct a volatile pointer to a field
let field_2 = unsafe { volatile.map(|ptr| NonNull::new(core::ptr::addr_of_mut!((*ptr.as_ptr()).field_2)).unwrap()) };
assert_eq!(field_2.read(), 255);Don’t misuse this method to do a non-volatile read of the referenced value:
use volatile::VolatilePtr;
let mut value = 5;
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
// DON'T DO THIS:
let mut readout = 0;
unsafe {
let _ = volatile.map(|value| {
readout = *value.as_ptr(); // non-volatile read, might lead to bugs
value
});
};§Safety
The pointer returned by f must satisfy the requirements of Self::new.
source§impl<'a, T, A> VolatilePtr<'a, T, A>where
T: ?Sized,
impl<'a, T, A> VolatilePtr<'a, T, A>where
T: ?Sized,
Methods for restricting access.
sourcepub fn restrict<To>(self) -> VolatilePtr<'a, T, A::Restricted>where
A: RestrictAccess<To>,
pub fn restrict<To>(self) -> VolatilePtr<'a, T, A::Restricted>where
A: RestrictAccess<To>,
Restricts access permissions to A.
§Example
use volatile::access::{ReadOnly, WriteOnly};
use volatile::VolatilePtr;
let mut value: i16 = -4;
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
let read_only = volatile.restrict::<ReadOnly>();
assert_eq!(read_only.read(), -4);
// read_only.write(10); // compile-time error
let no_access = read_only.restrict::<WriteOnly>();
// no_access.read(); // compile-time error
// no_access.write(10); // compile-time errorsource§impl<'a, T> VolatilePtr<'a, T, ReadWrite>where
T: ?Sized,
impl<'a, T> VolatilePtr<'a, T, ReadWrite>where
T: ?Sized,
Methods for restricting access.
sourcepub fn read_only(self) -> VolatilePtr<'a, T, ReadOnly>
pub fn read_only(self) -> VolatilePtr<'a, T, ReadOnly>
Restricts access permissions to read-only.
§Example
use volatile::VolatilePtr;
let mut value: i16 = -4;
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
let read_only = volatile.read_only();
assert_eq!(read_only.read(), -4);
// read_only.write(10); // compile-time errorsourcepub fn write_only(self) -> VolatilePtr<'a, T, WriteOnly>
pub fn write_only(self) -> VolatilePtr<'a, T, WriteOnly>
Restricts access permissions to write-only.
§Example
Creating a write-only pointer to a struct field:
use volatile::{VolatilePtr, map_field};
struct Example { field_1: u32, field_2: u8, }
let mut value = Example { field_1: 15, field_2: 255 };
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
// construct a volatile write-only pointer to `field_2`
let field_2 = map_field!(volatile.field_2).write_only();
field_2.write(14);
// field_2.read(); // compile-time errorsource§impl<'a, T, A> VolatilePtr<'a, [T], A>
impl<'a, T, A> VolatilePtr<'a, [T], A>
sourcepub fn len(self) -> usize
Available on crate feature unstable only.
pub fn len(self) -> usize
unstable only.Returns the length of the slice.
sourcepub fn is_empty(self) -> bool
Available on crate feature unstable only.
pub fn is_empty(self) -> bool
unstable only.Returns whether the slice is empty.
sourcepub fn index<I>(
self,
index: I,
) -> VolatilePtr<'a, <I as SliceIndex<[T]>>::Output, A>
Available on crate feature unstable only.
pub fn index<I>( self, index: I, ) -> VolatilePtr<'a, <I as SliceIndex<[T]>>::Output, A>
unstable only.Applies the index operation on the wrapped slice.
Returns a shared Volatile reference to the resulting subslice.
This is a convenience method for the map(|slice| slice.index(index)) operation, so it
has the same behavior as the indexing operation on slice (e.g. panic if index is
out-of-bounds).
§Examples
Accessing a single slice element:
use volatile::VolatilePtr;
use core::ptr::NonNull;
let array = [1, 2, 3];
let slice = &array[..];
let volatile = unsafe { VolatilePtr::new_read_only(NonNull::from(slice)) };
assert_eq!(volatile.index(1).read(), 2);Accessing a subslice:
use volatile::VolatilePtr;
use core::ptr::NonNull;
let array = [1, 2, 3];
let slice = &array[..];
let volatile = unsafe { VolatilePtr::new_read_only(NonNull::from(slice)) };
let subslice = volatile.index(1..);
assert_eq!(subslice.index(0).read(), 2);sourcepub fn iter(self) -> impl Iterator<Item = VolatilePtr<'a, T, A>>where
A: Access,
Available on crate feature unstable only.
pub fn iter(self) -> impl Iterator<Item = VolatilePtr<'a, T, A>>where
A: Access,
unstable only.Returns an iterator over the slice.
sourcepub fn copy_into_slice(self, dst: &mut [T])
Available on crate feature unstable only.
pub fn copy_into_slice(self, dst: &mut [T])
unstable only.Copies all elements from self into dst, using a volatile memcpy.
The length of dst must be the same as self.
The method is only available with the unstable feature enabled (requires a nightly
Rust compiler).
§Panics
This function will panic if the two slices have different lengths.
§Examples
Copying two elements from a volatile slice:
use volatile::VolatilePtr;
use core::ptr::NonNull;
let src = [1, 2];
// the `Volatile` type does not work with arrays, so convert `src` to a slice
let slice = &src[..];
let volatile = unsafe { VolatilePtr::new_read_only(NonNull::from(slice)) };
let mut dst = [5, 0, 0];
// Because the slices have to be the same length,
// we slice the destination slice from three elements
// to two. It will panic if we don't do this.
volatile.copy_into_slice(&mut dst[1..]);
assert_eq!(src, [1, 2]);
assert_eq!(dst, [5, 1, 2]);sourcepub fn copy_from_slice(self, src: &[T])
Available on crate feature unstable only.
pub fn copy_from_slice(self, src: &[T])
unstable only.Copies all elements from src into self, using a volatile memcpy.
The length of src must be the same as self.
This method is similar to the slice::copy_from_slice method of the standard library. The
difference is that this method performs a volatile copy.
The method is only available with the unstable feature enabled (requires a nightly
Rust compiler).
§Panics
This function will panic if the two slices have different lengths.
§Examples
Copying two elements from a slice into a volatile slice:
use volatile::VolatilePtr;
use core::ptr::NonNull;
let src = [1, 2, 3, 4];
let mut dst = [0, 0];
// the `Volatile` type does not work with arrays, so convert `dst` to a slice
let slice = &mut dst[..];
let volatile = unsafe { VolatilePtr::new(NonNull::from(slice)) };
// Because the slices have to be the same length,
// we slice the source slice from four elements
// to two. It will panic if we don't do this.
volatile.copy_from_slice(&src[2..]);
assert_eq!(src, [1, 2, 3, 4]);
assert_eq!(dst, [3, 4]);sourcepub fn copy_within(self, src: impl RangeBounds<usize>, dest: usize)
Available on crate feature unstable only.
pub fn copy_within(self, src: impl RangeBounds<usize>, dest: usize)
unstable only.Copies elements from one part of the slice to another part of itself, using a
volatile memmove.
src is the range within self to copy from. dest is the starting index of the
range within self to copy to, which will have the same length as src. The two ranges
may overlap. The ends of the two ranges must be less than or equal to self.len().
This method is similar to the slice::copy_within method of the standard library. The
difference is that this method performs a volatile copy.
This method is only available with the unstable feature enabled (requires a nightly
Rust compiler).
§Panics
This function will panic if either range exceeds the end of the slice, or if the end
of src is before the start.
§Examples
Copying four bytes within a slice:
extern crate core;
use volatile::VolatilePtr;
use core::ptr::NonNull;
let mut byte_array = *b"Hello, World!";
let slice: &mut [u8] = &mut byte_array[..];
let volatile = unsafe { VolatilePtr::new(NonNull::from(slice)) };
volatile.copy_within(1..5, 8);
assert_eq!(&byte_array, b"Hello, Wello!");sourcepub fn split_at(
self,
mid: usize,
) -> (VolatilePtr<'a, [T], A>, VolatilePtr<'a, [T], A>)where
A: Access,
Available on crate feature unstable only.
pub fn split_at(
self,
mid: usize,
) -> (VolatilePtr<'a, [T], A>, VolatilePtr<'a, [T], A>)where
A: Access,
unstable only.Divides one slice into two at an index.
The first will contain all indices from [0, mid) (excluding
the index mid itself) and the second will contain all
indices from [mid, len) (excluding the index len itself).
§Panics
Panics if mid > len.
sourcepub fn as_chunks<const N: usize>(
self,
) -> (VolatilePtr<'a, [[T; N]], A>, VolatilePtr<'a, [T], A>)where
A: Access,
Available on crate feature unstable only.
pub fn as_chunks<const N: usize>(
self,
) -> (VolatilePtr<'a, [[T; N]], A>, VolatilePtr<'a, [T], A>)where
A: Access,
unstable only.Splits the slice into a slice of N-element arrays,
starting at the beginning of the slice,
and a remainder slice with length strictly less than N.
§Panics
Panics if N is 0.
sourcepub unsafe fn as_chunks_unchecked<const N: usize>(
self,
) -> VolatilePtr<'a, [[T; N]], A>where
A: Access,
Available on crate feature unstable only.
pub unsafe fn as_chunks_unchecked<const N: usize>(
self,
) -> VolatilePtr<'a, [[T; N]], A>where
A: Access,
unstable only.Splits the slice into a slice of N-element arrays,
assuming that there’s no remainder.
§Safety
This may only be called when
- The slice splits exactly into
N-element chunks (akaself.len() % N == 0). N != 0.
source§impl<A> VolatilePtr<'_, [u8], A>
impl<A> VolatilePtr<'_, [u8], A>
Methods for volatile byte slices
sourcepub fn fill(self, value: u8)where
A: Writable,
Available on crate feature unstable only.
pub fn fill(self, value: u8)where
A: Writable,
unstable only.Sets all elements of the byte slice to the given value using a volatile memset.
This method is similar to the slice::fill method of the standard library, with the
difference that this method performs a volatile write operation. Another difference
is that this method is only available for byte slices (not general &mut [T] slices)
because there currently isn’t a instrinsic function that allows non-u8 values.
This method is only available with the unstable feature enabled (requires a nightly
Rust compiler).
§Example
use volatile::VolatilePtr;
use core::ptr::NonNull;
let mut vec = vec![0; 10];
let buf = unsafe { VolatilePtr::new(NonNull::from(vec.as_mut_slice())) };
buf.fill(1);
assert_eq!(unsafe { buf.as_raw_ptr().as_mut() }, &mut vec![1; 10]);source§impl<'a, T, A, const N: usize> VolatilePtr<'a, [T; N], A>
impl<'a, T, A, const N: usize> VolatilePtr<'a, [T; N], A>
Methods for converting arrays to slices
These methods are only available with the unstable feature enabled (requires a nightly
Rust compiler).
sourcepub fn as_slice(self) -> VolatilePtr<'a, [T], A>where
A: Access,
Available on crate feature unstable only.
pub fn as_slice(self) -> VolatilePtr<'a, [T], A>where
A: Access,
unstable only.Converts an array pointer to a slice pointer.
This makes it possible to use the methods defined on slices.
§Example
Copying two elements from a volatile array reference using copy_into_slice:
use volatile::VolatilePtr;
use core::ptr::NonNull;
let src = [1, 2];
let volatile = unsafe { VolatilePtr::new_read_only(NonNull::from(&src)) };
let mut dst = [0, 0];
// convert the `Volatile<&[i32; 2]>` array reference to a `Volatile<&[i32]>` slice
let volatile_slice = volatile.as_slice();
// we can now use the slice methods
volatile_slice.copy_into_slice(&mut dst);
assert_eq!(dst, [1, 2]);source§impl<'a, T, A> VolatilePtr<'a, T, A>where
T: ?Sized,
impl<'a, T, A> VolatilePtr<'a, T, A>where
T: ?Sized,
sourcepub const unsafe fn map_const<F, U>(self, f: F) -> VolatilePtr<'a, U, A>
Available on crate feature very_unstable only.
pub const unsafe fn map_const<F, U>(self, f: F) -> VolatilePtr<'a, U, A>
very_unstable only.source§impl<'a, T, A> VolatilePtr<'a, [T], A>
impl<'a, T, A> VolatilePtr<'a, [T], A>
Methods for volatile slices
sourcepub const fn index_const(self, index: usize) -> VolatilePtr<'a, T, A>
Available on crate features very_unstable and unstable only.
pub const fn index_const(self, index: usize) -> VolatilePtr<'a, T, A>
very_unstable and unstable only.Compile-time evaluable variant of Self::index.
This function is a copy of Self::index that uses unstable compiler functions
to be callable from const contexts.
Trait Implementations§
source§impl<T, A> Clone for VolatilePtr<'_, T, A>where
T: ?Sized,
impl<T, A> Clone for VolatilePtr<'_, T, A>where
T: ?Sized,
source§impl<T, A> Debug for VolatilePtr<'_, T, A>where
T: ?Sized,
impl<T, A> Debug for VolatilePtr<'_, T, A>where
T: ?Sized,
source§impl<T, A> Hash for VolatilePtr<'_, T, A>where
T: ?Sized,
impl<T, A> Hash for VolatilePtr<'_, T, A>where
T: ?Sized,
source§impl<T, A> Ord for VolatilePtr<'_, T, A>where
T: ?Sized,
impl<T, A> Ord for VolatilePtr<'_, T, A>where
T: ?Sized,
source§impl<T, A> PartialEq for VolatilePtr<'_, T, A>where
T: ?Sized,
impl<T, A> PartialEq for VolatilePtr<'_, T, A>where
T: ?Sized,
source§impl<T, A> PartialOrd for VolatilePtr<'_, T, A>where
T: ?Sized,
impl<T, A> PartialOrd for VolatilePtr<'_, T, A>where
T: ?Sized,
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
self and other) and is used by the <=
operator. Read more