use serde_json::Value;
use std::sync::Arc;
use crate::{MaybeSend, MaybeSync};
#[cfg(all(target_os = "wasi", target_env = "p1"))]
use std::cell::RefCell;
#[cfg(all(target_os = "wasi", target_env = "p1"))]
use std::collections::HashMap as StdHashMap;
#[cfg(not(all(target_os = "wasi", target_env = "p1")))]
pub type HashMap = Arc<dashmap::DashMap<String, Value>>;
#[cfg(all(target_os = "wasi", target_env = "p1"))]
pub type HashMap = Arc<RefCell<StdHashMap<String, Value>>>;
pub trait ExecutionState: MaybeSend + MaybeSync {
fn set_state(&self, key: &str, value: Value);
fn get_state(&self, key: &str) -> Option<Value>;
}
#[derive(Clone)]
pub struct DefaultExecutionState {
state: HashMap,
}
impl DefaultExecutionState {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[cfg(not(all(target_os = "wasi", target_env = "p1")))]
fn create_state() -> HashMap {
Arc::new(dashmap::DashMap::default())
}
#[cfg(all(target_os = "wasi", target_env = "p1"))]
fn create_state() -> HashMap {
Arc::new(RefCell::new(StdHashMap::new()))
}
}
impl Default for DefaultExecutionState {
fn default() -> Self {
Self {
state: Self::create_state(),
}
}
}
#[cfg(not(all(target_os = "wasi", target_env = "p1")))]
impl ExecutionState for DefaultExecutionState {
fn set_state(&self, key: &str, value: Value) {
self.state.insert(key.to_owned(), value);
}
fn get_state(&self, key: &str) -> Option<Value> {
self.state.get(key).map(|entry| entry.value().clone())
}
}
#[cfg(all(target_os = "wasi", target_env = "p1"))]
impl ExecutionState for DefaultExecutionState {
fn set_state(&self, key: &str, value: Value) {
self.state.borrow_mut().insert(key.to_owned(), value);
}
fn get_state(&self, key: &str) -> Option<Value> {
self.state.borrow().get(key).cloned()
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn default_execution_state_round_trips_values() {
let state = DefaultExecutionState::new();
assert!(state.get_state("missing").is_none());
state.set_state("key", json!(42));
assert_eq!(state.get_state("key"), Some(json!(42)));
}
}