Coverage Report

Created: 2026-06-30 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/include/plugin/plugin.h
Line
Count
Source
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright The WasmEdge Authors
3
4
//===-- wasmedge/plugin/plugin.h - Plugin class definition ----------------===//
5
//
6
// Part of the WasmEdge Project.
7
//
8
//===----------------------------------------------------------------------===//
9
///
10
/// \file
11
/// This file defines the Plugin class.
12
///
13
//===----------------------------------------------------------------------===//
14
#pragma once
15
16
#include "common/defines.h"
17
#include "common/filesystem.h"
18
#include "common/hash.h"
19
#include "common/version.h"
20
#include "loader/shared_library.h"
21
#include "po/argument_parser.h"
22
#include "runtime/instance/component/component.h"
23
#include "runtime/instance/module.h"
24
25
#include <cstdint>
26
#include <deque>
27
#include <memory>
28
#include <mutex>
29
#include <shared_mutex>
30
#include <vector>
31
32
#define EXPORT_GET_DESCRIPTOR(Descriptor)                                      \
33
  extern "C" WASMEDGE_EXPORT decltype(&Descriptor) GetDescriptor();            \
34
  extern "C" WASMEDGE_EXPORT decltype(&Descriptor) GetDescriptor() {           \
35
    return &Descriptor;                                                        \
36
  }
37
38
namespace WasmEdge {
39
namespace Plugin {
40
41
class PluginModule {
42
public:
43
  PluginModule(const PluginModule &) = delete;
44
  PluginModule &operator=(const PluginModule &) = delete;
45
  PluginModule(PluginModule &&) noexcept = default;
46
  PluginModule &operator=(PluginModule &&) noexcept = default;
47
48
  struct ModuleDescriptor {
49
    const char *Name;
50
    const char *Description;
51
    Runtime::Instance::ModuleInstance *(*Create)(
52
        const ModuleDescriptor *) noexcept;
53
  };
54
55
0
  constexpr PluginModule() noexcept {}
56
57
0
  constexpr const char *name() const noexcept {
58
0
    assuming(Desc);
59
0
    return Desc->Name;
60
0
  }
61
62
0
  constexpr const char *description() const noexcept {
63
0
    assuming(Desc);
64
0
    return Desc->Description;
65
0
  }
66
67
0
  std::unique_ptr<Runtime::Instance::ModuleInstance> create() const noexcept {
68
0
    assuming(Desc);
69
0
    return std::unique_ptr<Runtime::Instance::ModuleInstance>(
70
0
        Desc->Create(Desc));
71
0
  }
72
73
private:
74
  const ModuleDescriptor *Desc = nullptr;
75
76
  constexpr explicit PluginModule(const ModuleDescriptor *D) noexcept
77
0
      : Desc(D) {}
78
  friend class Plugin;
79
};
80
81
class PluginComponent {
82
public:
83
  PluginComponent(const PluginComponent &) = delete;
84
  PluginComponent &operator=(const PluginComponent &) = delete;
85
  PluginComponent(PluginComponent &&) noexcept = default;
86
  PluginComponent &operator=(PluginComponent &&) noexcept = default;
87
88
  struct ComponentDescriptor {
89
    const char *Name;
90
    const char *Description;
91
    Runtime::Instance::ComponentInstance *(*Create)(
92
        const ComponentDescriptor *) noexcept;
93
  };
94
95
0
  constexpr PluginComponent() noexcept {}
96
97
0
  constexpr const char *name() const noexcept {
98
0
    assuming(Desc);
99
0
    return Desc->Name;
100
0
  }
101
102
0
  constexpr const char *description() const noexcept {
103
0
    assuming(Desc);
104
0
    return Desc->Description;
105
0
  }
106
107
  std::unique_ptr<Runtime::Instance::ComponentInstance>
108
0
  create() const noexcept {
109
0
    assuming(Desc);
110
0
    return std::unique_ptr<Runtime::Instance::ComponentInstance>(
111
0
        Desc->Create(Desc));
112
0
  }
113
114
private:
115
  const ComponentDescriptor *Desc = nullptr;
116
117
  constexpr explicit PluginComponent(const ComponentDescriptor *D) noexcept
118
0
      : Desc(D) {}
119
  friend class Plugin;
120
};
121
122
class Plugin {
123
public:
124
  struct VersionData {
125
    uint32_t Major;
126
    uint32_t Minor;
127
    uint32_t Patch;
128
    uint32_t Build;
129
  };
130
  struct PluginDescriptor {
131
    const char *Name;
132
    const char *Description;
133
    uint32_t APIVersion;
134
    VersionData Version;
135
    size_t ModuleCount;
136
    PluginModule::ModuleDescriptor *ModuleDescriptions;
137
    size_t ComponentCount = 0;
138
    PluginComponent::ComponentDescriptor *ComponentDescriptions = nullptr;
139
    void (*AddOptions)(const PluginDescriptor *D,
140
                       PO::ArgumentParser &Parser) noexcept;
141
  };
142
143
  // Const value of current plugin API version.
144
  static inline constexpr const uint32_t CurrentAPIVersion [[maybe_unused]] =
145
      kPluginCurrentAPIVersion;
146
147
  // Static function to load plugins from default paths.
148
  WASMEDGE_EXPORT static void loadFromDefaultPaths() noexcept;
149
150
  // Static function to get default plugin paths.
151
  static std::vector<std::filesystem::path> getDefaultPluginPaths() noexcept;
152
153
  // Static function to load all plugins from given path.
154
  WASMEDGE_EXPORT static bool load(const std::filesystem::path &Path) noexcept;
155
156
  // Static function to register plugin with descriptor.
157
  static bool registerPlugin(const PluginDescriptor *Desc) noexcept;
158
159
  // Static function to add plugin options from arguments.
160
  static void addPluginOptions(PO::ArgumentParser &Parser) noexcept;
161
162
  // Static function to find loaded plugin by name.
163
  WASMEDGE_EXPORT static const Plugin *find(std::string_view Name) noexcept;
164
165
  // Static function to list loaded plugins.
166
  static const std::deque<Plugin> &plugins() noexcept;
167
168
  Plugin(const Plugin &) = delete;
169
  Plugin &operator=(const Plugin &) = delete;
170
  Plugin(Plugin &&) noexcept = default;
171
  Plugin &operator=(Plugin &&) noexcept = default;
172
173
  Plugin() noexcept = default;
174
  explicit Plugin(const PluginDescriptor *D) noexcept;
175
176
0
  constexpr const char *name() const noexcept {
177
0
    assuming(Desc);
178
0
    return Desc->Name;
179
0
  }
180
181
0
  constexpr const char *description() const noexcept {
182
0
    assuming(Desc);
183
0
    return Desc->Description;
184
0
  }
185
186
0
  constexpr VersionData version() const noexcept {
187
0
    assuming(Desc);
188
0
    return Desc->Version;
189
0
  }
190
191
0
  void registerOptions(PO::ArgumentParser &Parser) const noexcept {
192
0
    assuming(Desc);
193
0
    if (Desc->AddOptions) {
194
0
      Desc->AddOptions(Desc, Parser);
195
0
    }
196
0
  }
197
198
0
  Span<const PluginModule> modules() const noexcept {
199
0
    assuming(Desc);
200
0
    return ModuleRegistry;
201
0
  }
202
0
  Span<const PluginComponent> components() const noexcept {
203
0
    assuming(Desc);
204
0
    return ComponentRegistry;
205
0
  }
206
207
  WASMEDGE_EXPORT const PluginModule *
208
  findModule(std::string_view Name) const noexcept;
209
210
  WASMEDGE_EXPORT const PluginComponent *
211
  findComponent(std::string_view Name) const noexcept;
212
213
0
  std::filesystem::path path() const noexcept { return Path; }
214
215
private:
216
  // Guards PluginRegistry / PluginNameLookup.
217
  static std::shared_mutex Mutex;
218
  // std::deque (not std::vector) so that pointers/references returned by find()
219
  // and plugins() remain valid even when more plugins are appended later.
220
  static std::deque<Plugin> PluginRegistry;
221
  static std::unordered_map<std::string_view, std::size_t, Hash::Hash>
222
      PluginNameLookup;
223
224
  // Static function to load plugin from file. Thread-safe. Idempotent: a file
225
  // that has already been loaded in this process is skipped (not re-dlopen'd).
226
  static bool loadFile(const std::filesystem::path &Path) noexcept;
227
228
  // Static function to register built-in plugins. Thread-safe.
229
  static void registerBuiltInPlugins() noexcept;
230
231
  // Plugin contents.
232
  std::filesystem::path Path;
233
  const PluginDescriptor *Desc = nullptr;
234
  std::shared_ptr<Loader::SharedLibrary> Lib;
235
  std::vector<PluginModule> ModuleRegistry;
236
  std::vector<PluginComponent> ComponentRegistry;
237
  std::unordered_map<std::string_view, std::size_t, Hash::Hash>
238
      ModuleNameLookup;
239
  std::unordered_map<std::string_view, std::size_t, Hash::Hash>
240
      ComponentNameLookup;
241
};
242
243
} // namespace Plugin
244
} // namespace WasmEdge