use crate::proxy_wasm::hostcalls;
use crate::proxy_wasm::hostcalls::call_foreign_function;
use crate::proxy_wasm::types::{Bytes, Status};
use std::mem;
const U32_SIZE: usize = mem::size_of::<u32>();
fn get_shared_data(key: &str) -> Result<(Option<Bytes>, Option<u32>), Status> {
hostcalls::get_shared_data(key)
}
fn set_shared_data(key: &str, value: &[u8], version: Option<u32>) -> Result<(), Status> {
hostcalls::set_shared_data(
key,
if value.is_empty() { None } else { Some(value) },
version,
)
}
fn remove_shared_data(key: &str, version: Option<u32>) -> Result<Option<Bytes>, Status> {
let version: u32 = version.unwrap_or(0);
let mut arguments = Vec::from(key.as_bytes());
arguments.extend(version.to_le_bytes());
let result = call_foreign_function("remove_shared_data_key", Some(arguments.as_slice()));
match result {
Ok(bytes) => {
if let Some(bytes) = bytes {
let (value, _cas) = bytes.split_at(bytes.len() - U32_SIZE);
return Ok(Some(value.to_vec()));
}
Ok(None)
}
Err(Status::NotFound) => Ok(None),
Err(status) => Err(status),
}
}
fn keys_shared_data() -> Result<Vec<String>, Status> {
let result = call_foreign_function("get_shared_data_keys", None)?;
let keys = match result {
None => Vec::default(),
Some(bytes) => bytes
.split(|byte| (*byte) == 0)
.filter(|bytes| !bytes.is_empty())
.map(std::str::from_utf8)
.filter(|result| result.is_ok())
.map(|result| result.unwrap().to_string())
.collect(),
};
Ok(keys)
}
pub trait SharedData {
fn shared_data_get(&self, key: &str) -> (Option<Bytes>, Option<u32>);
fn shared_data_set(&self, key: &str, value: &[u8], version: Option<u32>) -> Result<(), Status>;
fn shared_data_remove(&self, key: &str, version: Option<u32>) -> Result<Option<Bytes>, Status>;
fn shared_data_keys(&self) -> Vec<String>;
}
pub struct DefaultSharedData;
impl SharedData for DefaultSharedData {
fn shared_data_get(&self, key: &str) -> (Option<Bytes>, Option<u32>) {
get_shared_data(key).unwrap_or_else(|e| {
log::warn!("Unhandled proxy-wasm error at DefaultSharedData::shared_data_get: {e:?}.");
(None, None)
})
}
fn shared_data_set(&self, key: &str, value: &[u8], cas: Option<u32>) -> Result<(), Status> {
set_shared_data(key, value, cas)
}
fn shared_data_remove(&self, key: &str, version: Option<u32>) -> Result<Option<Bytes>, Status> {
remove_shared_data(key, version)
}
fn shared_data_keys(&self) -> Vec<String> {
keys_shared_data().unwrap_or_default()
}
}