#[cfg(feature = "alloc")]
use devela::String;
use devela::{js_bool, js_number, js_uint32};
#[doc = crate::_tags!(runtime value)]
#[doc = crate::_doc_location!("lang/prog/ffi/js")]
#[non_exhaustive]
#[derive(Clone, Debug, PartialEq)]
#[allow(missing_docs)]
pub enum JsValue {
Null,
Undefined,
Boolean(js_bool),
Object(js_uint32),
Str(&'static str),
#[cfg(feature = "alloc")]
#[cfg_attr(nightly_doc, doc(cfg(feature = "alloc")))]
String(String),
Number(js_number),
}
impl JsValue {
#[inline(always)]
pub const fn type_tag(&self) -> u8 {
match self {
Self::Null => 0,
Self::Undefined => 1,
Self::Boolean(_) => 2,
Self::Object(_) => 3,
Self::Str(_) => 4,
#[cfg(feature = "alloc")]
Self::String(_) => 5,
Self::Number(_) => 6,
}
}
pub fn encode_into(&self, buf: &mut [u8]) -> usize {
let mut offset = 0;
buf[offset] = self.type_tag();
offset += 1;
match self {
Self::Boolean(b) => {
buf[offset] = *b as u8;
offset += 1;
}
Self::Object(handle) => {
buf[offset..offset + 4].copy_from_slice(&handle.to_le_bytes());
offset += 4;
}
Self::Str(s) => {
offset += self.encode_str(s, &mut buf[offset..]);
}
#[cfg(feature = "alloc")]
Self::String(s) => {
offset += self.encode_str(s.as_str(), &mut buf[offset..]);
}
Self::Number(n) => {
buf[offset..offset + 8].copy_from_slice(&n.to_le_bytes());
offset += 8;
}
Self::Null | Self::Undefined => (),
}
offset
}
#[inline(always)]
fn encode_str(&self, s: &str, buf: &mut [u8]) -> usize {
let (bytes, len) = (s.as_bytes(), s.len());
buf[..4].copy_from_slice(&(len as u32).to_le_bytes()); buf[4..4 + len].copy_from_slice(bytes); 4 + len }
}