blob: 05dc15ac496e782d81922a6e1f5a9d11710d11af [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 Tolnay7db73692019-10-20 14:51:12 -04009extern "C" {
David Tolnay8f16ae72020-10-08 18:21:13 -070010const char *cxxbridge05$cxx_string$data(const std::string &s) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040011 return s.data();
12}
13
David Tolnay8f16ae72020-10-08 18:21:13 -070014size_t cxxbridge05$cxx_string$length(const std::string &s) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040015 return s.length();
16}
17
David Tolnay750755e2020-03-01 13:04:08 -080018// rust::String
David Tolnay8f16ae72020-10-08 18:21:13 -070019void cxxbridge05$string$new(rust::String *self) noexcept;
20void cxxbridge05$string$clone(rust::String *self,
David Tolnay6c089102020-03-02 00:21:13 -080021 const rust::String &other) noexcept;
David Tolnay8f16ae72020-10-08 18:21:13 -070022bool cxxbridge05$string$from(rust::String *self, const char *ptr,
David Tolnay6c089102020-03-02 00:21:13 -080023 size_t len) noexcept;
David Tolnay8f16ae72020-10-08 18:21:13 -070024void cxxbridge05$string$drop(rust::String *self) noexcept;
25const char *cxxbridge05$string$ptr(const rust::String *self) noexcept;
26size_t cxxbridge05$string$len(const rust::String *self) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040027
David Tolnay750755e2020-03-01 13:04:08 -080028// rust::Str
David Tolnay8f16ae72020-10-08 18:21:13 -070029bool cxxbridge05$str$valid(const char *ptr, size_t len) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040030} // extern "C"
31
David Tolnay750755e2020-03-01 13:04:08 -080032namespace rust {
David Tolnay8f16ae72020-10-08 18:21:13 -070033inline namespace cxxbridge05 {
David Tolnay7db73692019-10-20 14:51:12 -040034
David Tolnay521d99d2020-08-26 20:45:40 -070035template <typename Exception>
36void panic [[noreturn]] (const char *msg) {
37#if defined(RUST_CXX_NO_EXCEPTIONS)
38 std::cerr << "Error: " << msg << ". Aborting." << std::endl;
39 std::terminate();
40#else
41 throw Exception(msg);
42#endif
43}
44
David Tolnayb10c4bc2020-08-26 21:55:29 -070045template void panic<std::out_of_range>[[noreturn]] (const char *msg);
David Tolnay521d99d2020-08-26 20:45:40 -070046
David Tolnay8f16ae72020-10-08 18:21:13 -070047String::String() noexcept { cxxbridge05$string$new(this); }
David Tolnay7db73692019-10-20 14:51:12 -040048
David Tolnay56082162020-03-01 12:57:33 -080049String::String(const String &other) noexcept {
David Tolnay8f16ae72020-10-08 18:21:13 -070050 cxxbridge05$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -040051}
52
David Tolnay56082162020-03-01 12:57:33 -080053String::String(String &&other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040054 this->repr = other.repr;
David Tolnay8f16ae72020-10-08 18:21:13 -070055 cxxbridge05$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -040056}
57
David Tolnay8f16ae72020-10-08 18:21:13 -070058String::~String() noexcept { cxxbridge05$string$drop(this); }
David Tolnay7db73692019-10-20 14:51:12 -040059
David Tolnay032d8532020-10-30 20:47:31 -070060static void initString(String *self, const char *s, size_t len) {
61 if (!cxxbridge05$string$from(self, s, len)) {
David Tolnay8d323662020-10-30 19:32:26 -070062 panic<std::invalid_argument>("data for rust::String is not utf-8");
63 }
64}
David Tolnay7db73692019-10-20 14:51:12 -040065
David Tolnay032d8532020-10-30 20:47:31 -070066String::String(const std::string &s) { initString(this, s.data(), s.length()); }
67
68String::String(const char *s) { initString(this, s, std::strlen(s)); }
David Tolnayc2bbd952020-07-29 18:15:26 -070069
70String::String(const char *s, size_t len) {
David Tolnay032d8532020-10-30 20:47:31 -070071 initString(this,
72 s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
73 len);
David Tolnay7db73692019-10-20 14:51:12 -040074}
75
David Tolnay56082162020-03-01 12:57:33 -080076String &String::operator=(const String &other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040077 if (this != &other) {
David Tolnay8f16ae72020-10-08 18:21:13 -070078 cxxbridge05$string$drop(this);
79 cxxbridge05$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -040080 }
81 return *this;
82}
83
David Tolnay56082162020-03-01 12:57:33 -080084String &String::operator=(String &&other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040085 if (this != &other) {
David Tolnay8f16ae72020-10-08 18:21:13 -070086 cxxbridge05$string$drop(this);
David Tolnay7db73692019-10-20 14:51:12 -040087 this->repr = other.repr;
David Tolnay8f16ae72020-10-08 18:21:13 -070088 cxxbridge05$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -040089 }
90 return *this;
91}
92
David Tolnayd9c4ac92020-03-01 20:33:58 -080093String::operator std::string() const {
94 return std::string(this->data(), this->size());
95}
96
David Tolnay56082162020-03-01 12:57:33 -080097const char *String::data() const noexcept {
David Tolnay8f16ae72020-10-08 18:21:13 -070098 return cxxbridge05$string$ptr(this);
David Tolnay7db73692019-10-20 14:51:12 -040099}
100
David Tolnay8f16ae72020-10-08 18:21:13 -0700101size_t String::size() const noexcept { return cxxbridge05$string$len(this); }
David Tolnay7db73692019-10-20 14:51:12 -0400102
David Tolnay8f16ae72020-10-08 18:21:13 -0700103size_t String::length() const noexcept { return cxxbridge05$string$len(this); }
David Tolnay7db73692019-10-20 14:51:12 -0400104
David Tolnayd1e2efc2020-03-03 22:25:43 -0800105String::String(unsafe_bitcopy_t, const String &bits) noexcept
106 : repr(bits.repr) {}
107
David Tolnay56082162020-03-01 12:57:33 -0800108std::ostream &operator<<(std::ostream &os, const String &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400109 os.write(s.data(), s.size());
110 return os;
111}
112
David Tolnay8d323662020-10-30 19:32:26 -0700113Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(1), 0}) {}
David Tolnay7db73692019-10-20 14:51:12 -0400114
David Tolnayd9c4ac92020-03-01 20:33:58 -0800115Str::Str(const Str &) noexcept = default;
David Tolnay7db73692019-10-20 14:51:12 -0400116
David Tolnay032d8532020-10-30 20:47:31 -0700117static void initStr(Str::Repr repr) {
118 if (!cxxbridge05$str$valid(repr.ptr, repr.len)) {
David Tolnay8d323662020-10-30 19:32:26 -0700119 panic<std::invalid_argument>("data for rust::Str is not utf-8");
120 }
121}
David Tolnay7db73692019-10-20 14:51:12 -0400122
David Tolnay032d8532020-10-30 20:47:31 -0700123Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
124 initStr(this->repr);
David Tolnay8d323662020-10-30 19:32:26 -0700125}
David Tolnay894c5e42020-07-29 18:20:00 -0700126
David Tolnay032d8532020-10-30 20:47:31 -0700127Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) { initStr(this->repr); }
128
David Tolnay8d323662020-10-30 19:32:26 -0700129Str::Str(const char *s, size_t len)
130 : repr(
131 Repr{s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
132 len}) {
David Tolnay032d8532020-10-30 20:47:31 -0700133 initStr(this->repr);
David Tolnayd9c4ac92020-03-01 20:33:58 -0800134}
David Tolnay7db73692019-10-20 14:51:12 -0400135
David Tolnay09dbe752020-03-01 13:00:40 -0800136Str &Str::operator=(Str other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400137 this->repr = other.repr;
138 return *this;
139}
140
David Tolnay09dbe752020-03-01 13:00:40 -0800141Str::operator std::string() const {
David Tolnay7db73692019-10-20 14:51:12 -0400142 return std::string(this->data(), this->size());
143}
144
David Tolnay09dbe752020-03-01 13:00:40 -0800145const char *Str::data() const noexcept { return this->repr.ptr; }
David Tolnay7db73692019-10-20 14:51:12 -0400146
David Tolnay09dbe752020-03-01 13:00:40 -0800147size_t Str::size() const noexcept { return this->repr.len; }
David Tolnay7db73692019-10-20 14:51:12 -0400148
David Tolnay09dbe752020-03-01 13:00:40 -0800149size_t Str::length() const noexcept { return this->repr.len; }
David Tolnay7db73692019-10-20 14:51:12 -0400150
David Tolnay09dbe752020-03-01 13:00:40 -0800151Str::Str(Repr repr_) noexcept : repr(repr_) {}
David Tolnay7db73692019-10-20 14:51:12 -0400152
David Tolnay09dbe752020-03-01 13:00:40 -0800153Str::operator Repr() noexcept { return this->repr; }
David Tolnay7db73692019-10-20 14:51:12 -0400154
David Tolnay09dbe752020-03-01 13:00:40 -0800155std::ostream &operator<<(std::ostream &os, const Str &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400156 os.write(s.data(), s.size());
157 return os;
158}
159
David Tolnay1e548172020-03-16 13:37:09 -0700160extern "C" {
David Tolnay8f16ae72020-10-08 18:21:13 -0700161const char *cxxbridge05$error(const char *ptr, size_t len) {
David Tolnay1e548172020-03-16 13:37:09 -0700162 char *copy = new char[len];
163 strncpy(copy, ptr, len);
164 return copy;
165}
166} // extern "C"
167
168Error::Error(Str::Repr msg) noexcept : msg(msg) {}
169
170Error::Error(const Error &other) {
David Tolnay8f16ae72020-10-08 18:21:13 -0700171 this->msg.ptr = cxxbridge05$error(other.msg.ptr, other.msg.len);
David Tolnay1e548172020-03-16 13:37:09 -0700172 this->msg.len = other.msg.len;
173}
174
175Error::Error(Error &&other) noexcept {
176 delete[] this->msg.ptr;
177 this->msg = other.msg;
178 other.msg.ptr = nullptr;
179 other.msg.len = 0;
180}
181
182Error::~Error() noexcept { delete[] this->msg.ptr; }
183
184const char *Error::what() const noexcept { return this->msg.ptr; }
185
David Tolnay8f16ae72020-10-08 18:21:13 -0700186} // namespace cxxbridge05
David Tolnay750755e2020-03-01 13:04:08 -0800187} // namespace rust
David Tolnay7db73692019-10-20 14:51:12 -0400188
189extern "C" {
David Tolnay8f16ae72020-10-08 18:21:13 -0700190void cxxbridge05$unique_ptr$std$string$null(
David Tolnay7db73692019-10-20 14:51:12 -0400191 std::unique_ptr<std::string> *ptr) noexcept {
192 new (ptr) std::unique_ptr<std::string>();
193}
David Tolnay8f16ae72020-10-08 18:21:13 -0700194void cxxbridge05$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
David Tolnay7db73692019-10-20 14:51:12 -0400195 std::string *raw) noexcept {
196 new (ptr) std::unique_ptr<std::string>(raw);
197}
David Tolnay8f16ae72020-10-08 18:21:13 -0700198const std::string *cxxbridge05$unique_ptr$std$string$get(
David Tolnay7db73692019-10-20 14:51:12 -0400199 const std::unique_ptr<std::string> &ptr) noexcept {
200 return ptr.get();
201}
David Tolnay8f16ae72020-10-08 18:21:13 -0700202std::string *cxxbridge05$unique_ptr$std$string$release(
David Tolnay7db73692019-10-20 14:51:12 -0400203 std::unique_ptr<std::string> &ptr) noexcept {
204 return ptr.release();
205}
David Tolnay8f16ae72020-10-08 18:21:13 -0700206void cxxbridge05$unique_ptr$std$string$drop(
David Tolnay7db73692019-10-20 14:51:12 -0400207 std::unique_ptr<std::string> *ptr) noexcept {
208 ptr->~unique_ptr();
209}
210} // extern "C"
Myron Ahneba35cf2020-02-05 19:41:51 +0700211
David Tolnay37dd7e12020-04-25 12:51:59 -0700212#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
David Tolnay8f16ae72020-10-08 18:21:13 -0700213 size_t cxxbridge05$std$vector$##RUST_TYPE##$size( \
David Tolnay37dd7e12020-04-25 12:51:59 -0700214 const std::vector<CXX_TYPE> &s) noexcept { \
215 return s.size(); \
216 } \
David Tolnay8f16ae72020-10-08 18:21:13 -0700217 const CXX_TYPE *cxxbridge05$std$vector$##RUST_TYPE##$get_unchecked( \
David Tolnay37dd7e12020-04-25 12:51:59 -0700218 const std::vector<CXX_TYPE> &s, size_t pos) noexcept { \
David Tolnay9626d082020-04-24 14:52:45 -0700219 return &s[pos]; \
David Tolnay37dd7e12020-04-25 12:51:59 -0700220 } \
David Tolnay8f16ae72020-10-08 18:21:13 -0700221 void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$null( \
David Tolnay996db1e2020-04-24 14:46:31 -0700222 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
223 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700224 } \
David Tolnay8f16ae72020-10-08 18:21:13 -0700225 void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$raw( \
David Tolnay996db1e2020-04-24 14:46:31 -0700226 std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
David Tolnay37dd7e12020-04-25 12:51:59 -0700227 std::vector<CXX_TYPE> *raw) noexcept { \
David Tolnay996db1e2020-04-24 14:46:31 -0700228 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700229 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700230 const std::vector<CXX_TYPE> \
David Tolnay8f16ae72020-10-08 18:21:13 -0700231 *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$get( \
David Tolnay996db1e2020-04-24 14:46:31 -0700232 const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700233 return ptr.get(); \
234 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700235 std::vector<CXX_TYPE> \
David Tolnay8f16ae72020-10-08 18:21:13 -0700236 *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$release( \
David Tolnay996db1e2020-04-24 14:46:31 -0700237 std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700238 return ptr.release(); \
239 } \
David Tolnay8f16ae72020-10-08 18:21:13 -0700240 void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$drop( \
David Tolnay996db1e2020-04-24 14:46:31 -0700241 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700242 ptr->~unique_ptr(); \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700243 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700244
David Tolnay6787be62020-04-25 11:01:02 -0700245#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE) \
David Tolnay8f16ae72020-10-08 18:21:13 -0700246 void cxxbridge05$rust_vec$##RUST_TYPE##$new( \
David Tolnayf97c2d52020-04-25 16:37:48 -0700247 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay8f16ae72020-10-08 18:21:13 -0700248 void cxxbridge05$rust_vec$##RUST_TYPE##$drop( \
David Tolnay6787be62020-04-25 11:01:02 -0700249 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay8f16ae72020-10-08 18:21:13 -0700250 size_t cxxbridge05$rust_vec$##RUST_TYPE##$len( \
David Tolnay6787be62020-04-25 11:01:02 -0700251 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay8f16ae72020-10-08 18:21:13 -0700252 const CXX_TYPE *cxxbridge05$rust_vec$##RUST_TYPE##$data( \
David Tolnay6787be62020-04-25 11:01:02 -0700253 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay8f16ae72020-10-08 18:21:13 -0700254 size_t cxxbridge05$rust_vec$##RUST_TYPE##$stride() noexcept;
David Tolnay6787be62020-04-25 11:01:02 -0700255
256#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
257 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700258 Vec<CXX_TYPE>::Vec() noexcept { \
David Tolnay8f16ae72020-10-08 18:21:13 -0700259 cxxbridge05$rust_vec$##RUST_TYPE##$new(this); \
David Tolnayf97c2d52020-04-25 16:37:48 -0700260 } \
261 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700262 void Vec<CXX_TYPE>::drop() noexcept { \
David Tolnay8f16ae72020-10-08 18:21:13 -0700263 return cxxbridge05$rust_vec$##RUST_TYPE##$drop(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700264 } \
265 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700266 size_t Vec<CXX_TYPE>::size() const noexcept { \
David Tolnay8f16ae72020-10-08 18:21:13 -0700267 return cxxbridge05$rust_vec$##RUST_TYPE##$len(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700268 } \
269 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700270 const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept { \
David Tolnay8f16ae72020-10-08 18:21:13 -0700271 return cxxbridge05$rust_vec$##RUST_TYPE##$data(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700272 } \
273 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700274 size_t Vec<CXX_TYPE>::stride() noexcept { \
David Tolnay8f16ae72020-10-08 18:21:13 -0700275 return cxxbridge05$rust_vec$##RUST_TYPE##$stride(); \
David Tolnay6787be62020-04-25 11:01:02 -0700276 }
277
278// Usize and isize are the same type as one of the below.
David Tolnayf336b3b2020-04-30 08:45:54 -0700279#define FOR_EACH_NUMERIC(MACRO) \
David Tolnay6787be62020-04-25 11:01:02 -0700280 MACRO(u8, uint8_t) \
281 MACRO(u16, uint16_t) \
282 MACRO(u32, uint32_t) \
283 MACRO(u64, uint64_t) \
284 MACRO(i8, int8_t) \
285 MACRO(i16, int16_t) \
286 MACRO(i32, int32_t) \
287 MACRO(i64, int64_t) \
288 MACRO(f32, float) \
289 MACRO(f64, double)
290
David Tolnayf336b3b2020-04-30 08:45:54 -0700291#define FOR_EACH_STD_VECTOR(MACRO) \
292 FOR_EACH_NUMERIC(MACRO) \
David Tolnay6787be62020-04-25 11:01:02 -0700293 MACRO(usize, size_t) \
David Tolnay47e239d2020-08-28 00:32:04 -0700294 MACRO(isize, rust::isize) \
295 MACRO(string, std::string)
David Tolnay6787be62020-04-25 11:01:02 -0700296
David Tolnayf336b3b2020-04-30 08:45:54 -0700297#define FOR_EACH_RUST_VEC(MACRO) \
298 FOR_EACH_NUMERIC(MACRO) \
David Tolnay33f56ad2020-08-27 17:06:35 -0700299 MACRO(bool, bool) \
300 MACRO(string, rust::String)
David Tolnayf336b3b2020-04-30 08:45:54 -0700301
David Tolnay4e7e7c42020-04-24 14:48:07 -0700302extern "C" {
David Tolnayf336b3b2020-04-30 08:45:54 -0700303FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
304FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
David Tolnay4e7e7c42020-04-24 14:48:07 -0700305} // extern "C"
David Tolnay6787be62020-04-25 11:01:02 -0700306
David Tolnay1768d8f2020-04-25 18:15:11 -0700307namespace rust {
David Tolnay8f16ae72020-10-08 18:21:13 -0700308inline namespace cxxbridge05 {
David Tolnayf336b3b2020-04-30 08:45:54 -0700309FOR_EACH_RUST_VEC(RUST_VEC_OPS)
David Tolnay8f16ae72020-10-08 18:21:13 -0700310} // namespace cxxbridge05
David Tolnay1768d8f2020-04-25 18:15:11 -0700311} // namespace rust