wasm_encoder/core/
memories.rs

1use crate::{encode_section, Encode, Section, SectionId};
2use alloc::vec::Vec;
3
4/// An encoder for the memory section.
5///
6/// Memory sections are only supported for modules.
7///
8/// # Example
9///
10/// ```
11/// use wasm_encoder::{Module, MemorySection, MemoryType};
12///
13/// let mut memories = MemorySection::new();
14/// memories.memory(MemoryType {
15///     minimum: 1,
16///     maximum: None,
17///     memory64: false,
18///     shared: false,
19///     page_size_log2: None,
20/// });
21///
22/// let mut module = Module::new();
23/// module.section(&memories);
24///
25/// let wasm_bytes = module.finish();
26/// ```
27#[derive(Clone, Default, Debug)]
28pub struct MemorySection {
29    bytes: Vec<u8>,
30    num_added: u32,
31}
32
33impl MemorySection {
34    /// Create a new memory section encoder.
35    pub fn new() -> Self {
36        Self::default()
37    }
38
39    /// The number of memories in the section.
40    pub fn len(&self) -> u32 {
41        self.num_added
42    }
43
44    /// Determines if the section is empty.
45    pub fn is_empty(&self) -> bool {
46        self.num_added == 0
47    }
48
49    /// Define a memory.
50    pub fn memory(&mut self, memory_type: MemoryType) -> &mut Self {
51        memory_type.encode(&mut self.bytes);
52        self.num_added += 1;
53        self
54    }
55}
56
57impl Encode for MemorySection {
58    fn encode(&self, sink: &mut Vec<u8>) {
59        encode_section(sink, self.num_added, &self.bytes);
60    }
61}
62
63impl Section for MemorySection {
64    fn id(&self) -> u8 {
65        SectionId::Memory.into()
66    }
67}
68
69/// A memory's type.
70#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
71pub struct MemoryType {
72    /// Minimum size, in pages, of this memory
73    pub minimum: u64,
74    /// Maximum size, in pages, of this memory
75    pub maximum: Option<u64>,
76    /// Whether or not this is a 64-bit memory.
77    pub memory64: bool,
78    /// Whether or not this memory is shared.
79    pub shared: bool,
80    /// The log base 2 of a custom page size for this memory.
81    ///
82    /// The default page size for Wasm memories is 64KiB, i.e. 2<sup>16</sup> or
83    /// `65536`.
84    ///
85    /// After the introduction of [the custom-page-sizes
86    /// proposal](https://github.com/WebAssembly/custom-page-sizes), Wasm can
87    /// customize the page size. It must be a power of two that is less than or
88    /// equal to 64KiB. Attempting to encode an invalid page size may panic.
89    pub page_size_log2: Option<u32>,
90}
91
92impl Encode for MemoryType {
93    fn encode(&self, sink: &mut Vec<u8>) {
94        let mut flags = 0;
95        if self.maximum.is_some() {
96            flags |= 0b0001;
97        }
98        if self.shared {
99            flags |= 0b0010;
100        }
101        if self.memory64 {
102            flags |= 0b0100;
103        }
104        if self.page_size_log2.is_some() {
105            flags |= 0b1000;
106        }
107        sink.push(flags);
108        self.minimum.encode(sink);
109        if let Some(max) = self.maximum {
110            max.encode(sink);
111        }
112        if let Some(p) = self.page_size_log2 {
113            p.encode(sink);
114        }
115    }
116}