rune/runtime/
to_value.rs

1use crate::alloc::prelude::*;
2use crate::alloc::{self, HashMap};
3use crate::any::AnyMarker;
4
5use super::{AnyObj, Object, RuntimeError, Value, VmError};
6
7/// Derive macro for the [`ToValue`] trait for converting types into the dynamic
8/// `Value` container.
9///
10/// # Examples
11///
12/// ```
13/// use rune::{ToValue, Vm};
14/// use rune::sync::Arc;
15///
16/// #[derive(ToValue)]
17/// struct Foo {
18///     field: u64,
19/// }
20///
21/// let mut sources = rune::sources! {
22///     entry => {
23///         pub fn main(foo) {
24///             foo.field + 1
25///         }
26///     }
27/// };
28///
29/// let unit = rune::prepare(&mut sources).build()?;
30/// let unit = Arc::try_new(unit)?;
31/// let mut vm = Vm::without_runtime(unit)?;
32///
33/// let value = vm.call(["main"], (Foo { field: 42 },))?;
34/// let value: u64 = rune::from_value(value)?;
35///
36/// assert_eq!(value, 43);
37/// # Ok::<_, rune::support::Error>(())
38/// ```
39pub use rune_macros::ToValue;
40
41/// Convert something into the dynamic [`Value`].
42///
43/// # Examples
44///
45/// ```
46/// use rune::{ToValue, Vm};
47/// use rune::sync::Arc;
48///
49/// #[derive(ToValue)]
50/// struct Foo {
51///     field: u64,
52/// }
53///
54/// let mut sources = rune::sources! {
55///     entry => {
56///         pub fn main(foo) {
57///             foo.field + 1
58///         }
59///     }
60/// };
61///
62/// let unit = rune::prepare(&mut sources).build()?;
63/// let unit = Arc::try_new(unit)?;
64/// let mut vm = Vm::without_runtime(unit)?;
65///
66/// let foo = vm.call(["main"], (Foo { field: 42 },))?;
67/// let foo: u64 = rune::from_value(foo)?;
68///
69/// assert_eq!(foo, 43);
70/// # Ok::<_, rune::support::Error>(())
71/// ```
72pub fn to_value(value: impl ToValue) -> Result<Value, RuntimeError> {
73    value.to_value()
74}
75
76/// Trait for converting types into the dynamic [`Value`] container.
77///
78/// # Examples
79///
80/// ```
81/// use rune::{ToValue, Vm};
82/// use rune::sync::Arc;
83///
84/// #[derive(ToValue)]
85/// struct Foo {
86///     field: u64,
87/// }
88///
89/// let mut sources = rune::sources! {
90///     entry => {
91///         pub fn main(foo) {
92///             foo.field + 1
93///         }
94///     }
95/// };
96///
97/// let unit = rune::prepare(&mut sources).build()?;
98/// let unit = Arc::try_new(unit)?;
99/// let mut vm = Vm::without_runtime(unit)?;
100///
101/// let foo = vm.call(["main"], (Foo { field: 42 },))?;
102/// let foo: u64 = rune::from_value(foo)?;
103///
104/// assert_eq!(foo, 43);
105/// # Ok::<_, rune::support::Error>(())
106/// ```
107#[diagnostic::on_unimplemented(
108    message = "ToValue is not implemented for `{Self}`",
109    label = "ToValue is not implemented for `{Self}`",
110    note = "This probably means that `{Self}` hasn't derived rune::Any"
111)]
112pub trait ToValue: Sized {
113    /// Convert into a value.
114    fn to_value(self) -> Result<Value, RuntimeError>;
115}
116
117/// Trait governing things that can be returned from native functions.
118pub trait IntoReturn
119where
120    Self: Sized,
121{
122    /// Convert something into a return value.
123    fn into_return(self) -> Result<Value, VmError>;
124}
125
126impl<T> IntoReturn for T
127where
128    T: ToValue,
129{
130    #[inline]
131    fn into_return(self) -> Result<Value, VmError> {
132        Ok(T::to_value(self)?)
133    }
134}
135
136impl ToValue for Value {
137    #[inline]
138    fn to_value(self) -> Result<Value, RuntimeError> {
139        Ok(self)
140    }
141}
142
143/// Trait for converting types into values.
144pub trait UnsafeToValue: Sized {
145    /// The type used to guard the unsafe value conversion.
146    type Guard: 'static;
147
148    /// Convert into a value.
149    ///
150    /// # Safety
151    ///
152    /// The value returned must not be used after the guard associated with it
153    /// has been dropped.
154    unsafe fn unsafe_to_value(self) -> Result<(Value, Self::Guard), RuntimeError>;
155}
156
157impl<T> ToValue for T
158where
159    T: AnyMarker,
160{
161    #[inline]
162    fn to_value(self) -> Result<Value, RuntimeError> {
163        Ok(Value::from(AnyObj::new(self)?))
164    }
165}
166
167impl<T> UnsafeToValue for T
168where
169    T: ToValue,
170{
171    type Guard = ();
172
173    #[inline]
174    unsafe fn unsafe_to_value(self) -> Result<(Value, Self::Guard), RuntimeError> {
175        Ok((self.to_value()?, ()))
176    }
177}
178
179impl ToValue for &Value {
180    #[inline]
181    fn to_value(self) -> Result<Value, RuntimeError> {
182        Ok(self.clone())
183    }
184}
185
186// Option impls
187
188impl<T> ToValue for Option<T>
189where
190    T: ToValue,
191{
192    #[inline]
193    fn to_value(self) -> Result<Value, RuntimeError> {
194        let option = match self {
195            Some(some) => Some(some.to_value()?),
196            None => None,
197        };
198
199        Ok(Value::try_from(option)?)
200    }
201}
202
203// String impls
204
205impl ToValue for alloc::Box<str> {
206    #[inline]
207    fn to_value(self) -> Result<Value, RuntimeError> {
208        let this = alloc::String::from(self);
209        Ok(Value::new(this)?)
210    }
211}
212
213impl ToValue for &str {
214    #[inline]
215    fn to_value(self) -> Result<Value, RuntimeError> {
216        let this = alloc::String::try_from(self)?;
217        Ok(Value::new(this)?)
218    }
219}
220
221impl ToValue for rust_alloc::boxed::Box<str> {
222    #[inline]
223    fn to_value(self) -> Result<Value, RuntimeError> {
224        let this = self.try_to_string()?;
225        Ok(Value::new(this)?)
226    }
227}
228
229impl ToValue for rust_alloc::string::String {
230    #[inline]
231    fn to_value(self) -> Result<Value, RuntimeError> {
232        let string = alloc::String::try_from(self)?;
233        Ok(Value::new(string)?)
234    }
235}
236
237impl<T, E> ToValue for Result<T, E>
238where
239    T: ToValue,
240    E: ToValue,
241{
242    fn to_value(self) -> Result<Value, RuntimeError> {
243        let result = match self {
244            Ok(ok) => Ok(ok.to_value()?),
245            Err(err) => Err(err.to_value()?),
246        };
247
248        Ok(Value::try_from(result)?)
249    }
250}
251
252// map impls
253
254macro_rules! impl_map {
255    ($ty:ty) => {
256        impl<T> ToValue for $ty
257        where
258            T: ToValue,
259        {
260            fn to_value(self) -> Result<Value, RuntimeError> {
261                let mut output = Object::with_capacity(self.len())?;
262
263                for (key, value) in self {
264                    let key = alloc::String::try_from(key)?;
265                    let value = value.to_value()?;
266                    output.insert(key, value)?;
267                }
268
269                Ok(Value::try_from(output)?)
270            }
271        }
272    };
273}
274
275impl_map!(HashMap<rust_alloc::string::String, T>);
276impl_map!(HashMap<alloc::String, T>);
277
278cfg_std! {
279    impl_map!(::std::collections::HashMap<rust_alloc::string::String, T>);
280    impl_map!(::std::collections::HashMap<alloc::String, T>);
281}