1use crate::{encode_section, ConstExpr, Encode, Section, SectionId, ValType};
2
3/// An encoder for the global section.
4///
5/// Global sections are only supported for modules.
6///
7/// # Example
8///
9/// ```
10/// use wasm_encoder::{ConstExpr, Module, GlobalSection, GlobalType, Instruction, ValType};
11///
12/// let mut globals = GlobalSection::new();
13/// globals.global(
14/// GlobalType {
15/// val_type: ValType::I32,
16/// mutable: false,
17/// shared: false,
18/// },
19/// &ConstExpr::i32_const(42),
20/// );
21///
22/// let mut module = Module::new();
23/// module.section(&globals);
24///
25/// let wasm_bytes = module.finish();
26/// ```
27#[derive(Clone, Default, Debug)]
28pub struct GlobalSection {
29 bytes: Vec<u8>,
30 num_added: u32,
31}
32
33impl GlobalSection {
34 /// Create a new global section encoder.
35 pub fn new() -> Self {
36 Self::default()
37 }
38
39 /// The number of globals 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 global.
50 pub fn global(&mut self, global_type: GlobalType, init_expr: &ConstExpr) -> &mut Self {
51 global_type.encode(&mut self.bytes);
52 init_expr.encode(&mut self.bytes);
53 self.num_added += 1;
54 self
55 }
56
57 /// Add a raw byte slice into this code section as a global.
58 pub fn raw(&mut self, data: &[u8]) -> &mut Self {
59 self.bytes.extend(data);
60 self.num_added += 1;
61 self
62 }
63}
64
65impl Encode for GlobalSection {
66 fn encode(&self, sink: &mut Vec<u8>) {
67 encode_section(sink, self.num_added, &self.bytes);
68 }
69}
70
71impl Section for GlobalSection {
72 fn id(&self) -> u8 {
73 SectionId::Global.into()
74 }
75}
76
77/// A global's type.
78#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
79pub struct GlobalType {
80 /// This global's value type.
81 pub val_type: ValType,
82 /// Whether this global is mutable or not.
83 pub mutable: bool,
84 /// Whether this global is shared or not.
85 pub shared: bool,
86}
87
88impl Encode for GlobalType {
89 fn encode(&self, sink: &mut Vec<u8>) {
90 self.val_type.encode(sink);
91 let mut flag: u8 = 0;
92 if self.mutable {
93 flag |= 0b01;
94 }
95 if self.shared {
96 flag |= 0b10;
97 }
98 sink.push(flag);
99 }
100}
101