blob: 8614d396ec7d6e6ebb3a4e303d826d8603e9cdf6 [file] [log] [blame]
David Tolnay736cbca2020-03-11 16:49:18 -07001#include "../include/cxx.h"
David Tolnay7db73692019-10-20 14:51:12 -04002#include <cstring>
David Tolnay71918ec2020-04-11 21:52:09 -07003#include <exception>
David Tolnay001102a2020-03-01 20:05:04 -08004#include <iostream>
David Tolnay7db73692019-10-20 14:51:12 -04005#include <memory>
6#include <stdexcept>
David Tolnay37dd7e12020-04-25 12:51:59 -07007#include <vector>
David Tolnay7db73692019-10-20 14:51:12 -04008
David Tolnayf262d382020-04-11 22:12:40 -07009template <typename Exception>
10static void panic [[noreturn]] (const char *msg) {
David Tolnayce5af542020-04-10 18:08:30 -070011#if defined(RUST_CXX_NO_EXCEPTIONS)
12 std::cerr << "Error: " << msg << ". Aborting." << std::endl;
David Tolnay71918ec2020-04-11 21:52:09 -070013 std::terminate();
David Tolnayce5af542020-04-10 18:08:30 -070014#else
15 throw Exception(msg);
16#endif
17}
18
David Tolnay7db73692019-10-20 14:51:12 -040019extern "C" {
David Tolnay69601622020-04-29 18:48:36 -070020const char *cxxbridge03$cxx_string$data(const std::string &s) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040021 return s.data();
22}
23
David Tolnay69601622020-04-29 18:48:36 -070024size_t cxxbridge03$cxx_string$length(const std::string &s) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040025 return s.length();
26}
27
David Tolnay750755e2020-03-01 13:04:08 -080028// rust::String
David Tolnay69601622020-04-29 18:48:36 -070029void cxxbridge03$string$new(rust::String *self) noexcept;
30void cxxbridge03$string$clone(rust::String *self,
David Tolnay6c089102020-03-02 00:21:13 -080031 const rust::String &other) noexcept;
David Tolnay69601622020-04-29 18:48:36 -070032bool cxxbridge03$string$from(rust::String *self, const char *ptr,
David Tolnay6c089102020-03-02 00:21:13 -080033 size_t len) noexcept;
David Tolnay69601622020-04-29 18:48:36 -070034void cxxbridge03$string$drop(rust::String *self) noexcept;
35const char *cxxbridge03$string$ptr(const rust::String *self) noexcept;
36size_t cxxbridge03$string$len(const rust::String *self) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040037
David Tolnay750755e2020-03-01 13:04:08 -080038// rust::Str
David Tolnay69601622020-04-29 18:48:36 -070039bool cxxbridge03$str$valid(const char *ptr, size_t len) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040040} // extern "C"
41
David Tolnay750755e2020-03-01 13:04:08 -080042namespace rust {
David Tolnay69601622020-04-29 18:48:36 -070043inline namespace cxxbridge03 {
David Tolnay7db73692019-10-20 14:51:12 -040044
David Tolnay69601622020-04-29 18:48:36 -070045String::String() noexcept { cxxbridge03$string$new(this); }
David Tolnay7db73692019-10-20 14:51:12 -040046
David Tolnay56082162020-03-01 12:57:33 -080047String::String(const String &other) noexcept {
David Tolnay69601622020-04-29 18:48:36 -070048 cxxbridge03$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -040049}
50
David Tolnay56082162020-03-01 12:57:33 -080051String::String(String &&other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040052 this->repr = other.repr;
David Tolnay69601622020-04-29 18:48:36 -070053 cxxbridge03$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -040054}
55
David Tolnay69601622020-04-29 18:48:36 -070056String::~String() noexcept { cxxbridge03$string$drop(this); }
David Tolnay7db73692019-10-20 14:51:12 -040057
David Tolnayc2bbd952020-07-29 18:15:26 -070058String::String(const std::string &s) : String(s.data(), s.length()) {}
David Tolnay7db73692019-10-20 14:51:12 -040059
David Tolnayc2bbd952020-07-29 18:15:26 -070060String::String(const char *s) : String(s, std::strlen(s)) {}
61
62String::String(const char *s, size_t len) {
David Tolnay69601622020-04-29 18:48:36 -070063 if (!cxxbridge03$string$from(this, s, len)) {
David Tolnayce5af542020-04-10 18:08:30 -070064 panic<std::invalid_argument>("data for rust::String is not utf-8");
David Tolnayd9c4ac92020-03-01 20:33:58 -080065 }
David Tolnay7db73692019-10-20 14:51:12 -040066}
67
David Tolnay56082162020-03-01 12:57:33 -080068String &String::operator=(const String &other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040069 if (this != &other) {
David Tolnay69601622020-04-29 18:48:36 -070070 cxxbridge03$string$drop(this);
71 cxxbridge03$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -040072 }
73 return *this;
74}
75
David Tolnay56082162020-03-01 12:57:33 -080076String &String::operator=(String &&other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040077 if (this != &other) {
David Tolnay69601622020-04-29 18:48:36 -070078 cxxbridge03$string$drop(this);
David Tolnay7db73692019-10-20 14:51:12 -040079 this->repr = other.repr;
David Tolnay69601622020-04-29 18:48:36 -070080 cxxbridge03$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -040081 }
82 return *this;
83}
84
David Tolnayd9c4ac92020-03-01 20:33:58 -080085String::operator std::string() const {
86 return std::string(this->data(), this->size());
87}
88
David Tolnay56082162020-03-01 12:57:33 -080089const char *String::data() const noexcept {
David Tolnay69601622020-04-29 18:48:36 -070090 return cxxbridge03$string$ptr(this);
David Tolnay7db73692019-10-20 14:51:12 -040091}
92
David Tolnay69601622020-04-29 18:48:36 -070093size_t String::size() const noexcept { return cxxbridge03$string$len(this); }
David Tolnay7db73692019-10-20 14:51:12 -040094
David Tolnay69601622020-04-29 18:48:36 -070095size_t String::length() const noexcept { return cxxbridge03$string$len(this); }
David Tolnay7db73692019-10-20 14:51:12 -040096
David Tolnayd1e2efc2020-03-03 22:25:43 -080097String::String(unsafe_bitcopy_t, const String &bits) noexcept
98 : repr(bits.repr) {}
99
David Tolnay56082162020-03-01 12:57:33 -0800100std::ostream &operator<<(std::ostream &os, const String &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400101 os.write(s.data(), s.size());
102 return os;
103}
104
David Tolnay69fe4c22020-03-01 13:57:24 -0800105Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
David Tolnay7db73692019-10-20 14:51:12 -0400106
David Tolnayd9c4ac92020-03-01 20:33:58 -0800107Str::Str(const Str &) noexcept = default;
David Tolnay7db73692019-10-20 14:51:12 -0400108
David Tolnay09dbe752020-03-01 13:00:40 -0800109Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
David Tolnay69601622020-04-29 18:48:36 -0700110 if (!cxxbridge03$str$valid(this->repr.ptr, this->repr.len)) {
David Tolnayce5af542020-04-10 18:08:30 -0700111 panic<std::invalid_argument>("data for rust::Str is not utf-8");
David Tolnay7db73692019-10-20 14:51:12 -0400112 }
113}
114
David Tolnaybb07a4f2020-03-16 23:04:00 -0700115Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
David Tolnay69601622020-04-29 18:48:36 -0700116 if (!cxxbridge03$str$valid(this->repr.ptr, this->repr.len)) {
David Tolnayce5af542020-04-10 18:08:30 -0700117 panic<std::invalid_argument>("data for rust::Str is not utf-8");
David Tolnayd9c4ac92020-03-01 20:33:58 -0800118 }
119}
David Tolnay7db73692019-10-20 14:51:12 -0400120
David Tolnay09dbe752020-03-01 13:00:40 -0800121Str &Str::operator=(Str other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400122 this->repr = other.repr;
123 return *this;
124}
125
David Tolnay09dbe752020-03-01 13:00:40 -0800126Str::operator std::string() const {
David Tolnay7db73692019-10-20 14:51:12 -0400127 return std::string(this->data(), this->size());
128}
129
David Tolnay09dbe752020-03-01 13:00:40 -0800130const char *Str::data() const noexcept { return this->repr.ptr; }
David Tolnay7db73692019-10-20 14:51:12 -0400131
David Tolnay09dbe752020-03-01 13:00:40 -0800132size_t Str::size() const noexcept { return this->repr.len; }
David Tolnay7db73692019-10-20 14:51:12 -0400133
David Tolnay09dbe752020-03-01 13:00:40 -0800134size_t Str::length() const noexcept { return this->repr.len; }
David Tolnay7db73692019-10-20 14:51:12 -0400135
David Tolnay09dbe752020-03-01 13:00:40 -0800136Str::Str(Repr repr_) noexcept : repr(repr_) {}
David Tolnay7db73692019-10-20 14:51:12 -0400137
David Tolnay09dbe752020-03-01 13:00:40 -0800138Str::operator Repr() noexcept { return this->repr; }
David Tolnay7db73692019-10-20 14:51:12 -0400139
David Tolnay09dbe752020-03-01 13:00:40 -0800140std::ostream &operator<<(std::ostream &os, const Str &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400141 os.write(s.data(), s.size());
142 return os;
143}
144
David Tolnay1e548172020-03-16 13:37:09 -0700145extern "C" {
David Tolnay69601622020-04-29 18:48:36 -0700146const char *cxxbridge03$error(const char *ptr, size_t len) {
David Tolnay1e548172020-03-16 13:37:09 -0700147 char *copy = new char[len];
148 strncpy(copy, ptr, len);
149 return copy;
150}
151} // extern "C"
152
153Error::Error(Str::Repr msg) noexcept : msg(msg) {}
154
155Error::Error(const Error &other) {
David Tolnay69601622020-04-29 18:48:36 -0700156 this->msg.ptr = cxxbridge03$error(other.msg.ptr, other.msg.len);
David Tolnay1e548172020-03-16 13:37:09 -0700157 this->msg.len = other.msg.len;
158}
159
160Error::Error(Error &&other) noexcept {
161 delete[] this->msg.ptr;
162 this->msg = other.msg;
163 other.msg.ptr = nullptr;
164 other.msg.len = 0;
165}
166
167Error::~Error() noexcept { delete[] this->msg.ptr; }
168
169const char *Error::what() const noexcept { return this->msg.ptr; }
170
David Tolnay69601622020-04-29 18:48:36 -0700171} // namespace cxxbridge03
David Tolnay750755e2020-03-01 13:04:08 -0800172} // namespace rust
David Tolnay7db73692019-10-20 14:51:12 -0400173
174extern "C" {
David Tolnay69601622020-04-29 18:48:36 -0700175void cxxbridge03$unique_ptr$std$string$null(
David Tolnay7db73692019-10-20 14:51:12 -0400176 std::unique_ptr<std::string> *ptr) noexcept {
177 new (ptr) std::unique_ptr<std::string>();
178}
David Tolnay69601622020-04-29 18:48:36 -0700179void cxxbridge03$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
David Tolnay7db73692019-10-20 14:51:12 -0400180 std::string *raw) noexcept {
181 new (ptr) std::unique_ptr<std::string>(raw);
182}
David Tolnay69601622020-04-29 18:48:36 -0700183const std::string *cxxbridge03$unique_ptr$std$string$get(
David Tolnay7db73692019-10-20 14:51:12 -0400184 const std::unique_ptr<std::string> &ptr) noexcept {
185 return ptr.get();
186}
David Tolnay69601622020-04-29 18:48:36 -0700187std::string *cxxbridge03$unique_ptr$std$string$release(
David Tolnay7db73692019-10-20 14:51:12 -0400188 std::unique_ptr<std::string> &ptr) noexcept {
189 return ptr.release();
190}
David Tolnay69601622020-04-29 18:48:36 -0700191void cxxbridge03$unique_ptr$std$string$drop(
David Tolnay7db73692019-10-20 14:51:12 -0400192 std::unique_ptr<std::string> *ptr) noexcept {
193 ptr->~unique_ptr();
194}
195} // extern "C"
Myron Ahneba35cf2020-02-05 19:41:51 +0700196
David Tolnay37dd7e12020-04-25 12:51:59 -0700197#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
David Tolnay69601622020-04-29 18:48:36 -0700198 size_t cxxbridge03$std$vector$##RUST_TYPE##$size( \
David Tolnay37dd7e12020-04-25 12:51:59 -0700199 const std::vector<CXX_TYPE> &s) noexcept { \
200 return s.size(); \
201 } \
David Tolnay69601622020-04-29 18:48:36 -0700202 const CXX_TYPE *cxxbridge03$std$vector$##RUST_TYPE##$get_unchecked( \
David Tolnay37dd7e12020-04-25 12:51:59 -0700203 const std::vector<CXX_TYPE> &s, size_t pos) noexcept { \
David Tolnay9626d082020-04-24 14:52:45 -0700204 return &s[pos]; \
David Tolnay37dd7e12020-04-25 12:51:59 -0700205 } \
David Tolnay69601622020-04-29 18:48:36 -0700206 void cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$null( \
David Tolnay996db1e2020-04-24 14:46:31 -0700207 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
208 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700209 } \
David Tolnay69601622020-04-29 18:48:36 -0700210 void cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$raw( \
David Tolnay996db1e2020-04-24 14:46:31 -0700211 std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
David Tolnay37dd7e12020-04-25 12:51:59 -0700212 std::vector<CXX_TYPE> *raw) noexcept { \
David Tolnay996db1e2020-04-24 14:46:31 -0700213 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700214 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700215 const std::vector<CXX_TYPE> \
David Tolnay69601622020-04-29 18:48:36 -0700216 *cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$get( \
David Tolnay996db1e2020-04-24 14:46:31 -0700217 const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700218 return ptr.get(); \
219 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700220 std::vector<CXX_TYPE> \
David Tolnay69601622020-04-29 18:48:36 -0700221 *cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$release( \
David Tolnay996db1e2020-04-24 14:46:31 -0700222 std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700223 return ptr.release(); \
224 } \
David Tolnay69601622020-04-29 18:48:36 -0700225 void cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$drop( \
David Tolnay996db1e2020-04-24 14:46:31 -0700226 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700227 ptr->~unique_ptr(); \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700228 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700229
David Tolnay6787be62020-04-25 11:01:02 -0700230#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE) \
David Tolnay69601622020-04-29 18:48:36 -0700231 void cxxbridge03$rust_vec$##RUST_TYPE##$new( \
David Tolnayf97c2d52020-04-25 16:37:48 -0700232 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay69601622020-04-29 18:48:36 -0700233 void cxxbridge03$rust_vec$##RUST_TYPE##$drop( \
David Tolnay6787be62020-04-25 11:01:02 -0700234 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay69601622020-04-29 18:48:36 -0700235 size_t cxxbridge03$rust_vec$##RUST_TYPE##$len( \
David Tolnay6787be62020-04-25 11:01:02 -0700236 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay69601622020-04-29 18:48:36 -0700237 const CXX_TYPE *cxxbridge03$rust_vec$##RUST_TYPE##$data( \
David Tolnay6787be62020-04-25 11:01:02 -0700238 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay69601622020-04-29 18:48:36 -0700239 size_t cxxbridge03$rust_vec$##RUST_TYPE##$stride() noexcept;
David Tolnay6787be62020-04-25 11:01:02 -0700240
241#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
242 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700243 Vec<CXX_TYPE>::Vec() noexcept { \
David Tolnay69601622020-04-29 18:48:36 -0700244 cxxbridge03$rust_vec$##RUST_TYPE##$new(this); \
David Tolnayf97c2d52020-04-25 16:37:48 -0700245 } \
246 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700247 void Vec<CXX_TYPE>::drop() noexcept { \
David Tolnay69601622020-04-29 18:48:36 -0700248 return cxxbridge03$rust_vec$##RUST_TYPE##$drop(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700249 } \
250 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700251 size_t Vec<CXX_TYPE>::size() const noexcept { \
David Tolnay69601622020-04-29 18:48:36 -0700252 return cxxbridge03$rust_vec$##RUST_TYPE##$len(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700253 } \
254 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700255 const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept { \
David Tolnay69601622020-04-29 18:48:36 -0700256 return cxxbridge03$rust_vec$##RUST_TYPE##$data(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700257 } \
258 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700259 size_t Vec<CXX_TYPE>::stride() noexcept { \
David Tolnay69601622020-04-29 18:48:36 -0700260 return cxxbridge03$rust_vec$##RUST_TYPE##$stride(); \
David Tolnay6787be62020-04-25 11:01:02 -0700261 }
262
263// Usize and isize are the same type as one of the below.
David Tolnayf336b3b2020-04-30 08:45:54 -0700264#define FOR_EACH_NUMERIC(MACRO) \
David Tolnay6787be62020-04-25 11:01:02 -0700265 MACRO(u8, uint8_t) \
266 MACRO(u16, uint16_t) \
267 MACRO(u32, uint32_t) \
268 MACRO(u64, uint64_t) \
269 MACRO(i8, int8_t) \
270 MACRO(i16, int16_t) \
271 MACRO(i32, int32_t) \
272 MACRO(i64, int64_t) \
273 MACRO(f32, float) \
274 MACRO(f64, double)
275
David Tolnayf336b3b2020-04-30 08:45:54 -0700276#define FOR_EACH_STD_VECTOR(MACRO) \
277 FOR_EACH_NUMERIC(MACRO) \
David Tolnay6787be62020-04-25 11:01:02 -0700278 MACRO(usize, size_t) \
279 MACRO(isize, rust::isize)
280
David Tolnayf336b3b2020-04-30 08:45:54 -0700281#define FOR_EACH_RUST_VEC(MACRO) \
282 FOR_EACH_NUMERIC(MACRO) \
283 MACRO(bool, bool)
284
David Tolnay4e7e7c42020-04-24 14:48:07 -0700285extern "C" {
David Tolnayf336b3b2020-04-30 08:45:54 -0700286FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
287FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
David Tolnay4e7e7c42020-04-24 14:48:07 -0700288} // extern "C"
David Tolnay6787be62020-04-25 11:01:02 -0700289
David Tolnay1768d8f2020-04-25 18:15:11 -0700290namespace rust {
David Tolnay69601622020-04-29 18:48:36 -0700291inline namespace cxxbridge03 {
David Tolnayf336b3b2020-04-30 08:45:54 -0700292FOR_EACH_RUST_VEC(RUST_VEC_OPS)
David Tolnay69601622020-04-29 18:48:36 -0700293} // namespace cxxbridge03
David Tolnay1768d8f2020-04-25 18:15:11 -0700294} // namespace rust