stabby_abi/
as_mut.rs

1//
2// Copyright (c) 2023 ZettaScale Technology
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7// which is available at https://www.apache.org/licenses/LICENSE-2.0.
8//
9// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10//
11// Contributors:
12//   Pierre Avital, <pierre.avital@me.com>
13//
14
15use core::ops::{Deref, DerefMut};
16
17impl<Source> super::AccessAs for Source {
18    fn ref_as<T: ?Sized>(&self) -> <Self as IGuardRef<T>>::Guard<'_>
19    where
20        Self: IGuardRef<T>,
21    {
22        self.guard_ref_inner()
23    }
24    fn mut_as<T: ?Sized>(&mut self) -> <Self as IGuardMut<T>>::GuardMut<'_>
25    where
26        Self: IGuardMut<T>,
27    {
28        self.guard_mut_inner()
29    }
30}
31
32/// Allows exposing an immutable reference to a temporary conversion.
33pub trait IGuardRef<T: ?Sized> {
34    /// The type of the guard which will clean up the temporary.
35    type Guard<'a>: Deref<Target = T>
36    where
37        Self: 'a;
38    /// Construct the temporary and guard it through an immutable reference.
39    fn guard_ref_inner(&self) -> Self::Guard<'_>;
40}
41
42/// Allows exposing an mutable reference to a temporary conversion.
43pub trait IGuardMut<T: ?Sized>: IGuardRef<T> {
44    /// The type of the guard which will clean up the temporary after applying its changes to the original.
45    type GuardMut<'a>: DerefMut<Target = T>
46    where
47        Self: 'a;
48    /// Construct the temporary and guard it through a mutable reference.
49    fn guard_mut_inner(&mut self) -> Self::GuardMut<'_>;
50}
51
52/// A guard exposing an immutable reference to `T` as an immutable reference to `As`
53pub struct RefAs<'a, T, As> {
54    source: core::marker::PhantomData<&'a T>,
55    target: core::mem::ManuallyDrop<As>,
56}
57impl<T, As> Deref for RefAs<'_, T, As> {
58    type Target = As;
59    fn deref(&self) -> &Self::Target {
60        &self.target
61    }
62}
63impl<T: Into<As>, As: Into<T>> IGuardRef<As> for T {
64    type Guard<'a>
65        = RefAs<'a, T, As>
66    where
67        Self: 'a;
68
69    fn guard_ref_inner(&self) -> Self::Guard<'_> {
70        RefAs {
71            source: core::marker::PhantomData,
72            target: core::mem::ManuallyDrop::new(unsafe { core::ptr::read(self).into() }),
73        }
74    }
75}
76
77/// A guard exposing an mutable reference to `T` as an mutable reference to `As`
78///
79/// Failing to destroy this guard will cause `T` not to receive any of the changes applied to the guard.
80pub struct MutAs<'a, T, As: Into<T>> {
81    source: &'a mut T,
82    target: core::mem::ManuallyDrop<As>,
83}
84impl<T, As: Into<T>> Deref for MutAs<'_, T, As> {
85    type Target = As;
86    fn deref(&self) -> &Self::Target {
87        &self.target
88    }
89}
90impl<T, As: Into<T>> DerefMut for MutAs<'_, T, As> {
91    fn deref_mut(&mut self) -> &mut Self::Target {
92        &mut self.target
93    }
94}
95impl<T, As: Into<T>> Drop for MutAs<'_, T, As> {
96    fn drop(&mut self) {
97        unsafe { core::ptr::write(self.source, core::ptr::read(&*self.target).into()) }
98    }
99}
100impl<T: Into<As>, As: Into<T>> IGuardMut<As> for T {
101    type GuardMut<'a>
102        = MutAs<'a, T, As>
103    where
104        Self: 'a;
105
106    fn guard_mut_inner(&mut self) -> Self::GuardMut<'_> {
107        MutAs {
108            target: core::mem::ManuallyDrop::new(unsafe { core::ptr::read(self).into() }),
109            source: self,
110        }
111    }
112}