Lines
93.15 %
Functions
20.51 %
Branches
100 %
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use finance::commodity::{Commodity, CommodityBuilder};
use log;
use rust_i18n::t;
use wasmtime::{Engine, Linker, Module, Store};
use crate::error::HookError;
use crate::wrappers::{
DataStore, wrap_wasm_i64, wrap_wasm_i64_get, wrap_wasm_str_list_get, wrap_wasm_str_map,
wrap_wasm_str_transform,
};
async fn update(
commodity: Commodity,
tags: Arc<Mutex<HashMap<String, String>>>,
script: &[u8],
) -> Result<Commodity, HookError> {
let engine = Engine::default();
let mut linker = Linker::new(&engine);
let mut builder = CommodityBuilder::new();
builder.id(commodity.id);
let store_data = Arc::new(DataStore {
data: Mutex::new((builder, commodity.fraction, tags.clone())),
memory: Mutex::new(None),
});
let mut store = Store::new(&engine, store_data.clone());
let set_frac = wrap_wasm_i64(&mut store, |builder, value| {
builder.0.fraction(value);
let get_frac = wrap_wasm_i64_get(&mut store, |builder| builder.1);
let module = Module::new(store.engine(), script).map_err(|e| {
log::error!("{}: {}", t!("Module creation error"), e);
HookError::WASM(e)
})?;
linker.define(&store, "env", "get_frac", get_frac)?;
linker.define(&store, "env", "set_frac", set_frac)?;
let get_tag_list = wrap_wasm_str_list_get(&mut store, |data| {
let tags = data
.2
.lock()
.map_err(|_| anyhow::anyhow!("Failed to lock tags"))?;
log::info!("{:?}", tags.keys().cloned());
Ok(tags.keys().cloned().collect())
linker.define(&store, "env", "get_tag_list", get_tag_list)?;
let update_tag = wrap_wasm_str_map(&mut store, |data, key, value| {
let mut tags = data
log::info!("Inserting {key:?} {value:?}");
tags.insert(key, value);
Ok(())
linker.define(&store, "env", "update_tag", update_tag)?;
let get_tag = wrap_wasm_str_transform(&mut store, |data, key| {
// Lock the tags HashMap
.map_err(|_| anyhow::anyhow!("Failed to lock tags HashMap"))?;
log::info!("Found value: {:?}", tags.get(&key).cloned());
// Fetch the value corresponding to the key
tags.get(&key)
.cloned()
.ok_or_else(|| anyhow::anyhow!("Key not found in tags: {}", key))
linker.define(&store, "env", "get_tag", get_tag)?;
let instance = linker.instantiate(&mut store, &module)?;
if let Some(memory) = instance.get_memory(&mut store, "memory") {
store_data.memory.lock()?.replace(memory);
} else {
log::error!("{}", t!("WASM memory access problem"));
return Err(HookError::WASMMem);
let process = instance.get_typed_func::<(), ()>(&mut store, "process")?;
process.call(&mut store, ())?;
log::info!("{:?}", store_data.clone().data.lock()?.2);
let result = store_data.clone().data.lock()?.0.build()?;
Ok(result)
}
pub async fn apply_commodity_hook(
hook: &[u8],
let updated = update(commodity, tags, hook).await?;
Ok(updated)