wasm_encoder/core/
data.rs

1use crate::{encode_section, encoding_size, ConstExpr, Encode, Section, SectionId};
2use alloc::vec::Vec;
3
4/// An encoder for the data section.
5///
6/// Data sections are only supported for modules.
7///
8/// # Example
9///
10/// ```
11/// use wasm_encoder::{
12///     ConstExpr, DataSection, Instruction, MemorySection, MemoryType,
13///     Module,
14/// };
15///
16/// let mut memory = MemorySection::new();
17/// memory.memory(MemoryType {
18///     minimum: 1,
19///     maximum: None,
20///     memory64: false,
21///     shared: false,
22///     page_size_log2: None,
23/// });
24///
25/// let mut data = DataSection::new();
26/// let memory_index = 0;
27/// let offset = ConstExpr::i32_const(42);
28/// let segment_data = b"hello";
29/// data.active(memory_index, &offset, segment_data.iter().copied());
30///
31/// let mut module = Module::new();
32/// module
33///     .section(&memory)
34///     .section(&data);
35///
36/// let wasm_bytes = module.finish();
37/// ```
38#[derive(Clone, Default, Debug)]
39pub struct DataSection {
40    bytes: Vec<u8>,
41    num_added: u32,
42}
43
44/// A segment in the data section.
45#[derive(Clone, Debug)]
46pub struct DataSegment<'a, D> {
47    /// This data segment's mode.
48    pub mode: DataSegmentMode<'a>,
49    /// This data segment's data.
50    pub data: D,
51}
52
53/// A data segment's mode.
54#[derive(Clone, Debug)]
55pub enum DataSegmentMode<'a> {
56    /// An active data segment.
57    Active {
58        /// The memory this segment applies to.
59        memory_index: u32,
60        /// The offset where this segment's data is initialized at.
61        offset: &'a ConstExpr,
62    },
63    /// A passive data segment.
64    ///
65    /// Passive data segments are part of the bulk memory proposal.
66    Passive,
67}
68
69impl DataSection {
70    /// Create a new data section encoder.
71    pub fn new() -> Self {
72        Self::default()
73    }
74
75    /// The number of data segments in the section.
76    pub fn len(&self) -> u32 {
77        self.num_added
78    }
79
80    /// Determines if the section is empty.
81    pub fn is_empty(&self) -> bool {
82        self.num_added == 0
83    }
84
85    /// Define a data segment.
86    pub fn segment<D>(&mut self, segment: DataSegment<D>) -> &mut Self
87    where
88        D: IntoIterator<Item = u8>,
89        D::IntoIter: ExactSizeIterator,
90    {
91        match segment.mode {
92            DataSegmentMode::Passive => {
93                self.bytes.push(0x01);
94            }
95            DataSegmentMode::Active {
96                memory_index: 0,
97                offset,
98            } => {
99                self.bytes.push(0x00);
100                offset.encode(&mut self.bytes);
101            }
102            DataSegmentMode::Active {
103                memory_index,
104                offset,
105            } => {
106                self.bytes.push(0x02);
107                memory_index.encode(&mut self.bytes);
108                offset.encode(&mut self.bytes);
109            }
110        }
111
112        let data = segment.data.into_iter();
113        data.len().encode(&mut self.bytes);
114        self.bytes.extend(data);
115
116        self.num_added += 1;
117        self
118    }
119
120    /// Define an active data segment.
121    pub fn active<D>(&mut self, memory_index: u32, offset: &ConstExpr, data: D) -> &mut Self
122    where
123        D: IntoIterator<Item = u8>,
124        D::IntoIter: ExactSizeIterator,
125    {
126        self.segment(DataSegment {
127            mode: DataSegmentMode::Active {
128                memory_index,
129                offset,
130            },
131            data,
132        })
133    }
134
135    /// Define a passive data segment.
136    ///
137    /// Passive data segments are part of the bulk memory proposal.
138    pub fn passive<D>(&mut self, data: D) -> &mut Self
139    where
140        D: IntoIterator<Item = u8>,
141        D::IntoIter: ExactSizeIterator,
142    {
143        self.segment(DataSegment {
144            mode: DataSegmentMode::Passive,
145            data,
146        })
147    }
148
149    /// Copy an already-encoded data segment into this data section.
150    pub fn raw(&mut self, already_encoded_data_segment: &[u8]) -> &mut Self {
151        self.bytes.extend_from_slice(already_encoded_data_segment);
152        self.num_added += 1;
153        self
154    }
155}
156
157impl Encode for DataSection {
158    fn encode(&self, sink: &mut Vec<u8>) {
159        encode_section(sink, self.num_added, &self.bytes);
160    }
161}
162
163impl Section for DataSection {
164    fn id(&self) -> u8 {
165        SectionId::Data.into()
166    }
167}
168
169/// An encoder for the data count section.
170#[derive(Clone, Copy, Debug)]
171pub struct DataCountSection {
172    /// The number of segments in the data section.
173    pub count: u32,
174}
175
176impl Encode for DataCountSection {
177    fn encode(&self, sink: &mut Vec<u8>) {
178        encoding_size(self.count).encode(sink);
179        self.count.encode(sink);
180    }
181}
182
183impl Section for DataCountSection {
184    fn id(&self) -> u8 {
185        SectionId::DataCount.into()
186    }
187}