#pragma once
#include <stdint.h>
#include <cstring>
#include <cassert>
#include <string>
#include <memory>
#ifndef RUST_VEC_CONTENT
#define RUST_VEC_CONTENT(T) size_t cap = 0; T* data = 0; size_t len = 0
#endif
#define RUST_NULLPTR(T) ((T*)__alignof(T))
#define RUST_IS_NULLPTR2(T, ptr) ((size_t)(ptr) <= __alignof(T))
#define RUST_IS_NULLPTR(ptr) ((size_t)(ptr) <= __alignof(decltype(*ptr)))
struct rust_refstr_t {
const char* data;
size_t len;
};
template <typename T>
struct RustVec {
RUST_VEC_CONTENT(T);
const T* begin() const { return data; }
const T* end() const { return data + len; }
T* begin() { return data; }
T* end() { return data + len; }
~RustVec() { clear(true); }
RustVec() { cap = 0; len = 0; data = RUST_NULLPTR(T); }
RustVec(const RustVec& ano) {
data = RUST_NULLPTR(T); len = cap = 0;
__set_from(ano.data, ano.len);
}
RustVec(const T* ptr, size_t cnt) {
data = RUST_NULLPTR(T); len = cap = 0;
__set_from(ptr, cnt);
}
RustVec(RustVec&& ano) noexcept {
len = ano.len;
cap = ano.cap;
data = ano.data;
ano.data = RUST_NULLPTR(T);
ano.len = 0;
ano.cap = 0;
}
void assign(const T* ptr, size_t cnt) {
clear();
__set_from(ptr, cnt);
}
void reserve(size_t newcap) {
if (cap >= newcap) return;
if (void* old_dp = data_ptr(); old_dp) {
data = (T*)realloc(old_dp, sizeof(T) * newcap);
} else {
data = (T*)malloc(sizeof(T) * newcap);
}
cap = newcap;
}
void resize(size_t newsz) {
reserve(newsz);
const auto sz = len;
if (sz == newsz) return;
if (sz > newsz) {
if constexpr (!std::is_trivially_destructible<T>::value) {
for (uintptr_t i = newsz; i < sz; ++i) {
data[i].~T();
}
}
} else {
if constexpr (std::is_trivially_constructible_v<T>) {
memset(data_ptr() + sz, 0, (newsz - sz) * sizeof(T));
} else {
for (uintptr_t i = sz; i < newsz; ++i) {
new (data + i) T();
}
}
}
len = newsz;
}
RustVec& operator = (const RustVec& ano) {
clear();
__set_from(ano.data, ano.len);
return *this;
}
RustVec& operator = (RustVec&& ano) noexcept {
clear(true);
std::swap(data, ano.data);
std::swap(len, ano.len);
std::swap(cap, ano.cap);
return *this;
}
void clear(bool free_ = false) {
if constexpr (!std::is_trivially_destructible<T>::value) {
for (uintptr_t i = 0; i < len; ++i) {
data[i].~T();
}
}
len = 0;
if (free_) {
if (data_ptr()) free(data);
data = RUST_NULLPTR(T);
cap = 0;
}
}
void push_back(const T& t) {
if (len == cap) {
cap = std::max<uintptr_t>(cap * 2, 32u);
void* old_dp = data_ptr();
data = (T*)realloc(old_dp, sizeof(T) * cap);
}
new (data + len) T(t);
++len;
}
T* data_ptr() { return RUST_IS_NULLPTR(data) ? nullptr : data; }
const T* data_ptr() const { return RUST_IS_NULLPTR(data) ? nullptr : data; }
size_t size() const { return len; }
bool empty() const { return len == 0; }
protected:
void __set_from(const T* data0, size_t len0)
{
if (cap < len0) {
if (data_ptr()) free(data);
data = (T*)malloc(sizeof(T) * len0);
cap = len0;
}
len = len0;
if constexpr (std::is_trivially_copyable<T>::value) {
if (data) memcpy(data, data0, sizeof(T) * len0);
} else {
for (uintptr_t i = 0; i < len0; ++i) {
new (data + i) T(data0[i]);
}
}
}
};
struct RustString : RustVec<char>
{
~RustString() { if (data_ptr()) free(data); data=0;cap=len=0; }
RustString() = default;
RustString(const RustString& ano) : RustVec<char>() {
__set_from(ano.data_ptr(), ano.len);
}
RustString(RustString&& ano) noexcept : RustVec<char>(std::move(ano)) {}
RustString(const char* str) {
cap = len = 0; data = RUST_NULLPTR(char);
__set_from(str, strlen(str));
}
RustString(const char* str, size_t len0) {
cap = len = 0; data = RUST_NULLPTR(char);
__set_from(str, len0);
}
const char* c_str() const {
auto ret = data_ptr();
assert(ret == 0 || ret[len] == 0);
return ret;
}
std::string str() const {
return std::string(data, len);
}
std::string_view view() const {
return std::string_view(data, len);
}
void assign(const char* ptr, size_t cnt) {
clear();
__set_from(ptr, cnt);
}
RustString& operator=(RustString&& ano) noexcept {
if (data_ptr()) free(data);
cap = len = 0; data = 0;
RustVec<char>::operator=(std::move(ano));
return *this;
}
RustString& operator=(const RustString& ano) {
__set_from(ano.data, ano.len);
return *this;
}
RustString& operator=(const std::string& ano) {
__set_from(ano.c_str(), ano.length());
return *this;
}
RustString& operator=(const std::string_view& ano) {
__set_from(ano.data(), ano.length());
return *this;
}
RustString& operator=(const char* cs) {
__set_from(cs, strlen(cs));
return *this;
}
bool operator == (const std::string_view& rhs) const { return view() == rhs; }
bool operator == (const std::string& rhs) const { return view() == rhs; }
bool operator == (const char* rhs) const { return view() == rhs; }
bool operator != (const std::string_view& rhs) const { return view() != rhs; }
bool operator != (const std::string& rhs) const { return view() != rhs; }
bool operator != (const char* rhs) const { return view() != rhs; }
#if _MSVC_LANG+0 >= 202002L || __cplusplus >= 202002L
auto operator<=> (const RustString& rhs) const {
size_t min_len = std::min(len, rhs.len);
int cmp = memcmp(data, rhs.data, min_len);
return cmp == 0 ? len<=>rhs.len : (cmp<=>0);
}
#endif
protected:
void __set_from(const char* data0, size_t len0)
{
if (cap < len0) {
if (data_ptr()) free(data);
data = (char*) malloc(len0+1);
cap = len0;
}
len = len0;
if (data_ptr()) {
memcpy(data, data0, len);
data[len] = 0;
}
}
};
namespace ffi
{
template <class T>
void force_ref(const T& obj) {
char buf[32];
snprintf(buf, 32, "%p", &obj);
}
template <class T>
void man_dtor(void* obj) {
((T*)obj)->~T();
}
template <class T>
void man_dtor_sp(void* obj) {
typedef std::shared_ptr<T> TPtr;
((TPtr*)obj)->~TPtr();
}
template <class T>
void enable_class() {
force_ref(&man_dtor<T>);
}
template <class T>
void enable_class_sp() {
force_ref<void(*)(void*)>(&man_dtor_sp<T>);
}
}
template <class T>
struct ValuePromise {
size_t strong_refc;
size_t weak_refc;
void (*f_set_value)(ValuePromise<T>* self, const T* ptr);
void set_value(const T& v) {
f_set_value(this, &v);
}
};