blob: 0fba35c410a735b7e86187264f1ef8e786e8eab3 [file] [log] [blame]
David Tolnay736cbca2020-03-11 16:49:18 -07001#include "../include/cxx.h"
David Tolnay54b13222020-10-30 20:58:32 -07002#include <cassert>
David Tolnay7db73692019-10-20 14:51:12 -04003#include <cstring>
David Tolnay71918ec2020-04-11 21:52:09 -07004#include <exception>
David Tolnay001102a2020-03-01 20:05:04 -08005#include <iostream>
David Tolnay7db73692019-10-20 14:51:12 -04006#include <memory>
7#include <stdexcept>
David Tolnay37dd7e12020-04-25 12:51:59 -07008#include <vector>
David Tolnay7db73692019-10-20 14:51:12 -04009
David Tolnay7db73692019-10-20 14:51:12 -040010extern "C" {
David Tolnay8f16ae72020-10-08 18:21:13 -070011const char *cxxbridge05$cxx_string$data(const std::string &s) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040012 return s.data();
13}
14
David Tolnay8f16ae72020-10-08 18:21:13 -070015size_t cxxbridge05$cxx_string$length(const std::string &s) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040016 return s.length();
17}
18
David Tolnay750755e2020-03-01 13:04:08 -080019// rust::String
David Tolnay8f16ae72020-10-08 18:21:13 -070020void cxxbridge05$string$new(rust::String *self) noexcept;
21void cxxbridge05$string$clone(rust::String *self,
David Tolnay6c089102020-03-02 00:21:13 -080022 const rust::String &other) noexcept;
David Tolnay8f16ae72020-10-08 18:21:13 -070023bool cxxbridge05$string$from(rust::String *self, const char *ptr,
David Tolnay6c089102020-03-02 00:21:13 -080024 size_t len) noexcept;
David Tolnay8f16ae72020-10-08 18:21:13 -070025void cxxbridge05$string$drop(rust::String *self) noexcept;
26const char *cxxbridge05$string$ptr(const rust::String *self) noexcept;
27size_t cxxbridge05$string$len(const rust::String *self) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040028
David Tolnay750755e2020-03-01 13:04:08 -080029// rust::Str
David Tolnay8f16ae72020-10-08 18:21:13 -070030bool cxxbridge05$str$valid(const char *ptr, size_t len) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040031} // extern "C"
32
David Tolnay750755e2020-03-01 13:04:08 -080033namespace rust {
David Tolnay8f16ae72020-10-08 18:21:13 -070034inline namespace cxxbridge05 {
David Tolnay7db73692019-10-20 14:51:12 -040035
David Tolnay521d99d2020-08-26 20:45:40 -070036template <typename Exception>
37void panic [[noreturn]] (const char *msg) {
38#if defined(RUST_CXX_NO_EXCEPTIONS)
39 std::cerr << "Error: " << msg << ". Aborting." << std::endl;
40 std::terminate();
41#else
42 throw Exception(msg);
43#endif
44}
45
David Tolnayb10c4bc2020-08-26 21:55:29 -070046template void panic<std::out_of_range>[[noreturn]] (const char *msg);
David Tolnay521d99d2020-08-26 20:45:40 -070047
David Tolnay8f16ae72020-10-08 18:21:13 -070048String::String() noexcept { cxxbridge05$string$new(this); }
David Tolnay7db73692019-10-20 14:51:12 -040049
David Tolnay56082162020-03-01 12:57:33 -080050String::String(const String &other) noexcept {
David Tolnay8f16ae72020-10-08 18:21:13 -070051 cxxbridge05$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -040052}
53
David Tolnay56082162020-03-01 12:57:33 -080054String::String(String &&other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040055 this->repr = other.repr;
David Tolnay8f16ae72020-10-08 18:21:13 -070056 cxxbridge05$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -040057}
58
David Tolnay8f16ae72020-10-08 18:21:13 -070059String::~String() noexcept { cxxbridge05$string$drop(this); }
David Tolnay7db73692019-10-20 14:51:12 -040060
David Tolnay032d8532020-10-30 20:47:31 -070061static void initString(String *self, const char *s, size_t len) {
62 if (!cxxbridge05$string$from(self, s, len)) {
David Tolnay8d323662020-10-30 19:32:26 -070063 panic<std::invalid_argument>("data for rust::String is not utf-8");
64 }
65}
David Tolnay7db73692019-10-20 14:51:12 -040066
David Tolnay032d8532020-10-30 20:47:31 -070067String::String(const std::string &s) { initString(this, s.data(), s.length()); }
68
David Tolnay54b13222020-10-30 20:58:32 -070069String::String(const char *s) {
70 assert(s != nullptr);
71 initString(this, s, std::strlen(s));
72}
David Tolnayc2bbd952020-07-29 18:15:26 -070073
74String::String(const char *s, size_t len) {
David Tolnay54b13222020-10-30 20:58:32 -070075 assert(s != nullptr || len == 0);
David Tolnay032d8532020-10-30 20:47:31 -070076 initString(this,
77 s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
78 len);
David Tolnay7db73692019-10-20 14:51:12 -040079}
80
David Tolnay56082162020-03-01 12:57:33 -080081String &String::operator=(const String &other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040082 if (this != &other) {
David Tolnay8f16ae72020-10-08 18:21:13 -070083 cxxbridge05$string$drop(this);
84 cxxbridge05$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -040085 }
86 return *this;
87}
88
David Tolnay56082162020-03-01 12:57:33 -080089String &String::operator=(String &&other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040090 if (this != &other) {
David Tolnay8f16ae72020-10-08 18:21:13 -070091 cxxbridge05$string$drop(this);
David Tolnay7db73692019-10-20 14:51:12 -040092 this->repr = other.repr;
David Tolnay8f16ae72020-10-08 18:21:13 -070093 cxxbridge05$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -040094 }
95 return *this;
96}
97
David Tolnayd9c4ac92020-03-01 20:33:58 -080098String::operator std::string() const {
99 return std::string(this->data(), this->size());
100}
101
David Tolnay56082162020-03-01 12:57:33 -0800102const char *String::data() const noexcept {
David Tolnay8f16ae72020-10-08 18:21:13 -0700103 return cxxbridge05$string$ptr(this);
David Tolnay7db73692019-10-20 14:51:12 -0400104}
105
David Tolnay8f16ae72020-10-08 18:21:13 -0700106size_t String::size() const noexcept { return cxxbridge05$string$len(this); }
David Tolnay7db73692019-10-20 14:51:12 -0400107
David Tolnay8f16ae72020-10-08 18:21:13 -0700108size_t String::length() const noexcept { return cxxbridge05$string$len(this); }
David Tolnay7db73692019-10-20 14:51:12 -0400109
David Tolnayd1e2efc2020-03-03 22:25:43 -0800110String::String(unsafe_bitcopy_t, const String &bits) noexcept
111 : repr(bits.repr) {}
112
David Tolnay56082162020-03-01 12:57:33 -0800113std::ostream &operator<<(std::ostream &os, const String &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400114 os.write(s.data(), s.size());
115 return os;
116}
117
David Tolnay8d323662020-10-30 19:32:26 -0700118Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(1), 0}) {}
David Tolnay7db73692019-10-20 14:51:12 -0400119
David Tolnay032d8532020-10-30 20:47:31 -0700120static void initStr(Str::Repr repr) {
121 if (!cxxbridge05$str$valid(repr.ptr, repr.len)) {
David Tolnay8d323662020-10-30 19:32:26 -0700122 panic<std::invalid_argument>("data for rust::Str is not utf-8");
123 }
124}
David Tolnay7db73692019-10-20 14:51:12 -0400125
David Tolnay032d8532020-10-30 20:47:31 -0700126Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
127 initStr(this->repr);
David Tolnay8d323662020-10-30 19:32:26 -0700128}
David Tolnay894c5e42020-07-29 18:20:00 -0700129
David Tolnay54b13222020-10-30 20:58:32 -0700130Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
131 assert(s != nullptr);
132 initStr(this->repr);
133}
David Tolnay032d8532020-10-30 20:47:31 -0700134
David Tolnay8d323662020-10-30 19:32:26 -0700135Str::Str(const char *s, size_t len)
136 : repr(
137 Repr{s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
138 len}) {
David Tolnay54b13222020-10-30 20:58:32 -0700139 assert(s != nullptr || len == 0);
David Tolnay032d8532020-10-30 20:47:31 -0700140 initStr(this->repr);
David Tolnayd9c4ac92020-03-01 20:33:58 -0800141}
David Tolnay7db73692019-10-20 14:51:12 -0400142
David Tolnay09dbe752020-03-01 13:00:40 -0800143Str &Str::operator=(Str other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400144 this->repr = other.repr;
145 return *this;
146}
147
David Tolnay09dbe752020-03-01 13:00:40 -0800148Str::operator std::string() const {
David Tolnay7db73692019-10-20 14:51:12 -0400149 return std::string(this->data(), this->size());
150}
151
David Tolnay09dbe752020-03-01 13:00:40 -0800152const char *Str::data() const noexcept { return this->repr.ptr; }
David Tolnay7db73692019-10-20 14:51:12 -0400153
David Tolnay09dbe752020-03-01 13:00:40 -0800154size_t Str::size() const noexcept { return this->repr.len; }
David Tolnay7db73692019-10-20 14:51:12 -0400155
David Tolnay09dbe752020-03-01 13:00:40 -0800156size_t Str::length() const noexcept { return this->repr.len; }
David Tolnay7db73692019-10-20 14:51:12 -0400157
David Tolnay09dbe752020-03-01 13:00:40 -0800158Str::Str(Repr repr_) noexcept : repr(repr_) {}
David Tolnay7db73692019-10-20 14:51:12 -0400159
David Tolnaycedcde12020-10-31 11:47:14 -0700160Str::operator Repr() const noexcept { return this->repr; }
David Tolnay7db73692019-10-20 14:51:12 -0400161
David Tolnay09dbe752020-03-01 13:00:40 -0800162std::ostream &operator<<(std::ostream &os, const Str &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400163 os.write(s.data(), s.size());
164 return os;
165}
166
David Tolnay1e548172020-03-16 13:37:09 -0700167extern "C" {
David Tolnay8f16ae72020-10-08 18:21:13 -0700168const char *cxxbridge05$error(const char *ptr, size_t len) {
David Tolnay1e548172020-03-16 13:37:09 -0700169 char *copy = new char[len];
David Tolnay504cf3c2020-10-31 16:08:04 -0700170 std::strncpy(copy, ptr, len);
David Tolnay1e548172020-03-16 13:37:09 -0700171 return copy;
172}
173} // extern "C"
174
David Tolnayd5712ee2020-10-31 17:10:00 -0700175Error::Error(const Error &other)
David Tolnay23c23192020-10-31 17:11:48 -0700176 : std::exception(other), msg(cxxbridge05$error(other.msg, other.len)),
177 len(other.len) {}
David Tolnay1e548172020-03-16 13:37:09 -0700178
David Tolnay23c23192020-10-31 17:11:48 -0700179Error::Error(Error &&other) noexcept
180 : std::exception(std::move(other)), msg(other.msg), len(other.len) {
David Tolnaya0c9bc72020-10-31 14:37:14 -0700181 other.msg = nullptr;
182 other.len = 0;
David Tolnay1e548172020-03-16 13:37:09 -0700183}
184
David Tolnaya0c9bc72020-10-31 14:37:14 -0700185Error::~Error() noexcept { delete[] this->msg; }
David Tolnay1e548172020-03-16 13:37:09 -0700186
David Tolnaya0c9bc72020-10-31 14:37:14 -0700187const char *Error::what() const noexcept { return this->msg; }
David Tolnay1e548172020-03-16 13:37:09 -0700188
David Tolnay8f16ae72020-10-08 18:21:13 -0700189} // namespace cxxbridge05
David Tolnay750755e2020-03-01 13:04:08 -0800190} // namespace rust
David Tolnay7db73692019-10-20 14:51:12 -0400191
192extern "C" {
David Tolnay8f16ae72020-10-08 18:21:13 -0700193void cxxbridge05$unique_ptr$std$string$null(
David Tolnay7db73692019-10-20 14:51:12 -0400194 std::unique_ptr<std::string> *ptr) noexcept {
195 new (ptr) std::unique_ptr<std::string>();
196}
David Tolnay8f16ae72020-10-08 18:21:13 -0700197void cxxbridge05$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
David Tolnay7db73692019-10-20 14:51:12 -0400198 std::string *raw) noexcept {
199 new (ptr) std::unique_ptr<std::string>(raw);
200}
David Tolnay8f16ae72020-10-08 18:21:13 -0700201const std::string *cxxbridge05$unique_ptr$std$string$get(
David Tolnay7db73692019-10-20 14:51:12 -0400202 const std::unique_ptr<std::string> &ptr) noexcept {
203 return ptr.get();
204}
David Tolnay8f16ae72020-10-08 18:21:13 -0700205std::string *cxxbridge05$unique_ptr$std$string$release(
David Tolnay7db73692019-10-20 14:51:12 -0400206 std::unique_ptr<std::string> &ptr) noexcept {
207 return ptr.release();
208}
David Tolnay8f16ae72020-10-08 18:21:13 -0700209void cxxbridge05$unique_ptr$std$string$drop(
David Tolnay7db73692019-10-20 14:51:12 -0400210 std::unique_ptr<std::string> *ptr) noexcept {
211 ptr->~unique_ptr();
212}
213} // extern "C"
Myron Ahneba35cf2020-02-05 19:41:51 +0700214
David Tolnay37dd7e12020-04-25 12:51:59 -0700215#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
David Tolnay8f16ae72020-10-08 18:21:13 -0700216 size_t cxxbridge05$std$vector$##RUST_TYPE##$size( \
David Tolnay37dd7e12020-04-25 12:51:59 -0700217 const std::vector<CXX_TYPE> &s) noexcept { \
218 return s.size(); \
219 } \
David Tolnay8f16ae72020-10-08 18:21:13 -0700220 const CXX_TYPE *cxxbridge05$std$vector$##RUST_TYPE##$get_unchecked( \
David Tolnay37dd7e12020-04-25 12:51:59 -0700221 const std::vector<CXX_TYPE> &s, size_t pos) noexcept { \
David Tolnay9626d082020-04-24 14:52:45 -0700222 return &s[pos]; \
David Tolnay37dd7e12020-04-25 12:51:59 -0700223 } \
David Tolnay8f16ae72020-10-08 18:21:13 -0700224 void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$null( \
David Tolnay996db1e2020-04-24 14:46:31 -0700225 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
226 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700227 } \
David Tolnay8f16ae72020-10-08 18:21:13 -0700228 void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$raw( \
David Tolnay996db1e2020-04-24 14:46:31 -0700229 std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
David Tolnay37dd7e12020-04-25 12:51:59 -0700230 std::vector<CXX_TYPE> *raw) noexcept { \
David Tolnay996db1e2020-04-24 14:46:31 -0700231 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700232 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700233 const std::vector<CXX_TYPE> \
David Tolnay8f16ae72020-10-08 18:21:13 -0700234 *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$get( \
David Tolnay996db1e2020-04-24 14:46:31 -0700235 const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700236 return ptr.get(); \
237 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700238 std::vector<CXX_TYPE> \
David Tolnay8f16ae72020-10-08 18:21:13 -0700239 *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$release( \
David Tolnay996db1e2020-04-24 14:46:31 -0700240 std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700241 return ptr.release(); \
242 } \
David Tolnay8f16ae72020-10-08 18:21:13 -0700243 void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$drop( \
David Tolnay996db1e2020-04-24 14:46:31 -0700244 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700245 ptr->~unique_ptr(); \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700246 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700247
David Tolnay6787be62020-04-25 11:01:02 -0700248#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE) \
David Tolnay8f16ae72020-10-08 18:21:13 -0700249 void cxxbridge05$rust_vec$##RUST_TYPE##$new( \
David Tolnayf97c2d52020-04-25 16:37:48 -0700250 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay8f16ae72020-10-08 18:21:13 -0700251 void cxxbridge05$rust_vec$##RUST_TYPE##$drop( \
David Tolnay6787be62020-04-25 11:01:02 -0700252 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay8f16ae72020-10-08 18:21:13 -0700253 size_t cxxbridge05$rust_vec$##RUST_TYPE##$len( \
David Tolnay6787be62020-04-25 11:01:02 -0700254 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay8f16ae72020-10-08 18:21:13 -0700255 const CXX_TYPE *cxxbridge05$rust_vec$##RUST_TYPE##$data( \
David Tolnay6787be62020-04-25 11:01:02 -0700256 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay8f16ae72020-10-08 18:21:13 -0700257 size_t cxxbridge05$rust_vec$##RUST_TYPE##$stride() noexcept;
David Tolnay6787be62020-04-25 11:01:02 -0700258
259#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
260 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700261 Vec<CXX_TYPE>::Vec() noexcept { \
David Tolnay8f16ae72020-10-08 18:21:13 -0700262 cxxbridge05$rust_vec$##RUST_TYPE##$new(this); \
David Tolnayf97c2d52020-04-25 16:37:48 -0700263 } \
264 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700265 void Vec<CXX_TYPE>::drop() noexcept { \
David Tolnay8f16ae72020-10-08 18:21:13 -0700266 return cxxbridge05$rust_vec$##RUST_TYPE##$drop(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700267 } \
268 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700269 size_t Vec<CXX_TYPE>::size() const noexcept { \
David Tolnay8f16ae72020-10-08 18:21:13 -0700270 return cxxbridge05$rust_vec$##RUST_TYPE##$len(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700271 } \
272 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700273 const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept { \
David Tolnay8f16ae72020-10-08 18:21:13 -0700274 return cxxbridge05$rust_vec$##RUST_TYPE##$data(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700275 } \
276 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700277 size_t Vec<CXX_TYPE>::stride() noexcept { \
David Tolnay8f16ae72020-10-08 18:21:13 -0700278 return cxxbridge05$rust_vec$##RUST_TYPE##$stride(); \
David Tolnay6787be62020-04-25 11:01:02 -0700279 }
280
281// Usize and isize are the same type as one of the below.
David Tolnayf336b3b2020-04-30 08:45:54 -0700282#define FOR_EACH_NUMERIC(MACRO) \
David Tolnay6787be62020-04-25 11:01:02 -0700283 MACRO(u8, uint8_t) \
284 MACRO(u16, uint16_t) \
285 MACRO(u32, uint32_t) \
286 MACRO(u64, uint64_t) \
287 MACRO(i8, int8_t) \
288 MACRO(i16, int16_t) \
289 MACRO(i32, int32_t) \
290 MACRO(i64, int64_t) \
291 MACRO(f32, float) \
292 MACRO(f64, double)
293
David Tolnayf336b3b2020-04-30 08:45:54 -0700294#define FOR_EACH_STD_VECTOR(MACRO) \
295 FOR_EACH_NUMERIC(MACRO) \
David Tolnay6787be62020-04-25 11:01:02 -0700296 MACRO(usize, size_t) \
David Tolnay47e239d2020-08-28 00:32:04 -0700297 MACRO(isize, rust::isize) \
298 MACRO(string, std::string)
David Tolnay6787be62020-04-25 11:01:02 -0700299
David Tolnayf336b3b2020-04-30 08:45:54 -0700300#define FOR_EACH_RUST_VEC(MACRO) \
301 FOR_EACH_NUMERIC(MACRO) \
David Tolnay33f56ad2020-08-27 17:06:35 -0700302 MACRO(bool, bool) \
303 MACRO(string, rust::String)
David Tolnayf336b3b2020-04-30 08:45:54 -0700304
David Tolnay4e7e7c42020-04-24 14:48:07 -0700305extern "C" {
David Tolnayf336b3b2020-04-30 08:45:54 -0700306FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
307FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
David Tolnay4e7e7c42020-04-24 14:48:07 -0700308} // extern "C"
David Tolnay6787be62020-04-25 11:01:02 -0700309
David Tolnay1768d8f2020-04-25 18:15:11 -0700310namespace rust {
David Tolnay8f16ae72020-10-08 18:21:13 -0700311inline namespace cxxbridge05 {
David Tolnayf336b3b2020-04-30 08:45:54 -0700312FOR_EACH_RUST_VEC(RUST_VEC_OPS)
David Tolnay8f16ae72020-10-08 18:21:13 -0700313} // namespace cxxbridge05
David Tolnay1768d8f2020-04-25 18:15:11 -0700314} // namespace rust