mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-10 14:48:27 +00:00
feat: Implement safe, checked module artifact deserialization
Enable rkyv validation of serialized module artifacts. Required additions: * derive the required CheckBytes trait for all types * Add `_checked` variants of all the deserialization functions Also enables the `strict` feature of rkyv by default. This will ensure consistent archive binary layout across architectures and Rust compiler versions.
This commit is contained in:
committed by
Christoph Herzog
parent
9cb4bf32c9
commit
47cc5bbf99
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -5709,6 +5709,7 @@ dependencies = [
|
|||||||
name = "wasmer-types"
|
name = "wasmer-types"
|
||||||
version = "3.2.0-beta.1"
|
version = "3.2.0-beta.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bytecheck",
|
||||||
"enum-iterator",
|
"enum-iterator",
|
||||||
"enumset",
|
"enumset",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
|||||||
@@ -238,6 +238,18 @@ impl Module {
|
|||||||
return Err(DeserializeError::Generic("You need to enable the `js-serializable-module` feature flag to deserialize a `Module`".to_string()));
|
return Err(DeserializeError::Generic("You need to enable the `js-serializable-module` feature flag to deserialize a `Module`".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deserialize_checked(
|
||||||
|
_engine: &impl AsEngineRef,
|
||||||
|
_bytes: impl IntoBytes,
|
||||||
|
) -> Result<Self, DeserializeError> {
|
||||||
|
#[cfg(feature = "js-serializable-module")]
|
||||||
|
return Self::from_binary(_engine, &_bytes.into_bytes())
|
||||||
|
.map_err(|e| DeserializeError::Compiler(e));
|
||||||
|
|
||||||
|
#[cfg(not(feature = "js-serializable-module"))]
|
||||||
|
return Err(DeserializeError::Generic("You need to enable the `js-serializable-module` feature flag to deserialize a `Module`".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn deserialize_from_file(
|
pub unsafe fn deserialize_from_file(
|
||||||
engine: &impl AsEngineRef,
|
engine: &impl AsEngineRef,
|
||||||
path: impl AsRef<Path>,
|
path: impl AsRef<Path>,
|
||||||
@@ -246,6 +258,14 @@ impl Module {
|
|||||||
Self::deserialize(engine, bytes)
|
Self::deserialize(engine, bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deserialize_from_file_checked(
|
||||||
|
engine: &impl AsEngineRef,
|
||||||
|
path: impl AsRef<Path>,
|
||||||
|
) -> Result<Self, DeserializeError> {
|
||||||
|
let bytes = std::fs::read(path.as_ref())?;
|
||||||
|
Self::deserialize_checked(engine, bytes)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_name(&mut self, name: &str) -> bool {
|
pub fn set_name(&mut self, name: &str) -> bool {
|
||||||
self.name = Some(name.to_string());
|
self.name = Some(name.to_string());
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -219,6 +219,8 @@ impl Module {
|
|||||||
|
|
||||||
/// Deserializes a serialized Module binary into a `Module`.
|
/// Deserializes a serialized Module binary into a `Module`.
|
||||||
///
|
///
|
||||||
|
/// Note: You should usually prefer the safe [`Module::deserialize_checked`].
|
||||||
|
///
|
||||||
/// # Important
|
/// # Important
|
||||||
///
|
///
|
||||||
/// This function only accepts a custom binary format, which will be different
|
/// This function only accepts a custom binary format, which will be different
|
||||||
@@ -253,6 +255,56 @@ impl Module {
|
|||||||
Ok(Self(module_imp::Module::deserialize(engine, bytes)?))
|
Ok(Self(module_imp::Module::deserialize(engine, bytes)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deserializes a serialized Module binary into a `Module`.
|
||||||
|
///
|
||||||
|
/// # Important
|
||||||
|
///
|
||||||
|
/// This function only accepts a custom binary format, which will be different
|
||||||
|
/// than the `wasm` binary format and may change among Wasmer versions.
|
||||||
|
/// (it should be the result of the serialization of a Module via the
|
||||||
|
/// `Module::serialize` method.).
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// # use wasmer::*;
|
||||||
|
/// # fn main() -> anyhow::Result<()> {
|
||||||
|
/// # let mut store = Store::default();
|
||||||
|
/// let module = Module::deserialize_checked(&store, serialized_data)?;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub fn deserialize_checked(
|
||||||
|
engine: &impl AsEngineRef,
|
||||||
|
bytes: impl IntoBytes,
|
||||||
|
) -> Result<Self, DeserializeError> {
|
||||||
|
Ok(Self(module_imp::Module::deserialize_checked(
|
||||||
|
engine, bytes,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserializes a a serialized Module located in a `Path` into a `Module`.
|
||||||
|
/// > Note: the module has to be serialized before with the `serialize` method.
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// # use wasmer::*;
|
||||||
|
/// # let mut store = Store::default();
|
||||||
|
/// # fn main() -> anyhow::Result<()> {
|
||||||
|
/// let module = Module::deserialize_from_file(&store, path)?;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub fn deserialize_from_file_checked(
|
||||||
|
engine: &impl AsEngineRef,
|
||||||
|
path: impl AsRef<Path>,
|
||||||
|
) -> Result<Self, DeserializeError> {
|
||||||
|
Ok(Self(module_imp::Module::deserialize_from_file_checked(
|
||||||
|
engine, path,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
|
||||||
/// Deserializes a a serialized Module located in a `Path` into a `Module`.
|
/// Deserializes a a serialized Module located in a `Path` into a `Module`.
|
||||||
/// > Note: the module has to be serialized before with the `serialize` method.
|
/// > Note: the module has to be serialized before with the `serialize` method.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -78,6 +78,19 @@ impl Module {
|
|||||||
Ok(Self::from_artifact(artifact))
|
Ok(Self::from_artifact(artifact))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deserialize_checked(
|
||||||
|
engine: &impl AsEngineRef,
|
||||||
|
bytes: impl IntoBytes,
|
||||||
|
) -> Result<Self, DeserializeError> {
|
||||||
|
let bytes = bytes.into_bytes();
|
||||||
|
let artifact = engine
|
||||||
|
.as_engine_ref()
|
||||||
|
.engine()
|
||||||
|
.0
|
||||||
|
.deserialize_checked(&bytes)?;
|
||||||
|
Ok(Self::from_artifact(artifact))
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn deserialize_from_file(
|
pub unsafe fn deserialize_from_file(
|
||||||
engine: &impl AsEngineRef,
|
engine: &impl AsEngineRef,
|
||||||
path: impl AsRef<Path>,
|
path: impl AsRef<Path>,
|
||||||
@@ -90,6 +103,18 @@ impl Module {
|
|||||||
Ok(Self::from_artifact(artifact))
|
Ok(Self::from_artifact(artifact))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deserialize_from_file_checked(
|
||||||
|
engine: &impl AsEngineRef,
|
||||||
|
path: impl AsRef<Path>,
|
||||||
|
) -> Result<Self, DeserializeError> {
|
||||||
|
let artifact = engine
|
||||||
|
.as_engine_ref()
|
||||||
|
.engine()
|
||||||
|
.0
|
||||||
|
.deserialize_from_file_checked(path.as_ref())?;
|
||||||
|
Ok(Self::from_artifact(artifact))
|
||||||
|
}
|
||||||
|
|
||||||
fn from_artifact(artifact: Arc<Artifact>) -> Self {
|
fn from_artifact(artifact: Arc<Artifact>) -> Self {
|
||||||
Self { artifact }
|
Self { artifact }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,6 +148,30 @@ impl Artifact {
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
/// This function is unsafe because rkyv reads directly without validating
|
/// This function is unsafe because rkyv reads directly without validating
|
||||||
/// the data.
|
/// the data.
|
||||||
|
pub fn deserialize_checked(engine: &Engine, bytes: &[u8]) -> Result<Self, DeserializeError> {
|
||||||
|
if !ArtifactBuild::is_deserializable(bytes) {
|
||||||
|
return Err(DeserializeError::Incompatible(
|
||||||
|
"Magic header not found".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let bytes = Self::get_byte_slice(bytes, ArtifactBuild::MAGIC_HEADER.len(), bytes.len())?;
|
||||||
|
|
||||||
|
let metadata_len = MetadataHeader::parse(bytes)?;
|
||||||
|
let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
|
||||||
|
let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
|
||||||
|
|
||||||
|
let serializable = SerializableModule::deserialize_checked(metadata_slice)?;
|
||||||
|
let artifact = ArtifactBuild::from_serializable(serializable);
|
||||||
|
let mut inner_engine = engine.inner_mut();
|
||||||
|
Self::from_parts(&mut inner_engine, artifact, engine.target())
|
||||||
|
.map_err(DeserializeError::Compiler)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize a ArtifactBuild
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// This function is unsafe because rkyv reads directly without validating the data.
|
||||||
pub unsafe fn deserialize(engine: &Engine, bytes: &[u8]) -> Result<Self, DeserializeError> {
|
pub unsafe fn deserialize(engine: &Engine, bytes: &[u8]) -> Result<Self, DeserializeError> {
|
||||||
if !ArtifactBuild::is_deserializable(bytes) {
|
if !ArtifactBuild::is_deserializable(bytes) {
|
||||||
let static_artifact = Self::deserialize_object(engine, bytes);
|
let static_artifact = Self::deserialize_object(engine, bytes);
|
||||||
|
|||||||
@@ -200,12 +200,28 @@ impl Engine {
|
|||||||
Ok(Arc::new(Artifact::deserialize(self, bytes)?))
|
Ok(Arc::new(Artifact::deserialize(self, bytes)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deserializes a WebAssembly module
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub fn deserialize_checked(&self, bytes: &[u8]) -> Result<Arc<Artifact>, DeserializeError> {
|
||||||
|
Ok(Arc::new(Artifact::deserialize_checked(self, bytes)?))
|
||||||
|
}
|
||||||
|
|
||||||
/// Deserializes a WebAssembly module from a path
|
/// Deserializes a WebAssembly module from a path
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub fn deserialize_from_file_checked(
|
||||||
|
&self,
|
||||||
|
file_ref: &Path,
|
||||||
|
) -> Result<Arc<Artifact>, DeserializeError> {
|
||||||
|
let contents = std::fs::read(file_ref)?;
|
||||||
|
self.deserialize_checked(&contents)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize from a file path.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The file's content must represent a serialized WebAssembly module.
|
/// See [`crate::Module::deserialize_from_file`].
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub unsafe fn deserialize_from_file(
|
pub unsafe fn deserialize_from_file(
|
||||||
&self,
|
&self,
|
||||||
file_ref: &Path,
|
file_ref: &Path,
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ serde_bytes = { version = "0.11", optional = true }
|
|||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
more-asserts = "0.2"
|
more-asserts = "0.2"
|
||||||
indexmap = { version = "1.6" }
|
indexmap = { version = "1.6" }
|
||||||
rkyv = { version = "0.7.40", features = ["indexmap"] }
|
rkyv = { version = "0.7.40", features = ["indexmap", "validation", "strict"] }
|
||||||
enum-iterator = "0.7.0"
|
enum-iterator = "0.7.0"
|
||||||
target-lexicon = { version = "0.12.2", default-features = false }
|
target-lexicon = { version = "0.12.2", default-features = false }
|
||||||
enumset = "1.0"
|
enumset = "1.0"
|
||||||
|
bytecheck = "0.6.8"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
memoffset = "0.6"
|
memoffset = "0.6"
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
/// Single source location to generated address mapping.
|
/// Single source location to generated address mapping.
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[archive_attr(derive(rkyv::CheckBytes))]
|
||||||
pub struct InstructionAddressMap {
|
pub struct InstructionAddressMap {
|
||||||
/// Original source location.
|
/// Original source location.
|
||||||
pub srcloc: SourceLoc,
|
pub srcloc: SourceLoc,
|
||||||
@@ -24,6 +25,7 @@ pub struct InstructionAddressMap {
|
|||||||
/// Function and its instructions addresses mappings.
|
/// Function and its instructions addresses mappings.
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)]
|
||||||
|
#[archive_attr(derive(rkyv::CheckBytes))]
|
||||||
pub struct FunctionAddressMap {
|
pub struct FunctionAddressMap {
|
||||||
/// Instructions maps.
|
/// Instructions maps.
|
||||||
/// The array is sorted by the InstructionAddressMap::code_offset field.
|
/// The array is sorted by the InstructionAddressMap::code_offset field.
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
/// the frame information after a `Trap`.
|
/// the frame information after a `Trap`.
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)]
|
||||||
|
#[archive_attr(derive(rkyv::CheckBytes))]
|
||||||
pub struct CompiledFunctionFrameInfo {
|
pub struct CompiledFunctionFrameInfo {
|
||||||
/// The traps (in the function body).
|
/// The traps (in the function body).
|
||||||
///
|
///
|
||||||
@@ -34,6 +35,7 @@ pub struct CompiledFunctionFrameInfo {
|
|||||||
/// The function body.
|
/// The function body.
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[archive_attr(derive(rkyv::CheckBytes))]
|
||||||
pub struct FunctionBody {
|
pub struct FunctionBody {
|
||||||
/// The function body bytes.
|
/// The function body bytes.
|
||||||
#[cfg_attr(feature = "enable-serde", serde(with = "serde_bytes"))]
|
#[cfg_attr(feature = "enable-serde", serde(with = "serde_bytes"))]
|
||||||
@@ -50,6 +52,7 @@ pub struct FunctionBody {
|
|||||||
/// and unwind information).
|
/// and unwind information).
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[archive_attr(derive(rkyv::CheckBytes))]
|
||||||
pub struct CompiledFunction {
|
pub struct CompiledFunction {
|
||||||
/// The function body.
|
/// The function body.
|
||||||
pub body: FunctionBody,
|
pub body: FunctionBody,
|
||||||
@@ -74,7 +77,9 @@ pub type CustomSections = PrimaryMap<SectionIndex, CustomSection>;
|
|||||||
/// In the future this structure may also hold other information useful
|
/// In the future this structure may also hold other information useful
|
||||||
/// for debugging.
|
/// for debugging.
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, PartialEq, Eq, Clone)]
|
#[derive(
|
||||||
|
RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Debug, PartialEq, Eq, Clone,
|
||||||
|
)]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
pub struct Dwarf {
|
pub struct Dwarf {
|
||||||
/// The section index in the [`Compilation`] that corresponds to the exception frames.
|
/// The section index in the [`Compilation`] that corresponds to the exception frames.
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use std::sync::Arc;
|
|||||||
/// or the `MemoryStyle` and `TableStyle`).
|
/// or the `MemoryStyle` and `TableStyle`).
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(Debug, Clone, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
|
#[archive_attr(derive(rkyv::CheckBytes))]
|
||||||
pub struct CompileModuleInfo {
|
pub struct CompileModuleInfo {
|
||||||
/// The features used for compiling the module
|
/// The features used for compiling the module
|
||||||
pub features: Features,
|
pub features: Features,
|
||||||
|
|||||||
@@ -21,8 +21,11 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
/// Relocation kinds for every ISA.
|
/// Relocation kinds for every ISA.
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(
|
||||||
|
RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Copy, Clone, Debug, PartialEq, Eq,
|
||||||
|
)]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum RelocationKind {
|
pub enum RelocationKind {
|
||||||
/// absolute 4-byte
|
/// absolute 4-byte
|
||||||
Abs4,
|
Abs4,
|
||||||
@@ -90,6 +93,7 @@ impl fmt::Display for RelocationKind {
|
|||||||
/// A record of a relocation to perform.
|
/// A record of a relocation to perform.
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[archive_attr(derive(rkyv::CheckBytes))]
|
||||||
pub struct Relocation {
|
pub struct Relocation {
|
||||||
/// The relocation kind.
|
/// The relocation kind.
|
||||||
pub kind: RelocationKind,
|
pub kind: RelocationKind,
|
||||||
@@ -103,8 +107,11 @@ pub struct Relocation {
|
|||||||
|
|
||||||
/// Destination function. Can be either user function or some special one, like `memory.grow`.
|
/// Destination function. Can be either user function or some special one, like `memory.grow`.
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(
|
||||||
|
RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Debug, Copy, Clone, PartialEq, Eq,
|
||||||
|
)]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum RelocationTarget {
|
pub enum RelocationTarget {
|
||||||
/// A relocation to a function defined locally in the wasm (not an imported one).
|
/// A relocation to a function defined locally in the wasm (not an imported one).
|
||||||
LocalFunc(LocalFunctionIndex),
|
LocalFunc(LocalFunctionIndex),
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
Archive,
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
Copy,
|
Copy,
|
||||||
Clone,
|
Clone,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
@@ -37,8 +38,11 @@ entity_impl!(SectionIndex);
|
|||||||
///
|
///
|
||||||
/// Determines how a custom section may be used.
|
/// Determines how a custom section may be used.
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
|
#[derive(
|
||||||
|
RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Debug, Clone, PartialEq, Eq,
|
||||||
|
)]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum CustomSectionProtection {
|
pub enum CustomSectionProtection {
|
||||||
/// A custom section with read permission.
|
/// A custom section with read permission.
|
||||||
Read,
|
Read,
|
||||||
@@ -53,6 +57,7 @@ pub enum CustomSectionProtection {
|
|||||||
/// in the emitted module.
|
/// in the emitted module.
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[archive_attr(derive(rkyv::CheckBytes))]
|
||||||
pub struct CustomSection {
|
pub struct CustomSection {
|
||||||
/// Memory protection that applies to this section.
|
/// Memory protection that applies to this section.
|
||||||
pub protection: CustomSectionProtection,
|
pub protection: CustomSectionProtection,
|
||||||
@@ -72,6 +77,7 @@ pub struct CustomSection {
|
|||||||
/// The bytes in the section.
|
/// The bytes in the section.
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)]
|
||||||
|
#[archive_attr(derive(rkyv::CheckBytes))]
|
||||||
pub struct SectionBody(#[cfg_attr(feature = "enable-serde", serde(with = "serde_bytes"))] Vec<u8>);
|
pub struct SectionBody(#[cfg_attr(feature = "enable-serde", serde(with = "serde_bytes"))] Vec<u8>);
|
||||||
|
|
||||||
impl SectionBody {
|
impl SectionBody {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
)]
|
)]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, rkyv::CheckBytes)]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
pub struct SourceLoc(u32);
|
pub struct SourceLoc(u32);
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ use crate::{
|
|||||||
SectionIndex, SerializeError, SignatureIndex,
|
SectionIndex, SerializeError, SignatureIndex,
|
||||||
};
|
};
|
||||||
use rkyv::{
|
use rkyv::{
|
||||||
archived_value, de::deserializers::SharedDeserializeMap, ser::serializers::AllocSerializer,
|
archived_value, check_archived_value, de::deserializers::SharedDeserializeMap,
|
||||||
ser::Serializer as RkyvSerializer, Archive, Deserialize as RkyvDeserialize,
|
ser::serializers::AllocSerializer, ser::Serializer as RkyvSerializer, Archive,
|
||||||
Serialize as RkyvSerialize,
|
Deserialize as RkyvDeserialize, Serialize as RkyvSerialize,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "enable-serde")]
|
#[cfg(feature = "enable-serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -50,6 +50,7 @@ pub trait SymbolRegistry: Send + Sync {
|
|||||||
/// Serializable struct that represents the compiled metadata.
|
/// Serializable struct that represents the compiled metadata.
|
||||||
#[derive(Debug, RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(Debug, RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
|
#[archive_attr(derive(rkyv::CheckBytes))]
|
||||||
pub struct ModuleMetadata {
|
pub struct ModuleMetadata {
|
||||||
/// Compile info
|
/// Compile info
|
||||||
pub compile_info: CompileModuleInfo,
|
pub compile_info: CompileModuleInfo,
|
||||||
@@ -114,6 +115,14 @@ impl ModuleMetadata {
|
|||||||
Self::deserialize_from_archive(archived)
|
Self::deserialize_from_archive(archived)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deserialize a Module from a slice.
|
||||||
|
/// The slice must have the following format:
|
||||||
|
/// RKYV serialization (any length) + POS (8 bytes)
|
||||||
|
pub fn deserialize_checked(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
|
||||||
|
let archived = Self::archive_from_slice_checked(metadata_slice)?;
|
||||||
|
Self::deserialize_from_archive(archived)
|
||||||
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// This method is unsafe.
|
/// This method is unsafe.
|
||||||
@@ -135,6 +144,25 @@ impl ModuleMetadata {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This method is unsafe.
|
||||||
|
/// Please check `ModuleMetadata::deserialize` for more details.
|
||||||
|
fn archive_from_slice_checked(
|
||||||
|
metadata_slice: &[u8],
|
||||||
|
) -> Result<&ArchivedModuleMetadata, DeserializeError> {
|
||||||
|
if metadata_slice.len() < 8 {
|
||||||
|
return Err(DeserializeError::Incompatible(
|
||||||
|
"invalid serialized ModuleMetadata".into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let mut pos: [u8; 8] = Default::default();
|
||||||
|
pos.copy_from_slice(&metadata_slice[metadata_slice.len() - 8..metadata_slice.len()]);
|
||||||
|
let pos: u64 = u64::from_le_bytes(pos);
|
||||||
|
check_archived_value::<Self>(&metadata_slice[..metadata_slice.len() - 8], pos as usize)
|
||||||
|
.map_err(|e| DeserializeError::CorruptedBinary(e.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Deserialize a compilation module from an archive
|
/// Deserialize a compilation module from an archive
|
||||||
pub fn deserialize_from_archive(
|
pub fn deserialize_from_archive(
|
||||||
archived: &ArchivedModuleMetadata,
|
archived: &ArchivedModuleMetadata,
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
/// Information about trap.
|
/// Information about trap.
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Clone, Debug, PartialEq, Eq)]
|
#[derive(
|
||||||
|
RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Clone, Debug, PartialEq, Eq,
|
||||||
|
)]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
pub struct TrapInformation {
|
pub struct TrapInformation {
|
||||||
/// The offset of the trapping instruction in native code. It is relative to the beginning of the function.
|
/// The offset of the trapping instruction in native code. It is relative to the beginning of the function.
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
/// [unwind info]: https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64?view=vs-2019
|
/// [unwind info]: https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64?view=vs-2019
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[archive_attr(derive(rkyv::CheckBytes))]
|
||||||
pub enum CompiledFunctionUnwindInfo {
|
pub enum CompiledFunctionUnwindInfo {
|
||||||
/// Windows UNWIND_INFO.
|
/// Windows UNWIND_INFO.
|
||||||
WindowsX64(Vec<u8>),
|
WindowsX64(Vec<u8>),
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
|
#[archive_attr(derive(rkyv::CheckBytes))]
|
||||||
pub struct PrimaryMap<K, V>
|
pub struct PrimaryMap<K, V>
|
||||||
where
|
where
|
||||||
K: EntityRef,
|
K: EntityRef,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ use serde::{
|
|||||||
/// The map does not track if an entry for a key has been inserted or not. Instead it behaves as if
|
/// The map does not track if an entry for a key has been inserted or not. Instead it behaves as if
|
||||||
/// all keys have a default entry from the beginning.
|
/// all keys have a default entry from the beginning.
|
||||||
#[derive(Debug, Clone, RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(Debug, Clone, RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
|
#[archive_attr(derive(rkyv::CheckBytes))]
|
||||||
pub struct SecondaryMap<K, V>
|
pub struct SecondaryMap<K, V>
|
||||||
where
|
where
|
||||||
K: EntityRef,
|
K: EntityRef,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
/// Features usually have a corresponding [WebAssembly proposal].
|
/// Features usually have a corresponding [WebAssembly proposal].
|
||||||
///
|
///
|
||||||
/// [WebAssembly proposal]: https://github.com/WebAssembly/proposals
|
/// [WebAssembly proposal]: https://github.com/WebAssembly/proposals
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq, rkyv::CheckBytes)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
Archive,
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
@@ -49,6 +50,7 @@ entity_impl!(LocalMemoryIndex);
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
Archive,
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
@@ -68,6 +70,7 @@ entity_impl!(LocalGlobalIndex);
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
Archive,
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
@@ -87,6 +90,7 @@ entity_impl!(FunctionIndex);
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
Archive,
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
@@ -106,6 +110,7 @@ entity_impl!(TableIndex);
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
Archive,
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
@@ -125,6 +130,7 @@ entity_impl!(GlobalIndex);
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
Archive,
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
@@ -144,6 +150,7 @@ entity_impl!(MemoryIndex);
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
Archive,
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
@@ -163,6 +170,7 @@ entity_impl!(SignatureIndex);
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
Archive,
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
@@ -182,6 +190,7 @@ entity_impl!(DataIndex);
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
Archive,
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
@@ -201,6 +210,7 @@ entity_impl!(ElemIndex);
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
Archive,
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
@@ -220,9 +230,11 @@ entity_impl!(CustomSectionIndex);
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
Archive,
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum ExportIndex {
|
pub enum ExportIndex {
|
||||||
/// Function export.
|
/// Function export.
|
||||||
Function(FunctionIndex),
|
Function(FunctionIndex),
|
||||||
@@ -236,10 +248,21 @@ pub enum ExportIndex {
|
|||||||
|
|
||||||
/// An entity to import.
|
/// An entity to import.
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, RkyvSerialize, RkyvDeserialize, Archive,
|
Clone,
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
RkyvSerialize,
|
||||||
|
RkyvDeserialize,
|
||||||
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum ImportIndex {
|
pub enum ImportIndex {
|
||||||
/// Function import.
|
/// Function import.
|
||||||
Function(FunctionIndex),
|
Function(FunctionIndex),
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
use crate::indexes::{FunctionIndex, GlobalIndex, MemoryIndex, TableIndex};
|
use crate::indexes::{FunctionIndex, GlobalIndex, MemoryIndex, TableIndex};
|
||||||
use crate::lib::std::boxed::Box;
|
use crate::lib::std::boxed::Box;
|
||||||
|
|
||||||
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
use rkyv::{Archive, CheckBytes, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
||||||
#[cfg(feature = "enable-serde")]
|
#[cfg(feature = "enable-serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// A WebAssembly table initializer.
|
/// A WebAssembly table initializer.
|
||||||
#[derive(Clone, Debug, Hash, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(Clone, Debug, Hash, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
|
#[archive_attr(derive(CheckBytes))]
|
||||||
pub struct TableInitializer {
|
pub struct TableInitializer {
|
||||||
/// The index of a table to initialize.
|
/// The index of a table to initialize.
|
||||||
pub table_index: TableIndex,
|
pub table_index: TableIndex,
|
||||||
@@ -23,6 +24,7 @@ pub struct TableInitializer {
|
|||||||
/// should be performed.
|
/// should be performed.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(Clone, Debug, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
|
#[archive_attr(derive(CheckBytes))]
|
||||||
pub struct DataInitializerLocation {
|
pub struct DataInitializerLocation {
|
||||||
/// The index of the memory to initialize.
|
/// The index of the memory to initialize.
|
||||||
pub memory_index: MemoryIndex,
|
pub memory_index: MemoryIndex,
|
||||||
@@ -49,6 +51,7 @@ pub struct DataInitializer<'data> {
|
|||||||
/// holding a reference to it
|
/// holding a reference to it
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(Debug, Clone, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
|
#[archive_attr(derive(CheckBytes))]
|
||||||
pub struct OwnedDataInitializer {
|
pub struct OwnedDataInitializer {
|
||||||
/// The location where the initialization is to be performed.
|
/// The location where the initialization is to be performed.
|
||||||
pub location: DataInitializerLocation,
|
pub location: DataInitializerLocation,
|
||||||
|
|||||||
@@ -18,9 +18,11 @@ use std::fmt;
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
Archive,
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
|
#[repr(u16)]
|
||||||
pub enum LibCall {
|
pub enum LibCall {
|
||||||
/// ceil.f32
|
/// ceil.f32
|
||||||
CeilF32,
|
CeilF32,
|
||||||
|
|||||||
@@ -7,9 +7,21 @@ use std::iter::Sum;
|
|||||||
use std::ops::{Add, AddAssign};
|
use std::ops::{Add, AddAssign};
|
||||||
|
|
||||||
/// Implementation styles for WebAssembly linear memory.
|
/// Implementation styles for WebAssembly linear memory.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(
|
||||||
|
Debug,
|
||||||
|
Clone,
|
||||||
|
Copy,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Hash,
|
||||||
|
RkyvSerialize,
|
||||||
|
RkyvDeserialize,
|
||||||
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum MemoryStyle {
|
pub enum MemoryStyle {
|
||||||
/// The actual memory can be resized and moved.
|
/// The actual memory can be resized and moved.
|
||||||
Dynamic {
|
Dynamic {
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ use crate::{
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use rkyv::{
|
use rkyv::{
|
||||||
de::SharedDeserializeRegistry, ser::ScratchSpace, ser::Serializer,
|
de::SharedDeserializeRegistry, ser::ScratchSpace, ser::Serializer,
|
||||||
ser::SharedSerializeRegistry, Archive, Archived, Deserialize as RkyvDeserialize, Fallible,
|
ser::SharedSerializeRegistry, Archive, Archived, CheckBytes, Deserialize as RkyvDeserialize,
|
||||||
Serialize as RkyvSerialize,
|
Fallible, Serialize as RkyvSerialize,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "enable-serde")]
|
#[cfg(feature = "enable-serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -26,6 +26,7 @@ use std::iter::ExactSizeIterator;
|
|||||||
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
|
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
|
||||||
|
|
||||||
#[derive(Debug, Clone, RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(Debug, Clone, RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
|
#[archive_attr(derive(CheckBytes))]
|
||||||
pub struct ModuleId {
|
pub struct ModuleId {
|
||||||
id: usize,
|
id: usize,
|
||||||
}
|
}
|
||||||
@@ -48,6 +49,7 @@ impl Default for ModuleId {
|
|||||||
/// Hash key of an import
|
/// Hash key of an import
|
||||||
#[derive(Debug, Hash, Eq, PartialEq, Clone, Default, RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(Debug, Hash, Eq, PartialEq, Clone, Default, RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
|
#[archive_attr(derive(CheckBytes, PartialEq, Eq, Hash))]
|
||||||
pub struct ImportKey {
|
pub struct ImportKey {
|
||||||
/// Module name
|
/// Module name
|
||||||
pub module: String,
|
pub module: String,
|
||||||
@@ -177,6 +179,7 @@ pub struct ModuleInfo {
|
|||||||
|
|
||||||
/// Mirror version of ModuleInfo that can derive rkyv traits
|
/// Mirror version of ModuleInfo that can derive rkyv traits
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
|
#[archive_attr(derive(CheckBytes))]
|
||||||
pub struct ArchivableModuleInfo {
|
pub struct ArchivableModuleInfo {
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
imports: IndexMap<ImportKey, ImportIndex>,
|
imports: IndexMap<ImportKey, ImportIndex>,
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ use crate::{
|
|||||||
SerializeError, SignatureIndex, TableIndex, TableStyle,
|
SerializeError, SignatureIndex, TableIndex, TableStyle,
|
||||||
};
|
};
|
||||||
use enumset::EnumSet;
|
use enumset::EnumSet;
|
||||||
|
use rkyv::check_archived_value;
|
||||||
use rkyv::{
|
use rkyv::{
|
||||||
archived_value, de::deserializers::SharedDeserializeMap, ser::serializers::AllocSerializer,
|
archived_value, de::deserializers::SharedDeserializeMap, ser::serializers::AllocSerializer,
|
||||||
ser::Serializer as RkyvSerializer, Archive, Deserialize as RkyvDeserialize,
|
ser::Serializer as RkyvSerializer, Archive, CheckBytes, Deserialize as RkyvDeserialize,
|
||||||
Serialize as RkyvSerialize,
|
Serialize as RkyvSerialize,
|
||||||
};
|
};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
@@ -17,6 +18,7 @@ use std::mem;
|
|||||||
/// The compilation related data for a serialized modules
|
/// The compilation related data for a serialized modules
|
||||||
#[derive(Archive, Default, RkyvDeserialize, RkyvSerialize)]
|
#[derive(Archive, Default, RkyvDeserialize, RkyvSerialize)]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
#[archive_attr(derive(CheckBytes))]
|
||||||
pub struct SerializableCompilation {
|
pub struct SerializableCompilation {
|
||||||
pub function_bodies: PrimaryMap<LocalFunctionIndex, FunctionBody>,
|
pub function_bodies: PrimaryMap<LocalFunctionIndex, FunctionBody>,
|
||||||
pub function_relocations: PrimaryMap<LocalFunctionIndex, Vec<Relocation>>,
|
pub function_relocations: PrimaryMap<LocalFunctionIndex, Vec<Relocation>>,
|
||||||
@@ -51,6 +53,7 @@ impl SerializableCompilation {
|
|||||||
/// Serializable struct that is able to serialize from and to a `ArtifactInfo`.
|
/// Serializable struct that is able to serialize from and to a `ArtifactInfo`.
|
||||||
#[derive(Archive, RkyvDeserialize, RkyvSerialize)]
|
#[derive(Archive, RkyvDeserialize, RkyvSerialize)]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
#[archive_attr(derive(CheckBytes))]
|
||||||
pub struct SerializableModule {
|
pub struct SerializableModule {
|
||||||
/// The main serializable compilation object
|
/// The main serializable compilation object
|
||||||
pub compilation: SerializableCompilation,
|
pub compilation: SerializableCompilation,
|
||||||
@@ -96,6 +99,16 @@ impl SerializableModule {
|
|||||||
Self::deserialize_from_archive(archived)
|
Self::deserialize_from_archive(archived)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deserialize a Module from a slice.
|
||||||
|
/// The slice must have the following format:
|
||||||
|
/// RKYV serialization (any length) + POS (8 bytes)
|
||||||
|
///
|
||||||
|
/// Unlike [`Self::deserialize`], this function will validate the data.
|
||||||
|
pub fn deserialize_checked(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
|
||||||
|
let archived = Self::archive_from_slice_checked(metadata_slice)?;
|
||||||
|
Self::deserialize_from_archive(archived)
|
||||||
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// This method is unsafe.
|
/// This method is unsafe.
|
||||||
@@ -117,6 +130,25 @@ impl SerializableModule {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deserialize an archived module.
|
||||||
|
///
|
||||||
|
/// In contrast to [`Self::deserialize`], this method performs validation
|
||||||
|
/// and is not unsafe.
|
||||||
|
fn archive_from_slice_checked(
|
||||||
|
metadata_slice: &[u8],
|
||||||
|
) -> Result<&ArchivedSerializableModule, DeserializeError> {
|
||||||
|
if metadata_slice.len() < 8 {
|
||||||
|
return Err(DeserializeError::Incompatible(
|
||||||
|
"invalid serialized data".into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let mut pos: [u8; 8] = Default::default();
|
||||||
|
pos.copy_from_slice(&metadata_slice[metadata_slice.len() - 8..metadata_slice.len()]);
|
||||||
|
let pos: u64 = u64::from_le_bytes(pos);
|
||||||
|
check_archived_value::<Self>(&metadata_slice[..metadata_slice.len() - 8], pos as usize)
|
||||||
|
.map_err(|err| DeserializeError::CorruptedBinary(err.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Deserialize a compilation module from an archive
|
/// Deserialize a compilation module from an archive
|
||||||
pub fn deserialize_from_archive(
|
pub fn deserialize_from_archive(
|
||||||
archived: &ArchivedSerializableModule,
|
archived: &ArchivedSerializableModule,
|
||||||
@@ -175,7 +207,7 @@ pub struct MetadataHeader {
|
|||||||
impl MetadataHeader {
|
impl MetadataHeader {
|
||||||
/// Current ABI version. Increment this any time breaking changes are made
|
/// Current ABI version. Increment this any time breaking changes are made
|
||||||
/// to the format of the serialized data.
|
/// to the format of the serialized data.
|
||||||
const CURRENT_VERSION: u32 = 3;
|
const CURRENT_VERSION: u32 = 4;
|
||||||
|
|
||||||
/// Magic number to identify wasmer metadata.
|
/// Magic number to identify wasmer metadata.
|
||||||
const MAGIC: [u8; 8] = *b"WASMER\0\0";
|
const MAGIC: [u8; 8] = *b"WASMER\0\0";
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
|
use bytecheck::CheckBytes;
|
||||||
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
||||||
#[cfg(feature = "enable-serde")]
|
#[cfg(feature = "enable-serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Implementation styles for WebAssembly tables.
|
/// Implementation styles for WebAssembly tables.
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(
|
||||||
|
Debug, Clone, Hash, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive, CheckBytes,
|
||||||
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum TableStyle {
|
pub enum TableStyle {
|
||||||
/// Signatures are stored in the table and checked in the caller.
|
/// Signatures are stored in the table and checked in the caller.
|
||||||
CallerChecksSignature,
|
CallerChecksSignature,
|
||||||
|
|||||||
@@ -14,7 +14,17 @@ use thiserror::Error;
|
|||||||
///
|
///
|
||||||
/// All trap instructions have an explicit trap code.
|
/// All trap instructions have an explicit trap code.
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, Copy, PartialEq, Eq, Debug, Hash, Error, RkyvSerialize, RkyvDeserialize, Archive,
|
Clone,
|
||||||
|
Copy,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
Error,
|
||||||
|
RkyvSerialize,
|
||||||
|
RkyvDeserialize,
|
||||||
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::lib::std::string::{String, ToString};
|
|||||||
use crate::lib::std::vec::Vec;
|
use crate::lib::std::vec::Vec;
|
||||||
use crate::units::Pages;
|
use crate::units::Pages;
|
||||||
|
|
||||||
|
use bytecheck::CheckBytes;
|
||||||
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
||||||
#[cfg(feature = "enable-serde")]
|
#[cfg(feature = "enable-serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -17,8 +18,9 @@ use serde::{Deserialize, Serialize};
|
|||||||
/// A list of all possible value types in WebAssembly.
|
/// A list of all possible value types in WebAssembly.
|
||||||
#[derive(Copy, Debug, Clone, Eq, PartialEq, Hash)]
|
#[derive(Copy, Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes)]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
/// Signed 32 bit integer.
|
/// Signed 32 bit integer.
|
||||||
I32,
|
I32,
|
||||||
@@ -58,10 +60,10 @@ impl fmt::Display for Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
/// The WebAssembly V128 type
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, CheckBytes)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
/// The WebAssembly V128 type
|
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
pub struct V128(pub(crate) [u8; 16]);
|
pub struct V128(pub(crate) [u8; 16]);
|
||||||
|
|
||||||
@@ -240,6 +242,7 @@ impl ExternType {
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
|
#[archive_attr(derive(CheckBytes))]
|
||||||
pub struct FunctionType {
|
pub struct FunctionType {
|
||||||
/// The parameters of the function
|
/// The parameters of the function
|
||||||
params: Box<[Type]>,
|
params: Box<[Type]>,
|
||||||
@@ -323,10 +326,11 @@ impl From<&Self> for FunctionType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Indicator of whether a global is mutable or not
|
/// Indicator of whether a global is mutable or not
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, CheckBytes)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum Mutability {
|
pub enum Mutability {
|
||||||
/// The global is constant and its value does not change
|
/// The global is constant and its value does not change
|
||||||
Const,
|
Const,
|
||||||
@@ -361,7 +365,7 @@ impl From<Mutability> for bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// WebAssembly global.
|
/// WebAssembly global.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, CheckBytes)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
@@ -408,8 +412,9 @@ impl fmt::Display for GlobalType {
|
|||||||
/// Globals are initialized via the `const` operators or by referring to another import.
|
/// Globals are initialized via the `const` operators or by referring to another import.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes)]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum GlobalInit {
|
pub enum GlobalInit {
|
||||||
/// An `i32.const`.
|
/// An `i32.const`.
|
||||||
I32Const(i32),
|
I32Const(i32),
|
||||||
@@ -442,6 +447,7 @@ pub enum GlobalInit {
|
|||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
|
#[archive_attr(derive(CheckBytes))]
|
||||||
pub struct TableType {
|
pub struct TableType {
|
||||||
/// The type of data stored in elements of the table.
|
/// The type of data stored in elements of the table.
|
||||||
pub ty: Type,
|
pub ty: Type,
|
||||||
@@ -482,6 +488,7 @@ impl fmt::Display for TableType {
|
|||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
|
||||||
|
#[archive_attr(derive(CheckBytes))]
|
||||||
pub struct MemoryType {
|
pub struct MemoryType {
|
||||||
/// The minimum number of pages in the memory.
|
/// The minimum number of pages in the memory.
|
||||||
pub minimum: Pages,
|
pub minimum: Pages,
|
||||||
|
|||||||
@@ -21,7 +21,17 @@ pub const WASM_MIN_PAGES: u32 = 0x100;
|
|||||||
|
|
||||||
/// Units of WebAssembly pages (as specified to be 65,536 bytes).
|
/// Units of WebAssembly pages (as specified to be 65,536 bytes).
|
||||||
#[derive(
|
#[derive(
|
||||||
Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RkyvSerialize, RkyvDeserialize, Archive,
|
Copy,
|
||||||
|
Clone,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
Hash,
|
||||||
|
RkyvSerialize,
|
||||||
|
RkyvDeserialize,
|
||||||
|
Archive,
|
||||||
|
rkyv::CheckBytes,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
#[archive(as = "Self")]
|
#[archive(as = "Self")]
|
||||||
|
|||||||
Reference in New Issue
Block a user