wasmer_types/
serialize.rs#![allow(missing_docs)]
use crate::entity::PrimaryMap;
use crate::{
compilation::target::CpuFeature, CompileModuleInfo, CompiledFunctionFrameInfo, CustomSection,
DeserializeError, Dwarf, Features, FunctionBody, FunctionIndex, LocalFunctionIndex,
MemoryIndex, MemoryStyle, ModuleInfo, OwnedDataInitializer, Relocation, SectionIndex,
SerializeError, SignatureIndex, TableIndex, TableStyle,
};
use enumset::EnumSet;
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
use std::convert::TryInto;
use std::mem;
#[derive(Archive, Default, RkyvDeserialize, RkyvSerialize)]
#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
#[allow(missing_docs)]
#[rkyv(derive(Debug))]
pub struct SerializableCompilation {
pub function_bodies: PrimaryMap<LocalFunctionIndex, FunctionBody>,
pub function_relocations: PrimaryMap<LocalFunctionIndex, Vec<Relocation>>,
pub function_frame_info: PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>,
pub function_call_trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
pub dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
pub custom_sections: PrimaryMap<SectionIndex, CustomSection>,
pub custom_section_relocations: PrimaryMap<SectionIndex, Vec<Relocation>>,
pub debug: Option<Dwarf>,
pub libcall_trampolines: SectionIndex,
pub libcall_trampoline_len: u32,
}
impl SerializableCompilation {
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()))
}
}
#[derive(Archive, RkyvDeserialize, RkyvSerialize)]
#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
#[allow(missing_docs)]
#[rkyv(derive(Debug))]
pub struct SerializableModule {
pub compilation: SerializableCompilation,
pub compile_info: CompileModuleInfo,
pub data_initializers: Box<[OwnedDataInitializer]>,
pub cpu_features: u64,
}
impl SerializableModule {
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 unsafe fn deserialize(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
let archived = Self::archive_from_slice_checked(metadata_slice)?;
Self::deserialize_from_archive(archived)
}
pub unsafe fn archive_from_slice(
metadata_slice: &[u8],
) -> Result<&ArchivedSerializableModule, DeserializeError> {
Ok(rkyv::access_unchecked(metadata_slice))
}
pub fn archive_from_slice_checked(
metadata_slice: &[u8],
) -> Result<&ArchivedSerializableModule, DeserializeError> {
rkyv::access::<_, rkyv::rancor::Error>(metadata_slice)
.map_err(|e| DeserializeError::CorruptedBinary(e.to_string()))
}
pub fn deserialize_from_archive(
archived: &ArchivedSerializableModule,
) -> Result<Self, DeserializeError> {
rkyv::deserialize::<_, rkyv::rancor::Error>(archived)
.map_err(|e| DeserializeError::CorruptedBinary(e.to_string()))
}
pub fn create_module_info(&self) -> ModuleInfo {
self.compile_info.module.as_ref().clone()
}
pub fn module_info(&self) -> &ModuleInfo {
&self.compile_info.module
}
pub fn features(&self) -> &Features {
&self.compile_info.features
}
pub fn cpu_features(&self) -> EnumSet<CpuFeature> {
EnumSet::from_u64(self.cpu_features)
}
pub fn data_initializers(&self) -> &[OwnedDataInitializer] {
&self.data_initializers
}
pub fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
&self.compile_info.memory_styles
}
pub fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
&self.compile_info.table_styles
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct MetadataHeader {
magic: [u8; 8],
version: u32,
len: u32,
}
impl MetadataHeader {
pub const CURRENT_VERSION: u32 = 8;
const MAGIC: [u8; 8] = *b"WASMER\0\0";
pub const LEN: usize = 16;
pub const ALIGN: usize = 16;
pub fn new(len: usize) -> Self {
Self {
magic: Self::MAGIC,
version: Self::CURRENT_VERSION,
len: len.try_into().expect("metadata exceeds maximum length"),
}
}
pub fn into_bytes(self) -> [u8; 16] {
unsafe { mem::transmute(self) }
}
pub fn parse(bytes: &[u8]) -> Result<usize, DeserializeError> {
if bytes.as_ptr() as usize % 8 != 0 {
return Err(DeserializeError::CorruptedBinary(
"misaligned metadata".to_string(),
));
}
let bytes: [u8; 16] = bytes
.get(..16)
.ok_or_else(|| {
DeserializeError::CorruptedBinary("invalid metadata header".to_string())
})?
.try_into()
.unwrap();
let header: Self = unsafe { mem::transmute(bytes) };
if header.magic != Self::MAGIC {
return Err(DeserializeError::Incompatible(
"The provided bytes were not serialized by Wasmer".to_string(),
));
}
if header.version != Self::CURRENT_VERSION {
return Err(DeserializeError::Incompatible(
"The provided bytes were serialized by an incompatible version of Wasmer"
.to_string(),
));
}
Ok(header.len as usize)
}
}