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}