emlite/
lib.rs

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/// Runs JS eval
25#[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/// A helper macro which packs values into a slice of Val
38#[macro_export]
39macro_rules! argv {
40    ($($rest:expr),*) => {{
41        [$($crate::Val::from($rest)),*]
42    }};
43}
44
45pub fn init() {
46    unsafe {
47        emlite_init_handle_table();
48    }
49}
50
51/// A wrapper around a javascript handle
52#[derive(Debug)]
53pub struct Val {
54    inner: Handle,
55}
56
57impl Val {
58    /// Returns the globalThis object
59    pub const fn global_this() -> Val {
60        Val { inner: EmlitePredefHandles::GlobalThis as _ }
61    }
62
63    /// Gets the property `prop`
64    pub fn get<T: Into<Val>>(&self, prop: T) -> Val {
65        let h = unsafe { emlite_val_get(self.as_handle(), prop.into().as_handle()) };
66        Val::take_ownership(h)
67    }
68
69    /// Gets a global object by `name`
70    pub fn global(name: &str) -> Val {
71        Val::global_this().get(name)
72    }
73
74    /// Gets a js null Val
75    pub const fn null() -> Val {
76        Val { inner: EmlitePredefHandles::Null as _ }
77    }
78
79    /// Gets a js undefined Val
80    pub const fn undefined() -> Val {
81        Val { inner: EmlitePredefHandles::Undefined as _ }
82    }
83
84    /// Gets a new js object
85    pub fn object() -> Val {
86        Val::take_ownership(unsafe { emlite_val_new_object() })
87    }
88
89    /// Gets a new js array
90    pub fn array() -> Val {
91        Val::take_ownership(unsafe { emlite_val_new_array() })
92    }
93
94    /// Set the underlying js object property `prop` to `val`
95    pub fn set<K: Into<Val>, V: Into<Val>>(&self, prop: K, val: V) {
96        unsafe {
97            emlite_val_set(
98                self.as_handle(),
99                prop.into().as_handle(),
100                val.into().as_handle(),
101            )
102        };
103    }
104
105    /// Checks whether a property `prop` exists
106    pub fn has<T: Into<Val>>(&self, prop: T) -> bool {
107        unsafe { emlite_val_has(self.as_handle(), prop.into().as_handle()) }
108    }
109
110    /// Checks whether a non-inherited property `prop` exists
111    pub fn has_own_property(&self, prop: &str) -> bool {
112        unsafe { emlite_val_obj_has_own_prop(self.as_handle(), prop.as_ptr() as _, prop.len()) }
113    }
114
115    /// Gets the typeof the underlying js object
116    pub fn type_of(&self) -> String {
117        unsafe {
118            let ptr = emlite_val_typeof(self.as_handle());
119            if ptr.is_null() {
120                String::from("undefined")
121            } else {
122                String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).to_string()
123            }
124        }
125    }
126
127    /// Gets the element at index `idx`. Assumes the underlying js type is indexable
128    pub fn at<T: Into<Val>>(&self, idx: T) -> Val {
129        Val::take_ownership(unsafe { emlite_val_get(self.as_handle(), idx.into().as_handle()) })
130    }
131
132    /// Converts the underlying js array to a Vec of V
133    pub fn to_vec<V: FromVal>(&self) -> Vec<V> {
134        let len = self.get("length").as_::<usize>();
135        let mut v: Vec<V> = Vec::with_capacity(len);
136        for i in 0..len {
137            v.push(self.at::<i32>(i as _).as_::<V>());
138        }
139        v
140    }
141
142    /// Calls the method `f` with `args`, can return an undefined js value
143    pub fn call(&self, f: &str, args: &[Val]) -> Val {
144        unsafe {
145            let arr = Val::take_ownership(emlite_val_new_array());
146            for arg in args {
147                emlite_val_push(arr.as_handle(), arg.as_handle());
148            }
149            Val::take_ownership(emlite_val_obj_call(
150                self.as_handle(),
151                f.as_ptr() as _,
152                f.len(),
153                arr.as_handle(),
154            ))
155        }
156    }
157
158    /// Calls the object's constructor with `args` constructing a new object
159    pub fn new(&self, args: &[Val]) -> Val {
160        unsafe {
161            let arr = Val::take_ownership(emlite_val_new_array());
162            for arg in args {
163                emlite_val_push(arr.as_handle(), arg.as_handle());
164            }
165            Val::take_ownership(emlite_val_construct_new(self.as_handle(), arr.as_handle()))
166        }
167    }
168
169    /// Invokes the function object with `args`, can return an undefined js value
170    pub fn invoke(&self, args: &[Val]) -> Val {
171        unsafe {
172            let arr = Val::take_ownership(emlite_val_new_array());
173            for arg in args {
174                emlite_val_push(arr.as_handle(), arg.as_handle());
175            }
176            Val::take_ownership(emlite_val_func_call(self.as_handle(), arr.as_handle()))
177        }
178    }
179
180    /// Creates js function from a function pointer and returns its handle wrapped in a Val object
181    pub fn make_fn_raw(f: fn(Handle, Handle) -> Handle, data: Handle) -> Val {
182        let idx: u32 = f as usize as u32;
183        unsafe { Val::take_ownership(emlite_val_make_callback(idx, data)) }
184    }
185
186    /// Creates a js function from a Rust closure and returns a Val
187    pub fn make_fn<F: FnMut(&[Val]) -> Val>(cb: F) -> Val {
188        fn shim(args: Handle, data: Handle) -> Handle {
189            let v = Val::take_ownership(args);
190            let vals: Vec<Val> = v.to_vec();
191            let func0 = Val::take_ownership(data);
192            let a = func0.as_::<i32>() as usize as *mut Box<dyn FnMut(&[Val]) -> Val>;
193            let f: &mut (dyn FnMut(&[Val]) -> Val) = unsafe { &mut **a };
194            core::mem::forget(func0);
195            f(&vals).as_handle()
196        }
197        #[allow(clippy::type_complexity)]
198        let a: *mut Box<dyn FnMut(&[Val]) -> Val> = Box::into_raw(Box::new(Box::new(cb)));
199        let data = Val::from(a as Handle);
200        unsafe {
201            emlite_val_inc_ref(data.as_handle());
202        }
203        Self::make_fn_raw(shim, data.as_handle())
204    }
205
206    /// Awaits the invoked function object
207    pub fn await_(&self) -> Val {
208        eval!(
209            r#"
210            (async () => {{
211                let obj = EMLITE_VALMAP.toValue({});
212                let ret = await obj;
213                return EMLITE_VALMAP.toHandle(ret);
214            }})()
215        "#,
216            self.as_handle()
217        )
218    }
219
220    /// Decrements the refcount of the underlying handle
221    pub fn delete(v: Val) {
222        unsafe {
223            emlite_val_dec_ref(v.as_handle());
224        }
225    }
226
227    /// Throws a js object represented by Val
228    pub fn throw(v: Val) -> ! {
229        unsafe {
230            emlite_val_throw(v.as_handle());
231        }
232    }
233
234    /// Checks whether this Val is an instanceof `v`
235    pub fn instanceof(&self, v: Val) -> bool {
236        unsafe { emlite_val_instanceof(self.as_handle(), v.as_handle()) }
237    }
238
239    pub fn is_number(&self) -> bool {
240        unsafe { emlite_val_is_number(self.as_handle()) }
241    }
242
243    pub fn is_bool(&self) -> bool {
244        unsafe { emlite_val_is_bool(self.as_handle()) }
245    }
246    
247    pub fn is_string(&self) -> bool {
248        unsafe { emlite_val_is_string(self.as_handle()) }
249    }
250
251    pub fn is_null(&self) -> bool {
252        self.as_handle() == EmlitePredefHandles::Null as u32
253    }
254
255    pub fn is_undefined(&self) -> bool {
256        self.as_handle() == EmlitePredefHandles::Undefined as u32
257    }
258
259    pub fn is_error(&self) -> bool {
260        self.instanceof(Val::global("Error"))
261    }
262
263    pub fn is_function(&self) -> bool {
264        self.instanceof(Val::global("Function"))
265    }
266
267    #[inline(always)]
268    pub fn as_<T>(&self) -> T
269    where
270        T: FromVal,
271    {
272        T::from_val(self)
273    }
274
275    /// Creates a Val from UTF-16 data
276    pub fn from_utf16(utf16: &[u16]) -> Val {
277        Val::from(utf16)
278    }
279
280    /// Extracts UTF-16 data as Option<Vec<u16>>
281    pub fn to_utf16(&self) -> Option<Vec<u16>> {
282        self.as_::<Option<Vec<u16>>>()
283    }
284
285    /// Extracts UTF-16 data, returning error if null or if self is error
286    pub fn to_utf16_result(&self) -> Result<Vec<u16>, Val> {
287        self.as_::<Result<Vec<u16>, Val>>()
288    }
289
290    /// Converts UTF-16 Vec<u16> to String, if possible
291    pub fn utf16_to_string(utf16: &[u16]) -> Result<String, ()> {
292        // Simple conversion that works for basic cases
293        // For a full implementation, you'd want proper UTF-16 decoding
294        match String::from_utf16(utf16) {
295            Ok(s) => Ok(s),
296            Err(_) => Err(()),
297        }
298    }
299
300    /// Creates a Val from a String by first converting to UTF-16
301    pub fn from_string_via_utf16(s: &str) -> Val {
302        let utf16: Vec<u16> = s.encode_utf16().collect();
303        Val::from_utf16(&utf16)
304    }
305}
306
307impl From<bool> for Val {
308    fn from(v: bool) -> Self {
309        Val::take_ownership(unsafe { emlite_val_make_bool(v as _) })
310    }
311}
312
313impl From<i8> for Val {
314    fn from(v: i8) -> Self {
315        Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
316    }
317}
318
319impl From<u8> for Val {
320    fn from(v: u8) -> Self {
321        Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
322    }
323}
324
325impl From<i16> for Val {
326    fn from(v: i16) -> Self {
327        Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
328    }
329}
330
331impl From<u16> for Val {
332    fn from(v: u16) -> Self {
333        Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
334    }
335}
336
337impl From<i32> for Val {
338    fn from(v: i32) -> Self {
339        Val::take_ownership(unsafe { emlite_val_make_int(v) })
340    }
341}
342
343impl From<u32> for Val {
344    fn from(v: u32) -> Self {
345        Val::take_ownership(unsafe { emlite_val_make_uint(v as _) })
346    }
347}
348
349impl From<i64> for Val {
350    fn from(v: i64) -> Self {
351        Val::take_ownership(unsafe { emlite_val_make_bigint(v as _) })
352    }
353}
354
355impl From<u64> for Val {
356    fn from(v: u64) -> Self {
357        Val::take_ownership(unsafe { emlite_val_make_biguint(v as _) })
358    }
359}
360
361impl From<usize> for Val {
362    fn from(v: usize) -> Self {
363        Val::take_ownership(unsafe { emlite_val_make_biguint(v as _) })
364    }
365}
366
367impl From<isize> for Val {
368    fn from(v: isize) -> Self {
369        Val::take_ownership(unsafe { emlite_val_make_bigint(v as _) })
370    }
371}
372
373impl From<f32> for Val {
374    fn from(v: f32) -> Self {
375        Val::take_ownership(unsafe { emlite_val_make_double(v as _) })
376    }
377}
378
379impl From<f64> for Val {
380    fn from(v: f64) -> Self {
381        Val::take_ownership(unsafe { emlite_val_make_double(v) })
382    }
383}
384
385impl From<()> for Val {
386    fn from(_: ()) -> Self {
387        Val::undefined()
388    }
389}
390
391impl From<&str> for Val {
392    fn from(s: &str) -> Self {
393        Val::take_ownership(unsafe { emlite_val_make_str(s.as_ptr() as _, s.len()) })
394    }
395}
396
397impl From<String> for Val {
398    fn from(s: String) -> Self {
399        Val::take_ownership(unsafe { emlite_val_make_str(s.as_ptr() as _, s.len()) })
400    }
401}
402
403impl From<&String> for Val {
404    fn from(s: &String) -> Self {
405        Val::take_ownership(unsafe { emlite_val_make_str(s.as_ptr() as _, s.len()) })
406    }
407}
408
409impl From<&[u16]> for Val {
410    fn from(s: &[u16]) -> Self {
411        Val::take_ownership(unsafe { emlite_val_make_str_utf16(s.as_ptr(), s.len()) })
412    }
413}
414
415impl From<Vec<u16>> for Val {
416    fn from(s: Vec<u16>) -> Self {
417        Val::take_ownership(unsafe { emlite_val_make_str_utf16(s.as_ptr(), s.len()) })
418    }
419}
420
421impl From<&Vec<u16>> for Val {
422    fn from(s: &Vec<u16>) -> Self {
423        Val::take_ownership(unsafe { emlite_val_make_str_utf16(s.as_ptr(), s.len()) })
424    }
425}
426
427impl From<&Val> for Val {
428    fn from(v: &Val) -> Self {
429        v.clone()
430    }
431}
432
433impl Drop for Val {
434    fn drop(&mut self) {
435        unsafe { emlite_val_dec_ref(self.as_handle()) }
436    }
437}
438
439impl Clone for Val {
440    fn clone(&self) -> Val {
441        unsafe {
442            emlite_val_inc_ref(self.as_handle());
443        }
444        Val::take_ownership(self.as_handle())
445    }
446}
447
448use core::ops::{Deref, DerefMut};
449
450/// A console wrapper
451#[derive(Clone, Debug)]
452pub struct Console {
453    val: Val,
454}
455
456impl Console {
457    /// Gets the console
458    pub const fn get() -> Console {
459        Console {
460            val: Val {
461                inner: EmlitePredefHandles::Console as _,
462            },
463        }
464    }
465
466    /// Logs into the console
467    pub fn log(&self, args: &[Val]) {
468        self.val.call("log", args);
469    }
470
471    /// console.warn
472    pub fn warn(&self, args: &[Val]) {
473        self.val.call("warn", args);
474    }
475
476    /// console.info
477    pub fn info(&self, args: &[Val]) {
478        self.val.call("info", args);
479    }
480
481    /// Returns the underlying handle of the console
482    pub fn as_handle(&self) -> Handle {
483        self.val.as_handle()
484    }
485}
486
487impl Deref for Console {
488    type Target = Val;
489
490    fn deref(&self) -> &Self::Target {
491        &self.val
492    }
493}
494
495impl DerefMut for Console {
496    fn deref_mut(&mut self) -> &mut Self::Target {
497        &mut self.val
498    }
499}
500
501impl From<Console> for Val {
502    fn from(val: Console) -> Self {
503        Val::take_ownership(val.as_handle())
504    }
505}
506
507use core::cmp::Ordering;
508use core::ops::Not;
509
510impl PartialEq for Val {
511    fn eq(&self, other: &Val) -> bool {
512        unsafe { emlite_val_strictly_equals(self.as_handle(), other.as_handle()) }
513    }
514}
515
516impl PartialOrd for Val {
517    fn partial_cmp(&self, other: &Val) -> Option<Ordering> {
518        unsafe {
519            if emlite_val_strictly_equals(self.as_handle(), other.as_handle()) {
520                Some(Ordering::Equal)
521            } else if emlite_val_gt(self.as_handle(), other.as_handle()) {
522                Some(Ordering::Greater)
523            } else if emlite_val_lt(self.as_handle(), other.as_handle()) {
524                Some(Ordering::Less)
525            } else {
526                None
527            }
528        }
529    }
530}
531
532impl Not for Val {
533    type Output = bool;
534
535    fn not(self) -> Self::Output {
536        unsafe { emlite_val_not(self.as_handle()) }
537    }
538}
539
540impl AsRef<Val> for Val {
541    #[inline]
542    fn as_ref(&self) -> &Val { self }
543}
544
545impl AsMut<Val> for Val {
546    #[inline]
547    fn as_mut(&mut self) -> &mut Val { self }
548}
549
550pub trait FromVal: Sized {
551    /// Creates a Val object from another
552    fn from_val(v: &Val) -> Self;
553    /// Takes the ownership of a handle
554    fn take_ownership(v: Handle) -> Self;
555    /// Returns the raw js handle
556    fn as_handle(&self) -> Handle;
557}
558
559impl FromVal for Val {
560    fn from_val(v: &Val) -> Self {
561        unsafe {
562            emlite_val_inc_ref(v.inner);
563        }
564        Val {
565            inner: v.as_handle(),
566        }
567    }
568    fn take_ownership(v: Handle) -> Self {
569        Val { inner: v }
570    }
571    #[inline(always)]
572    fn as_handle(&self) -> Handle {
573        self.inner
574    }
575}
576
577impl FromVal for Result<Val, Val> {
578    fn from_val(v: &Val) -> Self {
579        unsafe {
580            emlite_val_inc_ref(v.inner);
581        }
582        if v.is_error() {
583            Err(v.clone())
584        } else {
585            Ok(v.clone())
586        }
587    }
588    fn take_ownership(v: Handle) -> Self {
589        let temp = Val::take_ownership(v);
590        if temp.is_error() {
591            Err(temp)
592        } else {
593            Ok(temp)
594        }
595    }
596    #[inline(always)]
597    fn as_handle(&self) -> Handle {
598        match self {
599            Ok(ok) => ok.as_handle(),
600            Err(e) => e.as_handle(),
601        }
602    }
603}
604
605impl FromVal for bool {
606    fn from_val(v: &Val) -> Self {
607        unsafe {
608            !env::emlite_val_not(v.as_handle())
609        }
610    }
611    fn take_ownership(v: Handle) -> Self {
612        Self::from_val(&Val::take_ownership(v))
613    }
614    fn as_handle(&self) -> Handle {
615        if *self { EmlitePredefHandles::True as u32 } else { EmlitePredefHandles::False as u32 }
616    }
617}
618
619
620impl FromVal for Option<bool> {
621    fn from_val(v: &Val) -> Self {
622        unsafe {
623            if v.is_error() || v.is_null() || v.is_undefined() {
624                None
625            } else {
626                Some(!env::emlite_val_not(v.as_handle()))
627            }
628        }
629    }
630    fn take_ownership(v: Handle) -> Self {
631        let temp = Val::take_ownership(v);
632        if temp.is_error() || temp.is_null() || temp.is_undefined() {
633            None
634        } else {
635            unsafe { Some(!env::emlite_val_not(v)) }
636        }
637    }
638    fn as_handle(&self) -> Handle {
639        match self {
640            Some(ok) => if *ok { EmlitePredefHandles::True as u32 } else { EmlitePredefHandles::False as u32 },
641            None => EmlitePredefHandles::Undefined as u32,
642        }
643    }
644}
645
646impl FromVal for Result<bool, Val> {
647    fn from_val(v: &Val) -> Self {
648        unsafe {
649            if v.is_error() {
650                Err(v.clone())
651            } else {
652                Ok(!env::emlite_val_not(v.as_handle()))
653            }
654        }
655    }
656    fn take_ownership(v: Handle) -> Self {
657        let temp = Val::take_ownership(v);
658        if temp.is_error() {
659            Err(temp)
660        } else {
661            unsafe { Ok(!env::emlite_val_not(v)) }
662        }
663    }
664    fn as_handle(&self) -> Handle {
665        match self {
666            Ok(ok) => if *ok { EmlitePredefHandles::True as u32 } else { EmlitePredefHandles::False as u32 },
667            Err(e) => e.as_handle(),
668        }
669    }
670}
671
672macro_rules! impl_int {
673    ($($t:ty),*) => {$(
674        impl FromVal for $t {
675            fn from_val(v: &Val) -> Self {
676                unsafe {
677                    emlite_val_get_value_int(v.as_handle()) as Self
678                }
679            }
680            fn take_ownership(v: Handle) -> Self {
681                unsafe { emlite_val_get_value_int(v) as Self }
682            }
683            fn as_handle(&self) -> Handle {
684                0
685            }
686        }
687        impl FromVal for Option<$t> {
688            fn from_val(v: &Val) -> Self {
689                unsafe {
690                    if !v.is_number() {
691                        None
692                    } else {
693                        Some(emlite_val_get_value_int(v.as_handle()) as $t)
694                    }
695                }
696            }
697            fn take_ownership(v: Handle) -> Self {
698                let temp = Val::take_ownership(v);
699                if !temp.is_number() {
700                    None
701                } else {
702                    unsafe { Some(emlite_val_get_value_int(v) as $t) }
703                }
704            }
705            fn as_handle(&self) -> Handle {
706                0
707            }
708        }
709        impl FromVal for Result<$t, Val> {
710            fn from_val(v: &Val) -> Self {
711                unsafe {
712                    if v.is_error() {
713                        Err(v.clone())
714                    } else {
715                        Ok(emlite_val_get_value_int(v.as_handle()) as $t)
716                    }
717                }
718            }
719            fn take_ownership(v: Handle) -> Self {
720                let temp = Val::take_ownership(v);
721                if temp.is_error() {
722                    Err(temp)
723                } else {
724                    unsafe { Ok(emlite_val_get_value_int(v) as $t) }
725                }
726            }
727            fn as_handle(&self) -> Handle {
728                0
729            }
730        }
731    )*}
732}
733
734macro_rules! impl_uint {
735    ($($t:ty),*) => {$(
736        impl FromVal for $t {
737            fn from_val(v: &Val) -> Self {
738                unsafe {
739                    emlite_val_get_value_uint(v.as_handle()) as Self
740                }
741            }
742            fn take_ownership(v: Handle) -> Self {
743                unsafe { emlite_val_get_value_uint(v) as Self }
744            }
745            fn as_handle(&self) -> Handle {
746                0
747            }
748        }
749        impl FromVal for Option<$t> {
750            fn from_val(v: &Val) -> Self {
751                unsafe {
752                    if !v.is_number() {
753                        None
754                    } else {
755                        Some(emlite_val_get_value_uint(v.as_handle()) as $t)
756                    }
757                }
758            }
759            fn take_ownership(v: Handle) -> Self {
760                let temp = Val::take_ownership(v);
761                if !temp.is_number() {
762                    None
763                } else {
764                    unsafe { Some(emlite_val_get_value_uint(v) as $t) }
765                }
766            }
767            fn as_handle(&self) -> Handle {
768                0
769            }
770        }
771        impl FromVal for Result<$t, Val> {
772            fn from_val(v: &Val) -> Self {
773                unsafe {
774                    if v.is_error() {
775                        Err(v.clone())
776                    } else {
777                        Ok(emlite_val_get_value_uint(v.as_handle()) as $t)
778                    }
779                }
780            }
781            fn take_ownership(v: Handle) -> Self {
782                let temp = Val::take_ownership(v);
783                if temp.is_error() {
784                    Err(temp)
785                } else {
786                    unsafe { Ok(emlite_val_get_value_uint(v) as $t) }
787                }
788            }
789            fn as_handle(&self) -> Handle {
790                0
791            }
792        }
793    )*}
794}
795
796macro_rules! impl_bigint {
797    ($($t:ty),*) => {$(
798        impl FromVal for $t {
799            fn from_val(v: &Val) -> Self {
800                unsafe {
801                    emlite_val_get_value_bigint(v.as_handle()) as Self
802                }
803            }
804            fn take_ownership(v: Handle) -> Self {
805                unsafe { emlite_val_get_value_bigint(v) as Self }
806            }
807            fn as_handle(&self) -> Handle {
808                0
809            }
810        }
811        impl FromVal for Option<$t> {
812            fn from_val(v: &Val) -> Self {
813                unsafe {
814                    if !v.is_number() {
815                        None
816                    } else {
817                        Some(emlite_val_get_value_bigint(v.as_handle()) as $t)
818                    }
819                }
820            }
821            fn take_ownership(v: Handle) -> Self {
822                let temp = Val::take_ownership(v);
823                if !temp.is_number() {
824                    None
825                } else {
826                    unsafe { Some(emlite_val_get_value_bigint(v) as $t) }
827                }
828            }
829            fn as_handle(&self) -> Handle {
830                0
831            }
832        }
833        impl FromVal for Result<$t, Val> {
834            fn from_val(v: &Val) -> Self {
835                unsafe {
836                    if v.is_error() {
837                        Err(v.clone())
838                    } else {
839                        Ok(emlite_val_get_value_bigint(v.as_handle()) as $t)
840                    }
841                }
842            }
843            fn take_ownership(v: Handle) -> Self {
844                let temp = Val::take_ownership(v);
845                if temp.is_error() {
846                    Err(temp)
847                } else {
848                    unsafe { Ok(emlite_val_get_value_bigint(v) as $t) }
849                }
850            }
851            fn as_handle(&self) -> Handle {
852                0
853            }
854        }
855    )*}
856}
857
858macro_rules! impl_biguint {
859    ($($t:ty),*) => {$(
860        impl FromVal for $t {
861            fn from_val(v: &Val) -> Self {
862                unsafe {
863                    emlite_val_get_value_biguint(v.as_handle()) as Self
864                }
865            }
866            fn take_ownership(v: Handle) -> Self {
867                unsafe { emlite_val_get_value_biguint(v) as Self }
868            }
869            fn as_handle(&self) -> Handle {
870                0
871            }
872        }
873        impl FromVal for Option<$t> {
874            fn from_val(v: &Val) -> Self {
875                unsafe {
876                    if !v.is_number() {
877                        None
878                    } else {
879                        Some(emlite_val_get_value_biguint(v.as_handle()) as $t)
880                    }
881                }
882            }
883            fn take_ownership(v: Handle) -> Self {
884                let temp = Val::take_ownership(v);
885                if !temp.is_number() {
886                    None
887                } else {
888                    unsafe { Some(emlite_val_get_value_biguint(v) as $t) }
889                }
890            }
891            fn as_handle(&self) -> Handle {
892                0
893            }
894        }
895        impl FromVal for Result<$t, Val> {
896            fn from_val(v: &Val) -> Self {
897                unsafe {
898                    if v.is_error() {
899                        Err(v.clone())
900                    } else {
901                        Ok(emlite_val_get_value_biguint(v.as_handle()) as $t)
902                    }
903                }
904            }
905            fn take_ownership(v: Handle) -> Self {
906                let temp = Val::take_ownership(v);
907                if temp.is_error() {
908                    Err(temp)
909                } else {
910                    unsafe { Ok(emlite_val_get_value_biguint(v) as $t) }
911                }
912            }
913            fn as_handle(&self) -> Handle {
914                0
915            }
916        }
917    )*}
918}
919
920impl_int!(i8, i16, i32);
921impl_uint!(u8, u16, u32);
922impl_bigint!(i64, isize);
923impl_biguint!(u64, usize);
924
925macro_rules! impl_float {
926    ($($t:ty),*) => {$(
927        impl FromVal for $t {
928            fn from_val(v: &Val) -> Self {
929                unsafe { emlite_val_get_value_double(v.as_handle()) as Self }
930            }
931            fn take_ownership(v: Handle) -> Self {
932                unsafe { emlite_val_get_value_double(v) as Self }
933            }
934            fn as_handle(&self) -> Handle {
935                0
936            }
937        }
938        impl FromVal for Option<$t> {
939            fn from_val(v: &Val) -> Self {
940                unsafe {
941                    if !v.is_number() {
942                        None
943                    } else {
944                        Some(emlite_val_get_value_double(v.as_handle()) as $t)
945                    }
946                }
947            }
948            fn take_ownership(v: Handle) -> Self {
949                let temp = Val::take_ownership(v);
950                if !temp.is_number() {
951                    None
952                } else {
953                    unsafe { Some(emlite_val_get_value_double(v) as $t) }
954                }
955            }
956            fn as_handle(&self) -> Handle {
957                0
958            }
959        }
960        impl FromVal for Result<$t, Val> {
961            fn from_val(v: &Val) -> Self {
962                unsafe {
963                    if v.is_error() {
964                        Err(v.clone())
965                    } else {
966                        Ok(emlite_val_get_value_double(v.as_handle()) as $t)
967                    }
968                }
969            }
970            fn take_ownership(v: Handle) -> Self {
971                let temp = Val::take_ownership(v);
972                if temp.is_error() {
973                    Err(temp)
974                } else {
975                    unsafe { Ok(emlite_val_get_value_double(v) as $t) }
976                }
977            }
978            fn as_handle(&self) -> Handle {
979                0
980            }
981        }
982    )*}
983}
984
985impl_float!(f32, f64);
986
987impl FromVal for () {
988    fn from_val(_v: &Val) -> Self {
989        // Unit type doesn't carry any data, so we just return ()
990        ()
991    }
992    fn take_ownership(_v: Handle) -> Self {
993        ()
994    }
995    fn as_handle(&self) -> Handle {
996        EmlitePredefHandles::Undefined as u32
997    }
998}
999
1000impl FromVal for Option<String> {
1001    fn from_val(v: &Val) -> Self {
1002        unsafe {
1003            if !v.is_string() {
1004                return None;
1005            }
1006            let ptr = emlite_val_get_value_string(v.as_handle());
1007            if ptr.is_null() {
1008                None
1009            } else {
1010                Some(CStr::from_ptr(ptr).to_string_lossy().into_owned())
1011            }
1012        }
1013    }
1014    fn take_ownership(v: Handle) -> Self {
1015        unsafe {
1016            if !emlite_val_is_string(v) {
1017                return None;
1018            }
1019            let ptr = emlite_val_get_value_string(v);
1020            if ptr.is_null() {
1021                None
1022            } else {
1023                Some(CStr::from_ptr(ptr).to_string_lossy().into_owned())
1024            }
1025        }
1026    }
1027    fn as_handle(&self) -> Handle {
1028        0
1029    }
1030}
1031
1032
1033impl FromVal for Option<&str> {
1034    fn from_val(v: &Val) -> Self {
1035        unsafe {
1036            if !v.is_string() {
1037                return None;
1038            }
1039            let ptr = emlite_val_get_value_string(v.as_handle());
1040            if ptr.is_null() {
1041                None
1042            } else {
1043                Some(CStr::from_ptr(ptr).to_str().unwrap())
1044            }
1045        }
1046    }
1047    fn take_ownership(v: Handle) -> Self {
1048        unsafe {
1049            if !emlite_val_is_string(v) {
1050                return None;
1051            }
1052            let ptr = emlite_val_get_value_string(v);
1053            if ptr.is_null() {
1054                None
1055            } else {
1056                Some(CStr::from_ptr(ptr).to_str().unwrap())
1057            }
1058        }
1059    }
1060    fn as_handle(&self) -> Handle {
1061        0
1062    }
1063}
1064
1065
1066impl FromVal for Result<String, Val> {
1067    fn from_val(v: &Val) -> Self {
1068        unsafe {
1069            if v.is_error() {
1070                Err(v.clone())
1071            } else if !v.is_string() {
1072                Err(Val::global("Error").new(&["Expected string".into()]))
1073            } else {
1074                let ptr = emlite_val_get_value_string(v.as_handle());
1075                if ptr.is_null() {
1076                    Err(Val::global("Error").new(&["Null string".into()]))
1077                } else {
1078                    Ok(CStr::from_ptr(ptr).to_string_lossy().into_owned())
1079                }
1080            }
1081        }
1082    }
1083    fn take_ownership(v: Handle) -> Self {
1084        unsafe {
1085            let temp = Val::take_ownership(v);
1086            if temp.is_error() {
1087                Err(temp)
1088            } else if !temp.is_string() {
1089                Err(Val::global("Error").new(&["Expected string".into()]))
1090            } else {
1091                let ptr = emlite_val_get_value_string(v);
1092                if ptr.is_null() {
1093                    Err(Val::global("Error").new(&["Null string".into()]))
1094                } else {
1095                    Ok(CStr::from_ptr(ptr).to_string_lossy().into_owned())
1096                }
1097            }
1098        }
1099    }
1100    fn as_handle(&self) -> Handle {
1101        0
1102    }
1103}
1104
1105
1106impl FromVal for Result<&str, Val> {
1107    fn from_val(v: &Val) -> Self {
1108        unsafe {
1109            if v.is_error() {
1110                Err(v.clone())
1111            } else if !v.is_string() {
1112                Err(Val::global("Error").new(&["Expected string".into()]))
1113            } else {
1114                let ptr = emlite_val_get_value_string(v.as_handle());
1115                if ptr.is_null() {
1116                    Err(Val::global("Error").new(&["Null string".into()]))
1117                } else {
1118                    Ok(CStr::from_ptr(ptr).to_str().unwrap())
1119                }
1120            }
1121        }
1122    }
1123    fn take_ownership(v: Handle) -> Self {
1124        unsafe {
1125            let temp = Val::take_ownership(v);
1126            if temp.is_error() {
1127                Err(temp)
1128            } else if !temp.is_string() {
1129                Err(Val::global("Error").new(&["Expected string".into()]))
1130            } else {
1131                let ptr = emlite_val_get_value_string(v);
1132                if ptr.is_null() {
1133                    Err(Val::global("Error").new(&["Null string".into()]))
1134                } else {
1135                    Ok(CStr::from_ptr(ptr).to_str().unwrap())
1136                }
1137            }
1138        }
1139    }
1140    fn as_handle(&self) -> Handle {
1141        0
1142    }
1143}
1144
1145impl FromVal for Option<Vec<u16>> {
1146    fn from_val(v: &Val) -> Self {
1147        unsafe {
1148            let ptr = emlite_val_get_value_string_utf16(v.as_handle());
1149            if ptr.is_null() {
1150                None
1151            } else {
1152                // Find length by searching for null terminator
1153                let mut len = 0;
1154                let mut current = ptr;
1155                while *current != 0 {
1156                    len += 1;
1157                    current = current.add(1);
1158                }
1159                // Convert to Vec<u16>
1160                let slice = core::slice::from_raw_parts(ptr, len);
1161                Some(slice.to_vec())
1162            }
1163        }
1164    }
1165    fn take_ownership(v: Handle) -> Self {
1166        unsafe {
1167            let ptr = emlite_val_get_value_string_utf16(v);
1168            if ptr.is_null() {
1169                None
1170            } else {
1171                // Find length by searching for null terminator
1172                let mut len = 0;
1173                let mut current = ptr;
1174                while *current != 0 {
1175                    len += 1;
1176                    current = current.add(1);
1177                }
1178                // Convert to Vec<u16>
1179                let slice = core::slice::from_raw_parts(ptr, len);
1180                Some(slice.to_vec())
1181            }
1182        }
1183    }
1184    fn as_handle(&self) -> Handle {
1185        0
1186    }
1187}
1188
1189impl FromVal for Result<Vec<u16>, Val> {
1190    fn from_val(v: &Val) -> Self {
1191        unsafe {
1192            if v.is_error() {
1193                Err(v.clone())
1194            } else {
1195                let ptr = emlite_val_get_value_string_utf16(v.as_handle());
1196                if ptr.is_null() {
1197                    Err(Val::global("Error").new(&["Null UTF-16 string".into()]))
1198                } else {
1199                    // Find length by searching for null terminator
1200                    let mut len = 0;
1201                    let mut current = ptr;
1202                    while *current != 0 {
1203                        len += 1;
1204                        current = current.add(1);
1205                    }
1206                    // Convert to Vec<u16>
1207                    let slice = core::slice::from_raw_parts(ptr, len);
1208                    Ok(slice.to_vec())
1209                }
1210            }
1211        }
1212    }
1213    fn take_ownership(v: Handle) -> Self {
1214        unsafe {
1215            let temp = Val::take_ownership(v);
1216            if temp.is_error() {
1217                Err(temp)
1218            } else {
1219                let ptr = emlite_val_get_value_string_utf16(v);
1220                if ptr.is_null() {
1221                    Err(Val::global("Error").new(&["Null UTF-16 string".into()]))
1222                } else {
1223                    // Find length by searching for null terminator
1224                    let mut len = 0;
1225                    let mut current = ptr;
1226                    while *current != 0 {
1227                        len += 1;
1228                        current = current.add(1);
1229                    }
1230                    // Convert to Vec<u16>
1231                    let slice = core::slice::from_raw_parts(ptr, len);
1232                    Ok(slice.to_vec())
1233                }
1234            }
1235        }
1236    }
1237    fn as_handle(&self) -> Handle {
1238        0
1239    }
1240}
1241
1242/// A marker trait for types that can be constructed from JavaScript error values.
1243/// This allows Result<T, E> implementations where E: FromJsError.
1244pub trait FromJsError {
1245    fn from_js_error(val: &Val) -> Self;
1246}
1247
1248/// Implementation for Result<T, E> where T: FromVal and E: FromJsError.
1249/// This allows clean conversion using as_::<Result<T, E>>() for JavaScript error handling.
1250impl<T, E> FromVal for Result<T, E>
1251where
1252    T: FromVal,
1253    E: FromJsError,
1254{
1255    fn from_val(v: &Val) -> Self {
1256        if v.is_error() {
1257            Err(E::from_js_error(v))
1258        } else {
1259            Ok(T::from_val(v))
1260        }
1261    }
1262    fn take_ownership(handle: Handle) -> Self {
1263        let temp = Val::take_ownership(handle);
1264        if temp.is_error() {
1265            Err(E::from_js_error(&temp))
1266        } else {
1267            Ok(T::take_ownership(handle))
1268        }
1269    }
1270    fn as_handle(&self) -> Handle {
1271        match self {
1272            Ok(ok) => ok.as_handle(),
1273            Err(_) => 0, // Errors don't have meaningful handles in this context
1274        }
1275    }
1276}
1277