1#![no_std]
2extern crate alloc;
3
4pub mod env;
5use crate::env::*;
6use core::ffi::CStr;
7use alloc::string::String;
8use alloc::string::ToString;
9use alloc::boxed::Box;
10use alloc::vec::Vec;
11use alloc::format;
12
13#[repr(u32)]
14pub enum EmlitePredefHandles {
15 Null = 0,
16 Undefined,
17 False,
18 True,
19 GlobalThis,
20 Console,
21 Reserved,
22}
23
24#[macro_export]
26macro_rules! eval {
27 ($src: literal) => {{
28 $crate::Val::global("eval").invoke(&[$crate::Val::from($src)])
29 }};
30 ($src: literal $(, $arg:expr)* $(,)?) => {{
31 $crate::Val::global("eval").invoke(
32 &[$crate::Val::from(&format!($src, $( $arg ),*)) ]
33 )
34 }};
35}
36
37#[macro_export]
39macro_rules! argv {
40 ($($rest:expr),*) => {{
41 [$($crate::Val::from($rest)),*]
42 }};
43}
44
45#[derive(Debug)]
47pub struct Val {
48 inner: Handle,
49}
50
51impl Val {
52 pub const fn global_this() -> Val {
54 Val { inner: EmlitePredefHandles::GlobalThis as _ }
55 }
56
57 pub fn get<T: Into<Val>>(&self, prop: T) -> Val {
59 let h = unsafe { emlite_val_get(self.as_handle(), prop.into().as_handle()) };
60 Val::take_ownership(h)
61 }
62
63 pub fn global(name: &str) -> Val {
65 Val::global_this().get(name)
66 }
67
68 pub const fn null() -> Val {
70 Val { inner: EmlitePredefHandles::Null as _ }
71 }
72
73 pub const fn undefined() -> Val {
75 Val { inner: EmlitePredefHandles::Undefined as _ }
76 }
77
78 pub fn object() -> Val {
80 Val::take_ownership(unsafe { emlite_val_new_object() })
81 }
82
83 pub fn array() -> Val {
85 Val::take_ownership(unsafe { emlite_val_new_array() })
86 }
87
88 pub fn set<K: Into<Val>, V: Into<Val>>(&self, prop: K, val: V) {
90 unsafe {
91 emlite_val_set(
92 self.as_handle(),
93 prop.into().as_handle(),
94 val.into().as_handle(),
95 )
96 };
97 }
98
99 pub fn has<T: Into<Val>>(&self, prop: T) -> bool {
101 unsafe { emlite_val_has(self.as_handle(), prop.into().as_handle()) }
102 }
103
104 pub fn has_own_property(&self, prop: &str) -> bool {
106 unsafe { emlite_val_obj_has_own_prop(self.as_handle(), prop.as_ptr() as _, prop.len()) }
107 }
108
109 pub fn type_of(&self) -> String {
111 unsafe {
112 let ptr = emlite_val_typeof(self.as_handle());
113 String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).to_string()
114 }
115 }
116
117 pub fn at<T: Into<Val>>(&self, idx: T) -> Val {
119 Val::take_ownership(unsafe { emlite_val_get(self.as_handle(), idx.into().as_handle()) })
120 }
121
122 pub fn to_vec<V: FromVal>(&self) -> Vec<V> {
124 let len = self.get("length").as_::<usize>();
125 let mut v: Vec<V> = Vec::with_capacity(len);
126 for i in 0..len {
127 v.push(self.at::<i32>(i as _).as_::<V>());
128 }
129 v
130 }
131
132 pub fn call(&self, f: &str, args: &[Val]) -> Val {
134 unsafe {
135 let arr = Val::take_ownership(emlite_val_new_array());
136 for arg in args {
137 emlite_val_push(arr.as_handle(), arg.as_handle());
138 }
139 Val::take_ownership(emlite_val_obj_call(
140 self.as_handle(),
141 f.as_ptr() as _,
142 f.len(),
143 arr.as_handle(),
144 ))
145 }
146 }
147
148 pub fn new(&self, args: &[Val]) -> Val {
150 unsafe {
151 let arr = Val::take_ownership(emlite_val_new_array());
152 for arg in args {
153 emlite_val_push(arr.as_handle(), arg.as_handle());
154 }
155 Val::take_ownership(emlite_val_construct_new(self.as_handle(), arr.as_handle()))
156 }
157 }
158
159 pub fn invoke(&self, args: &[Val]) -> Val {
161 unsafe {
162 let arr = Val::take_ownership(emlite_val_new_array());
163 for arg in args {
164 emlite_val_push(arr.as_handle(), arg.as_handle());
165 }
166 Val::take_ownership(emlite_val_func_call(self.as_handle(), arr.as_handle()))
167 }
168 }
169
170 pub fn make_fn_raw(f: fn(Handle, Handle) -> Handle, data: Handle) -> Val {
172 let idx: u32 = f as usize as u32;
173 unsafe { Val::take_ownership(emlite_val_make_callback(idx, data)) }
174 }
175
176 pub fn make_fn<F: FnMut(&[Val]) -> Val>(cb: F) -> Val {
178 fn shim(args: Handle, data: Handle) -> Handle {
179 let v = Val::take_ownership(args);
180 let vals: Vec<Val> = v.to_vec();
181 let func0 = Val::take_ownership(data);
182 let a = func0.as_::<i32>() as usize as *mut Box<dyn FnMut(&[Val]) -> Val>;
183 let f: &mut (dyn FnMut(&[Val]) -> Val) = unsafe { &mut **a };
184 core::mem::forget(func0);
185 f(&vals).as_handle()
186 }
187 #[allow(clippy::type_complexity)]
188 let a: *mut Box<dyn FnMut(&[Val]) -> Val> = Box::into_raw(Box::new(Box::new(cb)));
189 let data = Val::from(a as Handle);
190 unsafe {
191 emlite_val_inc_ref(data.as_handle());
192 }
193 Self::make_fn_raw(shim, data.as_handle())
194 }
195
196 pub fn await_(&self) -> Val {
198 eval!(
199 r#"
200 (async () => {{
201 let obj = EMLITE_VALMAP.toValue({});
202 let ret = await obj;
203 return EMLITE_VALMAP.toHandle(ret);
204 }})()
205 "#,
206 self.as_handle()
207 )
208 }
209
210 pub fn delete(v: Val) {
212 unsafe {
213 emlite_val_dec_ref(v.as_handle());
214 }
215 }
216
217 pub fn throw(v: Val) -> ! {
219 unsafe {
220 emlite_val_throw(v.as_handle());
221 }
222 }
223
224 pub fn instanceof(&self, v: Val) -> bool {
226 unsafe { emlite_val_instanceof(self.as_handle(), v.as_handle()) }
227 }
228
229 pub fn is_number(&self) -> bool {
230 unsafe { emlite_val_is_number(self.as_handle()) }
231 }
232
233 pub fn is_string(&self) -> bool {
234 unsafe { emlite_val_is_string(self.as_handle()) }
235 }
236
237 pub fn is_null(&self) -> bool {
238 self.as_handle() == EmlitePredefHandles::Null as u32
239 }
240
241 pub fn is_undefined(&self) -> bool {
242 self.as_handle() == EmlitePredefHandles::Undefined as u32
243 }
244
245 pub fn is_error(&self) -> bool {
246 self.instanceof(Val::global("Error"))
247 }
248
249 pub fn is_function(&self) -> bool {
250 self.instanceof(Val::global("Function"))
251 }
252
253 #[inline(always)]
254 pub fn as_<T>(&self) -> T
255 where
256 T: FromVal,
257 {
258 T::from_val(self)
259 }
260}
261
262impl From<bool> for Val {
263 fn from(v: bool) -> Self {
264 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
265 }
266}
267
268impl From<i8> for Val {
269 fn from(v: i8) -> Self {
270 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
271 }
272}
273
274impl From<u8> for Val {
275 fn from(v: u8) -> Self {
276 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
277 }
278}
279
280impl From<i16> for Val {
281 fn from(v: i16) -> Self {
282 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
283 }
284}
285
286impl From<u16> for Val {
287 fn from(v: u16) -> Self {
288 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
289 }
290}
291
292impl From<i32> for Val {
293 fn from(v: i32) -> Self {
294 Val::take_ownership(unsafe { emlite_val_make_int(v) })
295 }
296}
297
298impl From<u32> for Val {
299 fn from(v: u32) -> Self {
300 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
301 }
302}
303
304impl From<i64> for Val {
305 fn from(v: i64) -> Self {
306 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
307 }
308}
309
310impl From<u64> for Val {
311 fn from(v: u64) -> Self {
312 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
313 }
314}
315
316impl From<usize> for Val {
317 fn from(v: usize) -> Self {
318 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
319 }
320}
321
322impl From<isize> for Val {
323 fn from(v: isize) -> Self {
324 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
325 }
326}
327
328impl From<f32> for Val {
329 fn from(v: f32) -> Self {
330 Val::take_ownership(unsafe { emlite_val_make_double(v as _) })
331 }
332}
333
334impl From<f64> for Val {
335 fn from(v: f64) -> Self {
336 Val::take_ownership(unsafe { emlite_val_make_double(v) })
337 }
338}
339
340impl From<()> for Val {
341 fn from(_: ()) -> Self {
342 Val::undefined()
343 }
344}
345
346impl From<&str> for Val {
347 fn from(s: &str) -> Self {
348 Val::take_ownership(unsafe { emlite_val_make_str(s.as_ptr() as _, s.len()) })
349 }
350}
351
352impl From<String> for Val {
353 fn from(s: String) -> Self {
354 Val::take_ownership(unsafe { emlite_val_make_str(s.as_ptr() as _, s.len()) })
355 }
356}
357
358impl From<&String> for Val {
359 fn from(s: &String) -> Self {
360 Val::take_ownership(unsafe { emlite_val_make_str(s.as_ptr() as _, s.len()) })
361 }
362}
363
364impl From<&Val> for Val {
365 fn from(v: &Val) -> Self {
366 v.clone()
367 }
368}
369
370impl Drop for Val {
371 fn drop(&mut self) {
372 unsafe { emlite_val_dec_ref(self.as_handle()) }
373 }
374}
375
376impl Clone for Val {
377 fn clone(&self) -> Val {
378 unsafe {
379 emlite_val_inc_ref(self.as_handle());
380 }
381 Val::take_ownership(self.as_handle())
382 }
383}
384
385use core::ops::{Deref, DerefMut};
386
387#[derive(Clone, Debug)]
389pub struct Console {
390 val: Val,
391}
392
393impl Console {
394 pub const fn get() -> Console {
396 Console {
397 val: Val {
398 inner: EmlitePredefHandles::Console as _,
399 },
400 }
401 }
402
403 pub fn log(&self, args: &[Val]) {
405 self.val.call("log", args);
406 }
407
408 pub fn warn(&self, args: &[Val]) {
410 self.val.call("warn", args);
411 }
412
413 pub fn info(&self, args: &[Val]) {
415 self.val.call("info", args);
416 }
417
418 pub fn as_handle(&self) -> Handle {
420 self.val.as_handle()
421 }
422}
423
424impl Deref for Console {
425 type Target = Val;
426
427 fn deref(&self) -> &Self::Target {
428 &self.val
429 }
430}
431
432impl DerefMut for Console {
433 fn deref_mut(&mut self) -> &mut Self::Target {
434 &mut self.val
435 }
436}
437
438impl From<Console> for Val {
439 fn from(val: Console) -> Self {
440 Val::take_ownership(val.inner)
441 }
442}
443
444use core::cmp::Ordering;
445use core::ops::Not;
446
447impl PartialEq for Val {
448 fn eq(&self, other: &Val) -> bool {
449 unsafe { emlite_val_strictly_equals(self.as_handle(), other.as_handle()) }
450 }
451}
452
453impl PartialOrd for Val {
454 fn partial_cmp(&self, other: &Val) -> Option<Ordering> {
455 unsafe {
456 if emlite_val_strictly_equals(self.as_handle(), other.as_handle()) {
457 Some(Ordering::Equal)
458 } else if emlite_val_gt(self.as_handle(), other.as_handle()) {
459 Some(Ordering::Greater)
460 } else if emlite_val_lt(self.as_handle(), other.as_handle()) {
461 Some(Ordering::Less)
462 } else {
463 None
464 }
465 }
466 }
467}
468
469impl Not for Val {
470 type Output = bool;
471
472 fn not(self) -> Self::Output {
473 unsafe { emlite_val_not(self.as_handle()) }
474 }
475}
476
477impl AsRef<Val> for Val {
478 #[inline]
479 fn as_ref(&self) -> &Val { self }
480}
481
482pub trait FromVal: Sized {
483 fn from_val(v: &Val) -> Self;
485 fn take_ownership(v: Handle) -> Self;
487 fn as_handle(&self) -> Handle;
489}
490
491impl FromVal for Val {
492 fn from_val(v: &Val) -> Self {
493 unsafe {
494 emlite_val_inc_ref(v.inner);
495 }
496 Val {
497 inner: v.as_handle(),
498 }
499 }
500 fn take_ownership(v: Handle) -> Self {
501 Val { inner: v }
502 }
503 #[inline(always)]
504 fn as_handle(&self) -> Handle {
505 self.inner
506 }
507}
508
509impl FromVal for bool {
510 fn from_val(v: &Val) -> Self {
511 unsafe {
512 !env::emlite_val_not(v.as_handle())
513 }
514 }
515 fn take_ownership(v: Handle) -> Self {
516 Self::from_val(&Val::take_ownership(v))
517 }
518 fn as_handle(&self) -> Handle {
519 if *self { EmlitePredefHandles::False as u32 } else { EmlitePredefHandles::True as u32 }
520 }
521}
522
523macro_rules! impl_int {
524 ($($t:ty),*) => {$(
525 impl FromVal for $t {
526 fn from_val(v: &Val) -> Self {
527 unsafe {
528 emlite_val_get_value_int(v.as_handle()) as Self
529 }
530 }
531 fn take_ownership(v: Handle) -> Self {
532 unsafe { emlite_val_get_value_int(v) as Self }
533 }
534 fn as_handle(&self) -> Handle {
535 0
536 }
537 }
538 )*}
539}
540
541impl_int!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
542
543macro_rules! impl_float {
544 ($($t:ty),*) => {$(
545 impl FromVal for $t {
546 fn from_val(v: &Val) -> Self {
547 unsafe { emlite_val_get_value_double(v.as_handle()) as Self }
548 }
549 fn take_ownership(v: Handle) -> Self {
550 unsafe { emlite_val_get_value_double(v) as Self }
551 }
552 fn as_handle(&self) -> Handle {
553 0
554 }
555 }
556 )*}
557}
558
559impl_float!(f32, f64);
560
561impl FromVal for String {
562 fn from_val(v: &Val) -> Self {
563 unsafe {
564 let ptr = emlite_val_get_value_string(v.as_handle());
565 CStr::from_ptr(ptr).to_string_lossy().into_owned()
566 }
567 }
568 fn take_ownership(v: Handle) -> Self {
569 unsafe {
570 let ptr = emlite_val_get_value_string(v);
571 CStr::from_ptr(ptr).to_string_lossy().into_owned()
572 }
573 }
574 fn as_handle(&self) -> Handle {
575 0
576 }
577}
578
579
580impl FromVal for &str {
581 fn from_val(v: &Val) -> Self {
582 unsafe {
583 let ptr = emlite_val_get_value_string(v.as_handle());
584 CStr::from_ptr(ptr).to_str().unwrap()
585 }
586 }
587 fn take_ownership(v: Handle) -> Self {
588 unsafe {
589 let ptr = emlite_val_get_value_string(v);
590 CStr::from_ptr(ptr).to_str().unwrap()
591 }
592 }
593 fn as_handle(&self) -> Handle {
594 0
595 }
596}