vertigo-cli 0.2.0-alpha

Reactive Real-DOM library for Rust - packaging tool
Documentation
use wasmtime::{
    AsContextMut,
    Caller,
    Extern,
    Instance,
    Memory,
    Store,
    StoreContextMut,
};

use crate::serve::request_state::RequestState;
use crate::serve::js_value::{JsValue, MemoryBlock};

pub enum DataContext<'a> {
    Caller {
        caller: Caller<'a, RequestState>,
    },
    Store {
        store: &'a mut Store<RequestState>,
        instance: Instance,
    }
}

impl<'a> DataContext<'a> {
    pub fn from_caller(caller: Caller<'a, RequestState>) -> Self {
        DataContext::Caller {
            caller,
        }
    }

    pub fn from_store(store: &'a mut Store<RequestState>, instance: Instance) -> Self {
        DataContext::Store {
            store,
            instance
        }
    }

    fn get_context(&mut self) -> StoreContextMut<'_, RequestState> {
        match self {
            Self::Caller { caller } => caller.as_context_mut(),
            Self::Store { store, ..} => store.as_context_mut(),
        }
    }
    fn get_memory(&mut self) -> Memory {
        match self {
            Self::Caller { caller } => {
                let Some(Extern::Memory(memory)) = caller.get_export("memory") else {
                    unreachable!()
                };

                memory
            },
            Self::Store { instance, store } => {
                let context = store.as_context_mut();
                let Some(Extern::Memory(memory)) = instance.get_export(context, "memory") else {
                    unreachable!();
                };

                memory
            }
        }
    }

    pub fn get_value(&mut self, ptr: u32, offset: u32) -> JsValue {
        let memory = self.get_memory();
        let context = self.get_context();

        let buff = memory.data(&context);

        let ptr = ptr as usize;
        let offset = offset as usize;

        let slice = &buff[ptr..(ptr+offset)];

        let block = MemoryBlock::from_slice(slice);
        match JsValue::from_block(block) {
            Ok(value) => value,
            Err(error) => {
                log::info!("JsValue decoding problem, error={error}");
                JsValue::Undefined
            }
        }
    }

    pub fn get_string_from(&mut self, ptr: u32, offset: u32) -> Option<String> {
        let memory = self.get_memory();
        let context = self.get_context();
        let buff = memory.data(&context);

        let ptr = ptr as usize;
        let offset = offset as usize;

        let slice = &buff[ptr..(ptr+offset)];

        let slice_vec = Vec::from(slice);

        let Ok(result) = String::from_utf8(slice_vec) else {
            log::error!("panic message decoding problem");
            return None;
        };

        Some(result)
    }

    fn alloc(&mut self, size: usize) -> usize {
        let alloc_inner = match self {
            Self::Caller { caller, .. } => {
                let Some(Extern::Func(alloc_inner)) = caller.get_export("alloc") else {
                    unreachable!();
                };
                alloc_inner
            },
            Self::Store { store, instance, .. } => {
                let Some(Extern::Func(alloc_inner)) = instance.get_export(store, "alloc") else {
                    unreachable!();
                };

                alloc_inner
            }
        };

        let mut context = self.get_context();
        let alloc = alloc_inner.typed::<u32, u32>(&mut context).unwrap();

        alloc.call(&mut context, size as u32).unwrap() as usize
    }

    pub fn save_value(&mut self, value: JsValue) -> u32 {
        if let JsValue::Undefined = value {
            return 0;
        }

        let block = value.to_snapshot();
        let block = block.convert_to_vec();
        let size = block.len();

        let ptr = self.alloc(size);

        let memory = self.get_memory();
        let context = self.get_context();
        let buff = memory.data_mut(context);

        buff[ptr..(ptr+size)].clone_from_slice(block.as_slice());

        ptr as u32
    }

}