rquickjs_core/value/convert.rs
1//! Utilities for converting to and from JavaScript values.
2
3use crate::{Atom, Ctx, Result, Value};
4
5mod atom;
6mod coerce;
7mod from;
8mod into;
9
10/// The wrapper for values to force coercion
11///
12/// ```
13/// # use rquickjs::{Runtime, Context, Result, convert::Coerced};
14/// # let rt = Runtime::new().unwrap();
15/// # let ctx = Context::full(&rt).unwrap();
16/// # ctx.with(|ctx| -> Result<()> {
17/// #
18/// // Coercion to string
19/// assert_eq!(ctx.eval::<Coerced<String>, _>("`abc`")?.0, "abc");
20/// assert_eq!(ctx.eval::<Coerced<String>, _>("123")?.0, "123");
21/// assert_eq!(ctx.eval::<Coerced<String>, _>("[1,'a']")?.0, "1,a");
22/// assert_eq!(ctx.eval::<Coerced<String>, _>("({})")?.0, "[object Object]");
23///
24/// // Coercion to integer
25/// assert!(ctx.eval::<i32, _>("`123`").is_err());
26/// assert_eq!(ctx.eval::<Coerced<i32>, _>("`123`")?.0, 123);
27///
28/// // Coercion to floating-point
29/// assert_eq!(ctx.eval::<f64, _>("123")?, 123.0);
30/// assert_eq!(ctx.eval::<Coerced<f64>, _>("123")?.0, 123.0);
31///
32/// assert!(ctx.eval::<f64, _>("`123.5`").is_err());
33/// assert_eq!(ctx.eval::<Coerced<f64>, _>("`123.5`")?.0, 123.5);
34/// #
35/// # Ok(())
36/// # }).unwrap();
37/// ```
38#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
39#[repr(transparent)]
40pub struct Coerced<T>(pub T);
41
42/// For converting JavaScript values to Rust values
43///
44/// This trait automatically converts any value which can be
45/// represented as an object, like [`Array`](crate::Array)
46/// to one if it is required.
47pub trait FromJs<'js>: Sized {
48 fn from_js(ctx: &Ctx<'js>, value: Value<'js>) -> Result<Self>;
49}
50
51/// Trait for converting values from atoms.
52pub trait FromAtom<'js>: Sized {
53 fn from_atom(atom: Atom<'js>) -> Result<Self>;
54}
55
56/// The Rust's [`FromIterator`](std::iter::FromIterator) trait to use with [`Ctx`]
57pub trait FromIteratorJs<'js, A>: Sized {
58 type Item;
59
60 fn from_iter_js<T>(ctx: &Ctx<'js>, iter: T) -> Result<Self>
61 where
62 T: IntoIterator<Item = A>;
63}
64
65/// For converting Rust values to JavaScript values
66pub trait IntoJs<'js> {
67 fn into_js(self, ctx: &Ctx<'js>) -> Result<Value<'js>>;
68}
69
70/// Trait for converting values to atoms.
71pub trait IntoAtom<'js> {
72 fn into_atom(self, ctx: &Ctx<'js>) -> Result<Atom<'js>>;
73}
74
75/// The Rust's [`Iterator`] trait extension which works with [`Ctx`]
76pub trait IteratorJs<'js, A> {
77 fn collect_js<B>(self, ctx: &Ctx<'js>) -> Result<B>
78 where
79 B: FromIteratorJs<'js, A>;
80}
81
82impl<'js, T, A> IteratorJs<'js, A> for T
83where
84 T: Iterator<Item = A>,
85{
86 fn collect_js<B>(self, ctx: &Ctx<'js>) -> Result<B>
87 where
88 B: FromIteratorJs<'js, A>,
89 {
90 B::from_iter_js(ctx, self)
91 }
92}
93
94/// A helper type for turning a tuple into a JavaScript array.
95/// Implements [`IntoJs`] and [`FromJs`] for tuples of various lengths
96pub struct List<T>(pub T);