rune/runtime/
borrow_mut.rs

1use core::fmt;
2use core::future::Future;
3use core::marker::PhantomData;
4use core::ops::{Deref, DerefMut};
5use core::pin::Pin;
6use core::ptr::NonNull;
7use core::task::{Context, Poll};
8
9use super::RawAccessGuard;
10
11/// Guard for data exclusively borrowed from a slot in the virtual machine.
12///
13/// These guards are necessary, since we need to guarantee certain forms of
14/// access depending on what we do. Releasing the guard releases the access.
15pub struct BorrowMut<'a, T: ?Sized> {
16    data: NonNull<T>,
17    guard: Option<RawAccessGuard>,
18    _marker: PhantomData<&'a mut T>,
19}
20
21impl<'a, T: ?Sized> BorrowMut<'a, T> {
22    /// Construct a borrow mut from static data.
23    #[inline]
24    pub(crate) fn from_ref(data: &'a mut T) -> Self {
25        Self {
26            data: NonNull::from(data),
27            guard: None,
28            _marker: PhantomData,
29        }
30    }
31
32    /// Construct a new exclusive guard.
33    ///
34    /// # Safety
35    ///
36    /// since this has implications for releasing access, the caller must
37    /// ensure that access has been acquired correctly using e.g.
38    /// [Access::exclusive]. Otherwise access can be release incorrectly once
39    /// this guard is dropped.
40    #[inline]
41    pub(crate) unsafe fn new(data: NonNull<T>, guard: RawAccessGuard) -> Self {
42        Self {
43            data,
44            guard: Some(guard),
45            _marker: PhantomData,
46        }
47    }
48
49    /// Map the mutable reference.
50    ///
51    /// # Examples
52    ///
53    /// ```
54    /// use rune::runtime::{BorrowMut, Bytes};
55    /// use rune::alloc::try_vec;
56    ///
57    /// let bytes = rune::to_value(Bytes::from_vec(try_vec![1, 2, 3, 4]))?;
58    /// let bytes = bytes.borrow_mut::<Bytes>()?;
59    ///
60    /// let mut bytes = BorrowMut::map(bytes, |bytes| &mut bytes[0..2]);
61    ///
62    /// assert_eq!(&mut bytes[..], &mut [1u8, 2u8][..]);
63    /// # Ok::<_, rune::support::Error>(())
64    /// ```
65    #[inline]
66    pub fn map<U: ?Sized>(mut this: Self, m: impl FnOnce(&mut T) -> &mut U) -> BorrowMut<'a, U> {
67        // SAFETY: This is safe per construction.
68        unsafe {
69            BorrowMut {
70                data: NonNull::from(m(this.data.as_mut())),
71                guard: this.guard,
72                _marker: PhantomData,
73            }
74        }
75    }
76
77    /// Try to map the mutable reference to a projection.
78    ///
79    /// # Examples
80    ///
81    /// ```
82    /// use rune::runtime::{BorrowMut, Bytes};
83    /// use rune::alloc::try_vec;
84    ///
85    /// let bytes = rune::to_value(Bytes::from_vec(try_vec![1, 2, 3, 4]))?;
86    /// let bytes = bytes.borrow_mut::<Bytes>()?;
87    ///
88    /// let Ok(mut bytes) = BorrowMut::try_map(bytes, |bytes| bytes.get_mut(0..2)) else {
89    ///     panic!("Conversion failed");
90    /// };
91    ///
92    /// assert_eq!(&mut bytes[..], &mut [1u8, 2u8][..]);
93    /// # Ok::<_, rune::support::Error>(())
94    /// ```
95    #[inline]
96    pub fn try_map<U: ?Sized>(
97        mut this: Self,
98        m: impl FnOnce(&mut T) -> Option<&mut U>,
99    ) -> Result<BorrowMut<'a, U>, Self> {
100        unsafe {
101            let Some(data) = m(this.data.as_mut()) else {
102                return Err(BorrowMut {
103                    data: this.data,
104                    guard: this.guard,
105                    _marker: PhantomData,
106                });
107            };
108
109            Ok(BorrowMut {
110                data: NonNull::from(data),
111                guard: this.guard,
112                _marker: PhantomData,
113            })
114        }
115    }
116}
117
118impl<T: ?Sized> Deref for BorrowMut<'_, T> {
119    type Target = T;
120
121    fn deref(&self) -> &Self::Target {
122        // SAFETY: This is correct per construction.
123        unsafe { self.data.as_ref() }
124    }
125}
126
127impl<T: ?Sized> DerefMut for BorrowMut<'_, T> {
128    fn deref_mut(&mut self) -> &mut Self::Target {
129        // SAFETY: This is correct per construction.
130        unsafe { self.data.as_mut() }
131    }
132}
133
134impl<T: ?Sized> fmt::Debug for BorrowMut<'_, T>
135where
136    T: fmt::Debug,
137{
138    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
139        fmt::Debug::fmt(&**self, fmt)
140    }
141}
142
143impl<F> Future for BorrowMut<'_, F>
144where
145    F: Unpin + Future,
146{
147    type Output = F::Output;
148
149    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
150        // NB: inner Future is Unpin.
151        let this = self.get_mut();
152        Pin::new(&mut **this).poll(cx)
153    }
154}