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