#pragma once
#include <assert.h>
#include <map>
#include <optional>
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <stdint.h>
#include <string>
#include <string_view>
#include <string.h>
#include <stdlib.h>
#include <new>
#include <span>
#include <utility>
namespace wit {
template <class R> class ResourceTable {
static std::map<int32_t, R> resources;
public:
static R *lookup_resource(int32_t id) {
auto result = resources.find(id);
return result == resources.end() ? nullptr : &result->second;
}
static int32_t store_resource(R &&value) {
auto last = resources.rbegin();
int32_t id = last == resources.rend() ? 0 : last->first + 1;
resources.insert(std::pair<int32_t, R>(id, std::move(value)));
return id;
}
static std::optional<R> remove_resource(int32_t id) {
auto iter = resources.find(id);
std::optional<R> result;
if (iter != resources.end()) {
result = std::move(iter->second);
resources.erase(iter);
}
return std::move(result);
}
};
struct Void {};
class string {
uint8_t const *data_;
size_t length;
static uint8_t const* empty_ptr() { return (uint8_t const *)1; }
public:
string(string const &b) : string(string::from_view(b.get_view())) {}
string(string &&b) : data_(b.data_), length(b.length) { b.data_ = nullptr; }
string &operator=(string const &) = delete;
string &operator=(string &&b) {
if (data_ && data_!=empty_ptr()) {
free(const_cast<uint8_t *>(data_));
}
data_ = b.data_;
length = b.length;
b.data_ = nullptr;
return *this;
}
string(char const *d, size_t l) : data_((uint8_t const *)d), length(l) {}
char const *data() const { return (char const *)data_; }
size_t size() const { return length; }
bool empty() const { return !length; }
~string() {
if (data_ && data_!=empty_ptr()) {
free(const_cast<uint8_t *>(data_));
}
}
void leak() { data_ = nullptr; }
static void drop_raw(void *ptr) { free(ptr); }
std::string_view get_view() const {
return std::string_view((const char *)data_, length);
}
std::string to_string() const {
return std::string((const char *)data_, length);
}
static string from_view(std::string_view v) {
if (!v.size()) return string((char const*)empty_ptr(), 0);
char* addr = (char*)malloc(v.size());
memcpy(addr, v.data(), v.size());
return string(addr, v.size());
}
char* begin() {
return (char*)data_;
}
char* end() {
return (char*)data_ + length;
}
char const* begin() const {
return (char const*)data_;
}
char const* end() const {
return (char const*)data_ + length;
}
};
template <class T> class vector {
T *data_;
size_t length;
static T* empty_ptr() { return (T*)alignof(T); }
public:
vector(vector const &) = delete;
vector(vector &&b) : data_(b.data_), length(b.length) { b.data_ = nullptr; }
vector &operator=(vector const &) = delete;
vector &operator=(vector &&b) {
if (data_ && length>0) {
free(data_);
}
data_ = b.data_;
length = b.length;
b.data_ = nullptr;
return *this;
}
vector(T *d, size_t l) : data_(d), length(l) {}
vector() : data_(empty_ptr()), length() {}
T const *data() const { return data_; }
T *data() { return data_; }
T &operator[](size_t n) { return data_[n]; }
T const &operator[](size_t n) const { return data_[n]; }
size_t size() const { return length; }
bool empty() const { return !length; }
~vector() {
if (data_ && length>0) {
for (unsigned i=0;i<length;++i) { data_[i].~T(); }
free((void*)data_);
}
}
static vector<T> allocate(size_t len) {
if (!len) return vector<T>(empty_ptr(), 0);
return vector<T>((T*)malloc(sizeof(T)*len), len);
}
void initialize(size_t n, T&& elem) {
new ((void*)(data_+n)) T(std::move(elem));
}
T* leak() { T*result = data_; data_ = nullptr; return result; }
static void drop_raw(void *ptr) { if (ptr!=empty_ptr()) free(ptr); }
std::span<T> get_view() const { return std::span<T>(data_, length); }
std::span<const T> get_const_view() const { return std::span<const T>(data_, length); }
template <class U> static vector<T> from_view(std::span<U> const& a) {
auto result = vector<T>::allocate(a.size());
for (uint32_t i=0;i<a.size();++i) {
new ((void*)(result.data_+i)) T(a[i]);
}
return result;
}
};
template <class K, class V> class unordered_map {
public:
using entry_type = std::pair<K, V>;
private:
entry_type *data_;
size_t length;
static entry_type* empty_ptr() { return (entry_type*)alignof(entry_type); }
public:
unordered_map(unordered_map const &) = delete;
unordered_map(unordered_map &&b) : data_(b.data_), length(b.length) {
b.data_ = nullptr;
b.length = 0;
}
unordered_map &operator=(unordered_map const &) = delete;
unordered_map &operator=(unordered_map &&b) {
if (data_ && length > 0) {
for (unsigned i = 0; i < length; ++i) { data_[i].~entry_type(); }
free(data_);
}
data_ = b.data_;
length = b.length;
b.data_ = nullptr;
b.length = 0;
return *this;
}
unordered_map(entry_type *d, size_t l) : data_(d), length(l) {}
unordered_map() : data_(empty_ptr()), length() {}
entry_type const *data() const { return data_; }
entry_type *data() { return data_; }
size_t size() const { return length; }
bool empty() const { return !length; }
~unordered_map() {
if (data_ && length > 0) {
for (unsigned i = 0; i < length; ++i) { data_[i].~entry_type(); }
free((void*)data_);
}
}
static unordered_map<K, V> allocate(size_t len) {
if (!len) return unordered_map<K, V>(empty_ptr(), 0);
return unordered_map<K, V>(
(entry_type*)malloc(sizeof(entry_type) * len), len);
}
void initialize(size_t n, entry_type&& entry) {
new ((void*)(data_ + n)) entry_type(std::move(entry));
}
entry_type *leak() {
entry_type *result = data_;
data_ = nullptr;
return result;
}
static void drop_raw(void *ptr) {
if (ptr != empty_ptr()) free(ptr);
}
entry_type *begin() { return data_; }
entry_type *end() { return data_ + length; }
entry_type const *begin() const { return data_; }
entry_type const *end() const { return data_ + length; }
};
template <class R> class ResourceExportBase {
public:
struct Deregister {
void operator()(R *ptr) const {
#ifdef WIT_SYMMETRIC
if (ptr->handle != nullptr)
#else
if (ptr->handle >= 0)
#endif
{
R::ResourceDrop(ptr->handle);
}
}
};
typedef std::unique_ptr<R, Deregister> Owned;
#ifdef WIT_SYMMETRIC
typedef uint8_t *handle_t;
static constexpr handle_t invalid = nullptr;
#else
typedef int32_t handle_t;
static const handle_t invalid = -1;
#endif
handle_t handle;
ResourceExportBase() : handle(R::ResourceNew((R *)this)) {}
~ResourceExportBase() {}
ResourceExportBase(ResourceExportBase const &) = delete;
ResourceExportBase(ResourceExportBase &&) = delete;
ResourceExportBase &operator=(ResourceExportBase &&b) = delete;
ResourceExportBase &operator=(ResourceExportBase const &) = delete;
handle_t get_handle() const { return handle; }
handle_t into_handle() {
handle_t result = handle;
handle = invalid;
return result;
}
};
class ResourceImportBase {
public:
#ifdef WIT_SYMMETRIC
typedef uint8_t *handle_t;
static constexpr handle_t invalid = nullptr;
#else
typedef int32_t handle_t;
static const handle_t invalid = -1;
#endif
protected:
handle_t handle;
public:
ResourceImportBase(handle_t h = invalid) : handle(h) {}
ResourceImportBase(ResourceImportBase &&r) : handle(r.handle) {
r.handle = invalid;
}
ResourceImportBase(ResourceImportBase const &) = delete;
void set_handle(handle_t h) { handle = h; }
handle_t get_handle() const { return handle; }
handle_t into_handle() {
handle_t h = handle;
handle = invalid;
return h;
}
ResourceImportBase &operator=(ResourceImportBase &&r) {
assert(handle == invalid);
handle = r.handle;
r.handle = invalid;
return *this;
}
ResourceImportBase &operator=(ResourceImportBase const &r) = delete;
};
}