blob: d9be1fbc6c8b3ed5d325995d1af397013b0e85bb [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 Tolnay8c730492020-03-13 01:29:06 -070020const char *cxxbridge02$cxx_string$data(const std::string &s) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040021 return s.data();
22}
23
David Tolnay8c730492020-03-13 01:29:06 -070024size_t cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -070029void cxxbridge02$string$new(rust::String *self) noexcept;
30void cxxbridge02$string$clone(rust::String *self,
David Tolnay6c089102020-03-02 00:21:13 -080031 const rust::String &other) noexcept;
David Tolnay8c730492020-03-13 01:29:06 -070032bool cxxbridge02$string$from(rust::String *self, const char *ptr,
David Tolnay6c089102020-03-02 00:21:13 -080033 size_t len) noexcept;
David Tolnay8c730492020-03-13 01:29:06 -070034void cxxbridge02$string$drop(rust::String *self) noexcept;
35const char *cxxbridge02$string$ptr(const rust::String *self) noexcept;
36size_t cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -070039bool cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -070043inline namespace cxxbridge02 {
David Tolnay7db73692019-10-20 14:51:12 -040044
David Tolnay8c730492020-03-13 01:29:06 -070045String::String() noexcept { cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -070048 cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -070053 cxxbridge02$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -040054}
55
David Tolnay8c730492020-03-13 01:29:06 -070056String::~String() noexcept { cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -070061 if (!cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -070068 if (!cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -070075 cxxbridge02$string$drop(this);
76 cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -070083 cxxbridge02$string$drop(this);
David Tolnay7db73692019-10-20 14:51:12 -040084 this->repr = other.repr;
David Tolnay8c730492020-03-13 01:29:06 -070085 cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -070095 return cxxbridge02$string$ptr(this);
David Tolnay7db73692019-10-20 14:51:12 -040096}
97
David Tolnay8c730492020-03-13 01:29:06 -070098size_t String::size() const noexcept { return cxxbridge02$string$len(this); }
David Tolnay7db73692019-10-20 14:51:12 -040099
David Tolnay8c730492020-03-13 01:29:06 -0700100size_t String::length() const noexcept { return cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -0700115 if (!cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -0700121 if (!cxxbridge02$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" {
151const char *cxxbridge02$error(const char *ptr, size_t len) {
152 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) {
161 this->msg.ptr = cxxbridge02$error(other.msg.ptr, other.msg.len);
162 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 Tolnay8c730492020-03-13 01:29:06 -0700176} // namespace cxxbridge02
David Tolnay750755e2020-03-01 13:04:08 -0800177} // namespace rust
David Tolnay7db73692019-10-20 14:51:12 -0400178
179extern "C" {
David Tolnay8c730492020-03-13 01:29:06 -0700180void cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -0700184void cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -0700188const std::string *cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -0700192std::string *cxxbridge02$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 Tolnay8c730492020-03-13 01:29:06 -0700196void cxxbridge02$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 Tolnaya83247c2020-04-24 14:36:10 -0700203 size_t cxxbridge02$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 Tolnaydd3f6342020-04-24 14:38:55 -0700207 const CXX_TYPE &cxxbridge02$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 Tolnaydd3f6342020-04-24 14:38:55 -0700209 return s[pos]; \
David Tolnay37dd7e12020-04-25 12:51:59 -0700210 } \
David Tolnaycc75ad22020-04-24 14:45:16 -0700211 void cxxbridge02$std$vector$##RUST_TYPE##$push_back( \
212 std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept { \
213 s.push_back(item); \
214 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700215 static_assert( \
216 sizeof(std::unique_ptr<std::vector<CXX_TYPE>>) == sizeof(void *), ""); \
217 static_assert( \
218 alignof(std::unique_ptr<std::vector<CXX_TYPE>>) == alignof(void *), ""); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700219 void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$null( \
David Tolnay996db1e2020-04-24 14:46:31 -0700220 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
221 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700222 } \
223 void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$new( \
David Tolnay996db1e2020-04-24 14:46:31 -0700224 std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
David Tolnay37dd7e12020-04-25 12:51:59 -0700225 std::vector<CXX_TYPE> *value) noexcept { \
David Tolnay996db1e2020-04-24 14:46:31 -0700226 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>( \
227 new std::vector<CXX_TYPE>(std::move(*value))); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700228 } \
229 void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$raw( \
David Tolnay996db1e2020-04-24 14:46:31 -0700230 std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
David Tolnay37dd7e12020-04-25 12:51:59 -0700231 std::vector<CXX_TYPE> *raw) noexcept { \
David Tolnay996db1e2020-04-24 14:46:31 -0700232 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700233 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700234 const std::vector<CXX_TYPE> \
235 *cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$get( \
David Tolnay996db1e2020-04-24 14:46:31 -0700236 const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700237 return ptr.get(); \
238 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700239 std::vector<CXX_TYPE> \
240 *cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$release( \
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 return ptr.release(); \
243 } \
244 void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$drop( \
David Tolnay996db1e2020-04-24 14:46:31 -0700245 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700246 ptr->~unique_ptr(); \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700247 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700248
David Tolnay4e7e7c42020-04-24 14:48:07 -0700249extern "C" {
Myron Ahneba35cf2020-02-05 19:41:51 +0700250STD_VECTOR_OPS(u8, uint8_t);
251STD_VECTOR_OPS(u16, uint16_t);
252STD_VECTOR_OPS(u32, uint32_t);
253STD_VECTOR_OPS(u64, uint64_t);
254STD_VECTOR_OPS(usize, size_t);
255STD_VECTOR_OPS(i8, int8_t);
256STD_VECTOR_OPS(i16, int16_t);
257STD_VECTOR_OPS(i32, int32_t);
258STD_VECTOR_OPS(i64, int64_t);
259STD_VECTOR_OPS(isize, rust::isize);
260STD_VECTOR_OPS(f32, float);
261STD_VECTOR_OPS(f64, double);
David Tolnay4e7e7c42020-04-24 14:48:07 -0700262} // extern "C"