use devela::{JsConsole, Str, js_int32, js_uint32};
#[cfg(all(feature = "alloc", unsafe··))]
use devela::{String, Vec};
#[doc = crate::_tags!(runtime namespace)]
#[doc = crate::_doc_location!("lang/prog/ffi/js")]
#[derive(Debug)]
pub struct Js;
#[rustfmt::skip]
impl Js {
pub fn console() -> JsConsole { JsConsole }
}
impl Js {
#[inline(always)]
pub fn read_str(
buffer: &mut [u8],
mut write_fn: impl FnMut(*mut u8, js_uint32) -> js_int32,
) -> &str {
let ptr = buffer.as_mut_ptr();
let cap = buffer.len() as js_uint32;
let len = write_fn(ptr, cap) as usize;
Str::from_utf8(&buffer[..len]).expect("Valid UTF-8") }
#[inline(always)]
#[cfg(not(feature = "safe_lang"))]
#[cfg(all(feature = "alloc", unsafe··))]
#[cfg_attr(nightly_doc, doc(cfg(all(feature = "alloc", unsafe··))))]
pub fn read_string(write_fn: impl FnMut(*mut u8, js_uint32) -> js_int32) -> String {
Js::read_string_capped(128, false, write_fn)
}
#[cfg(not(feature = "safe_lang"))]
#[cfg(all(feature = "alloc", unsafe··))]
#[cfg_attr(nightly_doc, doc(cfg(all(feature = "alloc", unsafe··))))]
pub fn read_string_capped(
mut cap: js_uint32,
truncate: bool,
mut write_fn: impl FnMut(*mut u8, js_uint32) -> js_int32,
) -> String {
loop {
let mut vec = Vec::with_capacity(cap as usize);
let ptr = vec.as_mut_ptr();
let result = write_fn(ptr, cap);
if !truncate && result < 0 {
cap = (-result) as js_uint32;
continue;
}
unsafe {
vec.set_len(result as usize);
return String::from_utf8_unchecked(vec);
}
}
}
}