#pragma once
#include <array>
#include <cassert>
#include <cstdint>
#include <string>
#include <vector>
#if __cpp_lib_ranges
#include <ranges>
#endif
#if __cpp_lib_string_view
#include <string_view>
#endif
#if __cpp_lib_span
#include <span>
#endif
#include <type_traits>
namespace ffi_types {
using usize = uintptr_t;
template <typename T, usize N>
using Array = std::array<T, N>;
}
#if _MSC_VER
#define _COPY_DELETE default
#else
#define _COPY_DELETE delete
#endif
namespace ffi_types {
template <typename T>
struct CBox;
template <typename T>
struct OptionBox {
using element_type = T;
using pointer = T*;
T* _ptr;
OptionBox() = delete;
OptionBox(const OptionBox&) = delete;
OptionBox(OptionBox&& b) noexcept : _ptr(b.release()) {}
explicit OptionBox(std::nullptr_t) noexcept : _ptr(nullptr) {}
explicit OptionBox(pointer p) noexcept : _ptr(p) {}
~OptionBox() noexcept {
if (this->get()) {
this->_drop();
}
}
void _drop() noexcept;
OptionBox& operator=(OptionBox&& b) noexcept {
this->_ptr = b.release();
return *this;
}
CBox<T> into() noexcept;
CBox<T>& as_c() noexcept {
return *reinterpret_cast<CBox<T>*>(this);
}
const CBox<T>& as_c() const noexcept {
return *reinterpret_cast<const CBox<T>*>(this);
}
typename std::add_lvalue_reference<element_type>::type operator*() const {
return *get();
}
pointer operator->() const {
return get();
}
pointer get() const {
return this->_ptr;
}
explicit operator bool() const noexcept {
return get() != nullptr;
}
bool operator==(std::nullptr_t) const {
return this->get() == nullptr;
}
bool operator!=(std::nullptr_t) const {
return this->get() != nullptr;
}
T* release() noexcept {
auto* ptr = this->_ptr;
this->_ptr = 0;
return ptr;
}
void reset(pointer p) noexcept {
if (this->get()) {
this->_drop();
}
this->_ptr = p;
}
};
static_assert(sizeof(OptionBox<int>) == sizeof(int*));
static_assert(std::is_standard_layout<OptionBox<int>>::value);
template <typename T>
struct Box : public OptionBox<T> {
explicit Box(T* p) noexcept : OptionBox<T>(p) {
assert(p != nullptr);
}
};
template <typename T>
struct [[nodiscard]] CBox {
CBox() = _COPY_DELETE;
CBox(const CBox&) = _COPY_DELETE;
CBox& operator=(const CBox& b) noexcept = _COPY_DELETE;
T* _ptr;
#if _MSC_VER
static CBox from(OptionBox<T>&& box) noexcept {
CBox cbox;
cbox._ptr = box.release();
return cbox;
}
#else
CBox(CBox&&) = default;
CBox& operator=(CBox&& b) noexcept = default;
CBox(OptionBox<T>&& box) noexcept : _ptr(box.release()) {}
static CBox from(OptionBox<T>&& box) noexcept {
return CBox(std::move(box));
}
#endif
explicit operator bool() const noexcept {
return _ptr != nullptr;
}
bool operator==(std::nullptr_t) noexcept {
return _ptr == nullptr;
}
OptionBox<T> operator()() noexcept {
auto box = OptionBox<T>(nullptr);
box.reset(this->_ptr);
this->_ptr = nullptr;
return box;
}
T* release() noexcept {
auto* ptr = this->_ptr;
this->_ptr = nullptr;
return ptr;
}
};
static_assert(sizeof(CBox<int>) == sizeof(int*));
static_assert(std::is_trivial<CBox<int>>::value);
static_assert(std::is_standard_layout<CBox<int>>::value);
template <typename T>
using COptionBox = CBox<T>;
template <typename T>
inline CBox<T> OptionBox<T>::into() noexcept {
return CBox<T>::from(std::move(*this));
}
template struct CBox<void>;
template <>
inline void OptionBox<void>::_drop() noexcept {
assert("void box doesn't support drop" && false);
}
struct DynRef {
void* _ptr;
void* _vtable;
DynRef() = delete;
DynRef(const DynRef&) = default;
DynRef(DynRef&&) = default;
};
struct MutDynRef {
void* _ptr;
void* _vtable;
MutDynRef() = delete;
MutDynRef(const MutDynRef&) = delete;
MutDynRef(MutDynRef&&) = default;
};
struct DynOwned {
void* _ptr;
void* _vtable;
DynOwned() = delete;
DynOwned(const DynOwned&) = delete;
DynOwned(DynOwned&&) = delete;
~DynOwned() = delete;
};
} namespace ffi_types {
#define EMPTY_SLICE_BEGIN(T) reinterpret_cast<T*>(alignof(T))
template <typename T>
T* _wrap_null(T* ptr) {
return ptr ? ptr : reinterpret_cast<T*>(alignof(std::remove_const_t<T>));
}
#if __cpp_lib_ranges
namespace ranges {
using std::ranges::data;
using std::ranges::size;
} #define SAFE_R R&&
#else
namespace ranges {
template <typename C>
auto data(C& x) noexcept {
auto begin = x.begin();
using iterator_type = decltype(begin);
using pointer_type = decltype(&*begin);
if constexpr (std::is_same_v<iterator_type, pointer_type>) {
return begin;
} else if constexpr (sizeof(iterator_type) == sizeof(uintptr_t)) {
return *reinterpret_cast<pointer_type*>(&begin);
} else {
if (begin != x.end()) {
return &*begin;
} else {
return static_cast<pointer_type>(nullptr);
}
}
}
template <typename C>
size_t size(C& x) noexcept {
return x.end() - x.begin();
}
} #define SAFE_R const R&
#endif
struct CharStrRef;
struct StrRef;
struct CStrRef;
struct CByteSliceRef;
class BoxedStr;
template <typename T>
struct CMutSliceRef;
template <typename T>
struct CSliceRef;
template <typename T>
struct CBoxedSlice;
struct CBoxedStr;
template <typename T>
struct _SliceRange {
T* _data;
usize _size;
auto* begin() const noexcept {
return this->_data;
}
auto* end() const noexcept {
return this->_data + _size;
}
};
template <typename T, template <typename _> typename I>
struct _SliceInterface {
using element_type = T;
using value_type = typename std::remove_cv_t<T>;
using size_type = uintptr_t;
using difference_type = intptr_t;
using pointer = element_type*;
using const_pointer = const element_type*;
using reference = element_type&;
using const_reference = const element_type&;
#if __cpp_lib_span
using iterator = typename std::span<element_type>::iterator;
#else
using iterator = pointer;
#endif
using reverse_iterator = std::reverse_iterator<iterator>;
size_type size() const noexcept {
return static_cast<const I<T>*>(this)->_size;
}
size_type size_bytes() const noexcept {
return this->size() * sizeof(element_type);
}
bool empty() const noexcept {
return this->size() == 0;
}
reference operator[](size_type idx) const noexcept {
assert(idx < this->size());
return this->data()[idx];
}
reference front() const noexcept {
return this->data()[0];
}
reference back() const noexcept {
return this->data()[size() - 1];
}
pointer data() const noexcept {
return static_cast<const I<T>*>(this)->_data;
}
#if __cpp_lib_span
iterator begin() const noexcept {
return span().begin();
}
#else
iterator begin() const noexcept {
return data();
}
#endif
iterator end() const noexcept {
return begin() + size();
}
reverse_iterator rbegin() const noexcept {
return reverse_iterator(end());
}
reverse_iterator rend() const noexcept {
return reverse_iterator(begin());
}
_SliceRange<element_type> get() const noexcept {
return {data(), size()};
}
#if __cpp_lib_span
std::span<element_type> span() const noexcept {
return std::span<T>(data(), size());
}
#endif
};
template <typename T>
struct MutSliceRef : public _SliceInterface<T, MutSliceRef> {
T* _data;
usize _size;
MutSliceRef() noexcept : _data(EMPTY_SLICE_BEGIN(T)), _size(0) {}
MutSliceRef(const MutSliceRef&) = default;
MutSliceRef(MutSliceRef&&) = default;
explicit MutSliceRef(T* head, usize size) noexcept : _data(_wrap_null(head)), _size(size) {}
template <class R>
MutSliceRef(SAFE_R range) noexcept
: _data(_wrap_null(ranges::data(range))), _size(static_cast<usize>(ranges::size(range))) {}
MutSliceRef& operator=(const MutSliceRef<T>&) = default;
MutSliceRef& operator=(MutSliceRef<T>&&) = default;
CMutSliceRef<T> into() const noexcept;
template <typename U = T>
std::enable_if_t<std::is_same_v<U, const uint8_t>, CharStrRef> as_char_str() const noexcept;
template <typename U = T>
std::enable_if_t<std::is_same_v<U, const uint8_t>, StrRef> as_str_unchecked() const noexcept;
};
static_assert(std::is_trivially_copyable<MutSliceRef<usize>>::value);
static_assert(std::is_standard_layout<MutSliceRef<usize>>::value);
template <typename T>
struct SliceRef : public MutSliceRef<const T> {
SliceRef() noexcept : MutSliceRef<const T>(){};
SliceRef(const SliceRef&) = default;
SliceRef(SliceRef&&) = default;
explicit SliceRef(const T* head, usize size) noexcept : MutSliceRef<const T>(head, size) {}
template <class R>
SliceRef(SAFE_R range) noexcept : MutSliceRef<const T>(range) {}
SliceRef& operator=(const SliceRef<T>&) = default;
SliceRef& operator=(SliceRef<T>&&) = default;
typename std::conditional<std::is_same_v<T, uint8_t>, CByteSliceRef, CSliceRef<T>>::type into() const noexcept;
template <typename B, typename U = T>
static std::enable_if_t<std::is_same_v<U, uint8_t>, SliceRef<uint8_t>> from_buffer(const B& buffer) noexcept {
return SliceRef<uint8_t>(reinterpret_cast<const uint8_t*>(&buffer), sizeof(B));
}
bool operator==(const SliceRef& other) const noexcept {
if (this->size() != other.size()) return false;
return std::equal(this->begin(), this->end(), other.begin());
}
bool operator!=(const SliceRef& other) const noexcept {
return !(*this == other);
}
};
static_assert(std::is_trivially_copyable<SliceRef<usize>>::value);
static_assert(std::is_standard_layout<SliceRef<usize>>::value);
using ByteSliceRef = SliceRef<uint8_t>;
template <typename T>
struct CMutSliceRef {
CMutSliceRef() = _COPY_DELETE;
CMutSliceRef(const CMutSliceRef&) = default;
CMutSliceRef& operator=(const CMutSliceRef<T>&) = default;
#if _MSC_VER
static CMutSliceRef from(const MutSliceRef<T>& slice) noexcept {
CMutSliceRef s;
s._data = slice._data;
s._size = slice._size;
return s;
}
#else
CMutSliceRef(const MutSliceRef<T>& slice) noexcept {
this->_data = slice._data;
this->_size = slice._size;
}
static CMutSliceRef from(const MutSliceRef<T>& slice) noexcept {
return CMutSliceRef(slice);
}
#endif
T* _data;
usize _size;
MutSliceRef<T> operator()() const noexcept {
return MutSliceRef<T>(this->_data, this->_size);
}
};
static_assert(std::is_trivial<CMutSliceRef<usize>>::value);
static_assert(std::is_standard_layout<CMutSliceRef<usize>>::value);
template <typename T>
struct CSliceRef {
CSliceRef() = _COPY_DELETE;
CSliceRef(const CSliceRef&) = default;
CSliceRef& operator=(const CSliceRef<T>&) = default;
#if _MSC_VER
static CSliceRef from(const SliceRef<T>& slice) noexcept {
CSliceRef s;
s._data = slice._data;
s._size = slice._size;
return s;
}
#else
CSliceRef(const SliceRef<T>& slice) noexcept {
this->_data = slice._data;
this->_size = slice._size;
}
static CSliceRef from(const SliceRef<T>& slice) noexcept {
return CSliceRef(slice);
}
#endif
const T* _data;
usize _size;
SliceRef<T> operator()() const noexcept {
return SliceRef<T>(this->_data, this->_size);
}
};
static_assert(std::is_trivial<CSliceRef<usize>>::value);
static_assert(std::is_standard_layout<CSliceRef<usize>>::value);
struct CByteSliceRef {
CByteSliceRef() = _COPY_DELETE;
CByteSliceRef(const CByteSliceRef&) = default;
CByteSliceRef& operator=(const CByteSliceRef&) = default;
#if _MSC_VER
static CByteSliceRef from(const ByteSliceRef& slice) noexcept {
CByteSliceRef s;
s._data = slice._data;
s._size = slice._size;
return s;
}
#else
CByteSliceRef(const ByteSliceRef& slice) noexcept {
this->_data = slice._data;
this->_size = slice._size;
}
static CByteSliceRef from(const ByteSliceRef& slice) noexcept {
return CByteSliceRef(slice);
}
#endif
const uint8_t* _data;
usize _size;
ByteSliceRef operator()() const noexcept {
ByteSliceRef slice;
slice._data = this->_data;
slice._size = this->_size;
return slice;
}
};
static_assert(std::is_trivial<CByteSliceRef>::value);
static_assert(std::is_standard_layout<CByteSliceRef>::value);
template <typename T>
class BoxedSlice : public MutSliceRef<T> {
public:
BoxedSlice() = delete;
BoxedSlice(const BoxedSlice<T>&) = delete;
BoxedSlice(BoxedSlice<T>&& s) noexcept : MutSliceRef<T>(s) {
s._data = EMPTY_SLICE_BEGIN(T);
s._size = 0;
}
BoxedSlice(std::nullptr_t) noexcept : MutSliceRef<T>() {}
~BoxedSlice() noexcept {
if (this->_size > 0) {
this->_drop();
}
}
BoxedSlice<T>& operator=(BoxedSlice<T>&& b) noexcept {
this->reset(b.release());
return *this;
}
void _drop() noexcept;
[[nodiscard]] BoxedSlice<T> clone() const noexcept;
CBoxedSlice<T> into() noexcept;
const CBoxedSlice<T>& as_c() const noexcept {
return *reinterpret_cast<const CBoxedSlice<T>*>(this);
}
CBoxedSlice<T>& as_c() noexcept {
return *reinterpret_cast<CBoxedSlice<T>*>(this);
}
void reset(_SliceRange<T> s) noexcept {
if (this->_size > 0) {
this->_drop();
}
this->_data = s._data;
this->_size = s._size;
}
_SliceRange<T> release() noexcept {
const auto range = this->get();
this->_data = EMPTY_SLICE_BEGIN(T);
this->_size = 0;
return range;
}
auto as_slice() noexcept {
return MutSliceRef<T>(this->_data, this->_size);
}
auto as_slice() const noexcept {
return SliceRef<T>(this->_data, this->_size);
}
};
static_assert(sizeof(usize) * 2 == sizeof(BoxedSlice<int>));
static_assert(std::is_standard_layout<BoxedSlice<usize>>::value);
using BoxedByteSlice = BoxedSlice<uint8_t>;
template <typename T>
struct [[nodiscard]] CBoxedSlice {
CBoxedSlice() = _COPY_DELETE;
CBoxedSlice(const CBoxedSlice&) = _COPY_DELETE;
CBoxedSlice& operator=(const CBoxedSlice<T>&) = _COPY_DELETE;
#if _MSC_VER
static CBoxedSlice from(BoxedSlice<T>&& slice) noexcept {
auto r = slice.release();
CBoxedSlice s;
s._data = r._data;
s._size = r._size;
return s;
}
#else
CBoxedSlice(CBoxedSlice&&) = default;
CBoxedSlice& operator=(CBoxedSlice<T>&&) = default;
CBoxedSlice(BoxedSlice<T>&& slice) noexcept {
auto r = slice.release();
this->_data = r._data;
this->_size = r._size;
}
static CBoxedSlice from(BoxedSlice<T>&& slice) noexcept {
return CBoxedSlice(std::move(slice));
}
#endif
T* _data;
usize _size;
BoxedSlice<T> operator()() noexcept {
auto slice = BoxedSlice<T>(nullptr);
auto r = this->release();
slice._data = r._data;
slice._size = r._size;
return slice;
}
_SliceRange<T> get() const noexcept {
return {this->_data, this->_size};
}
_SliceRange<T> release() noexcept {
const auto range = this->get();
this->_data = EMPTY_SLICE_BEGIN(T);
this->_size = 0;
return range;
}
};
static_assert(std::is_trivial<CBoxedSlice<int>>::value);
static_assert(std::is_standard_layout<CBoxedSlice<int>>::value);
struct CBoxedByteSlice {
CBoxedByteSlice() = _COPY_DELETE;
CBoxedByteSlice(const CBoxedByteSlice&) = default;
CBoxedByteSlice& operator=(const CBoxedByteSlice&) = default;
#if _MSC_VER
static CBoxedByteSlice from(BoxedByteSlice&& boxed) noexcept {
CBoxedByteSlice s;
s._data = boxed._data;
s._size = boxed._size;
return s;
}
#else
CBoxedByteSlice(BoxedByteSlice&& boxed) noexcept {
this->_data = boxed._data;
this->_size = boxed._size;
}
static CBoxedByteSlice from(BoxedByteSlice&& boxed) noexcept {
return CBoxedByteSlice(std::move(boxed));
}
#endif
uint8_t* _data;
usize _size;
BoxedByteSlice operator()() noexcept {
auto slice = BoxedByteSlice(nullptr);
auto r = this->release();
slice._data = r._data;
slice._size = r._size;
return slice;
}
_SliceRange<uint8_t> get() const noexcept {
return {this->_data, this->_size};
}
_SliceRange<uint8_t> release() noexcept {
const auto range = this->get();
this->_data = EMPTY_SLICE_BEGIN(uint8_t);
this->_size = 0;
return range;
}
};
static_assert(std::is_trivial<CBoxedByteSlice>::value);
static_assert(std::is_standard_layout<CBoxedByteSlice>::value);
struct CharStrRef {
CharStrRef() = _COPY_DELETE;
CharStrRef(const CharStrRef&) = default;
CharStrRef& operator=(const CharStrRef&) = default;
CharStrRef(const char* head, usize size) noexcept : _data(_wrap_null(head)), _size(size) {}
template <class R>
CharStrRef(SAFE_R range) noexcept : _data(_wrap_null(ranges::data(range))), _size(ranges::size(range)) {}
CharStrRef(std::nullptr_t) noexcept : _data(EMPTY_SLICE_BEGIN(const char)), _size(0) {}
const char* _data;
usize _size;
using element_type = const char;
using value_type = typename std::remove_cv_t<const char>;
using size_type = uintptr_t;
using difference_type = intptr_t;
using pointer = element_type*;
using const_pointer = const element_type*;
using reference = element_type&;
using const_reference = const element_type&;
using iterator = typename std::string_view::iterator;
using reverse_iterator = std::reverse_iterator<iterator>;
size_type size() const noexcept {
return this->_size;
}
size_type size_bytes() const noexcept {
return this->size() * sizeof(element_type);
}
bool empty() const noexcept {
return this->size() == 0;
}
reference operator[](size_type idx) const noexcept {
assert(idx < this->size());
return this->data()[idx];
}
reference front() const noexcept {
return this->data()[0];
}
reference back() const noexcept {
return this->data()[size() - 1];
}
pointer data() const noexcept {
return this->_data;
}
iterator begin() const noexcept {
return view().begin();
}
iterator end() const noexcept {
return begin() + size();
}
reverse_iterator rbegin() const noexcept {
return reverse_iterator(end());
}
reverse_iterator rend() const noexcept {
return reverse_iterator(begin());
}
_SliceRange<element_type> get() const noexcept {
return {data(), size()};
}
#if __cpp_lib_span
std::span<element_type> span() const noexcept {
return std::span<element_type>(data(), size());
}
#endif
StrRef as_str_unchecked() const noexcept;
#if __cpp_lib_string_view
CharStrRef(const char* s) noexcept : CharStrRef(std::string_view(s)) {}
std::string_view view() const noexcept {
return std::string_view(this->data(), this->size());
}
operator std::string_view() const noexcept {
return this->view();
}
std::string to_string() const noexcept {
return std::string(this->view());
}
bool operator==(std::string_view other) const noexcept {
return this->view() == other;
}
bool operator==(const CharStrRef& other) const noexcept {
return this->view() == other.view();
}
bool operator!=(std::string_view other) const noexcept {
return !(*this == other);
}
bool operator!=(const CharStrRef& other) const noexcept {
return !(*this == other);
}
#endif
};
static_assert(sizeof(SliceRef<char>) == sizeof(CharStrRef));
static_assert(std::is_trivial<CharStrRef>::value);
static_assert(std::is_standard_layout<CharStrRef>::value);
struct StrRef : public CharStrRef {
StrRef() = delete;
StrRef(const StrRef&) = default;
StrRef(const BoxedStr&) noexcept;
StrRef(std::nullptr_t) noexcept : CharStrRef(EMPTY_SLICE_BEGIN(const char), 0) {}
StrRef& operator=(const StrRef&) = default;
};
static_assert(std::is_trivially_copyable<StrRef>::value);
static_assert(std::is_standard_layout<StrRef>::value);
struct CStrRef {
CStrRef() = _COPY_DELETE;
CStrRef(const CStrRef&) = default;
CStrRef& operator=(const CStrRef&) = default;
#if !_MSC_VER
CStrRef(const StrRef& slice) noexcept {
this->_data = slice.data();
this->_size = slice.size();
}
#endif
const char* _data;
usize _size;
StrRef operator()() const noexcept {
auto s = StrRef(nullptr);
s._data = this->_data;
s._size = this->_size;
return s;
}
};
static_assert(std::is_trivial<CStrRef>::value);
static_assert(std::is_standard_layout<CStrRef>::value);
class BoxedStr : public StrRef {
public:
BoxedStr() = delete;
BoxedStr(const BoxedStr&) = delete;
BoxedStr(BoxedStr&& s) noexcept : StrRef(s) {
s._data = EMPTY_SLICE_BEGIN(const char);
s._size = 0;
}
BoxedStr(std::nullptr_t) noexcept : StrRef(nullptr) {}
~BoxedStr() noexcept {
if (this->_size > 0) {
this->_drop();
}
}
BoxedStr& operator=(BoxedStr&& b) noexcept {
this->reset(b.release());
return *this;
}
void _drop() noexcept;
[[nodiscard]] BoxedStr clone() const noexcept;
[[nodiscard]] const CBoxedStr& as_c() const noexcept {
return *reinterpret_cast<const CBoxedStr*>(this);
}
void reset(_SliceRange<const char> s) noexcept {
if (this->_size > 0) {
this->_drop();
}
this->_data = s._data;
this->_size = s._size;
}
_SliceRange<const char> release() noexcept {
const auto range = this->get();
this->_data = EMPTY_SLICE_BEGIN(const char);
this->_size = 0;
return range;
}
StrRef as_str() const noexcept {
return this->as_str_unchecked();
}
};
static_assert(sizeof(StrRef) == sizeof(BoxedStr));
static_assert(std::is_standard_layout<BoxedStr>::value);
struct [[nodiscard]] CBoxedStr {
CBoxedStr() = _COPY_DELETE;
CBoxedStr(const CBoxedStr&) = _COPY_DELETE;
CBoxedStr& operator=(const CBoxedStr&) = _COPY_DELETE;
const char* _data;
usize _size;
#if _MSC_VER
static CBoxedStr from(BoxedStr&& str) noexcept {
auto r = str.release();
CBoxedStr s;
s._data = r._data;
s._size = r._size;
return s;
}
#else
CBoxedStr(CBoxedStr&&) = default;
CBoxedStr& operator=(CBoxedStr&&) = default;
CBoxedStr(BoxedStr&& str) noexcept {
auto r = str.release();
this->_data = r._data;
this->_size = r._size;
}
static CBoxedStr from(BoxedStr&& slice) noexcept {
return CBoxedStr(std::move(slice));
}
#endif
BoxedStr operator()() noexcept {
auto slice = BoxedStr(nullptr);
auto r = this->release();
slice._data = r._data;
slice._size = r._size;
return slice;
}
_SliceRange<const char> release() noexcept {
const auto range = _SliceRange<const char>{_data, _size};
this->_data = EMPTY_SLICE_BEGIN(const char);
this->_size = 0;
return range;
}
};
static_assert(std::is_trivial<CBoxedStr>::value);
static_assert(std::is_standard_layout<CBoxedStr>::value);
template <typename T>
inline CMutSliceRef<T> MutSliceRef<T>::into() const noexcept {
return CMutSliceRef<T>::from(*this);
}
template <typename T>
inline typename std::conditional<std::is_same_v<T, uint8_t>, CByteSliceRef, CSliceRef<T>>::type SliceRef<T>::into()
const noexcept {
if constexpr (std::is_same_v<T, uint8_t>) {
return CByteSliceRef::from(*this);
} else {
return CSliceRef<T>::from(*this);
}
}
template <typename T>
inline CBoxedSlice<T> BoxedSlice<T>::into() noexcept {
return CBoxedSlice<T>::from(std::move(*this));
}
inline StrRef::StrRef(const BoxedStr& owned) noexcept : CharStrRef(owned._data, owned._size) {}
inline StrRef CharStrRef::as_str_unchecked() const noexcept {
return *reinterpret_cast<const StrRef*>(this);
}
template <>
template <>
inline CharStrRef MutSliceRef<const uint8_t>::as_char_str<const uint8_t>() const noexcept {
return CharStrRef(reinterpret_cast<const char*>(this->_data), this->_size);
}
template <>
template <>
inline StrRef MutSliceRef<const uint8_t>::as_str_unchecked<const uint8_t>() const noexcept {
return as_char_str().as_str_unchecked();
}
#undef SAFE_R
#undef EMPTY_SLICE_BEGIN
} #pragma once
namespace ffi_types {
extern "C" {
void _rust_ffi_boxed_str_drop(ffi_types::CBoxedStr _string);
void _rust_ffi_boxed_bytes_drop(ffi_types::CBoxedByteSlice _slice);
ffi_types::CBoxedStr _rust_ffi_boxed_str_clone(const ffi_types::CBoxedStr *string);
ffi_types::CBoxedByteSlice _rust_ffi_boxed_bytes_clone(const ffi_types::CBoxedByteSlice *slice);
}
} namespace ffi_types {
inline void BoxedStr::_drop() noexcept {
ffi_types::_rust_ffi_boxed_str_drop(CBoxedStr::from(std::move(*this)));
}
template <>
inline void BoxedSlice<uint8_t>::_drop() noexcept {
ffi_types::_rust_ffi_boxed_bytes_drop(CBoxedByteSlice::from(std::move(*this)));
}
[[nodiscard]] inline BoxedStr BoxedStr::clone() const noexcept {
return ffi_types::_rust_ffi_boxed_str_clone(&this->as_c())();
}
template <>
inline BoxedSlice<uint8_t> BoxedSlice<uint8_t>::clone() const noexcept {
return ffi_types::_rust_ffi_boxed_bytes_clone(reinterpret_cast<const CBoxedByteSlice*>(this))();
}
} #undef _COPY_DELETE
namespace rust {
using namespace ffi_types;
}