rune/modules/mem.rs
1//! Working with memory.
2
3use crate as rune;
4use crate::alloc::fmt::TryWrite;
5use crate::runtime::{self, Formatter, Value, VmResult};
6use crate::{Any, ContextError, Module};
7
8/// Working with memory.
9#[rune::module(::std::mem)]
10pub fn module() -> Result<Module, ContextError> {
11 let mut m = Module::from_meta(self::module_meta)?;
12 m.function_meta(drop)?;
13 m.function_meta(snapshot)?;
14
15 m.ty::<Snapshot>()?;
16 m.function_meta(Snapshot::display)?;
17 m.function_meta(Snapshot::debug)?;
18 m.function_meta(Snapshot::shared)?;
19 m.function_meta(Snapshot::is_exclusive)?;
20 m.function_meta(Snapshot::is_readable)?;
21 m.function_meta(Snapshot::is_writable)?;
22
23 Ok(m)
24}
25
26#[derive(Any)]
27#[rune(item = ::std::mem)]
28struct Snapshot {
29 inner: runtime::Snapshot,
30}
31
32impl Snapshot {
33 /// The number of shared references to the value.
34 ///
35 /// # Examples
36 ///
37 /// ```rune
38 /// use std::mem::snapshot;
39 ///
40 /// let v = [1, 2, 3];
41 ///
42 /// let s = snapshot(v)?;
43 /// assert_eq!(s.shared(), 0);
44 ///
45 /// // An iterators takes a shared reference to the collection being iterated over.
46 /// let it = v.iter();
47 ///
48 /// let s = snapshot(v)?;
49 /// assert_eq!(s.shared(), 1);
50 /// drop(it);
51 ///
52 /// let s = snapshot(v)?;
53 /// assert_eq!(s.shared(), 0);
54 /// ```
55 #[rune::function]
56 fn shared(&self) -> usize {
57 self.inner.shared()
58 }
59
60 /// Test if the snapshot indicates that the value is exclusively held.
61 ///
62 /// # Examples
63 ///
64 /// ```rune
65 /// use std::mem::snapshot;
66 ///
67 /// let v = [1, 2, 3];
68 ///
69 /// let s = snapshot(v)?;
70 /// assert_eq!(s.shared(), 0);
71 /// assert!(!s.is_exclusive());
72 /// assert!(s.is_readable());
73 /// assert!(s.is_writable());
74 ///
75 /// // Assign to a separate variable since the compiler will notice that `v` is moved.
76 /// let u = v;
77 ///
78 /// // Move the value into a closure, causing the original reference to become exclusively held.
79 /// let closure = move || {
80 /// v
81 /// };
82 ///
83 /// let s = snapshot(u)?;
84 /// assert!(s.is_exclusive());
85 /// assert!(!s.is_readable());
86 /// assert!(!s.is_writable());
87 /// ```
88 #[rune::function]
89 fn is_exclusive(&self) -> bool {
90 self.inner.is_exclusive()
91 }
92
93 /// Test if the snapshot indicates that the value is readable.
94 ///
95 /// # Examples
96 ///
97 /// ```rune
98 /// use std::mem::snapshot;
99 ///
100 /// let v = [1, 2, 3];
101 ///
102 /// let s = snapshot(v)?;
103 /// assert_eq!(s.shared(), 0);
104 /// assert!(!s.is_exclusive());
105 /// assert!(s.is_readable());
106 /// assert!(s.is_writable());
107 ///
108 /// // Assign to a separate variable since the compiler will notice that `v` is moved.
109 /// let u = v;
110 ///
111 /// // Move the value into a closure, causing the original reference to become exclusively held.
112 /// let closure = move || {
113 /// v
114 /// };
115 ///
116 /// let s = snapshot(u)?;
117 /// assert!(s.is_exclusive());
118 /// assert!(!s.is_readable());
119 /// assert!(!s.is_writable());
120 /// ```
121 #[rune::function]
122 fn is_readable(&self) -> bool {
123 self.inner.is_readable()
124 }
125
126 /// Test if the snapshot indicates that the value is writable.
127 ///
128 /// # Examples
129 ///
130 /// ```rune
131 /// use std::mem::snapshot;
132 ///
133 /// let v = [1, 2, 3];
134 ///
135 /// let s = snapshot(v)?;
136 /// assert_eq!(s.shared(), 0);
137 /// assert!(!s.is_exclusive());
138 /// assert!(s.is_readable());
139 /// assert!(s.is_writable());
140 ///
141 /// // Assign to a separate variable since the compiler will notice that `v` is moved.
142 /// let u = v;
143 ///
144 /// // Move the value into a closure, causing the original reference to become exclusively held.
145 /// let closure = move || {
146 /// v
147 /// };
148 ///
149 /// let s = snapshot(u)?;
150 /// assert!(s.is_exclusive());
151 /// assert!(!s.is_readable());
152 /// assert!(!s.is_writable());
153 /// ```
154 #[rune::function]
155 fn is_writable(&self) -> bool {
156 self.inner.is_writable()
157 }
158
159 #[rune::function(protocol = DISPLAY_FMT)]
160 fn display(&self, f: &mut Formatter) -> VmResult<()> {
161 vm_write!(f, "{}", self.inner)
162 }
163
164 #[rune::function(protocol = DEBUG_FMT)]
165 fn debug(&self, f: &mut Formatter) -> VmResult<()> {
166 vm_write!(f, "{:?}", self.inner)
167 }
168}
169
170/// Explicitly drop the given value, freeing up any memory associated with it.
171///
172/// Normally values are dropped as they go out of scope, but with this method it
173/// can be explicitly controlled instead.
174///
175/// # Examples
176///
177/// Basic usage:
178///
179/// ```rune
180/// let v = [1, 2, 3];
181/// drop(v);
182/// ```
183#[rune::function]
184fn drop(value: Value) -> VmResult<()> {
185 vm_try!(value.drop());
186 VmResult::Ok(())
187}
188
189/// Get the usage snapshot of a value.
190///
191/// A snapshot can be used to diagnose how many users a given value has.
192///
193/// # Examples
194///
195/// ```rune
196/// use std::mem::snapshot;
197///
198/// let v1 = [1, 2, 3];
199/// let a = snapshot(v1)?;
200/// let v2 = [v1];
201/// let b = snapshot(v1)?;
202///
203/// assert_eq!(a.shared(), 0);
204/// assert_eq!(b.shared(), 0);
205///
206/// dbg!(a);
207/// dbg!(b);
208/// ```
209#[rune::function]
210fn snapshot(value: Value) -> Option<Snapshot> {
211 value
212 .snapshot()
213 .map(|snapshot| Snapshot { inner: snapshot })
214}