blob: d0cf8c2ed507e3d634dd19d88e4ef67567ae432b [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;
David Tolnay9f921372020-03-01 21:09:25 -080074 using const_pointer = typename std::add_pointer<
75 typename std::add_const<value_type>::type>::type;
76 using pointer = typename std::add_pointer<value_type>::type;
David Tolnayf6292372020-03-01 21:09:11 -080077
David Tolnay324437a2020-03-01 13:02:24 -080078 Box(const Box &other) : Box(*other) {}
79 Box(Box &&other) noexcept : repr(other.repr) { other.repr = 0; }
80 Box(const T &val) {
David Tolnay7db73692019-10-20 14:51:12 -040081 this->uninit();
David Tolnay90838582020-02-23 00:57:03 -080082 ::new (this->deref_mut()) T(val);
David Tolnay7db73692019-10-20 14:51:12 -040083 }
David Tolnay324437a2020-03-01 13:02:24 -080084 Box &operator=(const Box &other) {
David Tolnay7db73692019-10-20 14:51:12 -040085 if (this != &other) {
86 if (this->repr) {
87 **this = *other;
88 } else {
89 this->uninit();
David Tolnay90838582020-02-23 00:57:03 -080090 ::new (this->deref_mut()) T(*other);
David Tolnay7db73692019-10-20 14:51:12 -040091 }
92 }
93 return *this;
94 }
David Tolnay324437a2020-03-01 13:02:24 -080095 Box &operator=(Box &&other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040096 if (this->repr) {
97 this->drop();
98 }
99 this->repr = other.repr;
100 other.repr = 0;
101 return *this;
102 }
David Tolnay324437a2020-03-01 13:02:24 -0800103 ~Box() noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400104 if (this->repr) {
105 this->drop();
106 }
107 }
108
109 const T *operator->() const noexcept { return this->deref(); }
110 const T &operator*() const noexcept { return *this->deref(); }
111 T *operator->() noexcept { return this->deref_mut(); }
112 T &operator*() noexcept { return *this->deref_mut(); }
113
114 // Important: requires that `raw` came from an into_raw call. Do not pass a
115 // pointer from `new` or any other source.
David Tolnay324437a2020-03-01 13:02:24 -0800116 static Box from_raw(T *raw) noexcept {
117 Box box;
David Tolnay7db73692019-10-20 14:51:12 -0400118 box.set_raw(raw);
119 return box;
120 }
121
122 T *into_raw() noexcept {
123 T *raw = this->deref_mut();
124 this->repr = 0;
125 return raw;
126 }
127
128private:
David Tolnay324437a2020-03-01 13:02:24 -0800129 Box() noexcept {}
David Tolnay7db73692019-10-20 14:51:12 -0400130 void uninit() noexcept;
131 void set_raw(T *) noexcept;
132 T *get_raw() noexcept;
133 void drop() noexcept;
134 const T *deref() const noexcept;
135 T *deref_mut() noexcept;
136 uintptr_t repr;
137};
David Tolnaye43b7372020-01-08 08:46:20 -0800138#endif // CXXBRIDGE01_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400139
David Tolnay56082162020-03-01 12:57:33 -0800140std::ostream &operator<<(std::ostream &os, const String &s);
David Tolnay09dbe752020-03-01 13:00:40 -0800141std::ostream &operator<<(std::ostream &os, const Str &s);
David Tolnay7db73692019-10-20 14:51:12 -0400142
David Tolnay3b0c9882020-03-01 14:08:57 -0800143// Snake case aliases for use in code that uses this style for type names.
144using string = String;
145using str = Str;
146template <class T> using box = Box<T>;
147
David Tolnay69fe4c22020-03-01 13:57:24 -0800148} // namespace cxxbridge01
David Tolnay750755e2020-03-01 13:04:08 -0800149} // namespace rust