use std::collections::{hash_map, HashMap};
use std::convert::TryFrom;
use unc_vm_types::FunctionType;
#[repr(C)]
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
pub struct VMSharedSignatureIndex(u32);
impl VMSharedSignatureIndex {
pub fn new(value: u32) -> Self {
Self(value)
}
}
#[derive(Debug)]
pub struct SignatureRegistry {
type_to_index: HashMap<FunctionType, VMSharedSignatureIndex>,
index_to_data: Vec<FunctionType>,
}
impl SignatureRegistry {
pub fn new() -> Self {
Self { type_to_index: HashMap::new(), index_to_data: Vec::new() }
}
pub fn register(&mut self, sig: FunctionType) -> VMSharedSignatureIndex {
let len = self.index_to_data.len();
match self.type_to_index.entry(sig.clone()) {
hash_map::Entry::Occupied(entry) => *entry.get(),
hash_map::Entry::Vacant(entry) => {
debug_assert!(
u32::try_from(len).is_ok(),
"invariant: can't have more than 2³²-1 signatures!"
);
let sig_id = VMSharedSignatureIndex::new(u32::try_from(len).unwrap());
entry.insert(sig_id);
self.index_to_data.push(sig);
sig_id
}
}
}
pub fn lookup(&self, idx: VMSharedSignatureIndex) -> Option<&FunctionType> {
self.index_to_data.get(idx.0 as usize)
}
}