blob: fe2f5be73d4895f1fd474d868bf2abae5bdec8cf [file] [log] [blame]
David Tolnay7db73692019-10-20 14:51:12 -04001#pragma once
2#include <array>
3#include <cstdint>
David Tolnay001102a2020-03-01 20:05:04 -08004#include <iosfwd>
David Tolnay7db73692019-10-20 14:51:12 -04005#include <string>
David Tolnayf6292372020-03-01 21:09:11 -08006#include <type_traits>
David Tolnay7db73692019-10-20 14:51:12 -04007
David Tolnay750755e2020-03-01 13:04:08 -08008namespace rust {
9inline namespace cxxbridge01 {
David Tolnay7db73692019-10-20 14:51:12 -040010
David Tolnay56082162020-03-01 12:57:33 -080011class String final {
David Tolnay7db73692019-10-20 14:51:12 -040012public:
David Tolnay56082162020-03-01 12:57:33 -080013 String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080014 String(const String &) noexcept;
15 String(String &&) noexcept;
David Tolnay56082162020-03-01 12:57:33 -080016 ~String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080017
18 String(const std::string &);
19 String(const char *);
20
21 String &operator=(const String &) noexcept;
22 String &operator=(String &&) noexcept;
23
David Tolnay404d6892020-03-01 20:19:41 -080024 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040025
26 // Note: no null terminator.
27 const char *data() const noexcept;
28 size_t size() const noexcept;
29 size_t length() const noexcept;
30
31private:
32 // Size and alignment statically verified by rust_string.rs.
33 std::array<uintptr_t, 3> repr;
34};
35
David Tolnay09dbe752020-03-01 13:00:40 -080036class Str final {
David Tolnay7db73692019-10-20 14:51:12 -040037public:
David Tolnay09dbe752020-03-01 13:00:40 -080038 Str() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080039 Str(const Str &) noexcept;
40
David Tolnay09dbe752020-03-01 13:00:40 -080041 Str(const std::string &s);
David Tolnayd9c4ac92020-03-01 20:33:58 -080042 Str(const char *s);
David Tolnay09dbe752020-03-01 13:00:40 -080043 Str(std::string &&s) = delete;
David Tolnayd9c4ac92020-03-01 20:33:58 -080044
45 Str &operator=(Str) noexcept;
46
David Tolnay404d6892020-03-01 20:19:41 -080047 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040048
49 // Note: no null terminator.
50 const char *data() const noexcept;
51 size_t size() const noexcept;
52 size_t length() const noexcept;
53
54 // Repr is PRIVATE; must not be used other than by our generated code.
55 //
56 // Not necessarily ABI compatible with &str. Codegen will translate to
57 // cxx::rust_str::RustStr which matches this layout.
58 struct Repr {
59 const char *ptr;
60 size_t len;
61 };
David Tolnayd9c4ac92020-03-01 20:33:58 -080062 Str(Repr) noexcept;
David Tolnaybaae4432020-03-01 20:20:10 -080063 explicit operator Repr() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040064
65private:
66 Repr repr;
67};
68
David Tolnaye43b7372020-01-08 08:46:20 -080069#ifndef CXXBRIDGE01_RUST_BOX
70#define CXXBRIDGE01_RUST_BOX
David Tolnay324437a2020-03-01 13:02:24 -080071template <typename T> class Box final {
David Tolnay7db73692019-10-20 14:51:12 -040072public:
David Tolnayf6292372020-03-01 21:09:11 -080073 using value_type = T;
74 using const_pointer = std::add_pointer_t<std::add_const_t<value_type>>;
75 using pointer = std::add_pointer_t<value_type>;
76
David Tolnay324437a2020-03-01 13:02:24 -080077 Box(const Box &other) : Box(*other) {}
78 Box(Box &&other) noexcept : repr(other.repr) { other.repr = 0; }
79 Box(const T &val) {
David Tolnay7db73692019-10-20 14:51:12 -040080 this->uninit();
David Tolnay90838582020-02-23 00:57:03 -080081 ::new (this->deref_mut()) T(val);
David Tolnay7db73692019-10-20 14:51:12 -040082 }
David Tolnay324437a2020-03-01 13:02:24 -080083 Box &operator=(const Box &other) {
David Tolnay7db73692019-10-20 14:51:12 -040084 if (this != &other) {
85 if (this->repr) {
86 **this = *other;
87 } else {
88 this->uninit();
David Tolnay90838582020-02-23 00:57:03 -080089 ::new (this->deref_mut()) T(*other);
David Tolnay7db73692019-10-20 14:51:12 -040090 }
91 }
92 return *this;
93 }
David Tolnay324437a2020-03-01 13:02:24 -080094 Box &operator=(Box &&other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040095 if (this->repr) {
96 this->drop();
97 }
98 this->repr = other.repr;
99 other.repr = 0;
100 return *this;
101 }
David Tolnay324437a2020-03-01 13:02:24 -0800102 ~Box() noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400103 if (this->repr) {
104 this->drop();
105 }
106 }
107
108 const T *operator->() const noexcept { return this->deref(); }
109 const T &operator*() const noexcept { return *this->deref(); }
110 T *operator->() noexcept { return this->deref_mut(); }
111 T &operator*() noexcept { return *this->deref_mut(); }
112
113 // Important: requires that `raw` came from an into_raw call. Do not pass a
114 // pointer from `new` or any other source.
David Tolnay324437a2020-03-01 13:02:24 -0800115 static Box from_raw(T *raw) noexcept {
116 Box box;
David Tolnay7db73692019-10-20 14:51:12 -0400117 box.set_raw(raw);
118 return box;
119 }
120
121 T *into_raw() noexcept {
122 T *raw = this->deref_mut();
123 this->repr = 0;
124 return raw;
125 }
126
127private:
David Tolnay324437a2020-03-01 13:02:24 -0800128 Box() noexcept {}
David Tolnay7db73692019-10-20 14:51:12 -0400129 void uninit() noexcept;
130 void set_raw(T *) noexcept;
131 T *get_raw() noexcept;
132 void drop() noexcept;
133 const T *deref() const noexcept;
134 T *deref_mut() noexcept;
135 uintptr_t repr;
136};
David Tolnaye43b7372020-01-08 08:46:20 -0800137#endif // CXXBRIDGE01_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400138
David Tolnay56082162020-03-01 12:57:33 -0800139std::ostream &operator<<(std::ostream &os, const String &s);
David Tolnay09dbe752020-03-01 13:00:40 -0800140std::ostream &operator<<(std::ostream &os, const Str &s);
David Tolnay7db73692019-10-20 14:51:12 -0400141
David Tolnay3b0c9882020-03-01 14:08:57 -0800142// Snake case aliases for use in code that uses this style for type names.
143using string = String;
144using str = Str;
145template <class T> using box = Box<T>;
146
David Tolnay69fe4c22020-03-01 13:57:24 -0800147} // namespace cxxbridge01
David Tolnay750755e2020-03-01 13:04:08 -0800148} // namespace rust