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}