Coverage Report

Created: 2024-10-16 07:58

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