1 #include "../include/cxx.h"
2 #include <cassert>
3 #include <cstring>
4 #include <exception>
5 #include <iostream>
6 #include <memory>
7 #include <stdexcept>
8 #include <type_traits>
9 #include <vector>
10
11 extern "C" {
cxxbridge05$cxx_string$data(const std::string & s)12 const char *cxxbridge05$cxx_string$data(const std::string &s) noexcept {
13 return s.data();
14 }
15
cxxbridge05$cxx_string$length(const std::string & s)16 size_t cxxbridge05$cxx_string$length(const std::string &s) noexcept {
17 return s.length();
18 }
19
20 // rust::String
21 void cxxbridge05$string$new(rust::String *self) noexcept;
22 void cxxbridge05$string$clone(rust::String *self,
23 const rust::String &other) noexcept;
24 bool cxxbridge05$string$from(rust::String *self, const char *ptr,
25 size_t len) noexcept;
26 void cxxbridge05$string$drop(rust::String *self) noexcept;
27 const char *cxxbridge05$string$ptr(const rust::String *self) noexcept;
28 size_t cxxbridge05$string$len(const rust::String *self) noexcept;
29
30 // rust::Str
31 bool cxxbridge05$str$valid(const char *ptr, size_t len) noexcept;
32 } // extern "C"
33
34 namespace rust {
35 inline namespace cxxbridge05 {
36
37 template <typename Exception>
panic(const char * msg)38 void panic [[noreturn]] (const char *msg) {
39 #if defined(RUST_CXX_NO_EXCEPTIONS)
40 std::cerr << "Error: " << msg << ". Aborting." << std::endl;
41 std::terminate();
42 #else
43 throw Exception(msg);
44 #endif
45 }
46
47 template void panic<std::out_of_range>[[noreturn]] (const char *msg);
48
String()49 String::String() noexcept { cxxbridge05$string$new(this); }
50
String(const String & other)51 String::String(const String &other) noexcept {
52 cxxbridge05$string$clone(this, other);
53 }
54
String(String && other)55 String::String(String &&other) noexcept {
56 this->repr = other.repr;
57 cxxbridge05$string$new(&other);
58 }
59
~String()60 String::~String() noexcept { cxxbridge05$string$drop(this); }
61
initString(String * self,const char * s,size_t len)62 static void initString(String *self, const char *s, size_t len) {
63 if (!cxxbridge05$string$from(self, s, len)) {
64 panic<std::invalid_argument>("data for rust::String is not utf-8");
65 }
66 }
67
String(const std::string & s)68 String::String(const std::string &s) { initString(this, s.data(), s.length()); }
69
String(const char * s)70 String::String(const char *s) {
71 assert(s != nullptr);
72 initString(this, s, std::strlen(s));
73 }
74
String(const char * s,size_t len)75 String::String(const char *s, size_t len) {
76 assert(s != nullptr || len == 0);
77 initString(this,
78 s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
79 len);
80 }
81
operator =(const String & other)82 String &String::operator=(const String &other) noexcept {
83 if (this != &other) {
84 cxxbridge05$string$drop(this);
85 cxxbridge05$string$clone(this, other);
86 }
87 return *this;
88 }
89
operator =(String && other)90 String &String::operator=(String &&other) noexcept {
91 if (this != &other) {
92 cxxbridge05$string$drop(this);
93 this->repr = other.repr;
94 cxxbridge05$string$new(&other);
95 }
96 return *this;
97 }
98
operator std::string() const99 String::operator std::string() const {
100 return std::string(this->data(), this->size());
101 }
102
data() const103 const char *String::data() const noexcept {
104 return cxxbridge05$string$ptr(this);
105 }
106
size() const107 size_t String::size() const noexcept { return cxxbridge05$string$len(this); }
108
length() const109 size_t String::length() const noexcept { return cxxbridge05$string$len(this); }
110
String(unsafe_bitcopy_t,const String & bits)111 String::String(unsafe_bitcopy_t, const String &bits) noexcept
112 : repr(bits.repr) {}
113
operator <<(std::ostream & os,const String & s)114 std::ostream &operator<<(std::ostream &os, const String &s) {
115 os.write(s.data(), s.size());
116 return os;
117 }
118
Str()119 Str::Str() noexcept : ptr(reinterpret_cast<const char *>(1)), len(0) {}
120
initStr(const char * ptr,size_t len)121 static void initStr(const char *ptr, size_t len) {
122 if (!cxxbridge05$str$valid(ptr, len)) {
123 panic<std::invalid_argument>("data for rust::Str is not utf-8");
124 }
125 }
126
Str(const std::string & s)127 Str::Str(const std::string &s) : ptr(s.data()), len(s.length()) {
128 initStr(this->ptr, this->len);
129 }
130
Str(const char * s)131 Str::Str(const char *s) : ptr(s), len(std::strlen(s)) {
132 assert(s != nullptr);
133 initStr(this->ptr, this->len);
134 }
135
Str(const char * s,size_t len)136 Str::Str(const char *s, size_t len)
137 : ptr(s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s),
138 len(len) {
139 assert(s != nullptr || len == 0);
140 initStr(this->ptr, this->len);
141 }
142
operator std::string() const143 Str::operator std::string() const {
144 return std::string(this->data(), this->size());
145 }
146
operator <<(std::ostream & os,const Str & s)147 std::ostream &operator<<(std::ostream &os, const Str &s) {
148 os.write(s.data(), s.size());
149 return os;
150 }
151
152 static_assert(std::is_trivially_copy_constructible<Str>::value,
153 "trivial Str(const Str &)");
154 static_assert(std::is_trivially_copy_assignable<Str>::value,
155 "trivial operator=(const Str &)");
156 static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()");
157
158 extern "C" {
cxxbridge05$error(const char * ptr,size_t len)159 const char *cxxbridge05$error(const char *ptr, size_t len) {
160 char *copy = new char[len];
161 std::strncpy(copy, ptr, len);
162 return copy;
163 }
164 } // extern "C"
165
Error(const Error & other)166 Error::Error(const Error &other)
167 : std::exception(other), msg(cxxbridge05$error(other.msg, other.len)),
168 len(other.len) {}
169
Error(Error && other)170 Error::Error(Error &&other) noexcept
171 : std::exception(std::move(other)), msg(other.msg), len(other.len) {
172 other.msg = nullptr;
173 other.len = 0;
174 }
175
~Error()176 Error::~Error() noexcept { delete[] this->msg; }
177
operator =(const Error & other)178 Error &Error::operator=(const Error &other) {
179 if (this != &other) {
180 std::exception::operator=(other);
181 delete[] this->msg;
182 this->msg = nullptr;
183 this->msg = cxxbridge05$error(other.msg, other.len);
184 this->len = other.len;
185 }
186 return *this;
187 }
188
operator =(Error && other)189 Error &Error::operator=(Error &&other) noexcept {
190 if (this != &other) {
191 std::exception::operator=(std::move(other));
192 this->msg = other.msg;
193 this->len = other.len;
194 other.msg = nullptr;
195 other.len = 0;
196 }
197 return *this;
198 }
199
what() const200 const char *Error::what() const noexcept { return this->msg; }
201
202 } // namespace cxxbridge05
203 } // namespace rust
204
205 extern "C" {
cxxbridge05$unique_ptr$std$string$null(std::unique_ptr<std::string> * ptr)206 void cxxbridge05$unique_ptr$std$string$null(
207 std::unique_ptr<std::string> *ptr) noexcept {
208 new (ptr) std::unique_ptr<std::string>();
209 }
cxxbridge05$unique_ptr$std$string$raw(std::unique_ptr<std::string> * ptr,std::string * raw)210 void cxxbridge05$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
211 std::string *raw) noexcept {
212 new (ptr) std::unique_ptr<std::string>(raw);
213 }
cxxbridge05$unique_ptr$std$string$get(const std::unique_ptr<std::string> & ptr)214 const std::string *cxxbridge05$unique_ptr$std$string$get(
215 const std::unique_ptr<std::string> &ptr) noexcept {
216 return ptr.get();
217 }
cxxbridge05$unique_ptr$std$string$release(std::unique_ptr<std::string> & ptr)218 std::string *cxxbridge05$unique_ptr$std$string$release(
219 std::unique_ptr<std::string> &ptr) noexcept {
220 return ptr.release();
221 }
cxxbridge05$unique_ptr$std$string$drop(std::unique_ptr<std::string> * ptr)222 void cxxbridge05$unique_ptr$std$string$drop(
223 std::unique_ptr<std::string> *ptr) noexcept {
224 ptr->~unique_ptr();
225 }
226 } // extern "C"
227
228 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
229 size_t cxxbridge05$std$vector$##RUST_TYPE##$size( \
230 const std::vector<CXX_TYPE> &s) noexcept { \
231 return s.size(); \
232 } \
233 const CXX_TYPE *cxxbridge05$std$vector$##RUST_TYPE##$get_unchecked( \
234 const std::vector<CXX_TYPE> &s, size_t pos) noexcept { \
235 return &s[pos]; \
236 } \
237 void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$null( \
238 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
239 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \
240 } \
241 void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$raw( \
242 std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
243 std::vector<CXX_TYPE> *raw) noexcept { \
244 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
245 } \
246 const std::vector<CXX_TYPE> \
247 *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$get( \
248 const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
249 return ptr.get(); \
250 } \
251 std::vector<CXX_TYPE> \
252 *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$release( \
253 std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
254 return ptr.release(); \
255 } \
256 void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$drop( \
257 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
258 ptr->~unique_ptr(); \
259 }
260
261 #define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE) \
262 void cxxbridge05$rust_vec$##RUST_TYPE##$new( \
263 rust::Vec<CXX_TYPE> *ptr) noexcept; \
264 void cxxbridge05$rust_vec$##RUST_TYPE##$drop( \
265 rust::Vec<CXX_TYPE> *ptr) noexcept; \
266 size_t cxxbridge05$rust_vec$##RUST_TYPE##$len( \
267 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
268 const CXX_TYPE *cxxbridge05$rust_vec$##RUST_TYPE##$data( \
269 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
270 void cxxbridge05$rust_vec$##RUST_TYPE##$reserve_total( \
271 rust::Vec<CXX_TYPE> *ptr, size_t cap) noexcept; \
272 void cxxbridge05$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr, \
273 size_t len) noexcept; \
274 size_t cxxbridge05$rust_vec$##RUST_TYPE##$stride() noexcept;
275
276 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
277 template <> \
278 Vec<CXX_TYPE>::Vec() noexcept { \
279 cxxbridge05$rust_vec$##RUST_TYPE##$new(this); \
280 } \
281 template <> \
282 void Vec<CXX_TYPE>::drop() noexcept { \
283 return cxxbridge05$rust_vec$##RUST_TYPE##$drop(this); \
284 } \
285 template <> \
286 size_t Vec<CXX_TYPE>::size() const noexcept { \
287 return cxxbridge05$rust_vec$##RUST_TYPE##$len(this); \
288 } \
289 template <> \
290 const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept { \
291 return cxxbridge05$rust_vec$##RUST_TYPE##$data(this); \
292 } \
293 template <> \
294 void Vec<CXX_TYPE>::reserve_total(size_t cap) noexcept { \
295 cxxbridge05$rust_vec$##RUST_TYPE##$reserve_total(this, cap); \
296 } \
297 template <> \
298 void Vec<CXX_TYPE>::set_len(size_t len) noexcept { \
299 cxxbridge05$rust_vec$##RUST_TYPE##$set_len(this, len); \
300 } \
301 template <> \
302 size_t Vec<CXX_TYPE>::stride() noexcept { \
303 return cxxbridge05$rust_vec$##RUST_TYPE##$stride(); \
304 }
305
306 // Usize and isize are the same type as one of the below.
307 #define FOR_EACH_NUMERIC(MACRO) \
308 MACRO(u8, uint8_t) \
309 MACRO(u16, uint16_t) \
310 MACRO(u32, uint32_t) \
311 MACRO(u64, uint64_t) \
312 MACRO(i8, int8_t) \
313 MACRO(i16, int16_t) \
314 MACRO(i32, int32_t) \
315 MACRO(i64, int64_t) \
316 MACRO(f32, float) \
317 MACRO(f64, double)
318
319 #define FOR_EACH_STD_VECTOR(MACRO) \
320 FOR_EACH_NUMERIC(MACRO) \
321 MACRO(usize, size_t) \
322 MACRO(isize, rust::isize) \
323 MACRO(string, std::string)
324
325 #define FOR_EACH_RUST_VEC(MACRO) \
326 FOR_EACH_NUMERIC(MACRO) \
327 MACRO(bool, bool) \
328 MACRO(string, rust::String)
329
330 extern "C" {
331 FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
332 FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
333 } // extern "C"
334
335 namespace rust {
336 inline namespace cxxbridge05 {
337 FOR_EACH_RUST_VEC(RUST_VEC_OPS)
338 } // namespace cxxbridge05
339 } // namespace rust
340