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}