Something went wrong. Try again.
Monorepo for PackTools - tooling for Minecraft Modpacks!
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174// The exported C ABI. Each function is a noexcept shell around `Runtime`: every exception stops// here and becomes PL_INTERNAL, and every string handed out is owned by the runtime.
#include "packluau.h"#include "runtime.hpp"
#include <cstdint>#include <exception>#include <memory>#include <string>#include <string_view>#include <utility>
struct pl_runtime { std::unique_ptr<packluau::Runtime> impl;};
namespace {
pl_str text_of(const std::string &text) noexcept { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): chars as UTF-8 bytes. return {.ptr = reinterpret_cast<const uint8_t *>(text.data()), .len = text.size()};}
pl_str literal(std::string_view text) noexcept { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): chars as UTF-8 bytes. return {.ptr = reinterpret_cast<const uint8_t *>(text.data()), .len = text.size()};}
/// Whether the host set every function: packluau calls them without checking.bool complete(const pl_host &host) noexcept { return host.realloc != nullptr && host.pack_info != nullptr && host.pack_get != nullptr && host.lock_len != nullptr && host.lock_row != nullptr && host.lock_find != nullptr && host.lock_at != nullptr && host.lock_diff != nullptr && host.lock_dependents != nullptr && host.fs_read != nullptr && host.fs_list != nullptr && host.fs_stat != nullptr && host.fs_sha512 != nullptr && host.git_head != nullptr && host.git_dirty != nullptr && host.git_read != nullptr && host.git_list != nullptr && host.git_log != nullptr && host.git_changed != nullptr && host.jar_metadata != nullptr && host.project_info != nullptr && host.sidecar_parse != nullptr && host.pack_sidecars != nullptr && host.text_lower != nullptr && host.text_did_you_mean != nullptr && host.workspace_projects != nullptr && host.workspace_find != nullptr && host.toml_decode != nullptr && host.lock_parse != nullptr && host.git_changed_workspace != nullptr && host.module_read != nullptr && host.last_error != nullptr;}
/// A failure with no runtime to own its text: the message must be static.pl_status fail_static(pl_error *err, pl_status status, const char *message) noexcept { *err = pl_error{.status = status, .message = literal(message), .chunk = {}, .line = 0, .kind = PL_FAIL_NONE}; return status;}
/// Stores `failure` in the runtime and points `err` at it.pl_status fail(pl_runtime *rt, pl_error *err, packluau::Failure failure) noexcept { const packluau::Failure &stored = rt->impl->keep(std::move(failure)); *err = pl_error{.status = stored.status, .message = text_of(stored.message), .chunk = text_of(stored.chunk), .line = stored.line, .kind = stored.kind}; return stored.status;}
/// An exception escaped `Runtime`: keep its text when there is memory to copy it.pl_status fail_exception(pl_runtime *rt, pl_error *err, const char *what) noexcept { try { return fail(rt, err, packluau::Failure{.status = PL_INTERNAL, .message = std::string("internal error: ") + what, .chunk = {}, .line = 0}); } catch (...) { return fail_static(err, PL_INTERNAL, "internal error (no memory to describe it)"); }}
} // namespace
#ifndef PACKLUAU_LUAU_VERSION#error "build.zig defines PACKLUAU_LUAU_VERSION from the root flake's pin"#endif
uint32_t packluau_abi(void) noexcept { return PACKLUAU_ABI;}
pl_str packluau_luau_version(void) noexcept { return literal(PACKLUAU_LUAU_VERSION);}
pl_status packluau_create(const pl_host *host, uint32_t host_abi, pl_runtime **out, pl_error *err) noexcept { if (err == nullptr) { return PL_INVALID; } if (out == nullptr || host == nullptr) { return fail_static(err, PL_INVALID, "packluau_create needs a host and an out pointer"); } *out = nullptr; if (host_abi != PACKLUAU_ABI) { return fail_static(err, PL_INVALID, "the host speaks a different PACKLUAU_ABI"); } if (host->size != sizeof(pl_host)) { return fail_static(err, PL_INVALID, "the host's pl_host has a different size"); } if (!complete(*host)) { return fail_static(err, PL_INVALID, "the host must provide every function in pl_host"); } try { auto created = packluau::Runtime::create(*host); if (!created) { return fail_static(err, created.error().status, "could not create the Luau state"); } auto runtime = std::make_unique<pl_runtime>(); runtime->impl = std::move(*created); // Ownership crosses the C ABI here; packluau_destroy takes it back. *out = runtime.release(); return PL_OK; } catch (...) { return fail_static(err, PL_INTERNAL, "an exception escaped while creating the runtime"); }}
pl_status packluau_run(pl_runtime *rt, const pl_run_request *req, pl_run_result *out, pl_error *err) noexcept { if (err == nullptr) { return PL_INVALID; } if (rt == nullptr || req == nullptr || out == nullptr) { return fail_static(err, PL_INVALID, "packluau_run needs a runtime, a request and a result"); } *out = pl_run_result{}; try { auto ran = rt->impl->run(*req); if (!ran) { return fail(rt, err, std::move(ran.error())); } const packluau::RunOutput &kept = rt->impl->keep(std::move(*ran)); *out = pl_run_result{.plan = text_of(kept.plan), .report = text_of(kept.report)}; return PL_OK; } catch (const std::exception &e) { return fail_exception(rt, err, e.what()); } catch (...) { return fail_exception(rt, err, "unknown exception"); }}
void packluau_free_result(pl_runtime *rt, pl_run_result *result) noexcept { if (rt != nullptr) { rt->impl->clear_output(); } if (result != nullptr) { *result = pl_run_result{}; }}
void packluau_free_error(pl_runtime *rt, pl_error *err) noexcept { if (rt != nullptr) { rt->impl->clear_failure(); } if (err != nullptr) { *err = pl_error{}; }}
void packluau_destroy(pl_runtime *rt) noexcept { // Takes back what packluau_create released. const std::unique_ptr<pl_runtime> owned(rt);}