bare_rust/
lib.rs

1use std::ffi::{c_void, CString};
2use std::ptr;
3use std::slice;
4use std::string;
5
6pub use bare_rust_ffi as ffi;
7
8use ffi::*;
9
10pub type Result<T> = std::result::Result<T, i32>;
11
12pub struct Env {
13    ptr: *mut js_env_t,
14}
15
16impl From<*mut js_env_t> for Env {
17    fn from(ptr: *mut js_env_t) -> Self {
18        return Self { ptr };
19    }
20}
21
22pub struct Value {
23    env: *mut js_env_t,
24    ptr: *mut js_value_t,
25}
26
27impl From<Value> for *mut js_value_t {
28    fn from(value: Value) -> Self {
29        value.ptr
30    }
31}
32
33pub struct Undefined(pub Value);
34
35impl Undefined {
36    pub fn new(env: &Env) -> Result<Self> {
37        let mut ptr: *mut js_value_t = ptr::null_mut();
38
39        let status = unsafe { js_get_undefined(env.ptr, &mut ptr) };
40
41        if status != 0 {
42            Err(status)
43        } else {
44            Ok(Self(Value { env: env.ptr, ptr }))
45        }
46    }
47}
48
49impl From<Undefined> for *mut js_value_t {
50    fn from(undefined: Undefined) -> Self {
51        undefined.0.ptr
52    }
53}
54
55impl From<Value> for Undefined {
56    fn from(value: Value) -> Self {
57        Self(value)
58    }
59}
60
61pub struct Null(pub Value);
62
63impl Null {
64    pub fn new(env: &Env) -> Result<Self> {
65        let mut ptr: *mut js_value_t = ptr::null_mut();
66
67        let status = unsafe { js_get_null(env.ptr, &mut ptr) };
68
69        if status != 0 {
70            Err(status)
71        } else {
72            Ok(Self(Value { env: env.ptr, ptr }))
73        }
74    }
75}
76
77impl From<Null> for *mut js_value_t {
78    fn from(null: Null) -> Self {
79        null.0.ptr
80    }
81}
82
83impl From<Value> for Null {
84    fn from(value: Value) -> Self {
85        Self(value)
86    }
87}
88
89pub struct Boolean(pub Value);
90
91impl Boolean {
92    pub fn new(env: &Env, value: bool) -> Result<Self> {
93        let mut ptr: *mut js_value_t = ptr::null_mut();
94
95        let status = unsafe { js_get_boolean(env.ptr, value, &mut ptr) };
96
97        if status != 0 {
98            Err(status)
99        } else {
100            Ok(Self(Value { env: env.ptr, ptr }))
101        }
102    }
103}
104
105impl From<Boolean> for bool {
106    fn from(boolean: Boolean) -> Self {
107        let mut value = false;
108
109        unsafe {
110            js_get_value_bool(boolean.0.env, boolean.0.ptr, &mut value);
111        }
112
113        value
114    }
115}
116
117impl From<Boolean> for *mut js_value_t {
118    fn from(boolean: Boolean) -> Self {
119        boolean.0.ptr
120    }
121}
122
123impl From<Value> for Boolean {
124    fn from(value: Value) -> Self {
125        Self(value)
126    }
127}
128
129pub struct Number(pub Value);
130
131impl Number {
132    pub fn with_i32(env: &Env, value: i32) -> Result<Self> {
133        let mut ptr: *mut js_value_t = ptr::null_mut();
134
135        let status = unsafe { js_create_int32(env.ptr, value, &mut ptr) };
136
137        if status != 0 {
138            Err(status)
139        } else {
140            Ok(Self(Value { env: env.ptr, ptr }))
141        }
142    }
143
144    pub fn with_u32(env: &Env, value: u32) -> Result<Self> {
145        let mut ptr: *mut js_value_t = ptr::null_mut();
146
147        let status = unsafe { js_create_uint32(env.ptr, value, &mut ptr) };
148
149        if status != 0 {
150            Err(status)
151        } else {
152            Ok(Self(Value { env: env.ptr, ptr }))
153        }
154    }
155
156    pub fn with_i64(env: &Env, value: i64) -> Result<Self> {
157        let mut ptr: *mut js_value_t = ptr::null_mut();
158
159        let status = unsafe { js_create_int64(env.ptr, value, &mut ptr) };
160
161        if status != 0 {
162            Err(status)
163        } else {
164            Ok(Self(Value { env: env.ptr, ptr }))
165        }
166    }
167
168    pub fn with_f64(env: &Env, value: f64) -> Result<Self> {
169        let mut ptr: *mut js_value_t = ptr::null_mut();
170
171        let status = unsafe { js_create_double(env.ptr, value, &mut ptr) };
172
173        if status != 0 {
174            Err(status)
175        } else {
176            Ok(Self(Value { env: env.ptr, ptr }))
177        }
178    }
179}
180
181impl From<Number> for i32 {
182    fn from(number: Number) -> Self {
183        let mut value = 0;
184
185        unsafe {
186            js_get_value_int32(number.0.env, number.0.ptr, &mut value);
187        }
188
189        value
190    }
191}
192
193impl From<Number> for u32 {
194    fn from(number: Number) -> Self {
195        let mut value = 0;
196
197        unsafe {
198            js_get_value_uint32(number.0.env, number.0.ptr, &mut value);
199        }
200
201        value
202    }
203}
204
205impl From<Number> for i64 {
206    fn from(number: Number) -> Self {
207        let mut value = 0;
208
209        unsafe {
210            js_get_value_int64(number.0.env, number.0.ptr, &mut value);
211        }
212
213        value
214    }
215}
216
217impl From<Number> for f64 {
218    fn from(number: Number) -> Self {
219        let mut value = 0.0;
220
221        unsafe {
222            js_get_value_double(number.0.env, number.0.ptr, &mut value);
223        }
224
225        value
226    }
227}
228
229impl From<Number> for *mut js_value_t {
230    fn from(number: Number) -> Self {
231        number.0.ptr
232    }
233}
234
235impl From<Value> for Number {
236    fn from(value: Value) -> Self {
237        Self(value)
238    }
239}
240
241pub struct BigInt(pub Value);
242
243impl BigInt {
244    pub fn with_i64(env: &Env, value: i64) -> Result<Self> {
245        let mut ptr: *mut js_value_t = ptr::null_mut();
246
247        let status = unsafe { js_create_bigint_int64(env.ptr, value, &mut ptr) };
248
249        if status != 0 {
250            Err(status)
251        } else {
252            Ok(Self(Value { env: env.ptr, ptr }))
253        }
254    }
255
256    pub fn with_u64(env: &Env, value: u64) -> Result<Self> {
257        let mut ptr: *mut js_value_t = ptr::null_mut();
258
259        let status = unsafe { js_create_bigint_uint64(env.ptr, value, &mut ptr) };
260
261        if status != 0 {
262            Err(status)
263        } else {
264            Ok(Self(Value { env: env.ptr, ptr }))
265        }
266    }
267}
268
269impl From<BigInt> for i64 {
270    fn from(bigint: BigInt) -> Self {
271        let mut value = 0;
272
273        unsafe {
274            js_get_value_bigint_int64(bigint.0.env, bigint.0.ptr, &mut value, ptr::null_mut());
275        }
276
277        value
278    }
279}
280
281impl From<BigInt> for u64 {
282    fn from(bigint: BigInt) -> Self {
283        let mut value = 0;
284
285        unsafe {
286            js_get_value_bigint_uint64(bigint.0.env, bigint.0.ptr, &mut value, ptr::null_mut());
287        }
288
289        value
290    }
291}
292
293impl From<BigInt> for *mut js_value_t {
294    fn from(bigint: BigInt) -> Self {
295        bigint.0.ptr
296    }
297}
298
299impl From<Value> for BigInt {
300    fn from(value: Value) -> Self {
301        Self(value)
302    }
303}
304
305pub struct String(pub Value);
306
307impl String {
308    pub fn new(env: &Env, value: &str) -> Result<Self> {
309        let mut ptr: *mut js_value_t = ptr::null_mut();
310
311        let status = unsafe {
312            js_create_string_utf8(
313                env.ptr,
314                value.as_ptr().cast(),
315                value.len() as usize,
316                &mut ptr,
317            )
318        };
319
320        if status != 0 {
321            Err(status)
322        } else {
323            Ok(Self(Value { env: env.ptr, ptr }))
324        }
325    }
326
327    pub fn to_bytes(&self) -> Vec<u8> {
328        let mut len = 0;
329
330        unsafe {
331            js_get_value_string_utf8(self.0.env, self.0.ptr, ptr::null_mut(), 0, &mut len);
332        }
333
334        let mut result = Vec::new();
335
336        result.resize(len, 0);
337
338        unsafe {
339            js_get_value_string_utf8(self.0.env, self.0.ptr, result.as_mut_ptr(), len, &mut len);
340        }
341
342        result
343    }
344}
345
346impl From<String> for string::String {
347    fn from(string: String) -> Self {
348        return string::String::from_utf8(string.to_bytes()).unwrap();
349    }
350}
351
352impl From<String> for *mut js_value_t {
353    fn from(string: String) -> Self {
354        string.0.ptr
355    }
356}
357
358impl From<Value> for String {
359    fn from(value: Value) -> Self {
360        Self(value)
361    }
362}
363
364pub struct Object(pub Value);
365
366impl Object {
367    pub fn new(env: &Env) -> Result<Self> {
368        let mut ptr: *mut js_value_t = ptr::null_mut();
369
370        let status = unsafe { js_create_object(env.ptr, &mut ptr) };
371
372        if status != 0 {
373            Err(status)
374        } else {
375            Ok(Self(Value { env: env.ptr, ptr }))
376        }
377    }
378
379    pub fn get_named_property<T>(&self, name: &str) -> Result<T>
380    where
381        T: From<Value>,
382    {
383        let key = CString::new(name).unwrap();
384
385        let mut ptr: *mut js_value_t = ptr::null_mut();
386
387        let status =
388            unsafe { js_get_named_property(self.0.env, self.0.ptr, key.as_ptr(), &mut ptr) };
389
390        if status != 0 {
391            Err(status)
392        } else {
393            Ok(T::from(Value {
394                env: self.0.env,
395                ptr,
396            }))
397        }
398    }
399
400    pub fn has_named_property<T>(&self, name: &str) -> Result<bool> {
401        let key = CString::new(name).unwrap();
402
403        let mut result = false;
404
405        let status =
406            unsafe { js_has_named_property(self.0.env, self.0.ptr, key.as_ptr(), &mut result) };
407
408        if status != 0 {
409            Err(status)
410        } else {
411            Ok(result)
412        }
413    }
414
415    pub fn set_named_property<T>(&mut self, name: &str, value: T) -> Result<()>
416    where
417        T: Into<*mut js_value_t>,
418    {
419        let key = CString::new(name).unwrap();
420
421        let status =
422            unsafe { js_set_named_property(self.0.env, self.0.ptr, key.as_ptr(), T::into(value)) };
423
424        if status != 0 {
425            Err(status)
426        } else {
427            Ok(())
428        }
429    }
430}
431
432impl From<Object> for *mut js_value_t {
433    fn from(object: Object) -> Self {
434        object.0.ptr
435    }
436}
437
438impl From<Value> for Object {
439    fn from(value: Value) -> Self {
440        Self(value)
441    }
442}
443
444pub struct Callback {
445    env: *mut js_env_t,
446    args: Vec<*mut js_value_t>,
447    receiver: *mut js_value_t,
448}
449
450impl Callback {
451    pub fn arg<T>(&self, i: usize) -> Option<T>
452    where
453        T: From<Value>,
454    {
455        if i < self.args.len() {
456            Some(T::from(Value {
457                env: self.env,
458                ptr: self.args[i],
459            }))
460        } else {
461            None
462        }
463    }
464
465    pub fn receiver<T>(&self) -> T
466    where
467        T: From<Value>,
468    {
469        T::from(Value {
470            env: self.env,
471            ptr: self.receiver,
472        })
473    }
474}
475
476pub struct Function(Value);
477
478impl Function {
479    pub fn new<F, R>(env: &Env, function: F) -> Result<Self>
480    where
481        F: FnMut(&Env, &Callback) -> R,
482        R: Into<*mut js_value_t>,
483    {
484        let mut function = function;
485
486        let closure: Box<dyn FnMut(&Env, &Callback) -> *mut js_value_t> =
487            Box::new(move |env, info| function(env, info).into());
488
489        let data = Box::into_raw(Box::new(closure)) as *mut _;
490
491        let mut ptr: *mut js_value_t = ptr::null_mut();
492
493        let status = unsafe {
494            js_create_function(
495                env.ptr,
496                ptr::null_mut(),
497                0,
498                Some(Function::call),
499                data,
500                &mut ptr,
501            )
502        };
503
504        if status != 0 {
505            return Err(status);
506        }
507
508        unsafe {
509            js_add_finalizer(
510                env.ptr,
511                ptr,
512                data,
513                Some(Function::drop),
514                ptr::null_mut(),
515                ptr::null_mut(),
516            );
517        }
518
519        Ok(Self(Value { env: env.ptr, ptr }))
520    }
521
522    extern "C" fn call(env: *mut js_env_t, info: *mut js_callback_info_t) -> *mut js_value_t {
523        let mut len: usize = 0;
524        let mut receiver: *mut js_value_t = ptr::null_mut();
525        let mut data: *mut c_void = ptr::null_mut();
526
527        unsafe {
528            js_get_callback_info(
529                env,
530                info,
531                &mut len,
532                ptr::null_mut(),
533                &mut receiver,
534                &mut data,
535            );
536        }
537
538        let mut args = Vec::new();
539
540        args.resize(len, ptr::null_mut());
541
542        if len > 0 {
543            unsafe {
544                js_get_callback_info(
545                    env,
546                    info,
547                    &mut len,
548                    args.as_mut_ptr(),
549                    ptr::null_mut(),
550                    ptr::null_mut(),
551                );
552            }
553        }
554
555        let closure: &mut Box<dyn FnMut(&Env, &Callback) -> *mut js_value_t> =
556            unsafe { &mut *(data as *mut Box<dyn FnMut(&Env, &Callback) -> *mut js_value_t>) };
557
558        return closure(
559            &Env::from(env),
560            &Callback {
561                env,
562                args,
563                receiver,
564            },
565        );
566    }
567
568    extern "C" fn drop(_: *mut js_env_t, data: *mut c_void, _: *mut c_void) -> () {
569        let _: Box<Box<dyn FnMut(&Env, &Callback)>> = unsafe { Box::from_raw(data as *mut _) };
570    }
571}
572
573impl From<Function> for *mut js_value_t {
574    fn from(function: Function) -> Self {
575        function.0.ptr
576    }
577}
578
579impl From<Value> for Function {
580    fn from(value: Value) -> Self {
581        Self(value)
582    }
583}
584
585pub struct ArrayBuffer(Value);
586
587impl ArrayBuffer {
588    pub fn new(env: &Env, len: usize) -> Result<Self> {
589        let mut ptr: *mut js_value_t = ptr::null_mut();
590
591        let status = unsafe { js_create_arraybuffer(env.ptr, len, ptr::null_mut(), &mut ptr) };
592
593        if status != 0 {
594            Err(status)
595        } else {
596            Ok(Self(Value { env: env.ptr, ptr }))
597        }
598    }
599
600    pub fn as_slice(&self) -> &[u8] {
601        self.as_mut_slice()
602    }
603
604    pub fn as_mut_slice(&self) -> &mut [u8] {
605        let mut len: usize = 0;
606        let mut data: *mut c_void = ptr::null_mut();
607
608        unsafe {
609            js_get_arraybuffer_info(self.0.env, self.0.ptr, &mut data, &mut len);
610        }
611
612        unsafe { slice::from_raw_parts_mut(data as *mut u8, len) }
613    }
614}
615
616impl From<ArrayBuffer> for *mut js_value_t {
617    fn from(arraybuffer: ArrayBuffer) -> Self {
618        arraybuffer.0.ptr
619    }
620}
621
622impl From<Value> for ArrayBuffer {
623    fn from(value: Value) -> Self {
624        Self(value)
625    }
626}
627
628pub trait TypedArray<T> {
629    fn as_slice(&self) -> &[T];
630    fn as_mut_slice(&self) -> &mut [T];
631}
632
633pub struct Uint8Array(Value);
634
635impl Uint8Array {
636    pub fn new(env: &Env, len: usize) -> Result<Self> {
637        let arraybuffer = ArrayBuffer::new(env, len)?;
638
639        let mut ptr: *mut js_value_t = ptr::null_mut();
640
641        let status = unsafe {
642            js_create_typedarray(
643                env.ptr,
644                js_typedarray_type_t::js_uint8array,
645                len,
646                arraybuffer.0.ptr,
647                0,
648                &mut ptr,
649            )
650        };
651
652        if status != 0 {
653            Err(status)
654        } else {
655            Ok(Self(Value { env: env.ptr, ptr }))
656        }
657    }
658}
659
660impl TypedArray<u8> for Uint8Array {
661    fn as_slice(&self) -> &[u8] {
662        self.as_mut_slice()
663    }
664
665    fn as_mut_slice(&self) -> &mut [u8] {
666        let mut len: usize = 0;
667        let mut data: *mut c_void = ptr::null_mut();
668
669        unsafe {
670            js_get_typedarray_info(
671                self.0.env,
672                self.0.ptr,
673                ptr::null_mut(),
674                &mut data,
675                &mut len,
676                ptr::null_mut(),
677                ptr::null_mut(),
678            );
679        }
680
681        unsafe { slice::from_raw_parts_mut(data as *mut u8, len) }
682    }
683}
684
685impl From<Uint8Array> for *mut js_value_t {
686    fn from(uint8array: Uint8Array) -> Self {
687        uint8array.0.ptr
688    }
689}
690
691impl From<Value> for Uint8Array {
692    fn from(value: Value) -> Self {
693        Self(value)
694    }
695}