volatile/volatile_ptr/
mod.rs

1use core::{cmp::Ordering, fmt, hash, marker::PhantomData, ptr::NonNull};
2
3use crate::access::ReadWrite;
4
5mod macros;
6mod operations;
7
8#[cfg(test)]
9mod tests;
10#[cfg(feature = "unstable")]
11mod unstable;
12#[cfg(feature = "very_unstable")]
13mod very_unstable;
14
15/// Wraps a pointer to make accesses to the referenced value volatile.
16///
17/// Allows volatile reads and writes on the referenced value. The referenced value needs to
18/// be `Copy` for reading and writing, as volatile reads and writes take and return copies
19/// of the value.
20///
21/// Since not all volatile resources (e.g. memory mapped device registers) are both readable
22/// and writable, this type supports limiting the allowed access types through an optional second
23/// generic parameter `A` that can be one of `ReadWrite`, `ReadOnly`, or `WriteOnly`. It defaults
24/// to `ReadWrite`, which allows all operations.
25///
26/// The size of this struct is the same as the size of the contained reference.
27#[must_use]
28#[repr(transparent)]
29pub struct VolatilePtr<'a, T, A = ReadWrite>
30where
31    T: ?Sized,
32{
33    pointer: NonNull<T>,
34    reference: PhantomData<&'a T>,
35    access: PhantomData<A>,
36}
37
38impl<'a, T, A> Copy for VolatilePtr<'a, T, A> where T: ?Sized {}
39
40impl<T, A> Clone for VolatilePtr<'_, T, A>
41where
42    T: ?Sized,
43{
44    fn clone(&self) -> Self {
45        *self
46    }
47}
48
49impl<T, A> fmt::Debug for VolatilePtr<'_, T, A>
50where
51    T: ?Sized,
52{
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54        fmt::Pointer::fmt(&self.pointer.as_ptr(), f)
55    }
56}
57
58impl<T, A> fmt::Pointer for VolatilePtr<'_, T, A>
59where
60    T: ?Sized,
61{
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        fmt::Pointer::fmt(&self.pointer.as_ptr(), f)
64    }
65}
66
67impl<T, A> PartialEq for VolatilePtr<'_, T, A>
68where
69    T: ?Sized,
70{
71    fn eq(&self, other: &Self) -> bool {
72        core::ptr::eq(self.pointer.as_ptr(), other.pointer.as_ptr())
73    }
74}
75
76impl<T, A> Eq for VolatilePtr<'_, T, A> where T: ?Sized {}
77
78impl<T, A> PartialOrd for VolatilePtr<'_, T, A>
79where
80    T: ?Sized,
81{
82    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
83        Some(self.cmp(other))
84    }
85}
86
87impl<T, A> Ord for VolatilePtr<'_, T, A>
88where
89    T: ?Sized,
90{
91    fn cmp(&self, other: &Self) -> Ordering {
92        #[allow(ambiguous_wide_pointer_comparisons)]
93        Ord::cmp(&self.pointer.as_ptr(), &other.pointer.as_ptr())
94    }
95}
96
97impl<T, A> hash::Hash for VolatilePtr<'_, T, A>
98where
99    T: ?Sized,
100{
101    fn hash<H: hash::Hasher>(&self, state: &mut H) {
102        self.pointer.as_ptr().hash(state);
103    }
104}