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
100
101
102
103
104
105
106
107
108
use crate::{
get_exception, handle_exception, qjs, Coerced, Ctx, Error, FromJs, Result, StdString, String,
Value,
};
use std::{
mem::MaybeUninit,
ops::{Deref, DerefMut},
};
impl<T> AsRef<T> for Coerced<T> {
fn as_ref(&self) -> &T {
&self.0
}
}
impl<T> AsMut<T> for Coerced<T> {
fn as_mut(&mut self) -> &mut T {
&mut self.0
}
}
impl<T> Deref for Coerced<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for Coerced<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'js> FromJs<'js> for Coerced<String<'js>> {
fn from_js(ctx: Ctx<'js>, value: Value<'js>) -> Result<Self> {
Ok(Coerced(unsafe {
let result = qjs::JS_ToString(ctx.ctx, value.as_js_value());
handle_exception(ctx, result)?;
String::from_js_value(ctx, result)
}))
}
}
impl<'js> FromJs<'js> for Coerced<StdString> {
fn from_js(ctx: Ctx<'js>, value: Value<'js>) -> Result<Self> {
<Coerced<String>>::from_js(ctx, value)
.and_then(|string| string.to_string())
.map(Coerced)
}
}
macro_rules! coerce_impls {
($($(#[$meta:meta])* $type:ident $func:ident,)*) => {
$(
$(#[$meta])*
impl<'js> FromJs<'js> for Coerced<$type> {
fn from_js(ctx: Ctx<'js>, value: Value<'js>) -> Result<Self> {
let mut result = MaybeUninit::uninit();
Ok(Coerced(unsafe {
if 0 > qjs::$func(ctx.ctx, result.as_mut_ptr(), value.as_js_value()) {
let type_ = value.type_of();
let error = get_exception(ctx);
return Err(Error::new_from_js_message(type_.as_str(), stringify!($type), error.to_string()));
}
result.assume_init()
}))
}
}
)*
};
}
coerce_impls! {
i32 JS_ToInt32,
i64 JS_ToInt64,
u64 JS_ToIndex,
f64 JS_ToFloat64,
}
impl<'js> FromJs<'js> for Coerced<bool> {
fn from_js(ctx: Ctx<'js>, value: Value<'js>) -> Result<Self> {
Ok(Coerced(unsafe {
let res = qjs::JS_ToBool(ctx.ctx, value.as_js_value());
if 0 > res {
let type_ = value.type_of();
let error = get_exception(ctx);
return Err(Error::new_from_js_message(
type_.as_str(),
stringify!($type),
error.to_string(),
));
}
res == 1
}))
}
}