blob: 5f7ac6ab3aad3987213d1434e7f061df68b01e0c [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 Tolnay56082162020-03-01 12:57:33 -080058String::String(const std::string &s) {
David Tolnay7db73692019-10-20 14:51:12 -040059 auto ptr = s.data();
60 auto len = s.length();
David Tolnay69601622020-04-29 18:48:36 -070061 if (!cxxbridge03$string$from(this, ptr, len)) {
David Tolnayce5af542020-04-10 18:08:30 -070062 panic<std::invalid_argument>("data for rust::String is not utf-8");
David Tolnay7db73692019-10-20 14:51:12 -040063 }
64}
65
David Tolnayd9c4ac92020-03-01 20:33:58 -080066String::String(const char *s) {
David Tolnaybb07a4f2020-03-16 23:04:00 -070067 auto len = std::strlen(s);
David Tolnay69601622020-04-29 18:48:36 -070068 if (!cxxbridge03$string$from(this, s, len)) {
David Tolnayce5af542020-04-10 18:08:30 -070069 panic<std::invalid_argument>("data for rust::String is not utf-8");
David Tolnayd9c4ac92020-03-01 20:33:58 -080070 }
David Tolnay7db73692019-10-20 14:51:12 -040071}
72
David Tolnay56082162020-03-01 12:57:33 -080073String &String::operator=(const String &other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040074 if (this != &other) {
David Tolnay69601622020-04-29 18:48:36 -070075 cxxbridge03$string$drop(this);
76 cxxbridge03$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -040077 }
78 return *this;
79}
80
David Tolnay56082162020-03-01 12:57:33 -080081String &String::operator=(String &&other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040082 if (this != &other) {
David Tolnay69601622020-04-29 18:48:36 -070083 cxxbridge03$string$drop(this);
David Tolnay7db73692019-10-20 14:51:12 -040084 this->repr = other.repr;
David Tolnay69601622020-04-29 18:48:36 -070085 cxxbridge03$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -040086 }
87 return *this;
88}
89
David Tolnayd9c4ac92020-03-01 20:33:58 -080090String::operator std::string() const {
91 return std::string(this->data(), this->size());
92}
93
David Tolnay56082162020-03-01 12:57:33 -080094const char *String::data() const noexcept {
David Tolnay69601622020-04-29 18:48:36 -070095 return cxxbridge03$string$ptr(this);
David Tolnay7db73692019-10-20 14:51:12 -040096}
97
David Tolnay69601622020-04-29 18:48:36 -070098size_t String::size() const noexcept { return cxxbridge03$string$len(this); }
David Tolnay7db73692019-10-20 14:51:12 -040099
David Tolnay69601622020-04-29 18:48:36 -0700100size_t String::length() const noexcept { return cxxbridge03$string$len(this); }
David Tolnay7db73692019-10-20 14:51:12 -0400101
David Tolnayd1e2efc2020-03-03 22:25:43 -0800102String::String(unsafe_bitcopy_t, const String &bits) noexcept
103 : repr(bits.repr) {}
104
David Tolnay56082162020-03-01 12:57:33 -0800105std::ostream &operator<<(std::ostream &os, const String &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400106 os.write(s.data(), s.size());
107 return os;
108}
109
David Tolnay69fe4c22020-03-01 13:57:24 -0800110Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
David Tolnay7db73692019-10-20 14:51:12 -0400111
David Tolnayd9c4ac92020-03-01 20:33:58 -0800112Str::Str(const Str &) noexcept = default;
David Tolnay7db73692019-10-20 14:51:12 -0400113
David Tolnay09dbe752020-03-01 13:00:40 -0800114Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
David Tolnay69601622020-04-29 18:48:36 -0700115 if (!cxxbridge03$str$valid(this->repr.ptr, this->repr.len)) {
David Tolnayce5af542020-04-10 18:08:30 -0700116 panic<std::invalid_argument>("data for rust::Str is not utf-8");
David Tolnay7db73692019-10-20 14:51:12 -0400117 }
118}
119
David Tolnaybb07a4f2020-03-16 23:04:00 -0700120Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
David Tolnay69601622020-04-29 18:48:36 -0700121 if (!cxxbridge03$str$valid(this->repr.ptr, this->repr.len)) {
David Tolnayce5af542020-04-10 18:08:30 -0700122 panic<std::invalid_argument>("data for rust::Str is not utf-8");
David Tolnayd9c4ac92020-03-01 20:33:58 -0800123 }
124}
David Tolnay7db73692019-10-20 14:51:12 -0400125
David Tolnay09dbe752020-03-01 13:00:40 -0800126Str &Str::operator=(Str other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400127 this->repr = other.repr;
128 return *this;
129}
130
David Tolnay09dbe752020-03-01 13:00:40 -0800131Str::operator std::string() const {
David Tolnay7db73692019-10-20 14:51:12 -0400132 return std::string(this->data(), this->size());
133}
134
David Tolnay09dbe752020-03-01 13:00:40 -0800135const char *Str::data() const noexcept { return this->repr.ptr; }
David Tolnay7db73692019-10-20 14:51:12 -0400136
David Tolnay09dbe752020-03-01 13:00:40 -0800137size_t Str::size() const noexcept { return this->repr.len; }
David Tolnay7db73692019-10-20 14:51:12 -0400138
David Tolnay09dbe752020-03-01 13:00:40 -0800139size_t Str::length() const noexcept { return this->repr.len; }
David Tolnay7db73692019-10-20 14:51:12 -0400140
David Tolnay09dbe752020-03-01 13:00:40 -0800141Str::Str(Repr repr_) noexcept : repr(repr_) {}
David Tolnay7db73692019-10-20 14:51:12 -0400142
David Tolnay09dbe752020-03-01 13:00:40 -0800143Str::operator Repr() noexcept { return this->repr; }
David Tolnay7db73692019-10-20 14:51:12 -0400144
David Tolnay09dbe752020-03-01 13:00:40 -0800145std::ostream &operator<<(std::ostream &os, const Str &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400146 os.write(s.data(), s.size());
147 return os;
148}
149
David Tolnay1e548172020-03-16 13:37:09 -0700150extern "C" {
David Tolnay69601622020-04-29 18:48:36 -0700151const char *cxxbridge03$error(const char *ptr, size_t len) {
David Tolnay1e548172020-03-16 13:37:09 -0700152 char *copy = new char[len];
153 strncpy(copy, ptr, len);
154 return copy;
155}
156} // extern "C"
157
158Error::Error(Str::Repr msg) noexcept : msg(msg) {}
159
160Error::Error(const Error &other) {
David Tolnay69601622020-04-29 18:48:36 -0700161 this->msg.ptr = cxxbridge03$error(other.msg.ptr, other.msg.len);
David Tolnay1e548172020-03-16 13:37:09 -0700162 this->msg.len = other.msg.len;
163}
164
165Error::Error(Error &&other) noexcept {
166 delete[] this->msg.ptr;
167 this->msg = other.msg;
168 other.msg.ptr = nullptr;
169 other.msg.len = 0;
170}
171
172Error::~Error() noexcept { delete[] this->msg.ptr; }
173
174const char *Error::what() const noexcept { return this->msg.ptr; }
175
David Tolnay69601622020-04-29 18:48:36 -0700176} // namespace cxxbridge03
David Tolnay750755e2020-03-01 13:04:08 -0800177} // namespace rust
David Tolnay7db73692019-10-20 14:51:12 -0400178
179extern "C" {
David Tolnay69601622020-04-29 18:48:36 -0700180void cxxbridge03$unique_ptr$std$string$null(
David Tolnay7db73692019-10-20 14:51:12 -0400181 std::unique_ptr<std::string> *ptr) noexcept {
182 new (ptr) std::unique_ptr<std::string>();
183}
David Tolnay69601622020-04-29 18:48:36 -0700184void cxxbridge03$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
David Tolnay7db73692019-10-20 14:51:12 -0400185 std::string *raw) noexcept {
186 new (ptr) std::unique_ptr<std::string>(raw);
187}
David Tolnay69601622020-04-29 18:48:36 -0700188const std::string *cxxbridge03$unique_ptr$std$string$get(
David Tolnay7db73692019-10-20 14:51:12 -0400189 const std::unique_ptr<std::string> &ptr) noexcept {
190 return ptr.get();
191}
David Tolnay69601622020-04-29 18:48:36 -0700192std::string *cxxbridge03$unique_ptr$std$string$release(
David Tolnay7db73692019-10-20 14:51:12 -0400193 std::unique_ptr<std::string> &ptr) noexcept {
194 return ptr.release();
195}
David Tolnay69601622020-04-29 18:48:36 -0700196void cxxbridge03$unique_ptr$std$string$drop(
David Tolnay7db73692019-10-20 14:51:12 -0400197 std::unique_ptr<std::string> *ptr) noexcept {
198 ptr->~unique_ptr();
199}
200} // extern "C"
Myron Ahneba35cf2020-02-05 19:41:51 +0700201
David Tolnay37dd7e12020-04-25 12:51:59 -0700202#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
David Tolnay69601622020-04-29 18:48:36 -0700203 size_t cxxbridge03$std$vector$##RUST_TYPE##$size( \
David Tolnay37dd7e12020-04-25 12:51:59 -0700204 const std::vector<CXX_TYPE> &s) noexcept { \
205 return s.size(); \
206 } \
David Tolnay69601622020-04-29 18:48:36 -0700207 const CXX_TYPE *cxxbridge03$std$vector$##RUST_TYPE##$get_unchecked( \
David Tolnay37dd7e12020-04-25 12:51:59 -0700208 const std::vector<CXX_TYPE> &s, size_t pos) noexcept { \
David Tolnay9626d082020-04-24 14:52:45 -0700209 return &s[pos]; \
David Tolnay37dd7e12020-04-25 12:51:59 -0700210 } \
David Tolnay69601622020-04-29 18:48:36 -0700211 void cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$null( \
David Tolnay996db1e2020-04-24 14:46:31 -0700212 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
213 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700214 } \
David Tolnay69601622020-04-29 18:48:36 -0700215 void cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$raw( \
David Tolnay996db1e2020-04-24 14:46:31 -0700216 std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
David Tolnay37dd7e12020-04-25 12:51:59 -0700217 std::vector<CXX_TYPE> *raw) noexcept { \
David Tolnay996db1e2020-04-24 14:46:31 -0700218 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700219 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700220 const std::vector<CXX_TYPE> \
David Tolnay69601622020-04-29 18:48:36 -0700221 *cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$get( \
David Tolnay996db1e2020-04-24 14:46:31 -0700222 const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700223 return ptr.get(); \
224 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700225 std::vector<CXX_TYPE> \
David Tolnay69601622020-04-29 18:48:36 -0700226 *cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$release( \
David Tolnay996db1e2020-04-24 14:46:31 -0700227 std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700228 return ptr.release(); \
229 } \
David Tolnay69601622020-04-29 18:48:36 -0700230 void cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$drop( \
David Tolnay996db1e2020-04-24 14:46:31 -0700231 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700232 ptr->~unique_ptr(); \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700233 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700234
David Tolnay6787be62020-04-25 11:01:02 -0700235#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE) \
David Tolnay69601622020-04-29 18:48:36 -0700236 void cxxbridge03$rust_vec$##RUST_TYPE##$new( \
David Tolnayf97c2d52020-04-25 16:37:48 -0700237 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay69601622020-04-29 18:48:36 -0700238 void cxxbridge03$rust_vec$##RUST_TYPE##$drop( \
David Tolnay6787be62020-04-25 11:01:02 -0700239 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay69601622020-04-29 18:48:36 -0700240 size_t cxxbridge03$rust_vec$##RUST_TYPE##$len( \
David Tolnay6787be62020-04-25 11:01:02 -0700241 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay69601622020-04-29 18:48:36 -0700242 const CXX_TYPE *cxxbridge03$rust_vec$##RUST_TYPE##$data( \
David Tolnay6787be62020-04-25 11:01:02 -0700243 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay69601622020-04-29 18:48:36 -0700244 size_t cxxbridge03$rust_vec$##RUST_TYPE##$stride() noexcept;
David Tolnay6787be62020-04-25 11:01:02 -0700245
246#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
247 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700248 Vec<CXX_TYPE>::Vec() noexcept { \
David Tolnay69601622020-04-29 18:48:36 -0700249 cxxbridge03$rust_vec$##RUST_TYPE##$new(this); \
David Tolnayf97c2d52020-04-25 16:37:48 -0700250 } \
251 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700252 void Vec<CXX_TYPE>::drop() noexcept { \
David Tolnay69601622020-04-29 18:48:36 -0700253 return cxxbridge03$rust_vec$##RUST_TYPE##$drop(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700254 } \
255 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700256 size_t Vec<CXX_TYPE>::size() const noexcept { \
David Tolnay69601622020-04-29 18:48:36 -0700257 return cxxbridge03$rust_vec$##RUST_TYPE##$len(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700258 } \
259 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700260 const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept { \
David Tolnay69601622020-04-29 18:48:36 -0700261 return cxxbridge03$rust_vec$##RUST_TYPE##$data(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700262 } \
263 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700264 size_t Vec<CXX_TYPE>::stride() noexcept { \
David Tolnay69601622020-04-29 18:48:36 -0700265 return cxxbridge03$rust_vec$##RUST_TYPE##$stride(); \
David Tolnay6787be62020-04-25 11:01:02 -0700266 }
267
268// Usize and isize are the same type as one of the below.
269#define FOR_EACH_SIZED_PRIMITIVE(MACRO) \
270 MACRO(u8, uint8_t) \
271 MACRO(u16, uint16_t) \
272 MACRO(u32, uint32_t) \
273 MACRO(u64, uint64_t) \
274 MACRO(i8, int8_t) \
275 MACRO(i16, int16_t) \
276 MACRO(i32, int32_t) \
277 MACRO(i64, int64_t) \
278 MACRO(f32, float) \
279 MACRO(f64, double)
280
281#define FOR_EACH_PRIMITIVE(MACRO) \
282 FOR_EACH_SIZED_PRIMITIVE(MACRO) \
283 MACRO(usize, size_t) \
284 MACRO(isize, rust::isize)
285
David Tolnay4e7e7c42020-04-24 14:48:07 -0700286extern "C" {
David Tolnay6787be62020-04-25 11:01:02 -0700287FOR_EACH_PRIMITIVE(STD_VECTOR_OPS)
288FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_EXTERNS)
David Tolnay4e7e7c42020-04-24 14:48:07 -0700289} // extern "C"
David Tolnay6787be62020-04-25 11:01:02 -0700290
David Tolnay1768d8f2020-04-25 18:15:11 -0700291namespace rust {
David Tolnay69601622020-04-29 18:48:36 -0700292inline namespace cxxbridge03 {
David Tolnay6787be62020-04-25 11:01:02 -0700293FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_OPS)
David Tolnay69601622020-04-29 18:48:36 -0700294} // namespace cxxbridge03
David Tolnay1768d8f2020-04-25 18:15:11 -0700295} // namespace rust