1use crate::gen::out::{Content, OutFile};
2use crate::syntax::{self, IncludeKind};
3use std::ops::{Deref, DerefMut};
4
5pub static HEADER: &str = "#pragma once\n#include <algorithm>\n#include <array>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <exception>\n#include <initializer_list>\n#include <iosfwd>\n#include <iterator>\n#include <new>\n#include <stdexcept>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <vector>\n#if defined(_WIN32)\n#include <basetsd.h>\n#else\n#include <sys/types.h>\n#endif\n\n#if __cplusplus >= 201703L\n#include <string_view>\n#endif\n\n#if __cplusplus >= 202002L\n#include <ranges>\n#endif\n\nnamespace rust {\ninline namespace cxxbridge1 {\n\nstruct unsafe_bitcopy_t;\n\nnamespace {\ntemplate <typename T>\nclass impl;\n}\n\n#ifndef CXXBRIDGE1_RUST_STRING\n#define CXXBRIDGE1_RUST_STRING\n// https://cxx.rs/binding/string.html\nclass String final {\npublic:\n String() noexcept;\n String(const String &) noexcept;\n String(String &&) noexcept;\n ~String() noexcept;\n\n String(const std::string &);\n String(const char *);\n String(const char *, std::size_t);\n String(const char16_t *);\n String(const char16_t *, std::size_t);\n#ifdef __cpp_char8_t\n String(const char8_t *s);\n String(const char8_t *s, std::size_t len);\n#endif\n\n // Replace invalid Unicode data with the replacement character (U+FFFD).\n static String lossy(const std::string &) noexcept;\n static String lossy(const char *) noexcept;\n static String lossy(const char *, std::size_t) noexcept;\n static String lossy(const char16_t *) noexcept;\n static String lossy(const char16_t *, std::size_t) noexcept;\n\n String &operator=(const String &) & noexcept;\n String &operator=(String &&) & noexcept;\n\n explicit operator std::string() const;\n\n // Note: no null terminator.\n const char *data() const noexcept;\n std::size_t size() const noexcept;\n std::size_t length() const noexcept;\n bool empty() const noexcept;\n\n const char *c_str() noexcept;\n\n std::size_t capacity() const noexcept;\n void reserve(size_t new_cap) noexcept;\n\n using iterator = char *;\n iterator begin() noexcept;\n iterator end() noexcept;\n\n using const_iterator = const char *;\n const_iterator begin() const noexcept;\n const_iterator end() const noexcept;\n const_iterator cbegin() const noexcept;\n const_iterator cend() const noexcept;\n\n bool operator==(const String &) const noexcept;\n bool operator!=(const String &) const noexcept;\n bool operator<(const String &) const noexcept;\n bool operator<=(const String &) const noexcept;\n bool operator>(const String &) const noexcept;\n bool operator>=(const String &) const noexcept;\n\n void swap(String &) noexcept;\n\n // Internal API only intended for the cxxbridge code generator.\n String(unsafe_bitcopy_t, const String &) noexcept;\n\nprivate:\n struct lossy_t;\n String(lossy_t, const char *, std::size_t) noexcept;\n String(lossy_t, const char16_t *, std::size_t) noexcept;\n friend void swap(String &lhs, String &rhs) noexcept { lhs.swap(rhs); }\n\n // Size and alignment statically verified by rust_string.rs.\n std::array<std::uintptr_t, 3> repr;\n};\n#endif // CXXBRIDGE1_RUST_STRING\n\n#ifndef CXXBRIDGE1_RUST_STR\n#define CXXBRIDGE1_RUST_STR\n// https://cxx.rs/binding/str.html\nclass Str final {\npublic:\n Str() noexcept;\n Str(const String &) noexcept;\n Str(const std::string &);\n Str(const char *);\n Str(const char *, std::size_t);\n\n Str &operator=(const Str &) & noexcept = default;\n\n explicit operator std::string() const;\n#if __cplusplus >= 201703L\n explicit operator std::string_view() const;\n#endif\n\n // Note: no null terminator.\n const char *data() const noexcept;\n std::size_t size() const noexcept;\n std::size_t length() const noexcept;\n bool empty() const noexcept;\n\n // Important in order for System V ABI to pass in registers.\n Str(const Str &) noexcept = default;\n ~Str() noexcept = default;\n\n using iterator = const char *;\n using const_iterator = const char *;\n const_iterator begin() const noexcept;\n const_iterator end() const noexcept;\n const_iterator cbegin() const noexcept;\n const_iterator cend() const noexcept;\n\n bool operator==(const Str &) const noexcept;\n bool operator!=(const Str &) const noexcept;\n bool operator<(const Str &) const noexcept;\n bool operator<=(const Str &) const noexcept;\n bool operator>(const Str &) const noexcept;\n bool operator>=(const Str &) const noexcept;\n\n void swap(Str &) noexcept;\n\nprivate:\n class uninit;\n Str(uninit) noexcept;\n friend impl<Str>;\n\n std::array<std::uintptr_t, 2> repr;\n};\n#endif // CXXBRIDGE1_RUST_STR\n\n#ifndef CXXBRIDGE1_RUST_SLICE\nnamespace detail {\ntemplate <bool>\nstruct copy_assignable_if {};\n\ntemplate <>\nstruct copy_assignable_if<false> {\n copy_assignable_if() noexcept = default;\n copy_assignable_if(const copy_assignable_if &) noexcept = default;\n copy_assignable_if &operator=(const copy_assignable_if &) & noexcept = delete;\n copy_assignable_if &operator=(copy_assignable_if &&) & noexcept = default;\n};\n} // namespace detail\n\n// https://cxx.rs/binding/slice.html\ntemplate <typename T>\nclass Slice final\n : private detail::copy_assignable_if<std::is_const<T>::value> {\npublic:\n using value_type = T;\n\n Slice() noexcept;\n Slice(T *, std::size_t count) noexcept;\n\n template <typename C>\n explicit Slice(C &c) : Slice(c.data(), c.size()) {}\n\n Slice &operator=(const Slice<T> &) & noexcept = default;\n Slice &operator=(Slice<T> &&) & noexcept = default;\n\n T *data() const noexcept;\n std::size_t size() const noexcept;\n std::size_t length() const noexcept;\n bool empty() const noexcept;\n\n T &operator[](std::size_t n) const noexcept;\n T &at(std::size_t n) const;\n T &front() const noexcept;\n T &back() const noexcept;\n\n // Important in order for System V ABI to pass in registers.\n Slice(const Slice<T> &) noexcept = default;\n ~Slice() noexcept = default;\n\n class iterator;\n iterator begin() const noexcept;\n iterator end() const noexcept;\n\n void swap(Slice &) noexcept;\n\nprivate:\n class uninit;\n Slice(uninit) noexcept;\n friend impl<Slice>;\n friend void sliceInit(void *, const void *, std::size_t) noexcept;\n friend void *slicePtr(const void *) noexcept;\n friend std::size_t sliceLen(const void *) noexcept;\n\n std::array<std::uintptr_t, 2> repr;\n};\n\n#ifdef __cpp_deduction_guides\ntemplate <typename C>\nexplicit Slice(C &c)\n -> Slice<std::remove_reference_t<decltype(*std::declval<C>().data())>>;\n#endif // __cpp_deduction_guides\n\ntemplate <typename T>\nclass Slice<T>::iterator final {\npublic:\n#if __cplusplus >= 202002L\n using iterator_category = std::contiguous_iterator_tag;\n#else\n using iterator_category = std::random_access_iterator_tag;\n#endif\n using value_type = T;\n using difference_type = std::ptrdiff_t;\n using pointer = typename std::add_pointer<T>::type;\n using reference = typename std::add_lvalue_reference<T>::type;\n\n reference operator*() const noexcept;\n pointer operator->() const noexcept;\n reference operator[](difference_type) const noexcept;\n\n iterator &operator++() noexcept;\n iterator operator++(int) noexcept;\n iterator &operator--() noexcept;\n iterator operator--(int) noexcept;\n\n iterator &operator+=(difference_type) noexcept;\n iterator &operator-=(difference_type) noexcept;\n iterator operator+(difference_type) const noexcept;\n friend inline iterator operator+(difference_type lhs, iterator rhs) noexcept {\n return rhs + lhs;\n }\n iterator operator-(difference_type) const noexcept;\n difference_type operator-(const iterator &) const noexcept;\n\n bool operator==(const iterator &) const noexcept;\n bool operator!=(const iterator &) const noexcept;\n bool operator<(const iterator &) const noexcept;\n bool operator<=(const iterator &) const noexcept;\n bool operator>(const iterator &) const noexcept;\n bool operator>=(const iterator &) const noexcept;\n\nprivate:\n friend class Slice;\n void *pos;\n std::size_t stride;\n};\n\n#if __cplusplus >= 202002L\nstatic_assert(std::ranges::contiguous_range<rust::Slice<const uint8_t>>);\nstatic_assert(std::contiguous_iterator<rust::Slice<const uint8_t>::iterator>);\n#endif\n\n#endif // CXXBRIDGE1_RUST_SLICE\n\n#ifndef CXXBRIDGE1_RUST_BOX\n// https://cxx.rs/binding/box.html\ntemplate <typename T>\nclass Box final {\npublic:\n using element_type = T;\n using const_pointer =\n typename std::add_pointer<typename std::add_const<T>::type>::type;\n using pointer = typename std::add_pointer<T>::type;\n\n Box() = delete;\n Box(Box &&) noexcept;\n ~Box() noexcept;\n\n explicit Box(const T &);\n explicit Box(T &&);\n\n Box &operator=(Box &&) & noexcept;\n\n const T *operator->() const noexcept;\n const T &operator*() const noexcept;\n T *operator->() noexcept;\n T &operator*() noexcept;\n\n template <typename... Fields>\n static Box in_place(Fields &&...);\n\n void swap(Box &) noexcept;\n\n // Important: requires that `raw` came from an into_raw call. Do not pass a\n // pointer from `new` or any other source.\n static Box from_raw(T *) noexcept;\n\n T *into_raw() noexcept;\n\n /* Deprecated */ using value_type = element_type;\n\nprivate:\n class uninit;\n class allocation;\n Box(uninit) noexcept;\n void drop() noexcept;\n\n friend void swap(Box &lhs, Box &rhs) noexcept { lhs.swap(rhs); }\n\n T *ptr;\n};\n#endif // CXXBRIDGE1_RUST_BOX\n\n#ifndef CXXBRIDGE1_RUST_VEC\n// https://cxx.rs/binding/vec.html\ntemplate <typename T>\nclass Vec final {\npublic:\n using value_type = T;\n\n Vec() noexcept;\n Vec(std::initializer_list<T>);\n Vec(const Vec &);\n Vec(Vec &&) noexcept;\n ~Vec() noexcept;\n\n Vec &operator=(Vec &&) & noexcept;\n Vec &operator=(const Vec &) &;\n\n std::size_t size() const noexcept;\n bool empty() const noexcept;\n const T *data() const noexcept;\n T *data() noexcept;\n std::size_t capacity() const noexcept;\n\n const T &operator[](std::size_t n) const noexcept;\n const T &at(std::size_t n) const;\n const T &front() const noexcept;\n const T &back() const noexcept;\n\n T &operator[](std::size_t n) noexcept;\n T &at(std::size_t n);\n T &front() noexcept;\n T &back() noexcept;\n\n void reserve(std::size_t new_cap);\n void push_back(const T &value);\n void push_back(T &&value);\n template <typename... Args>\n void emplace_back(Args &&...args);\n void truncate(std::size_t len);\n void clear();\n\n using iterator = typename Slice<T>::iterator;\n iterator begin() noexcept;\n iterator end() noexcept;\n\n using const_iterator = typename Slice<const T>::iterator;\n const_iterator begin() const noexcept;\n const_iterator end() const noexcept;\n const_iterator cbegin() const noexcept;\n const_iterator cend() const noexcept;\n\n void swap(Vec &) noexcept;\n\n // Internal API only intended for the cxxbridge code generator.\n Vec(unsafe_bitcopy_t, const Vec &) noexcept;\n\nprivate:\n void reserve_total(std::size_t new_cap) noexcept;\n void set_len(std::size_t len) noexcept;\n void drop() noexcept;\n\n friend void swap(Vec &lhs, Vec &rhs) noexcept { lhs.swap(rhs); }\n\n // Size and alignment statically verified by rust_vec.rs.\n std::array<std::uintptr_t, 3> repr;\n};\n#endif // CXXBRIDGE1_RUST_VEC\n\n#ifndef CXXBRIDGE1_RUST_FN\n// https://cxx.rs/binding/fn.html\ntemplate <typename Signature>\nclass Fn;\n\ntemplate <typename Ret, typename... Args>\nclass Fn<Ret(Args...)> final {\npublic:\n Ret operator()(Args... args) const noexcept;\n Fn operator*() const noexcept;\n\nprivate:\n Ret (*trampoline)(Args..., void *fn) noexcept;\n void *fn;\n};\n#endif // CXXBRIDGE1_RUST_FN\n\n#ifndef CXXBRIDGE1_RUST_ERROR\n#define CXXBRIDGE1_RUST_ERROR\n// https://cxx.rs/binding/result.html\nclass Error final : public std::exception {\npublic:\n Error(const Error &);\n Error(Error &&) noexcept;\n ~Error() noexcept override;\n\n Error &operator=(const Error &) &;\n Error &operator=(Error &&) & noexcept;\n\n const char *what() const noexcept override;\n\nprivate:\n Error() noexcept = default;\n friend impl<Error>;\n const char *msg;\n std::size_t len;\n};\n#endif // CXXBRIDGE1_RUST_ERROR\n\n#ifndef CXXBRIDGE1_RUST_ISIZE\n#define CXXBRIDGE1_RUST_ISIZE\n#if defined(_WIN32)\nusing isize = SSIZE_T;\n#else\nusing isize = ssize_t;\n#endif\n#endif // CXXBRIDGE1_RUST_ISIZE\n\nstd::ostream &operator<<(std::ostream &, const String &);\nstd::ostream &operator<<(std::ostream &, const Str &);\n\n#ifndef CXXBRIDGE1_RUST_OPAQUE\n#define CXXBRIDGE1_RUST_OPAQUE\n// Base class of generated opaque Rust types.\nclass Opaque {\npublic:\n Opaque() = delete;\n Opaque(const Opaque &) = delete;\n ~Opaque() = delete;\n};\n#endif // CXXBRIDGE1_RUST_OPAQUE\n\ntemplate <typename T>\nstd::size_t size_of();\ntemplate <typename T>\nstd::size_t align_of();\n\n// IsRelocatable<T> is used in assertions that a C++ type passed by value\n// between Rust and C++ is soundly relocatable by Rust.\n//\n// There may be legitimate reasons to opt out of the check for support of types\n// that the programmer knows are soundly Rust-movable despite not being\n// recognized as such by the C++ type system due to a move constructor or\n// destructor. To opt out of the relocatability check, do either of the\n// following things in any header used by `include!` in the bridge.\n//\n// --- if you define the type:\n// struct MyType {\n// ...\n// + using IsRelocatable = std::true_type;\n// };\n//\n// --- otherwise:\n// + template <>\n// + struct rust::IsRelocatable<MyType> : std::true_type {};\ntemplate <typename T>\nstruct IsRelocatable;\n\nusing u8 = std::uint8_t;\nusing u16 = std::uint16_t;\nusing u32 = std::uint32_t;\nusing u64 = std::uint64_t;\nusing usize = std::size_t; // see static asserts in cxx.cc\nusing i8 = std::int8_t;\nusing i16 = std::int16_t;\nusing i32 = std::int32_t;\nusing i64 = std::int64_t;\nusing f32 = float;\nusing f64 = double;\n\n// Snake case aliases for use in code that uses this style for type names.\nusing string = String;\nusing str = Str;\ntemplate <typename T>\nusing slice = Slice<T>;\ntemplate <typename T>\nusing box = Box<T>;\ntemplate <typename T>\nusing vec = Vec<T>;\nusing error = Error;\ntemplate <typename Signature>\nusing fn = Fn<Signature>;\ntemplate <typename T>\nusing is_relocatable = IsRelocatable<T>;\n\n\n\n////////////////////////////////////////////////////////////////////////////////\n/// end public API, begin implementation details\n\n#ifndef CXXBRIDGE1_PANIC\n#define CXXBRIDGE1_PANIC\ntemplate <typename Exception>\nvoid panic [[noreturn]] (const char *msg);\n#endif // CXXBRIDGE1_PANIC\n\n#ifndef CXXBRIDGE1_RUST_FN\n#define CXXBRIDGE1_RUST_FN\ntemplate <typename Ret, typename... Args>\nRet Fn<Ret(Args...)>::operator()(Args... args) const noexcept {\n return (*this->trampoline)(std::forward<Args>(args)..., this->fn);\n}\n\ntemplate <typename Ret, typename... Args>\nFn<Ret(Args...)> Fn<Ret(Args...)>::operator*() const noexcept {\n return *this;\n}\n#endif // CXXBRIDGE1_RUST_FN\n\n#ifndef CXXBRIDGE1_RUST_BITCOPY_T\n#define CXXBRIDGE1_RUST_BITCOPY_T\nstruct unsafe_bitcopy_t final {\n explicit unsafe_bitcopy_t() = default;\n};\n#endif // CXXBRIDGE1_RUST_BITCOPY_T\n\n#ifndef CXXBRIDGE1_RUST_BITCOPY\n#define CXXBRIDGE1_RUST_BITCOPY\nconstexpr unsafe_bitcopy_t unsafe_bitcopy{};\n#endif // CXXBRIDGE1_RUST_BITCOPY\n\n#ifndef CXXBRIDGE1_RUST_SLICE\n#define CXXBRIDGE1_RUST_SLICE\ntemplate <typename T>\nSlice<T>::Slice() noexcept {\n sliceInit(this, reinterpret_cast<void *>(align_of<T>()), 0);\n}\n\ntemplate <typename T>\nSlice<T>::Slice(T *s, std::size_t count) noexcept {\n assert(s != nullptr || count == 0);\n sliceInit(this,\n s == nullptr && count == 0\n ? reinterpret_cast<void *>(align_of<T>())\n : const_cast<typename std::remove_const<T>::type *>(s),\n count);\n}\n\ntemplate <typename T>\nT *Slice<T>::data() const noexcept {\n return reinterpret_cast<T *>(slicePtr(this));\n}\n\ntemplate <typename T>\nstd::size_t Slice<T>::size() const noexcept {\n return sliceLen(this);\n}\n\ntemplate <typename T>\nstd::size_t Slice<T>::length() const noexcept {\n return this->size();\n}\n\ntemplate <typename T>\nbool Slice<T>::empty() const noexcept {\n return this->size() == 0;\n}\n\ntemplate <typename T>\nT &Slice<T>::operator[](std::size_t n) const noexcept {\n assert(n < this->size());\n auto ptr = static_cast<char *>(slicePtr(this)) + size_of<T>() * n;\n return *reinterpret_cast<T *>(ptr);\n}\n\ntemplate <typename T>\nT &Slice<T>::at(std::size_t n) const {\n if (n >= this->size()) {\n panic<std::out_of_range>(\"rust::Slice index out of range\");\n }\n return (*this)[n];\n}\n\ntemplate <typename T>\nT &Slice<T>::front() const noexcept {\n assert(!this->empty());\n return (*this)[0];\n}\n\ntemplate <typename T>\nT &Slice<T>::back() const noexcept {\n assert(!this->empty());\n return (*this)[this->size() - 1];\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator::reference\nSlice<T>::iterator::operator*() const noexcept {\n return *static_cast<T *>(this->pos);\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator::pointer\nSlice<T>::iterator::operator->() const noexcept {\n return static_cast<T *>(this->pos);\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator::reference Slice<T>::iterator::operator[](\n typename Slice<T>::iterator::difference_type n) const noexcept {\n auto ptr = static_cast<char *>(this->pos) + this->stride * n;\n return *reinterpret_cast<T *>(ptr);\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator &Slice<T>::iterator::operator++() noexcept {\n this->pos = static_cast<char *>(this->pos) + this->stride;\n return *this;\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator Slice<T>::iterator::operator++(int) noexcept {\n auto ret = iterator(*this);\n this->pos = static_cast<char *>(this->pos) + this->stride;\n return ret;\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator &Slice<T>::iterator::operator--() noexcept {\n this->pos = static_cast<char *>(this->pos) - this->stride;\n return *this;\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator Slice<T>::iterator::operator--(int) noexcept {\n auto ret = iterator(*this);\n this->pos = static_cast<char *>(this->pos) - this->stride;\n return ret;\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator &Slice<T>::iterator::operator+=(\n typename Slice<T>::iterator::difference_type n) noexcept {\n this->pos = static_cast<char *>(this->pos) + this->stride * n;\n return *this;\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator &Slice<T>::iterator::operator-=(\n typename Slice<T>::iterator::difference_type n) noexcept {\n this->pos = static_cast<char *>(this->pos) - this->stride * n;\n return *this;\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator Slice<T>::iterator::operator+(\n typename Slice<T>::iterator::difference_type n) const noexcept {\n auto ret = iterator(*this);\n ret.pos = static_cast<char *>(this->pos) + this->stride * n;\n return ret;\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator Slice<T>::iterator::operator-(\n typename Slice<T>::iterator::difference_type n) const noexcept {\n auto ret = iterator(*this);\n ret.pos = static_cast<char *>(this->pos) - this->stride * n;\n return ret;\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator::difference_type\nSlice<T>::iterator::operator-(const iterator &other) const noexcept {\n auto diff = std::distance(static_cast<char *>(other.pos),\n static_cast<char *>(this->pos));\n return diff / static_cast<typename Slice<T>::iterator::difference_type>(\n this->stride);\n}\n\ntemplate <typename T>\nbool Slice<T>::iterator::operator==(const iterator &other) const noexcept {\n return this->pos == other.pos;\n}\n\ntemplate <typename T>\nbool Slice<T>::iterator::operator!=(const iterator &other) const noexcept {\n return this->pos != other.pos;\n}\n\ntemplate <typename T>\nbool Slice<T>::iterator::operator<(const iterator &other) const noexcept {\n return this->pos < other.pos;\n}\n\ntemplate <typename T>\nbool Slice<T>::iterator::operator<=(const iterator &other) const noexcept {\n return this->pos <= other.pos;\n}\n\ntemplate <typename T>\nbool Slice<T>::iterator::operator>(const iterator &other) const noexcept {\n return this->pos > other.pos;\n}\n\ntemplate <typename T>\nbool Slice<T>::iterator::operator>=(const iterator &other) const noexcept {\n return this->pos >= other.pos;\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator Slice<T>::begin() const noexcept {\n iterator it;\n it.pos = slicePtr(this);\n it.stride = size_of<T>();\n return it;\n}\n\ntemplate <typename T>\ntypename Slice<T>::iterator Slice<T>::end() const noexcept {\n iterator it = this->begin();\n it.pos = static_cast<char *>(it.pos) + it.stride * this->size();\n return it;\n}\n\ntemplate <typename T>\nvoid Slice<T>::swap(Slice &rhs) noexcept {\n std::swap(*this, rhs);\n}\n#endif // CXXBRIDGE1_RUST_SLICE\n\n#ifndef CXXBRIDGE1_RUST_BOX\n#define CXXBRIDGE1_RUST_BOX\ntemplate <typename T>\nclass Box<T>::uninit {};\n\ntemplate <typename T>\nclass Box<T>::allocation {\n static T *alloc() noexcept;\n static void dealloc(T *) noexcept;\n\npublic:\n allocation() noexcept : ptr(alloc()) {}\n ~allocation() noexcept {\n if (this->ptr) {\n dealloc(this->ptr);\n }\n }\n T *ptr;\n};\n\ntemplate <typename T>\nBox<T>::Box(Box &&other) noexcept : ptr(other.ptr) {\n other.ptr = nullptr;\n}\n\ntemplate <typename T>\nBox<T>::Box(const T &val) {\n allocation alloc;\n ::new (alloc.ptr) T(val);\n this->ptr = alloc.ptr;\n alloc.ptr = nullptr;\n}\n\ntemplate <typename T>\nBox<T>::Box(T &&val) {\n allocation alloc;\n ::new (alloc.ptr) T(std::move(val));\n this->ptr = alloc.ptr;\n alloc.ptr = nullptr;\n}\n\ntemplate <typename T>\nBox<T>::~Box() noexcept {\n if (this->ptr) {\n this->drop();\n }\n}\n\ntemplate <typename T>\nBox<T> &Box<T>::operator=(Box &&other) & noexcept {\n if (this->ptr) {\n this->drop();\n }\n this->ptr = other.ptr;\n other.ptr = nullptr;\n return *this;\n}\n\ntemplate <typename T>\nconst T *Box<T>::operator->() const noexcept {\n return this->ptr;\n}\n\ntemplate <typename T>\nconst T &Box<T>::operator*() const noexcept {\n return *this->ptr;\n}\n\ntemplate <typename T>\nT *Box<T>::operator->() noexcept {\n return this->ptr;\n}\n\ntemplate <typename T>\nT &Box<T>::operator*() noexcept {\n return *this->ptr;\n}\n\ntemplate <typename T>\ntemplate <typename... Fields>\nBox<T> Box<T>::in_place(Fields &&...fields) {\n allocation alloc;\n auto ptr = alloc.ptr;\n ::new (ptr) T{std::forward<Fields>(fields)...};\n alloc.ptr = nullptr;\n return from_raw(ptr);\n}\n\ntemplate <typename T>\nvoid Box<T>::swap(Box &rhs) noexcept {\n using std::swap;\n swap(this->ptr, rhs.ptr);\n}\n\ntemplate <typename T>\nBox<T> Box<T>::from_raw(T *raw) noexcept {\n Box box = uninit{};\n box.ptr = raw;\n return box;\n}\n\ntemplate <typename T>\nT *Box<T>::into_raw() noexcept {\n T *raw = this->ptr;\n this->ptr = nullptr;\n return raw;\n}\n\ntemplate <typename T>\nBox<T>::Box(uninit) noexcept {}\n#endif // CXXBRIDGE1_RUST_BOX\n\n#ifndef CXXBRIDGE1_RUST_VEC\n#define CXXBRIDGE1_RUST_VEC\ntemplate <typename T>\nVec<T>::Vec(std::initializer_list<T> init) : Vec{} {\n this->reserve_total(init.size());\n std::move(init.begin(), init.end(), std::back_inserter(*this));\n}\n\ntemplate <typename T>\nVec<T>::Vec(const Vec &other) : Vec() {\n this->reserve_total(other.size());\n std::copy(other.begin(), other.end(), std::back_inserter(*this));\n}\n\ntemplate <typename T>\nVec<T>::Vec(Vec &&other) noexcept : repr(other.repr) {\n new (&other) Vec();\n}\n\ntemplate <typename T>\nVec<T>::~Vec() noexcept {\n this->drop();\n}\n\ntemplate <typename T>\nVec<T> &Vec<T>::operator=(Vec &&other) & noexcept {\n this->drop();\n this->repr = other.repr;\n new (&other) Vec();\n return *this;\n}\n\ntemplate <typename T>\nVec<T> &Vec<T>::operator=(const Vec &other) & {\n if (this != &other) {\n this->drop();\n new (this) Vec(other);\n }\n return *this;\n}\n\ntemplate <typename T>\nbool Vec<T>::empty() const noexcept {\n return this->size() == 0;\n}\n\ntemplate <typename T>\nT *Vec<T>::data() noexcept {\n return const_cast<T *>(const_cast<const Vec<T> *>(this)->data());\n}\n\ntemplate <typename T>\nconst T &Vec<T>::operator[](std::size_t n) const noexcept {\n assert(n < this->size());\n auto data = reinterpret_cast<const char *>(this->data());\n return *reinterpret_cast<const T *>(data + n * size_of<T>());\n}\n\ntemplate <typename T>\nconst T &Vec<T>::at(std::size_t n) const {\n if (n >= this->size()) {\n panic<std::out_of_range>(\"rust::Vec index out of range\");\n }\n return (*this)[n];\n}\n\ntemplate <typename T>\nconst T &Vec<T>::front() const noexcept {\n assert(!this->empty());\n return (*this)[0];\n}\n\ntemplate <typename T>\nconst T &Vec<T>::back() const noexcept {\n assert(!this->empty());\n return (*this)[this->size() - 1];\n}\n\ntemplate <typename T>\nT &Vec<T>::operator[](std::size_t n) noexcept {\n assert(n < this->size());\n auto data = reinterpret_cast<char *>(this->data());\n return *reinterpret_cast<T *>(data + n * size_of<T>());\n}\n\ntemplate <typename T>\nT &Vec<T>::at(std::size_t n) {\n if (n >= this->size()) {\n panic<std::out_of_range>(\"rust::Vec index out of range\");\n }\n return (*this)[n];\n}\n\ntemplate <typename T>\nT &Vec<T>::front() noexcept {\n assert(!this->empty());\n return (*this)[0];\n}\n\ntemplate <typename T>\nT &Vec<T>::back() noexcept {\n assert(!this->empty());\n return (*this)[this->size() - 1];\n}\n\ntemplate <typename T>\nvoid Vec<T>::reserve(std::size_t new_cap) {\n this->reserve_total(new_cap);\n}\n\ntemplate <typename T>\nvoid Vec<T>::push_back(const T &value) {\n this->emplace_back(value);\n}\n\ntemplate <typename T>\nvoid Vec<T>::push_back(T &&value) {\n this->emplace_back(std::move(value));\n}\n\ntemplate <typename T>\ntemplate <typename... Args>\nvoid Vec<T>::emplace_back(Args &&...args) {\n auto size = this->size();\n this->reserve_total(size + 1);\n ::new (reinterpret_cast<T *>(reinterpret_cast<char *>(this->data()) +\n size * size_of<T>()))\n T(std::forward<Args>(args)...);\n this->set_len(size + 1);\n}\n\ntemplate <typename T>\nvoid Vec<T>::clear() {\n this->truncate(0);\n}\n\ntemplate <typename T>\ntypename Vec<T>::iterator Vec<T>::begin() noexcept {\n return Slice<T>(this->data(), this->size()).begin();\n}\n\ntemplate <typename T>\ntypename Vec<T>::iterator Vec<T>::end() noexcept {\n return Slice<T>(this->data(), this->size()).end();\n}\n\ntemplate <typename T>\ntypename Vec<T>::const_iterator Vec<T>::begin() const noexcept {\n return this->cbegin();\n}\n\ntemplate <typename T>\ntypename Vec<T>::const_iterator Vec<T>::end() const noexcept {\n return this->cend();\n}\n\ntemplate <typename T>\ntypename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept {\n return Slice<const T>(this->data(), this->size()).begin();\n}\n\ntemplate <typename T>\ntypename Vec<T>::const_iterator Vec<T>::cend() const noexcept {\n return Slice<const T>(this->data(), this->size()).end();\n}\n\ntemplate <typename T>\nvoid Vec<T>::swap(Vec &rhs) noexcept {\n using std::swap;\n swap(this->repr, rhs.repr);\n}\n\n// Internal API only intended for the cxxbridge code generator.\ntemplate <typename T>\nVec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}\n#endif // CXXBRIDGE1_RUST_VEC\n\n#ifndef CXXBRIDGE1_IS_COMPLETE\n#define CXXBRIDGE1_IS_COMPLETE\nnamespace detail {\nnamespace {\ntemplate <typename T, typename = std::size_t>\nstruct is_complete : std::false_type {};\ntemplate <typename T>\nstruct is_complete<T, decltype(sizeof(T))> : std::true_type {};\n} // namespace\n} // namespace detail\n#endif // CXXBRIDGE1_IS_COMPLETE\n\n#ifndef CXXBRIDGE1_LAYOUT\n#define CXXBRIDGE1_LAYOUT\nclass layout {\n template <typename T>\n friend std::size_t size_of();\n template <typename T>\n friend std::size_t align_of();\n template <typename T>\n static typename std::enable_if<std::is_base_of<Opaque, T>::value,\n std::size_t>::type\n do_size_of() {\n return T::layout::size();\n }\n template <typename T>\n static typename std::enable_if<!std::is_base_of<Opaque, T>::value,\n std::size_t>::type\n do_size_of() {\n return sizeof(T);\n }\n template <typename T>\n static\n typename std::enable_if<detail::is_complete<T>::value, std::size_t>::type\n size_of() {\n return do_size_of<T>();\n }\n template <typename T>\n static typename std::enable_if<std::is_base_of<Opaque, T>::value,\n std::size_t>::type\n do_align_of() {\n return T::layout::align();\n }\n template <typename T>\n static typename std::enable_if<!std::is_base_of<Opaque, T>::value,\n std::size_t>::type\n do_align_of() {\n return alignof(T);\n }\n template <typename T>\n static\n typename std::enable_if<detail::is_complete<T>::value, std::size_t>::type\n align_of() {\n return do_align_of<T>();\n }\n};\n\ntemplate <typename T>\nstd::size_t size_of() {\n return layout::size_of<T>();\n}\n\ntemplate <typename T>\nstd::size_t align_of() {\n return layout::align_of<T>();\n}\n#endif // CXXBRIDGE1_LAYOUT\n\n#ifndef CXXBRIDGE1_RELOCATABLE\n#define CXXBRIDGE1_RELOCATABLE\nnamespace detail {\ntemplate <typename... Ts>\nstruct make_void {\n using type = void;\n};\n\ntemplate <typename... Ts>\nusing void_t = typename make_void<Ts...>::type;\n\ntemplate <typename Void, template <typename...> class, typename...>\nstruct detect : std::false_type {};\ntemplate <template <typename...> class T, typename... A>\nstruct detect<void_t<T<A...>>, T, A...> : std::true_type {};\n\ntemplate <template <typename...> class T, typename... A>\nusing is_detected = detect<void, T, A...>;\n\ntemplate <typename T>\nusing detect_IsRelocatable = typename T::IsRelocatable;\n\ntemplate <typename T>\nstruct get_IsRelocatable\n : std::is_same<typename T::IsRelocatable, std::true_type> {};\n} // namespace detail\n\ntemplate <typename T>\nstruct IsRelocatable\n : std::conditional<\n detail::is_detected<detail::detect_IsRelocatable, T>::value,\n detail::get_IsRelocatable<T>,\n std::integral_constant<\n bool, std::is_trivially_move_constructible<T>::value &&\n std::is_trivially_destructible<T>::value>>::type {};\n#endif // CXXBRIDGE1_RELOCATABLE\n\n} // namespace cxxbridge1\n} // namespace rust\n"include_str!("include/cxx.h");
7
8#[derive(#[automatically_derived]
impl ::core::clone::Clone for Include {
#[inline]
fn clone(&self) -> Include {
Include {
path: ::core::clone::Clone::clone(&self.path),
kind: ::core::clone::Clone::clone(&self.kind),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Include {
#[inline]
fn eq(&self, other: &Include) -> bool {
self.path == other.path && self.kind == other.kind
}
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for Include {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "Include",
"path", &self.path, "kind", &&self.kind)
}
}Debug)]
13pub struct Include {
14 pub path: String,
17 pub kind: IncludeKind,
19}
20
21#[derive(#[automatically_derived]
impl<'a> ::core::default::Default for Includes<'a> {
#[inline]
fn default() -> Includes<'a> {
Includes {
custom: ::core::default::Default::default(),
algorithm: ::core::default::Default::default(),
array: ::core::default::Default::default(),
cassert: ::core::default::Default::default(),
cstddef: ::core::default::Default::default(),
cstdint: ::core::default::Default::default(),
cstring: ::core::default::Default::default(),
exception: ::core::default::Default::default(),
functional: ::core::default::Default::default(),
initializer_list: ::core::default::Default::default(),
iterator: ::core::default::Default::default(),
limits: ::core::default::Default::default(),
memory: ::core::default::Default::default(),
new: ::core::default::Default::default(),
ranges: ::core::default::Default::default(),
stdexcept: ::core::default::Default::default(),
string: ::core::default::Default::default(),
string_view: ::core::default::Default::default(),
type_traits: ::core::default::Default::default(),
utility: ::core::default::Default::default(),
vector: ::core::default::Default::default(),
basetsd: ::core::default::Default::default(),
sys_types: ::core::default::Default::default(),
content: ::core::default::Default::default(),
}
}
}Default, #[automatically_derived]
impl<'a> ::core::cmp::PartialEq for Includes<'a> {
#[inline]
fn eq(&self, other: &Includes<'a>) -> bool {
self.algorithm == other.algorithm && self.array == other.array &&
self.cassert == other.cassert &&
self.cstddef == other.cstddef &&
self.cstdint == other.cstdint &&
self.cstring == other.cstring &&
self.exception == other.exception &&
self.functional == other.functional &&
self.initializer_list == other.initializer_list &&
self.iterator == other.iterator &&
self.limits == other.limits && self.memory == other.memory
&& self.new == other.new && self.ranges == other.ranges &&
self.stdexcept == other.stdexcept &&
self.string == other.string &&
self.string_view == other.string_view &&
self.type_traits == other.type_traits &&
self.utility == other.utility && self.vector == other.vector
&& self.basetsd == other.basetsd &&
self.sys_types == other.sys_types &&
self.custom == other.custom && self.content == other.content
}
}PartialEq)]
22pub(crate) struct Includes<'a> {
23 pub custom: Vec<Include>,
24 pub algorithm: bool,
25 pub array: bool,
26 pub cassert: bool,
27 pub cstddef: bool,
28 pub cstdint: bool,
29 pub cstring: bool,
30 pub exception: bool,
31 pub functional: bool,
32 pub initializer_list: bool,
33 pub iterator: bool,
34 pub limits: bool,
35 pub memory: bool,
36 pub new: bool,
37 pub ranges: bool,
38 pub stdexcept: bool,
39 pub string: bool,
40 pub string_view: bool,
41 pub type_traits: bool,
42 pub utility: bool,
43 pub vector: bool,
44 pub basetsd: bool,
45 pub sys_types: bool,
46 pub content: Content<'a>,
47}
48
49impl<'a> Includes<'a> {
50 pub(crate) fn new() -> Self {
51 Includes::default()
52 }
53
54 pub(crate) fn insert(&mut self, include: impl Into<Include>) {
55 self.custom.push(include.into());
56 }
57
58 pub(crate) fn has_cxx_header(&self) -> bool {
59 self.custom
60 .iter()
61 .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h")
62 }
63}
64
65pub(super) fn write(out: &mut OutFile) {
66 let header = out.header;
67 let include = &mut out.include;
68 let cxx_header = include.has_cxx_header();
69 let out = &mut include.content;
70
71 if header {
72 out.write_fmt(format_args!("#pragma once\n"));writeln!(out, "#pragma once");
73 }
74
75 for include in &include.custom {
76 match include.kind {
77 IncludeKind::Quoted => {
78 out.write_fmt(format_args!("#include \"{0}\"\n",
include.path.escape_default()));writeln!(out, "#include \"{}\"", include.path.escape_default());
79 }
80 IncludeKind::Bracketed => {
81 out.write_fmt(format_args!("#include <{0}>\n", include.path));writeln!(out, "#include <{}>", include.path);
82 }
83 }
84 }
85
86 let Includes {
87 custom: _,
88 algorithm,
89 array,
90 cassert,
91 cstddef,
92 cstdint,
93 cstring,
94 exception,
95 functional,
96 initializer_list,
97 iterator,
98 limits,
99 memory,
100 new,
101 ranges,
102 stdexcept,
103 string,
104 string_view,
105 type_traits,
106 utility,
107 vector,
108 basetsd,
109 sys_types,
110 content: _,
111 } = *include;
112
113 if algorithm && !cxx_header {
114 out.write_fmt(format_args!("#include <algorithm>\n"));writeln!(out, "#include <algorithm>");
115 }
116 if array && !cxx_header {
117 out.write_fmt(format_args!("#include <array>\n"));writeln!(out, "#include <array>");
118 }
119 if cassert && !cxx_header {
120 out.write_fmt(format_args!("#include <cassert>\n"));writeln!(out, "#include <cassert>");
121 }
122 if cstddef && !cxx_header {
123 out.write_fmt(format_args!("#include <cstddef>\n"));writeln!(out, "#include <cstddef>");
124 }
125 if cstdint && !cxx_header {
126 out.write_fmt(format_args!("#include <cstdint>\n"));writeln!(out, "#include <cstdint>");
127 }
128 if cstring {
129 out.write_fmt(format_args!("#include <cstring>\n"));writeln!(out, "#include <cstring>");
130 }
131 if exception && !cxx_header {
132 out.write_fmt(format_args!("#include <exception>\n"));writeln!(out, "#include <exception>");
133 }
134 if functional {
135 out.write_fmt(format_args!("#include <functional>\n"));writeln!(out, "#include <functional>");
136 }
137 if initializer_list && !cxx_header {
138 out.write_fmt(format_args!("#include <initializer_list>\n"));writeln!(out, "#include <initializer_list>");
139 }
140 if iterator && !cxx_header {
141 out.write_fmt(format_args!("#include <iterator>\n"));writeln!(out, "#include <iterator>");
142 }
143 if limits {
144 out.write_fmt(format_args!("#include <limits>\n"));writeln!(out, "#include <limits>");
145 }
146 if memory {
147 out.write_fmt(format_args!("#include <memory>\n"));writeln!(out, "#include <memory>");
148 }
149 if new && !cxx_header {
150 out.write_fmt(format_args!("#include <new>\n"));writeln!(out, "#include <new>");
151 }
152 if stdexcept && !cxx_header {
153 out.write_fmt(format_args!("#include <stdexcept>\n"));writeln!(out, "#include <stdexcept>");
154 }
155 if string && !cxx_header {
156 out.write_fmt(format_args!("#include <string>\n"));writeln!(out, "#include <string>");
157 }
158 if type_traits && !cxx_header {
159 out.write_fmt(format_args!("#include <type_traits>\n"));writeln!(out, "#include <type_traits>");
160 }
161 if utility && !cxx_header {
162 out.write_fmt(format_args!("#include <utility>\n"));writeln!(out, "#include <utility>");
163 }
164 if vector && !cxx_header {
165 out.write_fmt(format_args!("#include <vector>\n"));writeln!(out, "#include <vector>");
166 }
167 if basetsd && !cxx_header {
168 out.write_fmt(format_args!("#if defined(_WIN32)\n"));writeln!(out, "#if defined(_WIN32)");
169 out.write_fmt(format_args!("#include <basetsd.h>\n"));writeln!(out, "#include <basetsd.h>");
170 }
171 if sys_types && !cxx_header {
172 if basetsd {
173 out.write_fmt(format_args!("#else\n"));writeln!(out, "#else");
174 } else {
175 out.write_fmt(format_args!("#if not defined(_WIN32)\n"));writeln!(out, "#if not defined(_WIN32)");
176 }
177 }
178 if sys_types && !cxx_header {
179 out.write_fmt(format_args!("#include <sys/types.h>\n"));writeln!(out, "#include <sys/types.h>");
180 }
181 if (basetsd || sys_types) && !cxx_header {
182 out.write_fmt(format_args!("#endif\n"));writeln!(out, "#endif");
183 }
184 if string_view && !cxx_header {
185 out.write_fmt(format_args!("#if __cplusplus >= 201703L\n"));writeln!(out, "#if __cplusplus >= 201703L");
186 out.write_fmt(format_args!("#include <string_view>\n"));writeln!(out, "#include <string_view>");
187 out.write_fmt(format_args!("#endif\n"));writeln!(out, "#endif");
188 }
189 if ranges && !cxx_header {
190 out.write_fmt(format_args!("#if __cplusplus >= 202002L\n"));writeln!(out, "#if __cplusplus >= 202002L");
191 out.write_fmt(format_args!("#include <ranges>\n"));writeln!(out, "#include <ranges>");
192 out.write_fmt(format_args!("#endif\n"));writeln!(out, "#endif");
193 }
194}
195
196impl<'i, 'a> Extend<&'i Include> for Includes<'a> {
197 fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
198 self.custom.extend(iter.into_iter().cloned());
199 }
200}
201
202impl From<&syntax::Include> for Include {
203 fn from(include: &syntax::Include) -> Self {
204 Include {
205 path: include.path.clone(),
206 kind: include.kind,
207 }
208 }
209}
210
211impl<'a> Deref for Includes<'a> {
212 type Target = Content<'a>;
213
214 fn deref(&self) -> &Self::Target {
215 &self.content
216 }
217}
218
219impl<'a> DerefMut for Includes<'a> {
220 fn deref_mut(&mut self) -> &mut Self::Target {
221 &mut self.content
222 }
223}