Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions crates/c-api/include/wasmtime/component.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Convenience header to include all of `wasmtime/component/*.hh`.

#ifndef WASMTIME_COMPONENT_HH
#define WASMTIME_COMPONENT_HH

#include <wasmtime/component/component.hh>

#endif // WASMTIME_COMPONENT_HH
7 changes: 7 additions & 0 deletions crates/c-api/include/wasmtime/component/component.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ wasmtime_component_get_export_index(
const wasmtime_component_export_index_t *instance_export_index,
const char *name, size_t name_len);

/**
* \brief Creates a new separately-owned copy of the specified index.
*/
WASM_API_EXTERN wasmtime_component_export_index_t *
wasmtime_component_export_index_clone(
const wasmtime_component_export_index_t *index);

/**
* \brief Deletes a #wasmtime_component_export_index_t
*
Expand Down
230 changes: 230 additions & 0 deletions crates/c-api/include/wasmtime/component/component.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/**
* \file wasmtime/component/component.hh
*/

#ifndef WASMTIME_COMPONENT_HH
#define WASMTIME_COMPONENT_HH

#include <wasmtime/conf.h>

#ifdef WASMTIME_FEATURE_COMPONENT_MODEL

#include <memory>
#include <optional>
#include <string_view>
#include <vector>
#include <wasmtime/component/component.h>
#include <wasmtime/engine.hh>
#include <wasmtime/error.hh>
#include <wasmtime/span.hh>
#include <wasmtime/wat.hh>

namespace wasmtime {
namespace component {

/**
* \brief An index to an exported item within a particular component.
*
* This structure is acquired from a `Component` and used to lookup exports on
* instances.
*/
class ExportIndex {
friend class Component;

struct deleter {
void operator()(wasmtime_component_export_index_t *p) const {
wasmtime_component_export_index_delete(p);
}
};

std::unique_ptr<wasmtime_component_export_index_t, deleter> ptr;

ExportIndex(wasmtime_component_export_index_t *raw) : ptr(raw) {}

public:
/// Copies another index into this one.
ExportIndex(const ExportIndex &other)
: ptr(wasmtime_component_export_index_clone(other.ptr.get())) {}
/// Copies another index into this one.
ExportIndex &operator=(const ExportIndex &other) {
ptr.reset(wasmtime_component_export_index_clone(other.ptr.get()));
return *this;
}

~ExportIndex() = default;
/// Moves resources from another component into this one.
ExportIndex(ExportIndex &&other) = default;
/// Moves resources from another component into this one.
ExportIndex &operator=(ExportIndex &&other) = default;

/// \brief Returns the underlying C API pointer.
const wasmtime_component_export_index_t *capi() const { return ptr.get(); }

/// \brief Returns the underlying C API pointer.
wasmtime_component_export_index_t *capi() { return ptr.get(); }
};

/**
* \brief Representation of a compiled WebAssembly component.
*/
class Component {
struct deleter {
void operator()(wasmtime_component_t *p) const {
wasmtime_component_delete(p);
}
};

std::unique_ptr<wasmtime_component_t, deleter> ptr;

Component(wasmtime_component_t *raw) : ptr(raw) {}

public:
/// Copies another component into this one.
Component(const Component &other)
: ptr(wasmtime_component_clone(other.ptr.get())) {}
/// Copies another component into this one.
Component &operator=(const Component &other) {
ptr.reset(wasmtime_component_clone(other.ptr.get()));
return *this;
}
~Component() = default;
/// Moves resources from another component into this one.
Component(Component &&other) = default;
/// Moves resources from another component into this one.
Component &operator=(Component &&other) = default;

/// \brief Returns the underlying C API pointer.
const wasmtime_component_t *capi() const { return ptr.get(); }

/// \brief Returns the underlying C API pointer.
wasmtime_component_t *capi() { return ptr.get(); }

#ifdef WASMTIME_FEATURE_COMPILER
/**
* \brief Compiles a component from the WebAssembly text format.
*
* This function will automatically use `wat2wasm` on the input and then
* delegate to the #compile function.
*/
static Result<Component> compile(Engine &engine, std::string_view wat) {
auto wasm = wat2wasm(wat);
if (!wasm) {
return wasm.err();
}
auto bytes = wasm.ok();
return compile(engine, bytes);
}

/**
* \brief Compiles a component from the WebAssembly binary format.
*
* This function compiles the provided WebAssembly binary specified by `wasm`
* within the compilation settings configured by `engine`. This method is
* synchronous and will not return until the component has finished compiling.
*
* This function can fail if the WebAssembly binary is invalid or doesn't
* validate (or similar). Note that this API does not compile WebAssembly
* modules, which is done with `Module` instead of `Component`.
*/
static Result<Component> compile(Engine &engine, Span<uint8_t> wasm) {
wasmtime_component_t *ret = nullptr;
auto *error =
wasmtime_component_new(engine.capi(), wasm.data(), wasm.size(), &ret);
if (error != nullptr) {
return Error(error);
}
return Component(ret);
}
#endif // WASMTIME_FEATURE_COMPILER

/**
* \brief Deserializes a previous list of bytes created with `serialize`.
*
* This function is intended to be much faster than `compile` where it uses
* the artifacts of a previous compilation to quickly create an in-memory
* component ready for instantiation.
*
* It is not safe to pass arbitrary input to this function, it is only safe to
* pass in output from previous calls to `serialize`. For more information see
* the Rust documentation -
* https://docs.wasmtime.dev/api/wasmtime/struct.Module.html#method.deserialize
*/
static Result<Component> deserialize(Engine &engine, Span<uint8_t> wasm) {
wasmtime_component_t *ret = nullptr;
auto *error = wasmtime_component_deserialize(engine.capi(), wasm.data(),
wasm.size(), &ret);
if (error != nullptr) {
return Error(error);
}
return Component(ret);
}

/**
* \brief Deserializes a component from an on-disk file.
*
* This function is the same as `deserialize` except that it reads the data
* for the serialized component from the path on disk. This can be faster than
* the alternative which may require copying the data around.
*
* It is not safe to pass arbitrary input to this function, it is only safe to
* pass in output from previous calls to `serialize`. For more information see
* the Rust documentation -
* https://docs.wasmtime.dev/api/wasmtime/struct.Module.html#method.deserialize
*/
static Result<Component> deserialize_file(Engine &engine,
const std::string &path) {
wasmtime_component_t *ret = nullptr;
auto *error =
wasmtime_component_deserialize_file(engine.capi(), path.c_str(), &ret);
if (error != nullptr) {
return Error(error);
}
return Component(ret);
}

#ifdef WASMTIME_FEATURE_COMPILER
/**
* \brief Serializes this component to a list of bytes.
*
* The returned bytes can then be used to later pass to `deserialize` to
* quickly recreate this component in a different process perhaps.
*/
Result<std::vector<uint8_t>> serialize() const {
wasm_byte_vec_t bytes;
auto *error = wasmtime_component_serialize(ptr.get(), &bytes);
if (error != nullptr) {
return Error(error);
}
std::vector<uint8_t> ret;
Span<uint8_t> raw(reinterpret_cast<uint8_t *>(bytes.data), bytes.size);
ret.assign(raw.begin(), raw.end());
wasm_byte_vec_delete(&bytes);
return ret;
}
#endif // WASMTIME_FEATURE_COMPILER

/**
* \brief Returns the export index for the export named `name` in this
* component.
*
* The `instance` argument is an optionally provided index which is the
* instance under which the `name` should be looked up.
*/
std::optional<ExportIndex> export_index(ExportIndex *instance,
std::string_view name) {
auto ret = wasmtime_component_get_export_index(
capi(), instance ? instance->capi() : nullptr, name.data(),
name.size());
if (ret) {
return ExportIndex(ret);
}
return std::nullopt;
};
};

} // namespace component
} // namespace wasmtime

#endif // WASMTIME_FEATURE_COMPONENT_MODEL

#endif // WASMTIME_COMPONENT_HH
6 changes: 6 additions & 0 deletions crates/c-api/include/wasmtime/engine.hh
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ public:

/// \brief Returns whether this engine is using Pulley for execution.
void is_pulley() const { wasmtime_engine_is_pulley(ptr.get()); }

/// \brief Returns the underlying C API pointer.
const wasm_engine_t *capi() const { return ptr.get(); }

/// \brief Returns the underlying C API pointer.
wasm_engine_t *capi() { return ptr.get(); }
};

} // namespace wasmtime
Expand Down
8 changes: 4 additions & 4 deletions crates/c-api/include/wasmtime/func.hh
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ template <> struct WasmType<std::optional<ExternRef>> {
return std::nullopt;
}
wasmtime_externref_t val;
wasmtime_externref_from_raw(cx.raw_context(), p->externref, &val);
wasmtime_externref_from_raw(cx.capi(), p->externref, &val);
return ExternRef(val);
}
};
Expand Down Expand Up @@ -618,7 +618,7 @@ public:
ptr = reinterpret_cast<wasmtime_val_raw_t *>(alignof(wasmtime_val_raw_t));
WasmTypeList<Params>::store(cx, ptr, params);
wasm_trap_t *trap = nullptr;
auto *error = wasmtime_func_call_unchecked(cx.raw_context(), &f.func, ptr,
auto *error = wasmtime_func_call_unchecked(cx.capi(), &f.func, ptr,
storage.size(), &trap);
if (error != nullptr) {
return TrapError(Error(error));
Expand Down Expand Up @@ -666,7 +666,7 @@ template <> struct detail::WasmType<std::optional<Func>> {
static void store(Store::Context cx, wasmtime_val_raw_t *p,
const std::optional<Func> func) {
if (func) {
p->funcref = wasmtime_func_to_raw(cx.raw_context(), &func->capi());
p->funcref = wasmtime_func_to_raw(cx.capi(), &func->capi());
} else {
p->funcref = 0;
}
Expand All @@ -677,7 +677,7 @@ template <> struct detail::WasmType<std::optional<Func>> {
return std::nullopt;
}
wasmtime_func_t ret;
wasmtime_func_from_raw(cx.raw_context(), p->funcref, &ret);
wasmtime_func_from_raw(cx.capi(), p->funcref, &ret);
return ret;
}
};
Expand Down
6 changes: 6 additions & 0 deletions crates/c-api/include/wasmtime/module.hh
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ public:
return ret;
}
#endif // WASMTIME_FEATURE_COMPILER

/// \brief Returns the underlying C API pointer.
const wasmtime_module_t *capi() const { return ptr.get(); }

/// \brief Returns the underlying C API pointer.
wasmtime_module_t *capi() { return ptr.get(); }
};

} // namespace wasmtime
Expand Down
13 changes: 11 additions & 2 deletions crates/c-api/include/wasmtime/store.hh
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,11 @@ public:
wasmtime_context_set_epoch_deadline(ptr, ticks_beyond_current);
}

/// Returns the raw context pointer for the C API.
wasmtime_context_t *raw_context() { return ptr; }
/// \brief Returns the underlying C API pointer.
const wasmtime_context_t *capi() const { return ptr; }

/// \brief Returns the underlying C API pointer.
wasmtime_context_t *capi() { return ptr; }
};

/// \brief Provides limits for a store. Used by hosts to limit resource
Expand Down Expand Up @@ -195,6 +198,12 @@ public:
/// Runs a garbage collection pass in the referenced store to collect loose
/// GC-managed objects, if any are available.
void gc() { context().gc(); }

/// \brief Returns the underlying C API pointer.
const wasmtime_store_t *capi() const { return ptr.get(); }

/// \brief Returns the underlying C API pointer.
wasmtime_store_t *capi() { return ptr.get(); }
};

} // namespace wasmtime
Expand Down
8 changes: 4 additions & 4 deletions crates/c-api/include/wasmtime/val.hh
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ public:
/// Consumes ownership of the underlying `wasmtime_externref_t` and returns
/// the result of `wasmtime_externref_to_raw`.
uint32_t take_raw(Store::Context cx) {
uint32_t ret = wasmtime_externref_to_raw(cx.raw_context(), &val);
uint32_t ret = wasmtime_externref_to_raw(cx.capi(), &val);
wasmtime_externref_set_null(&val);
return ret;
}

/// Returns `wasmtime_externref_to_raw`.
uint32_t borrow_raw(Store::Context cx) const {
return wasmtime_externref_to_raw(cx.raw_context(), &val);
return wasmtime_externref_to_raw(cx.capi(), &val);
}
};

Expand Down Expand Up @@ -148,14 +148,14 @@ public:
/// Consumes ownership of the underlying `wasmtime_anyref_t` and returns the
/// result of `wasmtime_anyref_to_raw`.
uint32_t take_raw(Store::Context cx) {
uint32_t ret = wasmtime_anyref_to_raw(cx.raw_context(), &val);
uint32_t ret = wasmtime_anyref_to_raw(cx.capi(), &val);
wasmtime_anyref_set_null(&val);
return ret;
}

/// Returns `wasmtime_anyref_to_raw`.
uint32_t borrow_raw(Store::Context cx) const {
return wasmtime_anyref_to_raw(cx.raw_context(), &val);
return wasmtime_anyref_to_raw(cx.capi(), &val);
}

/// \brief If this is an `i31`, get the value zero-extended.
Expand Down
9 changes: 9 additions & 0 deletions crates/c-api/src/component/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ pub unsafe extern "C" fn wasmtime_component_get_export_index(
.map(|export_index| Box::new(wasmtime_component_export_index_t { export_index }))
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn wasmtime_component_export_index_clone(
export_index: &wasmtime_component_export_index_t,
) -> Box<wasmtime_component_export_index_t> {
Box::new(wasmtime_component_export_index_t {
export_index: export_index.export_index,
})
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn wasmtime_component_export_index_delete(
_export_index: Box<wasmtime_component_export_index_t>,
Expand Down
Loading