#![allow(missing_docs)]
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
use wasmer_types::{
entity::{EntityRef, PrimaryMap},
DeserializeError, FunctionIndex, LocalFunctionIndex, OwnedDataInitializer, SerializeError,
SignatureIndex,
};
use super::{module::CompileModuleInfo, section::SectionIndex};
#[derive(
RkyvSerialize, RkyvDeserialize, Archive, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug,
)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[rkyv(derive(Debug), compare(PartialEq, PartialOrd))]
pub enum Symbol {
Metadata,
LocalFunction(LocalFunctionIndex),
Section(SectionIndex),
FunctionCallTrampoline(SignatureIndex),
DynamicFunctionTrampoline(FunctionIndex),
}
pub trait SymbolRegistry: Send + Sync {
fn symbol_to_name(&self, symbol: Symbol) -> String;
fn name_to_symbol(&self, name: &str) -> Option<Symbol>;
}
#[derive(Debug, RkyvSerialize, RkyvDeserialize, Archive)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[rkyv(derive(Debug))]
pub struct ModuleMetadata {
pub compile_info: CompileModuleInfo,
pub prefix: String,
pub data_initializers: Box<[OwnedDataInitializer]>,
pub function_body_lengths: PrimaryMap<LocalFunctionIndex, u64>,
pub cpu_features: u64,
}
pub struct ModuleMetadataSymbolRegistry {
pub prefix: String,
}
impl ModuleMetadata {
pub fn split(&mut self) -> (&mut CompileModuleInfo, ModuleMetadataSymbolRegistry) {
let compile_info = &mut self.compile_info;
let symbol_registry = ModuleMetadataSymbolRegistry {
prefix: self.prefix.clone(),
};
(compile_info, symbol_registry)
}
pub fn get_symbol_registry(&self) -> ModuleMetadataSymbolRegistry {
ModuleMetadataSymbolRegistry {
prefix: self.prefix.clone(),
}
}
pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
rkyv::to_bytes::<rkyv::rancor::Error>(self)
.map(|v| v.into_vec())
.map_err(|e| SerializeError::Generic(e.to_string()))
}
pub unsafe fn deserialize_unchecked(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
let archived = Self::archive_from_slice(metadata_slice)?;
Self::deserialize_from_archive(archived)
}
pub fn deserialize(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
let archived = Self::archive_from_slice_checked(metadata_slice)?;
Self::deserialize_from_archive(archived)
}
unsafe fn archive_from_slice(
metadata_slice: &[u8],
) -> Result<&ArchivedModuleMetadata, DeserializeError> {
Ok(rkyv::access_unchecked(metadata_slice))
}
fn archive_from_slice_checked(
metadata_slice: &[u8],
) -> Result<&ArchivedModuleMetadata, DeserializeError> {
rkyv::access::<_, rkyv::rancor::Error>(metadata_slice)
.map_err(|e| DeserializeError::CorruptedBinary(e.to_string()))
}
pub fn deserialize_from_archive(
archived: &ArchivedModuleMetadata,
) -> Result<Self, DeserializeError> {
rkyv::deserialize::<_, rkyv::rancor::Error>(archived)
.map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))
}
}
impl SymbolRegistry for ModuleMetadataSymbolRegistry {
fn symbol_to_name(&self, symbol: Symbol) -> String {
match symbol {
Symbol::Metadata => {
format!("WASMER_METADATA_{}", self.prefix.to_uppercase())
}
Symbol::LocalFunction(index) => {
format!("wasmer_function_{}_{}", self.prefix, index.index())
}
Symbol::Section(index) => format!("wasmer_section_{}_{}", self.prefix, index.index()),
Symbol::FunctionCallTrampoline(index) => {
format!(
"wasmer_trampoline_function_call_{}_{}",
self.prefix,
index.index()
)
}
Symbol::DynamicFunctionTrampoline(index) => {
format!(
"wasmer_trampoline_dynamic_function_{}_{}",
self.prefix,
index.index()
)
}
}
}
fn name_to_symbol(&self, name: &str) -> Option<Symbol> {
if name == self.symbol_to_name(Symbol::Metadata) {
Some(Symbol::Metadata)
} else if let Some(index) = name.strip_prefix(&format!("wasmer_function_{}_", self.prefix))
{
index
.parse::<u32>()
.ok()
.map(|index| Symbol::LocalFunction(LocalFunctionIndex::from_u32(index)))
} else if let Some(index) = name.strip_prefix(&format!("wasmer_section_{}_", self.prefix)) {
index
.parse::<u32>()
.ok()
.map(|index| Symbol::Section(SectionIndex::from_u32(index)))
} else if let Some(index) =
name.strip_prefix(&format!("wasmer_trampoline_function_call_{}_", self.prefix))
{
index
.parse::<u32>()
.ok()
.map(|index| Symbol::FunctionCallTrampoline(SignatureIndex::from_u32(index)))
} else if let Some(index) = name.strip_prefix(&format!(
"wasmer_trampoline_dynamic_function_{}_",
self.prefix
)) {
index
.parse::<u32>()
.ok()
.map(|index| Symbol::DynamicFunctionTrampoline(FunctionIndex::from_u32(index)))
} else {
None
}
}
}