Skip to main content

wasmi/memory/
data.rs

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