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}