From 7d6a147e4b4da4d4aaba3ee4cf93f81d06fce511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 25 Apr 2024 12:45:17 +0200 Subject: [PATCH 01/11] feat(access): add `RestrictAccess` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/access.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/access.rs b/src/access.rs index 6d529bd..822edda 100644 --- a/src/access.rs +++ b/src/access.rs @@ -1,5 +1,50 @@ //! Marker types for limiting access. +/// A trait for restricting one [`Access`] type to another [`Access`] type. +/// +/// Restricting `Self` to `To` results in [`Self::Restricted`]. +/// +/// Restriction is a symmetric operation which is denoted by ∩, as it is the intersection of permissions. +/// The following table holds: +/// +/// | `Self` | `To` | `Self` ∩ `To` | +/// | ------------- | ------------- | ------------- | +/// | `T` | `T` | `T` | +/// | [`ReadWrite`] | `T` | `T` | +/// | [`NoAccess`] | `T` | [`NoAccess`] | +/// | [`ReadOnly`] | [`WriteOnly`] | [`NoAccess`] | +pub trait RestrictAccess: Access { + /// The resulting [`Access`] type of `Self` restricted to `To`. + type Restricted: Access; +} + +impl RestrictAccess for ReadWrite { + type Restricted = To; +} + +impl RestrictAccess for NoAccess { + type Restricted = Self; +} + +// Sadly, we cannot provide more generic implementations, since they would overlap. +macro_rules! restrict_impl { + ($SelfT:ty, $To:ty, $Restricted:ty) => { + impl RestrictAccess<$To> for $SelfT { + type Restricted = $Restricted; + } + }; +} + +restrict_impl!(ReadOnly, ReadWrite, ReadOnly); +restrict_impl!(ReadOnly, ReadOnly, ReadOnly); +restrict_impl!(ReadOnly, WriteOnly, NoAccess); +restrict_impl!(ReadOnly, NoAccess, NoAccess); + +restrict_impl!(WriteOnly, ReadWrite, WriteOnly); +restrict_impl!(WriteOnly, ReadOnly, NoAccess); +restrict_impl!(WriteOnly, WriteOnly, WriteOnly); +restrict_impl!(WriteOnly, NoAccess, NoAccess); + /// Sealed trait that is implemented for the types in this module. pub trait Access: Copy + Default + private::Sealed { /// Reduced access level to safely share the corresponding value. From e632902a5fb70446111e64d3d051a48d538a5681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 25 Apr 2024 12:56:52 +0200 Subject: [PATCH 02/11] feat: generalize `restrict` to all access types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/volatile_ptr/operations.rs | 20 +++++++++++++++----- src/volatile_ref.rs | 20 +++++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/volatile_ptr/operations.rs b/src/volatile_ptr/operations.rs index 54c172d..05fbb5b 100644 --- a/src/volatile_ptr/operations.rs +++ b/src/volatile_ptr/operations.rs @@ -4,7 +4,7 @@ use core::{ }; use crate::{ - access::{Access, ReadOnly, ReadWrite, Readable, Writable, WriteOnly}, + access::{Access, ReadOnly, ReadWrite, Readable, RestrictAccess, Writable, WriteOnly}, VolatilePtr, }; @@ -211,7 +211,7 @@ where } /// Methods for restricting access. -impl<'a, T> VolatilePtr<'a, T, ReadWrite> +impl<'a, T, A> VolatilePtr<'a, T, A> where T: ?Sized, { @@ -220,7 +220,7 @@ where /// ## Example /// /// ``` - /// use volatile::access::ReadOnly; + /// use volatile::access::{ReadOnly, WriteOnly}; /// use volatile::VolatilePtr; /// /// let mut value: i16 = -4; @@ -229,14 +229,24 @@ where /// let read_only = volatile.restrict::(); /// assert_eq!(read_only.read(), -4); /// // read_only.write(10); // compile-time error + /// + /// let no_access = read_only.restrict::(); + /// // no_access.read(); // compile-time error + /// // no_access.write(10); // compile-time error /// ``` - pub fn restrict(self) -> VolatilePtr<'a, T, A> + pub fn restrict(self) -> VolatilePtr<'a, T, A::Restricted> where - A: Access, + A: RestrictAccess, { unsafe { VolatilePtr::new_restricted(Default::default(), self.pointer) } } +} +/// Methods for restricting access. +impl<'a, T> VolatilePtr<'a, T, ReadWrite> +where + T: ?Sized, +{ /// Restricts access permissions to read-only. /// /// ## Example diff --git a/src/volatile_ref.rs b/src/volatile_ref.rs index 3b98ac5..8ee69ab 100644 --- a/src/volatile_ref.rs +++ b/src/volatile_ref.rs @@ -1,5 +1,5 @@ use crate::{ - access::{Access, Copyable, ReadOnly, ReadWrite, WriteOnly}, + access::{Access, Copyable, ReadOnly, ReadWrite, RestrictAccess, WriteOnly}, volatile_ptr::VolatilePtr, }; use core::{cmp::Ordering, fmt, hash, marker::PhantomData, ptr::NonNull}; @@ -194,7 +194,7 @@ where } /// Methods for restricting access. -impl<'a, T> VolatileRef<'a, T, ReadWrite> +impl<'a, T, A> VolatileRef<'a, T, A> where T: ?Sized, { @@ -203,7 +203,7 @@ where /// ## Example /// /// ``` - /// use volatile::access::ReadOnly; + /// use volatile::access::{ReadOnly, WriteOnly}; /// use volatile::VolatileRef; /// /// let mut value: i16 = -4; @@ -212,14 +212,24 @@ where /// let read_only = volatile.restrict::(); /// assert_eq!(read_only.as_ptr().read(), -4); /// // read_only.as_ptr().write(10); // compile-time error + /// + /// let no_access = read_only.restrict::(); + /// // no_access.read(); // compile-time error + /// // no_access.write(10); // compile-time error /// ``` - pub fn restrict(self) -> VolatileRef<'a, T, A> + pub fn restrict(self) -> VolatileRef<'a, T, A::Restricted> where - A: Access, + A: RestrictAccess, { unsafe { VolatileRef::new_restricted(Default::default(), self.pointer) } } +} +/// Methods for restricting access. +impl<'a, T> VolatileRef<'a, T, ReadWrite> +where + T: ?Sized, +{ /// Restricts access permissions to read-only. /// /// ## Example From e4c858dfb01f9c11c3550ea35c0dcc80f238f596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 25 Apr 2024 12:46:09 +0200 Subject: [PATCH 03/11] refactor(ref): implement `borrow` and `as_ptr` via `RestrictAccess` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/volatile_ref.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/volatile_ref.rs b/src/volatile_ref.rs index 8ee69ab..5de3287 100644 --- a/src/volatile_ref.rs +++ b/src/volatile_ref.rs @@ -139,9 +139,9 @@ where /// This method creates a `VolatileRef` tied to the lifetime of the `&VolatileRef` it is created from. /// This is useful for providing a volatile reference without moving the original `VolatileRef`. /// In comparison with creating a `&VolatileRef<'a, T>`, this avoids the additional indirection and lifetime. - pub fn borrow(&self) -> VolatileRef<'_, T, A::RestrictShared> + pub fn borrow(&self) -> VolatileRef<'_, T, A::Restricted> where - A: Access, + A: RestrictAccess, { unsafe { VolatileRef::new_restricted(Default::default(), self.pointer) } } @@ -161,9 +161,9 @@ where /// Borrows this `VolatileRef` as a read-only [`VolatilePtr`]. /// /// Use this method to do (partial) volatile reads of the referenced data. - pub fn as_ptr(&self) -> VolatilePtr<'_, T, A::RestrictShared> + pub fn as_ptr(&self) -> VolatilePtr<'_, T, A::Restricted> where - A: Access, + A: RestrictAccess, { unsafe { VolatilePtr::new_restricted(Default::default(), self.pointer) } } From ee4a3444bad9a3127aa2eaaec15612c1efdf8806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 25 Apr 2024 12:46:31 +0200 Subject: [PATCH 04/11] feat(access): deprecate `{Access,Readable}::RestrictShared` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/access.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/access.rs b/src/access.rs index 822edda..034a764 100644 --- a/src/access.rs +++ b/src/access.rs @@ -48,12 +48,14 @@ restrict_impl!(WriteOnly, NoAccess, NoAccess); /// Sealed trait that is implemented for the types in this module. pub trait Access: Copy + Default + private::Sealed { /// Reduced access level to safely share the corresponding value. + #[deprecated = "replaced by `RestrictAccess::Restricted`"] type RestrictShared: Access; } /// Helper trait that is implemented by [`ReadWrite`] and [`ReadOnly`]. pub trait Readable: Copy + Default + private::Sealed { /// Reduced access level to safely share the corresponding value. + #[deprecated = "replaced by `RestrictAccess::Restricted`"] type RestrictShared: Readable + Access; } @@ -67,6 +69,7 @@ impl Access for T where T: Readable + Default + Copy, { + #[allow(deprecated)] type RestrictShared = ::RestrictShared; } From a9d96653d894b4688009976f1a7ebead2132f1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 25 Apr 2024 16:39:01 +0200 Subject: [PATCH 05/11] refactor(access): implement `Copyable` via `RestrictAccess` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/access.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/access.rs b/src/access.rs index 034a764..70a64cc 100644 --- a/src/access.rs +++ b/src/access.rs @@ -64,6 +64,7 @@ pub trait Writable: Access + private::Sealed {} /// Implemented for access types that permit copying of `VolatileRef`. pub trait Copyable: private::Sealed {} +impl> Copyable for A {} impl Access for T where @@ -87,7 +88,6 @@ pub struct ReadOnly; impl Readable for ReadOnly { type RestrictShared = ReadOnly; } -impl Copyable for ReadOnly {} /// Zero-sized marker type for allowing only write access. #[derive(Debug, Default, Copy, Clone)] @@ -103,7 +103,6 @@ pub struct NoAccess; impl Access for NoAccess { type RestrictShared = NoAccess; } -impl Copyable for NoAccess {} mod private { pub trait Sealed {} From 16cb5aae3b20032eb8663525bbfc04856d486635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 25 Apr 2024 16:39:44 +0200 Subject: [PATCH 06/11] refactor(access): implement `Writeable` via `RestrictAccess` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/access.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/access.rs b/src/access.rs index 70a64cc..b640f2e 100644 --- a/src/access.rs +++ b/src/access.rs @@ -61,6 +61,7 @@ pub trait Readable: Copy + Default + private::Sealed { /// Helper trait that is implemented by [`ReadWrite`] and [`WriteOnly`]. pub trait Writable: Access + private::Sealed {} +impl> Writable for A {} /// Implemented for access types that permit copying of `VolatileRef`. pub trait Copyable: private::Sealed {} @@ -80,7 +81,6 @@ pub struct ReadWrite; impl Readable for ReadWrite { type RestrictShared = ReadOnly; } -impl Writable for ReadWrite {} /// Zero-sized marker type for allowing only read access. #[derive(Debug, Default, Copy, Clone)] @@ -95,7 +95,6 @@ pub struct WriteOnly; impl Access for WriteOnly { type RestrictShared = NoAccess; } -impl Writable for WriteOnly {} /// Zero-sized marker type that grants no access. #[derive(Debug, Default, Copy, Clone)] From 70b74cc1421d730c381f9216a276e16e4e9e8425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 25 Apr 2024 16:42:12 +0200 Subject: [PATCH 07/11] refactor(access): implement `Readable` via `RestrictAccess` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/access.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/access.rs b/src/access.rs index b640f2e..075c7b2 100644 --- a/src/access.rs +++ b/src/access.rs @@ -58,6 +58,9 @@ pub trait Readable: Copy + Default + private::Sealed { #[deprecated = "replaced by `RestrictAccess::Restricted`"] type RestrictShared: Readable + Access; } +impl> Readable for A { + type RestrictShared = ReadOnly; +} /// Helper trait that is implemented by [`ReadWrite`] and [`WriteOnly`]. pub trait Writable: Access + private::Sealed {} @@ -78,16 +81,10 @@ where /// Zero-sized marker type for allowing both read and write access. #[derive(Debug, Default, Copy, Clone)] pub struct ReadWrite; -impl Readable for ReadWrite { - type RestrictShared = ReadOnly; -} /// Zero-sized marker type for allowing only read access. #[derive(Debug, Default, Copy, Clone)] pub struct ReadOnly; -impl Readable for ReadOnly { - type RestrictShared = ReadOnly; -} /// Zero-sized marker type for allowing only write access. #[derive(Debug, Default, Copy, Clone)] From 863c5a3f9865b52197d3050eb15d2a401e027851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 25 Apr 2024 18:03:27 +0200 Subject: [PATCH 08/11] refactor(access): implement `Access` for `ReadWrite` and `ReadOnly` directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/access.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/access.rs b/src/access.rs index 075c7b2..b02c1d4 100644 --- a/src/access.rs +++ b/src/access.rs @@ -70,21 +70,21 @@ impl> Writable for A {} pub trait Copyable: private::Sealed {} impl> Copyable for A {} -impl Access for T -where - T: Readable + Default + Copy, -{ - #[allow(deprecated)] - type RestrictShared = ::RestrictShared; -} - /// Zero-sized marker type for allowing both read and write access. #[derive(Debug, Default, Copy, Clone)] pub struct ReadWrite; +impl Access for ReadWrite { + #[allow(deprecated)] + type RestrictShared = ::RestrictShared; +} /// Zero-sized marker type for allowing only read access. #[derive(Debug, Default, Copy, Clone)] pub struct ReadOnly; +impl Access for ReadOnly { + #[allow(deprecated)] + type RestrictShared = ::RestrictShared; +} /// Zero-sized marker type for allowing only write access. #[derive(Debug, Default, Copy, Clone)] From 24a3177ba1ec5bad6c2cb7303f9405f2b9e3248d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 25 Apr 2024 18:04:27 +0200 Subject: [PATCH 09/11] refactor(access): specify `RestrictShared` via ` RestrictAccess` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/access.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/access.rs b/src/access.rs index b02c1d4..5ea1077 100644 --- a/src/access.rs +++ b/src/access.rs @@ -59,7 +59,7 @@ pub trait Readable: Copy + Default + private::Sealed { type RestrictShared: Readable + Access; } impl> Readable for A { - type RestrictShared = ReadOnly; + type RestrictShared = >::Restricted; } /// Helper trait that is implemented by [`ReadWrite`] and [`WriteOnly`]. @@ -74,30 +74,28 @@ impl> Copyable for A {} #[derive(Debug, Default, Copy, Clone)] pub struct ReadWrite; impl Access for ReadWrite { - #[allow(deprecated)] - type RestrictShared = ::RestrictShared; + type RestrictShared = >::Restricted; } /// Zero-sized marker type for allowing only read access. #[derive(Debug, Default, Copy, Clone)] pub struct ReadOnly; impl Access for ReadOnly { - #[allow(deprecated)] - type RestrictShared = ::RestrictShared; + type RestrictShared = >::Restricted; } /// Zero-sized marker type for allowing only write access. #[derive(Debug, Default, Copy, Clone)] pub struct WriteOnly; impl Access for WriteOnly { - type RestrictShared = NoAccess; + type RestrictShared = >::Restricted; } /// Zero-sized marker type that grants no access. #[derive(Debug, Default, Copy, Clone)] pub struct NoAccess; impl Access for NoAccess { - type RestrictShared = NoAccess; + type RestrictShared = >::Restricted; } mod private { From 25cbee367970cb3b528e8b2ba6fed4d9a3dcb7d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Fri, 26 Apr 2024 10:48:39 +0200 Subject: [PATCH 10/11] feat(access): remove `RestrictShared` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/access.rs | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/src/access.rs b/src/access.rs index 5ea1077..e431ce4 100644 --- a/src/access.rs +++ b/src/access.rs @@ -46,21 +46,11 @@ restrict_impl!(WriteOnly, WriteOnly, WriteOnly); restrict_impl!(WriteOnly, NoAccess, NoAccess); /// Sealed trait that is implemented for the types in this module. -pub trait Access: Copy + Default + private::Sealed { - /// Reduced access level to safely share the corresponding value. - #[deprecated = "replaced by `RestrictAccess::Restricted`"] - type RestrictShared: Access; -} +pub trait Access: Copy + Default + private::Sealed {} /// Helper trait that is implemented by [`ReadWrite`] and [`ReadOnly`]. -pub trait Readable: Copy + Default + private::Sealed { - /// Reduced access level to safely share the corresponding value. - #[deprecated = "replaced by `RestrictAccess::Restricted`"] - type RestrictShared: Readable + Access; -} -impl> Readable for A { - type RestrictShared = >::Restricted; -} +pub trait Readable: Copy + Default + private::Sealed {} +impl> Readable for A {} /// Helper trait that is implemented by [`ReadWrite`] and [`WriteOnly`]. pub trait Writable: Access + private::Sealed {} @@ -73,30 +63,22 @@ impl> Copyable for A {} /// Zero-sized marker type for allowing both read and write access. #[derive(Debug, Default, Copy, Clone)] pub struct ReadWrite; -impl Access for ReadWrite { - type RestrictShared = >::Restricted; -} +impl Access for ReadWrite {} /// Zero-sized marker type for allowing only read access. #[derive(Debug, Default, Copy, Clone)] pub struct ReadOnly; -impl Access for ReadOnly { - type RestrictShared = >::Restricted; -} +impl Access for ReadOnly {} /// Zero-sized marker type for allowing only write access. #[derive(Debug, Default, Copy, Clone)] pub struct WriteOnly; -impl Access for WriteOnly { - type RestrictShared = >::Restricted; -} +impl Access for WriteOnly {} /// Zero-sized marker type that grants no access. #[derive(Debug, Default, Copy, Clone)] pub struct NoAccess; -impl Access for NoAccess { - type RestrictShared = >::Restricted; -} +impl Access for NoAccess {} mod private { pub trait Sealed {} From c64c9af3349d8d038b8c41831ccebc452245778f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Fri, 26 Apr 2024 10:51:59 +0200 Subject: [PATCH 11/11] fix(access): make `Readable`, `Writable`, and `Copyable` bounds consistent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/access.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/access.rs b/src/access.rs index e431ce4..19b29bf 100644 --- a/src/access.rs +++ b/src/access.rs @@ -49,15 +49,15 @@ restrict_impl!(WriteOnly, NoAccess, NoAccess); pub trait Access: Copy + Default + private::Sealed {} /// Helper trait that is implemented by [`ReadWrite`] and [`ReadOnly`]. -pub trait Readable: Copy + Default + private::Sealed {} +pub trait Readable: Access {} impl> Readable for A {} /// Helper trait that is implemented by [`ReadWrite`] and [`WriteOnly`]. -pub trait Writable: Access + private::Sealed {} +pub trait Writable: Access {} impl> Writable for A {} /// Implemented for access types that permit copying of `VolatileRef`. -pub trait Copyable: private::Sealed {} +pub trait Copyable: Access {} impl> Copyable for A {} /// Zero-sized marker type for allowing both read and write access.