1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
use crate::{
collections::arena::ArenaIndex,
module::{self, PassiveDataSegmentBytes},
store::Stored,
AsContextMut,
};
use core::convert::AsRef;
/// A raw index to a data segment entity.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct DataSegmentIdx(u32);
impl ArenaIndex for DataSegmentIdx {
fn into_usize(self) -> usize {
self.0 as usize
}
fn from_usize(value: usize) -> Self {
let value = value.try_into().unwrap_or_else(|error| {
panic!("index {value} is out of bounds as data segment index: {error}")
});
Self(value)
}
}
/// A Wasm data segment reference.
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct DataSegment(Stored<DataSegmentIdx>);
impl DataSegment {
/// Creates a new linear memory reference.
pub fn from_inner(stored: Stored<DataSegmentIdx>) -> Self {
Self(stored)
}
/// Returns the underlying stored representation.
pub fn as_inner(&self) -> &Stored<DataSegmentIdx> {
&self.0
}
/// Allocates a new active [`DataSegment`] on the store.
///
/// # Errors
///
/// If more than [`u32::MAX`] much linear memory is allocated.
pub fn new_active(mut ctx: impl AsContextMut) -> Self {
ctx.as_context_mut()
.store
.inner
.alloc_data_segment(DataSegmentEntity::active())
}
/// Allocates a new passive [`DataSegment`] on the store.
///
/// # Errors
///
/// If more than [`u32::MAX`] much linear memory is allocated.
pub fn new_passive(mut ctx: impl AsContextMut, bytes: PassiveDataSegmentBytes) -> Self {
ctx.as_context_mut()
.store
.inner
.alloc_data_segment(DataSegmentEntity::passive(bytes))
}
}
/// An instantiated [`DataSegmentEntity`].
///
/// # Note
///
/// With the `bulk-memory` Wasm proposal it is possible to interact
/// with data segments at runtime. Therefore Wasm instances now have
/// a need to have an instantiated representation of data segments.
#[derive(Debug)]
pub struct DataSegmentEntity {
/// The underlying bytes of the instance data segment.
///
/// # Note
///
/// These bytes are just readable after instantiation.
/// Using Wasm `data.drop` simply replaces the instance
/// with an empty one.
bytes: Option<PassiveDataSegmentBytes>,
}
impl DataSegmentEntity {
/// Creates a new active [`DataSegmentEntity`].
pub fn active() -> Self {
Self { bytes: None }
}
/// Creates a new passive [`DataSegmentEntity`] with its `bytes`.
pub fn passive(bytes: PassiveDataSegmentBytes) -> Self {
Self { bytes: Some(bytes) }
}
}
impl From<&'_ module::DataSegment> for DataSegmentEntity {
fn from(segment: &'_ module::DataSegment) -> Self {
Self {
bytes: segment.passive_data_segment_bytes(),
}
}
}
impl DataSegmentEntity {
/// Returns the bytes of the [`DataSegmentEntity`].
pub fn bytes(&self) -> &[u8] {
self.bytes
.as_ref()
.map(AsRef::as_ref)
.unwrap_or_else(|| &[])
}
/// Drops the bytes of the [`DataSegmentEntity`].
pub fn drop_bytes(&mut self) {
self.bytes = None;
}
}