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::{
8    AnyObj, ConstValue, FromConstValue, Mut, RawAnyGuard, Ref, RuntimeError, Value, VmResult,
9};
10
11/// Derive macro for the [`FromValue`] trait for converting types from the
12/// dynamic `Value` container.
13///
14/// This can be implemented for structs and variants.
15///
16/// For structs, this will try to decode any struct-like data into the desired data type:
17///
18/// ```rust
19/// use std::sync::Arc;
20/// use rune::{FromValue, Vm};
21///
22/// #[derive(Debug, PartialEq, FromValue)]
23/// struct Foo {
24///     a: u64,
25///     b: u64,
26/// }
27///
28/// let mut sources = rune::sources! {
29///     entry => {
30///         struct Foo {
31///             a,
32///             b,
33///         }
34///
35///         pub fn main() {
36///             Foo { a: 1, b: 2 }
37///         }
38///     }
39/// };
40///
41/// let unit = rune::prepare(&mut sources).build()?;
42///
43/// let mut vm = Vm::without_runtime(Arc::new(unit));
44/// let foo = vm.call(["main"], ())?;
45/// let foo: Foo = rune::from_value(foo)?;
46///
47/// assert_eq!(foo, Foo { a: 1, b: 2 });
48/// # Ok::<_, rune::support::Error>(())
49/// ```
50///
51/// For enums, the variant name of the rune-local variant is matched:
52///
53/// ```rust
54/// use std::sync::Arc;
55/// use rune::{FromValue, Vm};
56///
57/// #[derive(Debug, PartialEq, FromValue)]
58/// enum Enum {
59///     Variant(u32),
60///     Variant2 { a: u32, b: u32 },
61/// }
62///
63/// let mut sources = rune::sources! {
64///     entry => {
65///         enum Enum {
66///             Variant(a),
67///         }
68///
69///         pub fn main() {
70///             Enum::Variant(42)
71///         }
72///     }
73/// };
74///
75/// let unit = rune::prepare(&mut sources).build()?;
76///
77/// let mut vm = Vm::without_runtime(Arc::new(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::{ToValue, Vm};
113/// use std::sync::Arc;
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///
130/// let mut vm = Vm::without_runtime(Arc::new(unit));
131/// let foo = vm.call(["main"], (Foo { field: 42 },))?;
132/// let foo: u64 = rune::from_value(foo)?;
133///
134/// assert_eq!(foo, 43);
135/// # Ok::<_, rune::support::Error>(())
136/// ```
137pub fn from_value<T>(value: impl IntoValue) -> Result<T, RuntimeError>
138where
139    T: FromValue,
140{
141    T::from_value(value.into_value())
142}
143
144/// Trait for converting types from the dynamic [Value] container.
145///
146/// # Examples
147///
148/// ```
149/// use rune::{FromValue, Vm};
150/// use std::sync::Arc;
151///
152/// #[derive(FromValue)]
153/// struct Foo {
154///     field: u64,
155/// }
156///
157/// let mut sources = rune::sources! {
158///     entry => {
159///         pub fn main() {
160///             #{field: 42}
161///         }
162///     }
163/// };
164///
165/// let unit = rune::prepare(&mut sources).build()?;
166///
167/// let mut vm = Vm::without_runtime(Arc::new(unit));
168/// let foo = vm.call(["main"], ())?;
169/// let foo: Foo = rune::from_value(foo)?;
170///
171/// assert_eq!(foo.field, 42);
172/// # Ok::<_, rune::support::Error>(())
173/// ```
174#[diagnostic::on_unimplemented(
175    message = "FromValue is not implemented for `{Self}`",
176    label = "FromValue is not implemented for `{Self}`",
177    note = "This probably means that `{Self}` hasn't derived rune::Any"
178)]
179pub trait FromValue: 'static + Sized {
180    /// Try to convert to the given type, from the given value.
181    fn from_value(value: Value) -> Result<Self, RuntimeError>;
182}
183
184/// Unsafe to mut coercion.
185pub trait UnsafeToMut {
186    /// The raw guard returned.
187    ///
188    /// Must only be dropped *after* the value returned from this function is no
189    /// longer live.
190    type Guard: 'static;
191
192    /// # Safety
193    ///
194    /// Caller must ensure that the returned reference does not outlive the
195    /// guard.
196    unsafe fn unsafe_to_mut<'a>(value: Value) -> Result<(&'a mut Self, Self::Guard), RuntimeError>;
197}
198
199/// Unsafe to ref coercion.
200pub trait UnsafeToRef {
201    /// The raw guard returned.
202    ///
203    /// Must only be dropped *after* the value returned from this function is no
204    /// longer live.
205    type Guard: 'static;
206
207    /// # Safety
208    ///
209    /// Caller must ensure that the returned reference does not outlive the
210    /// guard.
211    unsafe fn unsafe_to_ref<'a>(value: Value) -> Result<(&'a Self, Self::Guard), RuntimeError>;
212}
213
214/// A potentially unsafe conversion for value conversion.
215///
216/// This trait is used to convert values to references, which can be safely used
217/// while an external function call is used. That sort of use is safe because we
218/// hold onto the guard returned by the conversion during external function
219/// calls.
220#[deprecated = "Rune: Implementing this trait will no longer work. Use UnsafeToRef and UnsafeToMut instead."]
221pub trait UnsafeFromValue: Sized {
222    /// The output type from the unsafe coercion.
223    type Output: 'static;
224
225    /// The raw guard returned.
226    ///
227    /// Must only be dropped *after* the value returned from this function is
228    /// no longer live.
229    type Guard: 'static;
230
231    /// Convert the given reference using unsafe assumptions to a value.
232    ///
233    /// # Safety
234    ///
235    /// The return value of this function may only be used while a virtual
236    /// machine is not being modified.
237    ///
238    /// You must also make sure that the returned value does not outlive the
239    /// guard.
240    fn unsafe_from_value(value: Value) -> VmResult<(Self::Output, Self::Guard)>;
241
242    /// Coerce the output of an unsafe from value into the final output type.
243    ///
244    /// # Safety
245    ///
246    /// The return value of this function may only be used while a virtual
247    /// machine is not being modified.
248    ///
249    /// You must also make sure that the returned value does not outlive the
250    /// guard.
251    unsafe fn unsafe_coerce(output: Self::Output) -> Self;
252}
253
254impl<T> FromValue for T
255where
256    T: AnyMarker,
257{
258    #[inline]
259    fn from_value(value: Value) -> Result<Self, RuntimeError> {
260        value.downcast()
261    }
262}
263
264impl<T> FromValue for Mut<T>
265where
266    T: AnyMarker,
267{
268    #[inline]
269    fn from_value(value: Value) -> Result<Self, RuntimeError> {
270        value.into_mut()
271    }
272}
273
274impl<T> FromValue for Ref<T>
275where
276    T: AnyMarker,
277{
278    #[inline]
279    fn from_value(value: Value) -> Result<Self, RuntimeError> {
280        value.into_ref()
281    }
282}
283
284impl FromValue for AnyObj {
285    #[inline]
286    fn from_value(value: Value) -> Result<Self, RuntimeError> {
287        value.into_any_obj()
288    }
289}
290
291impl FromValue for Value {
292    #[inline]
293    fn from_value(value: Value) -> Result<Self, RuntimeError> {
294        Ok(value)
295    }
296}
297
298// Option impls
299
300impl<T> FromValue for Option<T>
301where
302    T: FromValue,
303{
304    #[inline]
305    fn from_value(value: Value) -> Result<Self, RuntimeError> {
306        Ok(match value.downcast::<Option<Value>>()? {
307            Some(some) => Some(T::from_value(some.clone())?),
308            None => None,
309        })
310    }
311}
312
313impl FromValue for ::rust_alloc::string::String {
314    #[inline]
315    fn from_value(value: Value) -> Result<Self, RuntimeError> {
316        let string = String::from_value(value)?;
317        let string = ::rust_alloc::string::String::from(string);
318        Ok(string)
319    }
320}
321
322impl FromValue for alloc::Box<str> {
323    #[inline]
324    fn from_value(value: Value) -> Result<Self, RuntimeError> {
325        let string = value.borrow_string_ref()?;
326        let string = alloc::Box::try_from(string.as_ref())?;
327        Ok(string)
328    }
329}
330
331#[cfg(feature = "alloc")]
332impl FromValue for ::rust_alloc::boxed::Box<str> {
333    #[inline]
334    fn from_value(value: Value) -> Result<Self, RuntimeError> {
335        let string = value.borrow_string_ref()?;
336        let string = ::rust_alloc::boxed::Box::<str>::from(string.as_ref());
337        Ok(string)
338    }
339}
340
341impl FromValue for Ref<str> {
342    #[inline]
343    fn from_value(value: Value) -> Result<Self, RuntimeError> {
344        Ok(Ref::map(Ref::<String>::from_value(value)?, String::as_str))
345    }
346}
347
348impl UnsafeToRef for str {
349    type Guard = RawAnyGuard;
350
351    #[inline]
352    unsafe fn unsafe_to_ref<'a>(value: Value) -> Result<(&'a Self, Self::Guard), RuntimeError> {
353        let string = value.into_ref::<String>()?;
354        let (string, guard) = Ref::into_raw(string);
355        Ok((string.as_ref().as_str(), guard))
356    }
357}
358
359impl UnsafeToMut for str {
360    type Guard = RawAnyGuard;
361
362    #[inline]
363    unsafe fn unsafe_to_mut<'a>(value: Value) -> Result<(&'a mut Self, Self::Guard), RuntimeError> {
364        let string = value.into_mut::<String>()?;
365        let (mut string, guard) = Mut::into_raw(string);
366        Ok((string.as_mut().as_mut_str(), guard))
367    }
368}
369
370impl<T, E> FromValue for Result<T, E>
371where
372    T: FromValue,
373    E: FromValue,
374{
375    #[inline]
376    fn from_value(value: Value) -> Result<Self, RuntimeError> {
377        Ok(match value.downcast::<Result<Value, Value>>()? {
378            Ok(ok) => Result::Ok(T::from_value(ok.clone())?),
379            Err(err) => Result::Err(E::from_value(err.clone())?),
380        })
381    }
382}
383
384impl FromValue for bool {
385    #[inline]
386    fn from_value(value: Value) -> Result<Self, RuntimeError> {
387        value.as_bool()
388    }
389}
390
391impl FromConstValue for bool {
392    #[inline]
393    fn from_const_value(value: ConstValue) -> Result<Self, RuntimeError> {
394        value.as_bool()
395    }
396}
397
398impl FromValue for char {
399    #[inline]
400    fn from_value(value: Value) -> Result<Self, RuntimeError> {
401        value.as_char()
402    }
403}
404
405impl FromConstValue for char {
406    #[inline]
407    fn from_const_value(value: ConstValue) -> Result<Self, RuntimeError> {
408        value.as_char()
409    }
410}
411
412macro_rules! impl_integer {
413    ($($ty:ty),* $(,)?) => {
414        $(
415            impl FromValue for $ty {
416                #[inline]
417                fn from_value(value: Value) -> Result<Self, RuntimeError> {
418                    value.as_integer()
419                }
420            }
421
422            impl FromConstValue for $ty {
423                #[inline]
424                fn from_const_value(value: ConstValue) -> Result<Self, RuntimeError> {
425                    value.as_integer()
426                }
427            }
428        )*
429    };
430}
431
432impl_integer!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
433
434impl FromValue for f64 {
435    #[inline]
436    fn from_value(value: Value) -> Result<Self, RuntimeError> {
437        value.as_float()
438    }
439}
440
441impl FromValue for f32 {
442    #[inline]
443    fn from_value(value: Value) -> Result<Self, RuntimeError> {
444        Ok(value.as_float()? as f32)
445    }
446}
447
448cfg_std! {
449    macro_rules! impl_map {
450        ($ty:ty, $key:ty) => {
451            impl<T> FromValue for $ty
452            where
453                T: FromValue,
454            {
455                fn from_value(value: Value) -> Result<Self, RuntimeError> {
456                    let object = value.downcast::<$crate::runtime::Object>()?;
457
458                    let mut output = <$ty>::with_capacity(object.len());
459
460                    for (key, value) in object {
461                        let key = <$key>::try_from(key)?;
462                        let value = <T>::from_value(value)?;
463                        output.insert(key, value);
464                    }
465
466                    Ok(output)
467                }
468            }
469        };
470    }
471
472    impl_map!(::std::collections::HashMap<String, T>, String);
473    impl_map!(::std::collections::HashMap<::rust_alloc::string::String, T>, ::rust_alloc::string::String);
474}
475
476macro_rules! impl_try_map {
477    ($ty:ty, $key:ty) => {
478        impl<T> FromValue for $ty
479        where
480            T: FromValue,
481        {
482            fn from_value(value: Value) -> Result<Self, RuntimeError> {
483                let object = value.downcast::<$crate::runtime::Object>()?;
484
485                let mut output = <$ty>::try_with_capacity(object.len())?;
486
487                for (key, value) in object {
488                    let key = <$key>::try_from(key)?;
489                    let value = <T>::from_value(value)?;
490                    output.try_insert(key, value)?;
491                }
492
493                Ok(output)
494            }
495        }
496    };
497}
498
499impl_try_map!(alloc::HashMap<String, T>, String);
500#[cfg(feature = "alloc")]
501impl_try_map!(alloc::HashMap<::rust_alloc::string::String, T>, ::rust_alloc::string::String);
502
503impl FromValue for Ordering {
504    #[inline]
505    fn from_value(value: Value) -> Result<Self, RuntimeError> {
506        value.as_ordering()
507    }
508}
509
510impl FromValue for Hash {
511    #[inline]
512    fn from_value(value: Value) -> Result<Self, RuntimeError> {
513        value.as_hash()
514    }
515}