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