1use super::object::{Any, ObjectRef};
2use crate::internal::error::Result;
3use crate::internal::{object, value};
4use crate::public::{Bind, Global, Unbind};
5
6decl_ref! {
7 struct Value(value::Value)
8}
9
10impl<'cx> Value<'cx> {
11 pub fn as_float(&self) -> Option<f64> {
12 self.inner.clone().to_float()
13 }
14
15 pub fn is_float(&self) -> bool {
16 self.inner.is_float()
17 }
18
19 pub fn as_int(&self) -> Option<i32> {
20 self.inner.clone().to_int()
21 }
22
23 pub fn is_int(&self) -> bool {
24 self.inner.is_int()
25 }
26
27 pub fn as_bool(&self) -> Option<bool> {
28 self.inner.clone().to_bool()
29 }
30
31 pub fn is_bool(&self) -> bool {
32 self.inner.is_bool()
33 }
34
35 pub fn as_none(&self) -> Option<()> {
36 self.inner.clone().to_none()
37 }
38
39 pub fn is_none(&self) -> bool {
40 self.inner.is_none()
41 }
42
43 pub fn as_object<T: ObjectRef<'cx>>(&self, global: Global<'cx>) -> Option<T> {
44 self.as_any().and_then(|v| Any::cast(v, global))
45 }
46
47 pub fn as_any(&self) -> Option<Any<'cx>> {
48 self.inner.clone().to_any().map(|v| {
49 unsafe { v.bind_raw::<'cx>() }
51 })
52 }
53
54 pub fn is_object(&self) -> bool {
55 self.inner.is_object()
56 }
57}
58
59pub trait FromValue<'cx>: Sized {
60 fn from_value(value: Value<'cx>, global: Global<'cx>) -> Result<Self>;
61}
62
63pub trait IntoValue<'cx>: Sized {
64 fn into_value(self, global: Global<'cx>) -> Result<Value<'cx>>;
65}
66
67impl<'cx> IntoValue<'cx> for Value<'cx> {
68 fn into_value(self, _: Global<'cx>) -> Result<Value<'cx>> {
69 Ok(self)
70 }
71}
72
73impl<'cx> FromValue<'cx> for Value<'cx> {
74 fn from_value(value: Value<'cx>, _: Global<'cx>) -> Result<Self> {
75 Ok(value)
76 }
77}
78
79impl<'cx> IntoValue<'cx> for i32 {
80 fn into_value(self, global: Global<'cx>) -> Result<Value<'cx>> {
81 Ok(value::Value::int(self).bind(global))
82 }
83}
84
85impl<'cx> FromValue<'cx> for i32 {
86 fn from_value(value: Value<'cx>, _: Global<'cx>) -> Result<Self> {
87 match value.as_int() {
88 Some(value) => Ok(value),
89 None => crate::fail!("value is not an int"),
90 }
91 }
92}
93
94impl<'cx> IntoValue<'cx> for f64 {
95 fn into_value(self, global: Global<'cx>) -> Result<Value<'cx>> {
96 Ok(value::Value::float(self).bind(global))
97 }
98}
99
100impl<'cx> FromValue<'cx> for f64 {
101 fn from_value(value: Value<'cx>, _: Global<'cx>) -> Result<Self> {
102 match value.as_float() {
103 Some(value) => Ok(value),
104 None => crate::fail!("value is not a float"),
105 }
106 }
107}
108
109impl<'cx> IntoValue<'cx> for bool {
110 fn into_value(self, global: Global<'cx>) -> Result<Value<'cx>> {
111 Ok(value::Value::bool(self).bind(global))
112 }
113}
114
115impl<'cx> FromValue<'cx> for bool {
116 fn from_value(value: Value<'cx>, _: Global<'cx>) -> Result<Self> {
117 match value.as_bool() {
118 Some(value) => Ok(value),
119 None => crate::fail!("value is not a bool"),
120 }
121 }
122}
123
124impl<'cx> IntoValue<'cx> for () {
125 fn into_value(self, global: Global<'cx>) -> Result<Value<'cx>> {
126 Ok(value::Value::none().bind(global))
127 }
128}
129
130impl<'cx> FromValue<'cx> for () {
131 fn from_value(value: Value<'cx>, global: Global<'cx>) -> Result<Self> {
132 let _ = (value, global);
133 Ok(())
134 }
135}
136
137impl<'cx, T> IntoValue<'cx> for Option<T>
138where
139 T: IntoValue<'cx>,
140{
141 fn into_value(self, global: Global<'cx>) -> Result<Value<'cx>> {
142 match self {
143 Some(value) => value.into_value(global),
144 None => Ok(value::Value::none().bind(global)),
145 }
146 }
147}
148
149impl<'cx, T> FromValue<'cx> for Option<T>
150where
151 T: FromValue<'cx>,
152{
153 fn from_value(value: Value<'cx>, global: Global<'cx>) -> Result<Self> {
154 if value.is_none() {
155 Ok(None)
156 } else {
157 T::from_value(value, global).map(Some)
158 }
159 }
160}
161
162impl<'cx, T> IntoValue<'cx> for Result<T>
163where
164 T: IntoValue<'cx>,
165{
166 fn into_value(self, global: Global<'cx>) -> Result<Value<'cx>> {
167 self?.into_value(global)
168 }
169}
170
171impl<'cx, T> IntoValue<'cx> for T
172where
173 T: ObjectRef<'cx>,
174{
175 fn into_value(self, global: Global<'cx>) -> Result<Value<'cx>> {
176 Ok(value::Value::object(self.as_any(global.clone()).unbind()).bind(global))
177 }
178}
179
180impl<'cx, T> FromValue<'cx> for T
181where
182 T: ObjectRef<'cx>,
183{
184 fn from_value(value: Value<'cx>, global: Global<'cx>) -> Result<Self> {
185 let object = value
186 .as_any()
187 .ok_or_else(|| error!("value is not an object"))?;
188 let object = T::from_any(object, global).ok_or_else(|| {
189 error!(
190 "value is not an instance of {}",
191 ::core::any::type_name::<T>()
192 )
193 })?;
194 Ok(object)
195 }
196}
197
198impl<'cx> FromValue<'cx> for String {
199 fn from_value(value: Value<'cx>, _: Global<'cx>) -> Result<Self> {
200 let Some(str) = value.unbind().to_object::<object::Str>() else {
201 fail!("value is not a string")
202 };
203 Ok(str.as_str().to_string())
204 }
205}
206
207impl<'cx> IntoValue<'cx> for String {
208 fn into_value(self, global: Global<'cx>) -> Result<Value<'cx>> {
209 global.new_string(self).into_value(global)
210 }
211}
212
213pub trait FromValuePack<'cx> {
214 type Output: Sized;
215 fn from_value_pack(args: &[value::Value], global: Global<'cx>) -> Result<Self::Output>;
216 fn len() -> usize;
217}
218
219impl<'cx> FromValuePack<'cx> for () {
220 type Output = ();
221
222 fn from_value_pack(args: &[value::Value], _: Global<'cx>) -> Result<Self::Output> {
223 #[allow(clippy::len_zero)]
224 if args.len() > 0 {
225 fail!("expected at most 0 args, got {}", args.len());
226 }
227 Ok(())
228 }
229
230 fn len() -> usize {
231 0
232 }
233}
234
235macro_rules! impl_from_value_pack {
236 ($($T:ident),*) => {
237 impl<'cx, $($T),*> FromValuePack<'cx> for ($($T,)*)
238 where
239 $(
240 $T: FromValue<'cx>,
241 )*
242 {
243 type Output = ($($T,)*);
244
245 #[allow(non_snake_case)]
246 fn from_value_pack(args: &[$crate::internal::value::Value], global: Global<'cx>) -> Result<Self::Output> {
247 let num_args = args.len();
248 let expected_num_args = Self::len();
249
250 if num_args > expected_num_args {
251 fail!("expected at most {expected_num_args} args, got {num_args}");
252 }
253 if num_args < expected_num_args {
254 fail!("expected at least {expected_num_args} args, got {num_args}");
255 }
256
257 let mut offset = 0;
258 $(
259 let $T = unsafe { args.get_unchecked(offset).clone() }.bind(global.clone());
260 let $T = <$T>::from_value($T, global.clone())?;
261 offset += 1;
262 )*
263 let _ = offset;
264
265 Ok(($($T,)*))
266 }
267
268 #[inline]
269 fn len() -> usize {
270 __count!($($T)*)
271 }
272 }
273 };
274}
275
276impl_from_value_pack!(A);
277impl_from_value_pack!(A, B);
278impl_from_value_pack!(A, B, C);
279impl_from_value_pack!(A, B, C, D);
280impl_from_value_pack!(A, B, C, D, E);
281impl_from_value_pack!(A, B, C, D, E, F);
282impl_from_value_pack!(A, B, C, D, E, F, G);
283impl_from_value_pack!(A, B, C, D, E, F, G, H);
284impl_from_value_pack!(A, B, C, D, E, F, G, H, I);
285impl_from_value_pack!(A, B, C, D, E, F, G, H, I, J);
286impl_from_value_pack!(A, B, C, D, E, F, G, H, I, J, K);
287impl_from_value_pack!(A, B, C, D, E, F, G, H, I, J, K, L);
288
289#[cfg(feature = "serde")]
290mod serde {
291 use ::serde::Serialize;
292
293 use super::*;
294
295 impl<'cx> Serialize for Value<'cx> {
296 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
297 where
298 S: ::serde::Serializer,
299 {
300 self.inner.serialize(serializer)
301 }
302 }
303}