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