use bstr::BString;
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use std::cell::OnceCell;
use std::rc::Rc;
use crate::symbols::{Symbol, SymbolTable};
use crate::types::TypeValue;
use crate::wasm::WasmExport;
thread_local! {
static BUILTIN_METHODS: OnceCell<Rc<SymbolTable>> = const { OnceCell::new() };
}
#[derive(Serialize, Deserialize)]
pub(crate) enum Map {
IntegerKeys {
deputy: Option<TypeValue>,
map: IndexMap<i64, TypeValue>,
},
StringKeys { deputy: Option<TypeValue>, map: IndexMap<BString, TypeValue> },
}
impl Map {
pub fn builtin_methods() -> Rc<SymbolTable> {
BUILTIN_METHODS.with(|cell| {
cell.get_or_init(|| {
let mut s = SymbolTable::new();
for (name, func) in WasmExport::get_methods("Map") {
s.insert(name, Symbol::Func(Rc::new(func)));
}
Rc::new(s)
})
.clone()
})
}
pub fn deputy(&self) -> TypeValue {
match self {
Map::IntegerKeys { deputy, .. } => {
deputy.as_ref().unwrap().clone()
}
Map::StringKeys { deputy, .. } => deputy.as_ref().unwrap().clone(),
}
}
pub fn with_integer_keys(&self) -> &IndexMap<i64, TypeValue> {
match self {
Map::IntegerKeys { map, .. } => map,
_ => panic!(
"calling `with_integers_keys` on an map that is not `Map::IntegerKeys`"
),
}
}
pub fn with_string_keys(&self) -> &IndexMap<BString, TypeValue> {
match self {
Map::StringKeys { map, .. } => map,
_ => panic!(
"calling `with_string_keys` on an map that is not `Map::StringKeys`"
),
}
}
pub fn len(&self) -> usize {
match self {
Map::IntegerKeys { map, .. } => map.len(),
Map::StringKeys { map, .. } => map.len(),
}
}
}