mod convert;
mod encoder;
mod extras;
mod layout;
mod streaming;
use convert::*;
use tensogram::{self as core, DecodeOptions};
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn decode(
buf: &[u8],
verify_hash: Option<bool>,
restore_non_finite: Option<bool>,
) -> Result<DecodedMessage, JsError> {
let options = DecodeOptions {
verify_hash: verify_hash.unwrap_or(false),
restore_non_finite: restore_non_finite.unwrap_or(true),
..Default::default()
};
let (metadata, objects) = core::decode(buf, &options).map_err(js_err)?;
Ok(DecodedMessage { metadata, objects })
}
#[wasm_bindgen]
pub fn decode_metadata(buf: &[u8]) -> Result<JsValue, JsError> {
let meta = core::decode_metadata(buf).map_err(js_err)?;
metadata_to_js(&meta)
}
#[wasm_bindgen]
pub fn decode_object(
buf: &[u8],
index: usize,
verify_hash: Option<bool>,
restore_non_finite: Option<bool>,
) -> Result<DecodedMessage, JsError> {
let options = DecodeOptions {
verify_hash: verify_hash.unwrap_or(false),
restore_non_finite: restore_non_finite.unwrap_or(true),
..Default::default()
};
let (metadata, descriptor, data) = core::decode_object(buf, index, &options).map_err(js_err)?;
Ok(DecodedMessage {
metadata,
objects: vec![(descriptor, data)],
})
}
#[wasm_bindgen]
pub fn scan(buf: &[u8]) -> Result<JsValue, JsError> {
let positions = core::scan(buf);
to_js(&positions)
}
#[wasm_bindgen]
#[allow(clippy::too_many_arguments)]
pub fn encode(
metadata_js: JsValue,
objects_js: js_sys::Array,
hash: Option<bool>,
allow_nan: Option<bool>,
allow_inf: Option<bool>,
nan_mask_method: Option<String>,
pos_inf_mask_method: Option<String>,
neg_inf_mask_method: Option<String>,
small_mask_threshold_bytes: Option<usize>,
) -> Result<js_sys::Uint8Array, JsError> {
let metadata = metadata_from_js(&metadata_js)?;
let (descriptors, data_vec) = extract_descriptor_data_pairs(&objects_js)?;
let pairs: Vec<(&core::DataObjectDescriptor, &[u8])> = descriptors
.iter()
.zip(data_vec.iter())
.map(|(d, v)| (d, v.as_slice()))
.collect();
let options = build_encode_options_full(
hash,
allow_nan,
allow_inf,
nan_mask_method.as_deref(),
pos_inf_mask_method.as_deref(),
neg_inf_mask_method.as_deref(),
small_mask_threshold_bytes,
)?;
let encoded = core::encode(&metadata, &pairs, &options).map_err(js_err)?;
Ok(js_sys::Uint8Array::from(encoded.as_slice()))
}
#[wasm_bindgen]
pub struct DecodedMessage {
metadata: core::GlobalMetadata,
objects: Vec<core::DecodedObject>,
}
#[wasm_bindgen]
impl DecodedMessage {
pub fn metadata(&self) -> Result<JsValue, JsError> {
metadata_to_js(&self.metadata)
}
pub fn object_count(&self) -> usize {
self.objects.len()
}
pub fn object_descriptor(&self, index: usize) -> Result<JsValue, JsError> {
let _ = self.payload(index)?;
to_js(&self.objects[index].0)
}
pub fn object_data_f32(&self, index: usize) -> Result<js_sys::Float32Array, JsError> {
let data = self.payload(index)?;
view_as_f32(data)
}
pub fn object_data_f64(&self, index: usize) -> Result<js_sys::Float64Array, JsError> {
let data = self.payload(index)?;
view_as_f64(data)
}
pub fn object_data_i32(&self, index: usize) -> Result<js_sys::Int32Array, JsError> {
let data = self.payload(index)?;
view_as_i32(data)
}
pub fn object_data_u8(&self, index: usize) -> Result<js_sys::Uint8Array, JsError> {
let data = self.payload(index)?;
Ok(view_as_u8(data))
}
pub fn object_data_copy_f32(&self, index: usize) -> Result<js_sys::Float32Array, JsError> {
let data = self.payload(index)?;
copy_as_f32(data)
}
pub fn object_byte_length(&self, index: usize) -> Result<usize, JsError> {
Ok(self.payload(index)?.len())
}
}
impl DecodedMessage {
fn payload(&self, index: usize) -> Result<&[u8], JsError> {
if index >= self.objects.len() {
return Err(JsError::new(&format!(
"object index {index} out of range (have {})",
self.objects.len()
)));
}
Ok(&self.objects[index].1)
}
pub(crate) fn from_single_object(
descriptor: core::DataObjectDescriptor,
data: Vec<u8>,
) -> Self {
Self {
metadata: core::GlobalMetadata::default(),
objects: vec![(descriptor, data)],
}
}
}
pub use streaming::StreamingDecoder;
pub use encoder::StreamingEncoder;
pub use layout::{
decode_object_from_frame, decode_range_from_frame, parse_descriptor_cbor, parse_footer_chunk,
parse_header_chunk, read_data_object_frame_footer, read_data_object_frame_header,
read_postamble_info, read_preamble_info,
};
pub use extras::{
compute_hash, decode_range, encode_pre_encoded, simple_packing_compute_params, validate_buffer,
};