volatile/
access.rs

1//! Marker types for limiting access.
2
3/// A trait for restricting one [`Access`] type to another [`Access`] type.
4///
5/// Restricting `Self` to `To` results in [`Self::Restricted`].
6///
7/// Restriction is a symmetric operation which is denoted by ∩, as it is the intersection of permissions.
8/// The following table holds:
9///
10/// | `Self`        | `To`          | `Self` ∩ `To` |
11/// | ------------- | ------------- | ------------- |
12/// | `T`           | `T`           | `T`           |
13/// | [`ReadWrite`] | `T`           | `T`           |
14/// | [`NoAccess`]  | `T`           | [`NoAccess`]  |
15/// | [`ReadOnly`]  | [`WriteOnly`] | [`NoAccess`]  |
16pub trait RestrictAccess<To>: Access {
17    /// The resulting [`Access`] type of `Self` restricted to `To`.
18    type Restricted: Access;
19}
20
21impl<To: Access> RestrictAccess<To> for ReadWrite {
22    type Restricted = To;
23}
24
25impl<To> RestrictAccess<To> for NoAccess {
26    type Restricted = Self;
27}
28
29// Sadly, we cannot provide more generic implementations, since they would overlap.
30macro_rules! restrict_impl {
31    ($SelfT:ty, $To:ty, $Restricted:ty) => {
32        impl RestrictAccess<$To> for $SelfT {
33            type Restricted = $Restricted;
34        }
35    };
36}
37
38restrict_impl!(ReadOnly, ReadWrite, ReadOnly);
39restrict_impl!(ReadOnly, ReadOnly, ReadOnly);
40restrict_impl!(ReadOnly, WriteOnly, NoAccess);
41restrict_impl!(ReadOnly, NoAccess, NoAccess);
42
43restrict_impl!(WriteOnly, ReadWrite, WriteOnly);
44restrict_impl!(WriteOnly, ReadOnly, NoAccess);
45restrict_impl!(WriteOnly, WriteOnly, WriteOnly);
46restrict_impl!(WriteOnly, NoAccess, NoAccess);
47
48/// Sealed trait that is implemented for the types in this module.
49pub trait Access: Copy + Default + private::Sealed {}
50
51/// Helper trait that is implemented by [`ReadWrite`] and [`ReadOnly`].
52pub trait Readable: Access {}
53impl<A: RestrictAccess<ReadOnly, Restricted = ReadOnly>> Readable for A {}
54
55/// Helper trait that is implemented by [`ReadWrite`] and [`WriteOnly`].
56pub trait Writable: Access {}
57impl<A: RestrictAccess<WriteOnly, Restricted = WriteOnly>> Writable for A {}
58
59/// Implemented for access types that permit copying of `VolatileRef`.
60pub trait Copyable: Access {}
61impl<A: RestrictAccess<ReadOnly, Restricted = Self>> Copyable for A {}
62
63/// Zero-sized marker type for allowing both read and write access.
64#[derive(Debug, Default, Copy, Clone)]
65pub struct ReadWrite;
66impl Access for ReadWrite {}
67
68/// Zero-sized marker type for allowing only read access.
69#[derive(Debug, Default, Copy, Clone)]
70pub struct ReadOnly;
71impl Access for ReadOnly {}
72
73/// Zero-sized marker type for allowing only write access.
74#[derive(Debug, Default, Copy, Clone)]
75pub struct WriteOnly;
76impl Access for WriteOnly {}
77
78/// Zero-sized marker type that grants no access.
79#[derive(Debug, Default, Copy, Clone)]
80pub struct NoAccess;
81impl Access for NoAccess {}
82
83mod private {
84    pub trait Sealed {}
85
86    impl Sealed for super::ReadWrite {}
87    impl Sealed for super::ReadOnly {}
88    impl Sealed for super::WriteOnly {}
89    impl Sealed for super::NoAccess {}
90}