Coverage Report

Created: 2026-09-28 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/include/loader/serialize.h
Line
Count
Source
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright The WasmEdge Authors
3
4
//===-- wasmedge/loader/serialize.h - Serializer class definition ---------===//
5
//
6
// Part of the WasmEdge Project.
7
//
8
//===----------------------------------------------------------------------===//
9
///
10
/// \file
11
/// This file contains the declaration of the Serializer class, which serializes
12
/// a validated AST Module into its canonical encoding.
13
///
14
//===----------------------------------------------------------------------===//
15
#pragma once
16
17
#include "ast/module.h"
18
#include "common/errcode.h"
19
20
#include <cstring>
21
#include <type_traits>
22
#include <vector>
23
24
namespace WasmEdge {
25
namespace Loader {
26
27
class Serializer {
28
public:
29
  Serializer() noexcept = default;
30
  ~Serializer() noexcept = default;
31
32
  /// Serialize a WASM module.
33
  Expect<std::vector<uint8_t>>
34
  serializeModule(const AST::Module &Mod) const noexcept;
35
36
  /// \name Serialize functions for WASM sections.
37
  /// @{
38
  void serializeSection(const AST::CustomSection &Sec,
39
                        std::vector<uint8_t> &OutVec) const noexcept;
40
  void serializeSection(const AST::TypeSection &Sec,
41
                        std::vector<uint8_t> &OutVec) const noexcept;
42
  void serializeSection(const AST::ImportSection &Sec,
43
                        std::vector<uint8_t> &OutVec) const noexcept;
44
  void serializeSection(const AST::FunctionSection &Sec,
45
                        std::vector<uint8_t> &OutVec) const noexcept;
46
  void serializeSection(const AST::TableSection &Sec,
47
                        std::vector<uint8_t> &OutVec) const noexcept;
48
  void serializeSection(const AST::MemorySection &Sec,
49
                        std::vector<uint8_t> &OutVec) const noexcept;
50
  void serializeSection(const AST::GlobalSection &Sec,
51
                        std::vector<uint8_t> &OutVec) const noexcept;
52
  void serializeSection(const AST::ExportSection &Sec,
53
                        std::vector<uint8_t> &OutVec) const noexcept;
54
  void serializeSection(const AST::StartSection &Sec,
55
                        std::vector<uint8_t> &OutVec) const noexcept;
56
  void serializeSection(const AST::ElementSection &Sec,
57
                        std::vector<uint8_t> &OutVec) const noexcept;
58
  void serializeSection(const AST::CodeSection &Sec,
59
                        std::vector<uint8_t> &OutVec) const noexcept;
60
  void serializeSection(const AST::DataSection &Sec,
61
                        std::vector<uint8_t> &OutVec) const noexcept;
62
  void serializeSection(const AST::DataCountSection &Sec,
63
                        std::vector<uint8_t> &OutVec) const noexcept;
64
  void serializeSection(const AST::TagSection &Sec,
65
                        std::vector<uint8_t> &OutVec) const noexcept;
66
  /// @}
67
68
0
  void serializeU32(uint32_t Num, std::vector<uint8_t> &OutVec) const noexcept {
69
0
    serializeUN<uint32_t, 32>(Num, OutVec, OutVec.end());
70
0
  }
71
0
  void serializeS32(int32_t Num, std::vector<uint8_t> &OutVec) const noexcept {
72
0
    serializeSN<int32_t, 32>(Num, OutVec);
73
0
  }
74
0
  void serializeS64(int64_t Num, std::vector<uint8_t> &OutVec) const noexcept {
75
0
    serializeSN<int64_t, 64>(Num, OutVec);
76
0
  }
77
0
  void serializeF32(float Num, std::vector<uint8_t> &OutVec) const noexcept {
78
0
    serializeFN<float, uint32_t>(Num, OutVec);
79
0
  }
80
0
  void serializeF64(double Num, std::vector<uint8_t> &OutVec) const noexcept {
81
0
    serializeFN<double, uint64_t>(Num, OutVec);
82
0
  }
83
84
private:
85
  /// \name Serialize functions for the other nodes of AST.
86
  /// @{
87
  void serializeSegment(const AST::TableSegment &Seg,
88
                        std::vector<uint8_t> &OutVec) const noexcept;
89
  void serializeSegment(const AST::GlobalSegment &Seg,
90
                        std::vector<uint8_t> &OutVec) const noexcept;
91
  void serializeSegment(const AST::ElementSegment &Seg,
92
                        std::vector<uint8_t> &OutVec) const noexcept;
93
  void serializeSegment(const AST::CodeSegment &Seg,
94
                        std::vector<uint8_t> &OutVec) const noexcept;
95
  void serializeSegment(const AST::DataSegment &Seg,
96
                        std::vector<uint8_t> &OutVec) const noexcept;
97
  void serializeDesc(const AST::ImportDesc &Desc,
98
                     std::vector<uint8_t> &OutVec) const noexcept;
99
  void serializeDesc(const AST::ExportDesc &Desc,
100
                     std::vector<uint8_t> &OutVec) const noexcept;
101
  void serializeHeapType(const ValType &Type,
102
                         std::vector<uint8_t> &OutVec) const noexcept;
103
  void serializeRefType(const ValType &Type,
104
                        std::vector<uint8_t> &OutVec) const noexcept;
105
  void serializeValType(const ValType &Type,
106
                        std::vector<uint8_t> &OutVec) const noexcept;
107
  void serializeLimit(const AST::Limit &Lim,
108
                      std::vector<uint8_t> &OutVec) const noexcept;
109
  void serializeType(const AST::SubType &SType,
110
                     std::vector<uint8_t> &OutVec) const noexcept;
111
  void serializeType(const AST::FunctionType &Type,
112
                     std::vector<uint8_t> &OutVec) const noexcept;
113
  void serializeType(const AST::TableType &Type,
114
                     std::vector<uint8_t> &OutVec) const noexcept;
115
  void serializeType(const AST::MemoryType &Type,
116
                     std::vector<uint8_t> &OutVec) const noexcept;
117
  void serializeType(const AST::GlobalType &Type,
118
                     std::vector<uint8_t> &OutVec) const noexcept;
119
  void serializeType(const AST::FieldType &Type,
120
                     std::vector<uint8_t> &OutVec) const noexcept;
121
  void serializeType(const AST::TagType &Type,
122
                     std::vector<uint8_t> &OutVec) const noexcept;
123
  void serializeExpression(const AST::Expression &Expr,
124
                           std::vector<uint8_t> &OutVec) const noexcept;
125
  void serializeInstruction(const AST::Instruction &Instr,
126
                            std::vector<uint8_t> &OutVec) const noexcept;
127
  /// @}
128
129
  /// \name Helper functions
130
  /// @{
131
  template <typename NumType, size_t N>
132
  void serializeUN(NumType Num, std::vector<uint8_t> &OutVec,
133
0
                   std::vector<uint8_t>::iterator It) const noexcept {
134
0
    uint8_t Buf[N / 7 + 1];
135
0
    uint32_t Len = 0;
136
0
    do {
137
0
      uint8_t X = std::make_unsigned_t<NumType>(Num) & 0x7FU;
138
0
      Num >>= 7;
139
0
      if (Num) {
140
0
        X |= 0x80U;
141
0
      }
142
0
      Buf[Len] = X;
143
0
      Len++;
144
0
    } while (Num);
145
0
    OutVec.insert(It, Buf, Buf + Len);
146
0
  }
Unexecuted instantiation: void WasmEdge::Loader::Serializer::serializeUN<unsigned int, 32ul>(unsigned int, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, std::__1::__wrap_iter<unsigned char*>) const
Unexecuted instantiation: void WasmEdge::Loader::Serializer::serializeUN<unsigned long, 64ul>(unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, std::__1::__wrap_iter<unsigned char*>) const
147
148
  void serializeU32(uint32_t Num, std::vector<uint8_t> &OutVec,
149
0
                    std::vector<uint8_t>::iterator It) const noexcept {
150
0
    serializeUN<uint32_t, 32>(Num, OutVec, It);
151
0
  }
152
  void serializeU64(uint64_t Num, std::vector<uint8_t> &OutVec,
153
0
                    std::vector<uint8_t>::iterator It) const noexcept {
154
0
    serializeUN<uint64_t, 64>(Num, OutVec, It);
155
0
  }
156
0
  void serializeU64(uint64_t Num, std::vector<uint8_t> &OutVec) const noexcept {
157
0
    serializeUN<uint64_t, 64>(Num, OutVec, OutVec.end());
158
0
  }
159
160
  template <typename NumType, size_t N>
161
0
  void serializeSN(NumType Num, std::vector<uint8_t> &OutVec) const noexcept {
162
0
    uint8_t Buf[N / 7 + 1];
163
0
    uint32_t Len = 0;
164
0
    bool More = true;
165
0
    while (More) {
166
0
      uint8_t X = static_cast<std::make_unsigned_t<NumType>>(Num) & 0x7FU;
167
0
      Num >>= 7;
168
0
      if ((Num == 0 && !(X & 0x40)) || (Num == -1 && X & 0x40)) {
169
0
        More = false;
170
0
      } else {
171
0
        X |= 0x80;
172
0
      }
173
0
      Buf[Len] = X;
174
0
      Len++;
175
0
    }
176
0
    OutVec.insert(OutVec.end(), Buf, Buf + Len);
177
0
  }
Unexecuted instantiation: void WasmEdge::Loader::Serializer::serializeSN<int, 32ul>(int, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const
Unexecuted instantiation: void WasmEdge::Loader::Serializer::serializeSN<long, 64ul>(long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const
Unexecuted instantiation: void WasmEdge::Loader::Serializer::serializeSN<long, 33ul>(long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const
178
179
0
  void serializeS33(int64_t Num, std::vector<uint8_t> &OutVec) const noexcept {
180
0
    serializeSN<int64_t, 33>(Num, OutVec);
181
0
  }
182
183
  template <typename NumType, typename IntType>
184
  typename std::enable_if_t<
185
      sizeof(NumType) == sizeof(IntType) && std::is_integral_v<IntType>, void>
186
0
  serializeFN(NumType Num, std::vector<uint8_t> &OutVec) const noexcept {
187
0
    std::make_unsigned_t<IntType> Buf = 0;
188
0
    std::memcpy(&Buf, &Num, sizeof(NumType));
189
    // Force conversion into little endian.
190
0
    for (uint32_t I = 0; I < sizeof(NumType); I++) {
191
0
      OutVec.push_back(static_cast<uint8_t>(Buf & 0xFFU));
192
0
      Buf = Buf >> 8;
193
0
    }
194
0
  }
Unexecuted instantiation: _ZNK8WasmEdge6Loader10Serializer11serializeFNIfjEENSt3__19enable_ifIXaaeqstT_stT0_sr3stdE13is_integral_vIS6_EEvE4typeES5_RNS3_6vectorIhNS3_9allocatorIhEEEE
Unexecuted instantiation: _ZNK8WasmEdge6Loader10Serializer11serializeFNIdmEENSt3__19enable_ifIXaaeqstT_stT0_sr3stdE13is_integral_vIS6_EEvE4typeES5_RNS3_6vectorIhNS3_9allocatorIhEEEE
195
196
  template <typename T, typename L>
197
  void serializeSectionContent(const T &Sec, uint8_t Code,
198
                               std::vector<uint8_t> &OutVec,
199
0
                               L &&Func) const noexcept {
200
    // Section: section_id + size:u32 + content.
201
0
    auto Content = Sec.getContent();
202
0
    if (Content.size()) {
203
0
      assuming(Content.size() <= UINT32_MAX);
204
      // Section ID.
205
0
      OutVec.push_back(Code);
206
0
      auto OrgSize = OutVec.size();
207
      // Content: vec(T).
208
0
      serializeU32(static_cast<uint32_t>(Content.size()), OutVec);
209
0
      for (const auto &Item : Content) {
210
0
        Func(Item, OutVec);
211
0
      }
212
      // Backward insert the section size.
213
0
      serializeU32(static_cast<uint32_t>(OutVec.size() - OrgSize), OutVec,
214
0
                   std::next(OutVec.begin(), static_cast<ptrdiff_t>(OrgSize)));
215
0
    }
216
0
  }
Unexecuted instantiation: serial_section.cpp:void WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::ImportSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::ImportSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::ImportSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::ImportSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:void WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::FunctionSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::FunctionSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::FunctionSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::FunctionSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:void WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::TableSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::TableSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::TableSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::TableSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:void WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::MemorySection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::MemorySection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::MemorySection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::MemorySection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:void WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::GlobalSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::GlobalSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::GlobalSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::GlobalSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:void WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::ExportSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::ExportSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::ExportSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::ExportSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:void WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::ElementSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::ElementSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::ElementSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::ElementSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:void WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::CodeSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::CodeSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::CodeSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::CodeSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:void WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::DataSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::DataSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::DataSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::DataSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:void WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::TagSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::TagSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::TagSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::TagSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
217
  /// @}
218
};
219
220
} // namespace Loader
221
} // namespace WasmEdge