1use std::borrow::Cow;
8use std::ptr::NonNull;
9use std::rc::Rc;
10use std::time::SystemTime;
11
12use chrono::DateTime;
13use mozjs::jsapi::{
14 JS_GetFunctionObject, JS_IdToValue, JS_NewStringCopyN, JS_WrapValue, JSFunction, JSObject, JSString,
15 PropertyKey as JSPropertyKey, Symbol as JSSymbol,
16};
17use mozjs::jsval::{
18 BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, ObjectOrNullValue, ObjectValue, StringValue, SymbolValue,
19 UInt32Value, UndefinedValue,
20};
21use mozjs::rust::{maybe_wrap_object_or_null_value, maybe_wrap_object_value, maybe_wrap_value};
22use mozjs::typedarray as jsta;
23
24use crate::object::RegExp;
25use crate::string::byte::{BytePredicate, ByteStr, ByteString};
26use crate::typedarray::{ArrayBuffer, TypedArray, TypedArrayElement};
27use crate::{Array, Context, Date, Function, Object, Promise, PropertyKey, Symbol, Value};
28
29pub trait ToValue<'cx> {
31 fn to_value(&self, cx: &'cx Context, value: &mut Value);
33
34 fn as_value(&self, cx: &'cx Context) -> Value<'cx> {
36 let mut value = Value::undefined(cx);
37 self.to_value(cx, &mut value);
38 value
39 }
40}
41
42impl ToValue<'_> for () {
43 fn to_value(&self, _: &Context, value: &mut Value) {
44 value.handle_mut().set(UndefinedValue());
45 }
46}
47
48impl ToValue<'_> for bool {
49 fn to_value(&self, _: &Context, value: &mut Value) {
50 value.handle_mut().set(BooleanValue(*self));
51 }
52}
53
54macro_rules! impl_to_value_for_integer {
55 ($ty:ty, signed) => {
56 impl ToValue<'_> for $ty {
57 fn to_value(&self, _: &Context, value: &mut Value) {
58 value.handle_mut().set(Int32Value(i32::from(*self)));
59 }
60 }
61 };
62 ($ty:ty, unsigned) => {
63 impl ToValue<'_> for $ty {
64 fn to_value(&self, _: &Context, value: &mut Value) {
65 value.handle_mut().set(UInt32Value(u32::from(*self)));
66 }
67 }
68 };
69}
70
71impl_to_value_for_integer!(i8, signed);
72impl_to_value_for_integer!(i16, signed);
73impl_to_value_for_integer!(i32, signed);
74
75impl_to_value_for_integer!(u8, unsigned);
76impl_to_value_for_integer!(u16, unsigned);
77impl_to_value_for_integer!(u32, unsigned);
78
79macro_rules! impl_to_value_as_double {
80 ($ty:ty, int) => {
81 impl ToValue<'_> for $ty {
82 fn to_value(&self, _: &Context, value: &mut Value) {
83 value.handle_mut().set(DoubleValue(*self as f64));
84 }
85 }
86 };
87 ($ty:ty, float) => {
88 impl ToValue<'_> for $ty {
89 fn to_value(&self, _: &Context, value: &mut Value) {
90 value.handle_mut().set(DoubleValue(f64::from(*self)));
91 }
92 }
93 };
94}
95
96impl_to_value_as_double!(i64, int);
97impl_to_value_as_double!(u64, int);
98impl_to_value_as_double!(f32, float);
99impl_to_value_as_double!(f64, float);
100
101impl ToValue<'_> for *mut JSString {
102 fn to_value(&self, cx: &Context, value: &mut Value) {
103 value.handle_mut().set(StringValue(unsafe { &**self }));
104 unsafe {
105 JS_WrapValue(cx.as_ptr(), value.handle_mut().into());
106 }
107 }
108}
109
110impl<'cx> ToValue<'cx> for crate::String<'cx> {
111 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
112 self.handle().to_value(cx, value);
113 }
114}
115
116impl ToValue<'_> for str {
117 fn to_value(&self, cx: &Context, value: &mut Value) {
118 let string = crate::String::copy_from_str(cx, self);
119 if let Some(string) = string {
120 string.to_value(cx, value);
121 } else {
122 panic!("Failed to Instantiate String");
123 }
124 }
125}
126
127impl<'cx> ToValue<'cx> for String {
128 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
129 (**self).to_value(cx, value);
130 }
131}
132
133impl<'cx, T: ToOwned + ToValue<'cx>> ToValue<'cx> for Cow<'_, T> {
134 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
135 self.as_ref().to_value(cx, value);
136 }
137}
138
139impl<'cx, T: BytePredicate> ToValue<'cx> for ByteStr<T> {
140 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
141 unsafe { JS_NewStringCopyN(cx.as_ptr(), self.as_ptr().cast(), self.len()).to_value(cx, value) };
142 }
143}
144
145impl<'cx, T: BytePredicate> ToValue<'cx> for ByteString<T> {
146 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
147 (**self).to_value(cx, value);
148 }
149}
150
151impl ToValue<'_> for *mut JSObject {
152 fn to_value(&self, cx: &Context, value: &mut Value) {
153 value.handle_mut().set(ObjectOrNullValue(*self));
154 unsafe {
155 maybe_wrap_object_or_null_value(cx.as_ptr(), value.handle_mut());
156 }
157 }
158}
159
160impl ToValue<'_> for NonNull<JSObject> {
161 fn to_value(&self, cx: &Context, value: &mut Value) {
162 value.handle_mut().set(ObjectValue(self.as_ptr()));
163 unsafe {
164 maybe_wrap_object_value(cx.as_ptr(), value.handle_mut());
165 }
166 }
167}
168
169impl<'cx> ToValue<'cx> for Object<'cx> {
170 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
171 self.handle().to_value(cx, value);
172 }
173}
174
175impl<'cx> ToValue<'cx> for Array<'cx> {
176 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
177 self.handle().to_value(cx, value);
178 }
179}
180
181impl<'cx> ToValue<'cx> for Date<'cx> {
182 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
183 self.handle().to_value(cx, value);
184 }
185}
186
187impl ToValue<'_> for SystemTime {
188 fn to_value(&self, cx: &Context, value: &mut Value) {
189 Date::from_date(cx, DateTime::from(*self)).to_value(cx, value);
190 }
191}
192
193impl<'cx> ToValue<'cx> for Promise<'cx> {
194 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
195 self.handle().to_value(cx, value);
196 }
197}
198
199impl<'cx> ToValue<'cx> for RegExp<'cx> {
200 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
201 self.handle().to_value(cx, value);
202 }
203}
204
205impl<T: jsta::TypedArrayElement, S: jsta::JSObjectStorage> ToValue<'_> for jsta::TypedArray<T, S> {
206 fn to_value(&self, cx: &Context, value: &mut Value) {
207 unsafe { self.underlying_object().as_raw().to_value(cx, value) }
208 }
209}
210
211impl<'cx> ToValue<'cx> for ArrayBuffer<'cx> {
212 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
213 self.handle().to_value(cx, value);
214 }
215}
216
217impl<'cx, T: TypedArrayElement> ToValue<'cx> for TypedArray<'cx, T> {
218 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
219 self.handle().to_value(cx, value);
220 }
221}
222
223impl<'cx> ToValue<'cx> for *mut JSFunction {
224 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
225 unsafe { JS_GetFunctionObject(*self) }.to_value(cx, value);
226 }
227}
228
229impl<'cx> ToValue<'cx> for Function<'cx> {
230 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
231 self.handle().to_value(cx, value);
232 }
233}
234
235impl ToValue<'_> for *mut JSSymbol {
236 fn to_value(&self, _: &Context, value: &mut Value) {
237 value.handle_mut().set(SymbolValue(unsafe { &**self }));
238 }
239}
240
241impl<'cx> ToValue<'cx> for Symbol<'cx> {
242 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
243 self.handle().to_value(cx, value);
244 }
245}
246
247impl ToValue<'_> for JSVal {
248 fn to_value(&self, cx: &Context, value: &mut Value) {
249 value.handle_mut().set(*self);
250 unsafe {
251 maybe_wrap_value(cx.as_ptr(), value.handle_mut());
252 }
253 }
254}
255
256impl<'cx> ToValue<'cx> for Value<'cx> {
257 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
258 self.handle().to_value(cx, value);
259 }
260}
261
262impl<'cx> ToValue<'cx> for JSPropertyKey {
263 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
264 unsafe {
265 JS_IdToValue(cx.as_ptr(), *self, value.handle_mut().into());
266 }
267 }
268}
269
270impl<'cx> ToValue<'cx> for PropertyKey<'cx> {
271 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
272 self.handle().to_value(cx, value);
273 }
274}
275
276impl<'cx, T: ToValue<'cx> + ?Sized> ToValue<'cx> for &'_ T {
277 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
278 (*self).to_value(cx, value);
279 }
280}
281
282impl<'cx, T: ToValue<'cx> + ?Sized> ToValue<'cx> for Box<T> {
283 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
284 (**self).to_value(cx, value);
285 }
286}
287
288impl<'cx, T: ToValue<'cx> + ?Sized> ToValue<'cx> for Rc<T> {
289 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
290 (**self).to_value(cx, value);
291 }
292}
293
294impl<'cx, T: ToValue<'cx>> ToValue<'cx> for Option<T> {
295 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
296 match self {
297 Some(t) => t.to_value(cx, value),
298 None => value.handle_mut().set(NullValue()),
299 }
300 }
301}
302
303impl<'cx, T: ToValue<'cx>> ToValue<'cx> for [T] {
304 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
305 let array = Array::new_with_length(cx, self.len());
306
307 for (i, t) in self.iter().enumerate() {
308 assert!(array.set_as(cx, i as u32, t));
309 }
310
311 array.to_value(cx, value);
312 }
313}
314
315impl<'cx, const N: usize, T: ToValue<'cx>> ToValue<'cx> for [T; N] {
316 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
317 <[T]>::to_value(self, cx, value);
318 }
319}
320
321impl<'cx, T: ToValue<'cx>> ToValue<'cx> for Vec<T> {
322 fn to_value(&self, cx: &'cx Context, value: &mut Value) {
323 (**self).to_value(cx, value);
324 }
325}