blob: 395ec1873f5623644145b8889a3b234528f44275 [file] [log] [blame]
David Tolnay7db73692019-10-20 14:51:12 -04001#pragma once
2#include <array>
3#include <cstdint>
4#include <iostream>
5#include <string>
6
David Tolnay649337e2020-02-25 18:11:16 -08007namespace cxxbridge01 {}
8namespace cxxbridge = cxxbridge01;
9
David Tolnaye43b7372020-01-08 08:46:20 -080010namespace cxxbridge01 {
David Tolnay7db73692019-10-20 14:51:12 -040011
David Tolnay56082162020-03-01 12:57:33 -080012class String final {
David Tolnay7db73692019-10-20 14:51:12 -040013public:
David Tolnay56082162020-03-01 12:57:33 -080014 String() noexcept;
15 String(const String &other) noexcept;
16 String(String &&other) noexcept;
17 String(const char *s);
18 String(const std::string &s);
19 String &operator=(const String &other) noexcept;
20 String &operator=(String &&other) noexcept;
21 ~String() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040022 operator std::string() const;
23
24 // Note: no null terminator.
25 const char *data() const noexcept;
26 size_t size() const noexcept;
27 size_t length() const noexcept;
28
29private:
30 // Size and alignment statically verified by rust_string.rs.
31 std::array<uintptr_t, 3> repr;
32};
33
34class RustStr final {
35public:
36 RustStr() noexcept;
37 RustStr(const char *s);
38 RustStr(const std::string &s);
39 RustStr(std::string &&s) = delete;
40 RustStr(const RustStr &other) noexcept;
41 RustStr &operator=(RustStr other) noexcept;
42 operator std::string() const;
43
44 // Note: no null terminator.
45 const char *data() const noexcept;
46 size_t size() const noexcept;
47 size_t length() const noexcept;
48
49 // Repr is PRIVATE; must not be used other than by our generated code.
50 //
51 // Not necessarily ABI compatible with &str. Codegen will translate to
52 // cxx::rust_str::RustStr which matches this layout.
53 struct Repr {
54 const char *ptr;
55 size_t len;
56 };
57 RustStr(Repr repr) noexcept;
58 operator Repr() noexcept;
59
60private:
61 Repr repr;
62};
63
David Tolnaye43b7372020-01-08 08:46:20 -080064#ifndef CXXBRIDGE01_RUST_BOX
65#define CXXBRIDGE01_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -040066template <typename T> class RustBox final {
67public:
68 RustBox(const RustBox &other) : RustBox(*other) {}
69 RustBox(RustBox &&other) noexcept : repr(other.repr) { other.repr = 0; }
70 RustBox(const T &val) {
71 this->uninit();
David Tolnay90838582020-02-23 00:57:03 -080072 ::new (this->deref_mut()) T(val);
David Tolnay7db73692019-10-20 14:51:12 -040073 }
74 RustBox &operator=(const RustBox &other) {
75 if (this != &other) {
76 if (this->repr) {
77 **this = *other;
78 } else {
79 this->uninit();
David Tolnay90838582020-02-23 00:57:03 -080080 ::new (this->deref_mut()) T(*other);
David Tolnay7db73692019-10-20 14:51:12 -040081 }
82 }
83 return *this;
84 }
85 RustBox &operator=(RustBox &&other) noexcept {
86 if (this->repr) {
87 this->drop();
88 }
89 this->repr = other.repr;
90 other.repr = 0;
91 return *this;
92 }
93 ~RustBox() noexcept {
94 if (this->repr) {
95 this->drop();
96 }
97 }
98
99 const T *operator->() const noexcept { return this->deref(); }
100 const T &operator*() const noexcept { return *this->deref(); }
101 T *operator->() noexcept { return this->deref_mut(); }
102 T &operator*() noexcept { return *this->deref_mut(); }
103
104 // Important: requires that `raw` came from an into_raw call. Do not pass a
105 // pointer from `new` or any other source.
106 static RustBox from_raw(T *raw) noexcept {
107 RustBox box;
108 box.set_raw(raw);
109 return box;
110 }
111
112 T *into_raw() noexcept {
113 T *raw = this->deref_mut();
114 this->repr = 0;
115 return raw;
116 }
117
118private:
119 RustBox() noexcept {}
120 void uninit() noexcept;
121 void set_raw(T *) noexcept;
122 T *get_raw() noexcept;
123 void drop() noexcept;
124 const T *deref() const noexcept;
125 T *deref_mut() noexcept;
126 uintptr_t repr;
127};
David Tolnaye43b7372020-01-08 08:46:20 -0800128#endif // CXXBRIDGE01_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400129
David Tolnay56082162020-03-01 12:57:33 -0800130std::ostream &operator<<(std::ostream &os, const String &s);
David Tolnay7db73692019-10-20 14:51:12 -0400131std::ostream &operator<<(std::ostream &os, const RustStr &s);
132
David Tolnaye43b7372020-01-08 08:46:20 -0800133} // namespace cxxbridge01