blob: 5de479c4f2803fbc8087dab6bda25b2ffd958388 [file] [log] [blame]
David Tolnay7db73692019-10-20 14:51:12 -04001#pragma once
2#include <array>
David Tolnay30430f12020-03-19 20:49:00 -07003#include <cstddef>
David Tolnay7db73692019-10-20 14:51:12 -04004#include <cstdint>
David Tolnayb7a7cb62020-03-17 21:18:40 -07005#include <exception>
David Tolnay001102a2020-03-01 20:05:04 -08006#include <iosfwd>
David Tolnay7db73692019-10-20 14:51:12 -04007#include <string>
David Tolnayf6292372020-03-01 21:09:11 -08008#include <type_traits>
David Tolnay4791f1c2020-03-17 21:53:16 -07009#include <utility>
David Tolnay7db73692019-10-20 14:51:12 -040010
David Tolnay750755e2020-03-01 13:04:08 -080011namespace rust {
David Tolnay8c730492020-03-13 01:29:06 -070012inline namespace cxxbridge02 {
David Tolnay7db73692019-10-20 14:51:12 -040013
David Tolnayd1e2efc2020-03-03 22:25:43 -080014struct unsafe_bitcopy_t;
15
David Tolnayb7a7cb62020-03-17 21:18:40 -070016#ifndef CXXBRIDGE02_RUST_STRING
17#define CXXBRIDGE02_RUST_STRING
David Tolnay56082162020-03-01 12:57:33 -080018class String final {
David Tolnay7db73692019-10-20 14:51:12 -040019public:
David Tolnay56082162020-03-01 12:57:33 -080020 String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080021 String(const String &) noexcept;
22 String(String &&) noexcept;
David Tolnay56082162020-03-01 12:57:33 -080023 ~String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080024
25 String(const std::string &);
26 String(const char *);
27
28 String &operator=(const String &) noexcept;
29 String &operator=(String &&) noexcept;
30
David Tolnay404d6892020-03-01 20:19:41 -080031 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040032
33 // Note: no null terminator.
34 const char *data() const noexcept;
35 size_t size() const noexcept;
36 size_t length() const noexcept;
37
David Tolnayd1e2efc2020-03-03 22:25:43 -080038 // Internal API only intended for the cxxbridge code generator.
39 String(unsafe_bitcopy_t, const String &) noexcept;
40
David Tolnay7db73692019-10-20 14:51:12 -040041private:
42 // Size and alignment statically verified by rust_string.rs.
43 std::array<uintptr_t, 3> repr;
44};
David Tolnayb7a7cb62020-03-17 21:18:40 -070045#endif // CXXBRIDGE02_RUST_STRING
David Tolnay7db73692019-10-20 14:51:12 -040046
David Tolnayb7a7cb62020-03-17 21:18:40 -070047#ifndef CXXBRIDGE02_RUST_STR
48#define CXXBRIDGE02_RUST_STR
David Tolnay09dbe752020-03-01 13:00:40 -080049class Str final {
David Tolnay7db73692019-10-20 14:51:12 -040050public:
David Tolnay09dbe752020-03-01 13:00:40 -080051 Str() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080052 Str(const Str &) noexcept;
53
David Tolnay851677c2020-03-01 23:49:46 -080054 Str(const std::string &);
55 Str(const char *);
56 Str(std::string &&) = delete;
David Tolnayd9c4ac92020-03-01 20:33:58 -080057
58 Str &operator=(Str) noexcept;
59
David Tolnay404d6892020-03-01 20:19:41 -080060 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040061
62 // Note: no null terminator.
63 const char *data() const noexcept;
64 size_t size() const noexcept;
65 size_t length() const noexcept;
66
67 // Repr is PRIVATE; must not be used other than by our generated code.
68 //
69 // Not necessarily ABI compatible with &str. Codegen will translate to
70 // cxx::rust_str::RustStr which matches this layout.
71 struct Repr {
72 const char *ptr;
73 size_t len;
74 };
David Tolnayd9c4ac92020-03-01 20:33:58 -080075 Str(Repr) noexcept;
David Tolnaybaae4432020-03-01 20:20:10 -080076 explicit operator Repr() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040077
78private:
79 Repr repr;
80};
David Tolnayb7a7cb62020-03-17 21:18:40 -070081#endif // CXXBRIDGE02_RUST_STR
David Tolnay7db73692019-10-20 14:51:12 -040082
David Tolnay8c730492020-03-13 01:29:06 -070083#ifndef CXXBRIDGE02_RUST_BOX
84#define CXXBRIDGE02_RUST_BOX
David Tolnay324437a2020-03-01 13:02:24 -080085template <typename T> class Box final {
David Tolnay7db73692019-10-20 14:51:12 -040086public:
David Tolnayf6292372020-03-01 21:09:11 -080087 using value_type = T;
David Tolnay9f921372020-03-01 21:09:25 -080088 using const_pointer = typename std::add_pointer<
89 typename std::add_const<value_type>::type>::type;
90 using pointer = typename std::add_pointer<value_type>::type;
David Tolnayf6292372020-03-01 21:09:11 -080091
David Tolnay324437a2020-03-01 13:02:24 -080092 Box(const Box &other) : Box(*other) {}
David Tolnay33169bd2020-03-06 13:02:08 -080093 Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
David Tolnay324437a2020-03-01 13:02:24 -080094 Box(const T &val) {
David Tolnay7db73692019-10-20 14:51:12 -040095 this->uninit();
David Tolnay33169bd2020-03-06 13:02:08 -080096 ::new (this->ptr) T(val);
David Tolnay7db73692019-10-20 14:51:12 -040097 }
David Tolnay324437a2020-03-01 13:02:24 -080098 Box &operator=(const Box &other) {
David Tolnay7db73692019-10-20 14:51:12 -040099 if (this != &other) {
David Tolnay33169bd2020-03-06 13:02:08 -0800100 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400101 **this = *other;
102 } else {
103 this->uninit();
David Tolnay33169bd2020-03-06 13:02:08 -0800104 ::new (this->ptr) T(*other);
David Tolnay7db73692019-10-20 14:51:12 -0400105 }
106 }
107 return *this;
108 }
David Tolnay324437a2020-03-01 13:02:24 -0800109 Box &operator=(Box &&other) noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800110 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400111 this->drop();
112 }
David Tolnay33169bd2020-03-06 13:02:08 -0800113 this->ptr = other.ptr;
114 other.ptr = nullptr;
David Tolnay7db73692019-10-20 14:51:12 -0400115 return *this;
116 }
David Tolnay324437a2020-03-01 13:02:24 -0800117 ~Box() noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800118 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400119 this->drop();
120 }
121 }
122
David Tolnay33169bd2020-03-06 13:02:08 -0800123 const T *operator->() const noexcept { return this->ptr; }
124 const T &operator*() const noexcept { return *this->ptr; }
125 T *operator->() noexcept { return this->ptr; }
126 T &operator*() noexcept { return *this->ptr; }
David Tolnay7db73692019-10-20 14:51:12 -0400127
128 // Important: requires that `raw` came from an into_raw call. Do not pass a
129 // pointer from `new` or any other source.
David Tolnay324437a2020-03-01 13:02:24 -0800130 static Box from_raw(T *raw) noexcept {
131 Box box;
David Tolnay33169bd2020-03-06 13:02:08 -0800132 box.ptr = raw;
David Tolnay7db73692019-10-20 14:51:12 -0400133 return box;
134 }
135
136 T *into_raw() noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800137 T *raw = this->ptr;
138 this->ptr = nullptr;
David Tolnay7db73692019-10-20 14:51:12 -0400139 return raw;
140 }
141
142private:
David Tolnay324437a2020-03-01 13:02:24 -0800143 Box() noexcept {}
David Tolnay7db73692019-10-20 14:51:12 -0400144 void uninit() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400145 void drop() noexcept;
David Tolnay33169bd2020-03-06 13:02:08 -0800146 T *ptr;
David Tolnay7db73692019-10-20 14:51:12 -0400147};
David Tolnay8c730492020-03-13 01:29:06 -0700148#endif // CXXBRIDGE02_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400149
David Tolnay75dca2e2020-03-25 20:17:52 -0700150#ifndef CXXBRIDGE02_RUST_FN
151#define CXXBRIDGE02_RUST_FN
152template <typename Signature, bool Throws = false> class Fn;
153
154template <typename Ret, typename... Args, bool Throws>
155class Fn<Ret(Args...), Throws> {
156public:
David Tolnay533d4582020-04-08 20:29:14 -0700157 Ret operator()(Args... args) const noexcept(!Throws);
158 Fn operator*() const noexcept;
David Tolnay75dca2e2020-03-25 20:17:52 -0700159
160private:
161 Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
162 void *fn;
163};
164
165template <typename Signature> using TryFn = Fn<Signature, true>;
166#endif // CXXBRIDGE02_RUST_FN
167
David Tolnayb7a7cb62020-03-17 21:18:40 -0700168#ifndef CXXBRIDGE02_RUST_ERROR
169#define CXXBRIDGE02_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700170class Error final : std::exception {
171public:
172 Error(const Error &);
173 Error(Error &&) noexcept;
174 Error(Str::Repr) noexcept;
175 ~Error() noexcept;
176 const char *what() const noexcept override;
177
178private:
179 Str::Repr msg;
180};
David Tolnayb7a7cb62020-03-17 21:18:40 -0700181#endif // CXXBRIDGE02_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700182
David Tolnay851677c2020-03-01 23:49:46 -0800183std::ostream &operator<<(std::ostream &, const String &);
184std::ostream &operator<<(std::ostream &, const Str &);
David Tolnay7db73692019-10-20 14:51:12 -0400185
David Tolnay3b0c9882020-03-01 14:08:57 -0800186// Snake case aliases for use in code that uses this style for type names.
187using string = String;
188using str = Str;
189template <class T> using box = Box<T>;
David Tolnay1e548172020-03-16 13:37:09 -0700190using error = Error;
David Tolnay75dca2e2020-03-25 20:17:52 -0700191template <typename Signature, bool Throws = false>
192using fn = Fn<Signature, Throws>;
193template <typename Signature> using try_fn = TryFn<Signature>;
David Tolnay3b0c9882020-03-01 14:08:57 -0800194
David Tolnayb7a7cb62020-03-17 21:18:40 -0700195#ifndef CXXBRIDGE02_RUST_BITCOPY
196#define CXXBRIDGE02_RUST_BITCOPY
David Tolnayd1e2efc2020-03-03 22:25:43 -0800197struct unsafe_bitcopy_t {
198 explicit unsafe_bitcopy_t() = default;
199};
200constexpr unsafe_bitcopy_t unsafe_bitcopy{};
David Tolnayb7a7cb62020-03-17 21:18:40 -0700201#endif // CXXBRIDGE02_RUST_BITCOPY
David Tolnayd1e2efc2020-03-03 22:25:43 -0800202
David Tolnay75dca2e2020-03-25 20:17:52 -0700203template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700204Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
David Tolnay75dca2e2020-03-25 20:17:52 -0700205 return (*this->trampoline)(std::move(args)..., this->fn);
206}
207
David Tolnaya23129c2020-04-08 20:08:21 -0700208template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700209Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
David Tolnaya23129c2020-04-08 20:08:21 -0700210 return *this;
211}
212
David Tolnay8c730492020-03-13 01:29:06 -0700213} // namespace cxxbridge02
David Tolnay750755e2020-03-01 13:04:08 -0800214} // namespace rust