basisu_c_sys 0.7.1

Rust binding and wrappers for the Basis Universal pure C API
Documentation
use async_lock::OnceCell as AsyncOnceCell;
use js_sys::{Object, Reflect, Uint8Array};
use std::cell::OnceCell;

#[repr(transparent)]
#[derive(Debug, Copy, Clone)]
pub struct Bool32(pub u32);

impl Bool32 {
    pub fn is_ok(&self) -> bool {
        self.0 != 0
    }
    pub fn is_err(&self) -> bool {
        !self.is_ok()
    }
}

mod binding {
    use js_sys::Uint8Array;
    use wasm_bindgen::prelude::*;

    #[cfg(feature = "encoder")]
    include!(concat!(env!("OUT_DIR"), "/wasm_encoder_binding.rs"));
    #[cfg(not(feature = "encoder"))]
    include!(concat!(env!("OUT_DIR"), "/wasm_transcoder_binding.rs"));
}
use binding::Basisu;

#[cfg(feature = "encoder")]
const BASISU_WASM: &[u8] = include_bytes!("../wasm/basisu_encoder.wasm");
#[cfg(not(feature = "encoder"))]
const BASISU_WASM: &[u8] = include_bytes!("../wasm/basisu_transcoder.wasm");

thread_local! {
    static BASISU_INSTANCE: OnceCell<Basisu> = OnceCell::new();
}

static BASISU_INITIALIZED: AsyncOnceCell<()> = AsyncOnceCell::new();

mod instance {
    use js_sys::Object;
    use wasm_bindgen::prelude::wasm_bindgen;

    use crate::web::binding::Basisu;

    #[cfg(feature = "encoder")]
    #[wasm_bindgen(module = "/wasm/basisu_encoder.js")]
    extern "C" {
        #[wasm_bindgen(js_name = "default")]
        pub async fn new_instance(args: &Object) -> Basisu;
    }

    #[cfg(not(feature = "encoder"))]
    #[wasm_bindgen(module = "/wasm/basisu_transcoder.js")]
    extern "C" {
        #[wasm_bindgen(js_name = "default")]
        pub async fn new_instance(args: &Object) -> Basisu;
    }
}

/// Instantiate the embedded basisu wasm, required on web before calling other functions.
/// This is no-op on native platforms.
pub async fn instantiate_embedded_basisu_wasm() {
    BASISU_INITIALIZED
        .get_or_init(async || {
            let binary = Uint8Array::new_from_slice(BASISU_WASM);
            let args = Object::new();
            Reflect::set(&args, &"wasmBinary".into(), &binary).unwrap();
            let instance = instance::new_instance(&args).await;
            BASISU_INSTANCE.with(|cell| {
                cell.set(instance).unwrap();
            });
            ()
        })
        .await;
}

#[cfg(feature = "encoder")]
#[cfg_attr(docsrs, doc(cfg(feature = "encoder")))]
pub mod encoder {
    use super::BASISU_INSTANCE;
    use super::Bool32;
    include!(concat!(env!("OUT_DIR"), "/wasm_encoder_pub_funcs.rs"));
}

pub mod transcoder {
    use super::BASISU_INSTANCE;
    use super::Bool32;
    include!(concat!(env!("OUT_DIR"), "/wasm_transcoder_pub_funcs.rs"));
}

pub(crate) unsafe fn copy_host_memory_to_basisu_impl(data: &[u8], basisu_ptr: u64) {
    BASISU_INSTANCE.with(|inst| {
        let inst = inst.get().unwrap();
        inst.wasm_heap_memory()
            .set(&Uint8Array::from(data), basisu_ptr as u32);
    });
}

pub(crate) unsafe fn copy_basisu_memory_to_host_impl(
    basisu_ptr: u64,
    count: u64,
) -> alloc::vec::Vec<u8> {
    BASISU_INSTANCE.with(|inst| {
        let inst = inst.get().unwrap();
        inst.wasm_heap_memory()
            .subarray(basisu_ptr as u32, (basisu_ptr + count) as u32)
            .to_vec()
    })
}