rune/runtime/
from_value.rs

1use core::cmp::Ordering;
2
3use crate::alloc::{self, String};
4use crate::any::AnyMarker;
5use crate::hash::Hash;
6
7use super::{Mut, RawAnyGuard, Ref, RuntimeError, Value};
8
9/// Derive macro for the [`FromValue`] trait for converting types from the
10/// dynamic `Value` container.
11///
12/// This can be implemented for structs and variants.
13///
14/// For structs, this will try to decode any struct-like data into the desired data type:
15///
16/// ```rust
17/// use rune::{FromValue, Vm};
18/// use rune::sync::Arc;
19///
20/// #[derive(Debug, PartialEq, FromValue)]
21/// struct Foo {
22///     a: u64,
23///     b: u64,
24/// }
25///
26/// let mut sources = rune::sources! {
27///     entry => {
28///         struct Foo {
29///             a,
30///             b,
31///         }
32///
33///         pub fn main() {
34///             Foo { a: 1, b: 2 }
35///         }
36///     }
37/// };
38///
39/// let unit = rune::prepare(&mut sources).build()?;
40/// let unit = Arc::try_new(unit)?;
41///
42/// let mut vm = Vm::without_runtime(unit)?;
43/// let foo = vm.call(["main"], ())?;
44/// let foo: Foo = rune::from_value(foo)?;
45///
46/// assert_eq!(foo, Foo { a: 1, b: 2 });
47/// # Ok::<_, rune::support::Error>(())
48/// ```
49///
50/// For enums, the variant name of the rune-local variant is matched:
51///
52/// ```rust
53/// use rune::{FromValue, Vm};
54/// use rune::sync::Arc;
55///
56/// #[derive(Debug, PartialEq, FromValue)]
57/// enum Enum {
58///     Variant(u32),
59///     Variant2 { a: u32, b: u32 },
60/// }
61///
62/// let mut sources = rune::sources! {
63///     entry => {
64///         enum Enum {
65///             Variant(a),
66///         }
67///
68///         pub fn main() {
69///             Enum::Variant(42)
70///         }
71///     }
72/// };
73///
74/// let unit = rune::prepare(&mut sources).build()?;
75/// let unit = Arc::try_new(unit)?;
76///
77/// let mut vm = Vm::without_runtime(unit)?;
78/// let foo = vm.call(["main"], ())?;
79/// let foo: Enum = rune::from_value(foo)?;
80///
81/// assert_eq!(foo, Enum::Variant(42));
82/// # Ok::<_, rune::support::Error>(())
83/// ```
84pub use rune_macros::FromValue;
85
86/// Cheap conversion trait to convert something infallibly into a dynamic [`Value`].
87pub trait IntoValue {
88    /// Convert into a dynamic [`Value`].
89    #[doc(hidden)]
90    fn into_value(self) -> Value;
91}
92
93impl IntoValue for Value {
94    #[inline]
95    fn into_value(self) -> Value {
96        self
97    }
98}
99
100impl IntoValue for &Value {
101    #[inline]
102    fn into_value(self) -> Value {
103        self.clone()
104    }
105}
106
107/// Convert something into the dynamic [`Value`].
108///
109/// # Examples
110///
111/// ```
112/// use rune::sync::Arc;
113/// use rune::{ToValue, Vm};
114///
115/// #[derive(ToValue)]
116/// struct Foo {
117///     field: u64,
118/// }
119///
120/// let mut sources = rune::sources! {
121///     entry => {
122///         pub fn main(foo) {
123///             foo.field + 1
124///         }
125///     }
126/// };
127///
128/// let unit = rune::prepare(&mut sources).build()?;
129/// let unit = Arc::try_new(unit)?;
130/// let mut vm = Vm::without_runtime(unit)?;
131///
132/// let foo = vm.call(["main"], (Foo { field: 42 },))?;
133/// let foo: u64 = rune::from_value(foo)?;
134///
135/// assert_eq!(foo, 43);
136/// # Ok::<_, rune::support::Error>(())
137/// ```
138pub fn from_value<T>(value: impl IntoValue) -> Result<T, RuntimeError>
139where
140    T: FromValue,
141{
142    T::from_value(value.into_value())
143}
144
145/// Trait for converting types from the dynamic [Value] container.
146///
147/// # Examples
148///
149/// ```
150/// use rune::sync::Arc;
151/// use rune::{FromValue, Vm};
152///
153/// #[derive(FromValue)]
154/// struct Foo {
155///     field: u64,
156/// }
157///
158/// let mut sources = rune::sources! {
159///     entry => {
160///         pub fn main() {
161///             #{field: 42}
162///         }
163///     }
164/// };
165///
166/// let unit = rune::prepare(&mut sources).build()?;
167/// let unit = Arc::try_new(unit)?;
168/// let mut vm = Vm::without_runtime(unit)?;
169///
170/// let foo = vm.call(["main"], ())?;
171/// let foo: Foo = rune::from_value(foo)?;
172///
173/// assert_eq!(foo.field, 42);
174/// # Ok::<_, rune::support::Error>(())
175/// ```
176#[diagnostic::on_unimplemented(
177    message = "FromValue is not implemented for `{Self}`",
178    label = "FromValue is not implemented for `{Self}`",
179    note = "This probably means that `{Self}` hasn't derived rune::Any"
180)]
181pub trait FromValue: 'static + Sized {
182    /// Try to convert to the given type, from the given value.
183    fn from_value(value: Value) -> Result<Self, RuntimeError>;
184}
185
186/// Unsafe to mut coercion.
187pub trait UnsafeToMut {
188    /// The raw guard returned.
189    ///
190    /// Must only be dropped *after* the value returned from this function is no
191    /// longer live.
192    type Guard: 'static;
193
194    /// # Safety
195    ///
196    /// Caller must ensure that the returned reference does not outlive the
197    /// guard.
198    unsafe fn unsafe_to_mut<'a>(value: Value) -> Result<(&'a mut Self, Self::Guard), RuntimeError>;
199}
200
201/// Unsafe to ref coercion.
202pub trait UnsafeToRef {
203    /// The raw guard returned.
204    ///
205    /// Must only be dropped *after* the value returned from this function is no
206    /// longer live.
207    type Guard: 'static;
208
209    /// # Safety
210    ///
211    /// Caller must ensure that the returned reference does not outlive the
212    /// guard.
213    unsafe fn unsafe_to_ref<'a>(value: Value) -> Result<(&'a Self, Self::Guard), RuntimeError>;
214}
215
216impl<T> FromValue for T
217where
218    T: AnyMarker,
219{
220    #[inline]
221    fn from_value(value: Value) -> Result<Self, RuntimeError> {
222        value.downcast()
223    }
224}
225
226impl FromValue for Value {
227    #[inline]
228    fn from_value(value: Value) -> Result<Self, RuntimeError> {
229        Ok(value)
230    }
231}
232
233// Option impls
234
235impl<T> FromValue for Option<T>
236where
237    T: FromValue,
238{
239    #[inline]
240    fn from_value(value: Value) -> Result<Self, RuntimeError> {
241        Ok(match value.downcast::<Option<Value>>()? {
242            Some(some) => Some(T::from_value(some.clone())?),
243            None => None,
244        })
245    }
246}
247
248impl FromValue for rust_alloc::string::String {
249    #[inline]
250    fn from_value(value: Value) -> Result<Self, RuntimeError> {
251        let string = String::from_value(value)?;
252        let string = rust_alloc::string::String::from(string);
253        Ok(string)
254    }
255}
256
257impl FromValue for alloc::Box<str> {
258    #[inline]
259    fn from_value(value: Value) -> Result<Self, RuntimeError> {
260        let string = value.borrow_string_ref()?;
261        let string = alloc::Box::try_from(string.as_ref())?;
262        Ok(string)
263    }
264}
265
266impl FromValue for rust_alloc::boxed::Box<str> {
267    #[inline]
268    fn from_value(value: Value) -> Result<Self, RuntimeError> {
269        let string = value.borrow_string_ref()?;
270        let string = rust_alloc::boxed::Box::<str>::from(string.as_ref());
271        Ok(string)
272    }
273}
274
275impl FromValue for Ref<str> {
276    #[inline]
277    fn from_value(value: Value) -> Result<Self, RuntimeError> {
278        Ok(Ref::map(Ref::<String>::from_value(value)?, String::as_str))
279    }
280}
281
282impl UnsafeToRef for str {
283    type Guard = RawAnyGuard;
284
285    #[inline]
286    unsafe fn unsafe_to_ref<'a>(value: Value) -> Result<(&'a Self, Self::Guard), RuntimeError> {
287        let string = value.into_ref::<String>()?;
288        let (string, guard) = Ref::into_raw(string);
289        Ok((string.as_ref().as_str(), guard))
290    }
291}
292
293impl UnsafeToMut for str {
294    type Guard = RawAnyGuard;
295
296    #[inline]
297    unsafe fn unsafe_to_mut<'a>(value: Value) -> Result<(&'a mut Self, Self::Guard), RuntimeError> {
298        let string = value.into_mut::<String>()?;
299        let (mut string, guard) = Mut::into_raw(string);
300        Ok((string.as_mut().as_mut_str(), guard))
301    }
302}
303
304impl<T, E> FromValue for Result<T, E>
305where
306    T: FromValue,
307    E: FromValue,
308{
309    #[inline]
310    fn from_value(value: Value) -> Result<Self, RuntimeError> {
311        Ok(match value.downcast::<Result<Value, Value>>()? {
312            Ok(ok) => Result::Ok(T::from_value(ok.clone())?),
313            Err(err) => Result::Err(E::from_value(err.clone())?),
314        })
315    }
316}
317
318impl FromValue for bool {
319    #[inline]
320    fn from_value(value: Value) -> Result<Self, RuntimeError> {
321        value.as_bool()
322    }
323}
324
325impl FromValue for char {
326    #[inline]
327    fn from_value(value: Value) -> Result<Self, RuntimeError> {
328        value.as_char()
329    }
330}
331
332macro_rules! impl_integer {
333    ($($ty:ty),* $(,)?) => {
334        $(
335            impl FromValue for $ty {
336                #[inline]
337                fn from_value(value: Value) -> Result<Self, RuntimeError> {
338                    value.as_integer()
339                }
340            }
341        )*
342    };
343}
344
345impl_integer!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
346
347impl FromValue for f64 {
348    #[inline]
349    fn from_value(value: Value) -> Result<Self, RuntimeError> {
350        value.as_float()
351    }
352}
353
354impl FromValue for f32 {
355    #[inline]
356    fn from_value(value: Value) -> Result<Self, RuntimeError> {
357        Ok(value.as_float()? as f32)
358    }
359}
360
361cfg_std! {
362    macro_rules! impl_map {
363        ($ty:ty, $key:ty) => {
364            impl<T> FromValue for $ty
365            where
366                T: FromValue,
367            {
368                fn from_value(value: Value) -> Result<Self, RuntimeError> {
369                    let object = value.downcast::<$crate::runtime::Object>()?;
370
371                    let mut output = <$ty>::with_capacity(object.len());
372
373                    for (key, value) in object {
374                        let key = <$key>::try_from(key)?;
375                        let value = <T>::from_value(value)?;
376                        output.insert(key, value);
377                    }
378
379                    Ok(output)
380                }
381            }
382        };
383    }
384
385    impl_map!(::std::collections::HashMap<String, T>, String);
386    impl_map!(::std::collections::HashMap<rust_alloc::string::String, T>, rust_alloc::string::String);
387}
388
389macro_rules! impl_try_map {
390    ($ty:ty, $key:ty) => {
391        impl<T> FromValue for $ty
392        where
393            T: FromValue,
394        {
395            fn from_value(value: Value) -> Result<Self, RuntimeError> {
396                let object = value.downcast::<$crate::runtime::Object>()?;
397
398                let mut output = <$ty>::try_with_capacity(object.len())?;
399
400                for (key, value) in object {
401                    let key = <$key>::try_from(key)?;
402                    let value = <T>::from_value(value)?;
403                    output.try_insert(key, value)?;
404                }
405
406                Ok(output)
407            }
408        }
409    };
410}
411
412impl_try_map!(alloc::HashMap<String, T>, String);
413impl_try_map!(alloc::HashMap<rust_alloc::string::String, T>, rust_alloc::string::String);
414
415impl FromValue for Ordering {
416    #[inline]
417    fn from_value(value: Value) -> Result<Self, RuntimeError> {
418        value.as_ordering()
419    }
420}
421
422impl FromValue for Hash {
423    #[inline]
424    fn from_value(value: Value) -> Result<Self, RuntimeError> {
425        value.as_hash()
426    }
427}