blob: a668a666818869fb71760190970eb4329f3594d0 [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 Tolnay750755e2020-03-01 13:04:08 -08007namespace rust {
8inline namespace cxxbridge01 {
David Tolnay7db73692019-10-20 14:51:12 -04009
David Tolnay56082162020-03-01 12:57:33 -080010class String final {
David Tolnay7db73692019-10-20 14:51:12 -040011public:
David Tolnay56082162020-03-01 12:57:33 -080012 String() noexcept;
13 String(const String &other) noexcept;
14 String(String &&other) noexcept;
15 String(const char *s);
16 String(const std::string &s);
17 String &operator=(const String &other) noexcept;
18 String &operator=(String &&other) noexcept;
19 ~String() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040020 operator std::string() const;
21
22 // Note: no null terminator.
23 const char *data() const noexcept;
24 size_t size() const noexcept;
25 size_t length() const noexcept;
26
27private:
28 // Size and alignment statically verified by rust_string.rs.
29 std::array<uintptr_t, 3> repr;
30};
31
David Tolnay09dbe752020-03-01 13:00:40 -080032class Str final {
David Tolnay7db73692019-10-20 14:51:12 -040033public:
David Tolnay09dbe752020-03-01 13:00:40 -080034 Str() noexcept;
35 Str(const char *s);
36 Str(const std::string &s);
37 Str(std::string &&s) = delete;
38 Str(const Str &other) noexcept;
39 Str &operator=(Str other) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040040 operator std::string() const;
41
42 // Note: no null terminator.
43 const char *data() const noexcept;
44 size_t size() const noexcept;
45 size_t length() const noexcept;
46
47 // Repr is PRIVATE; must not be used other than by our generated code.
48 //
49 // Not necessarily ABI compatible with &str. Codegen will translate to
50 // cxx::rust_str::RustStr which matches this layout.
51 struct Repr {
52 const char *ptr;
53 size_t len;
54 };
David Tolnay09dbe752020-03-01 13:00:40 -080055 Str(Repr repr) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040056 operator Repr() noexcept;
57
58private:
59 Repr repr;
60};
61
David Tolnaye43b7372020-01-08 08:46:20 -080062#ifndef CXXBRIDGE01_RUST_BOX
63#define CXXBRIDGE01_RUST_BOX
David Tolnay324437a2020-03-01 13:02:24 -080064template <typename T> class Box final {
David Tolnay7db73692019-10-20 14:51:12 -040065public:
David Tolnay324437a2020-03-01 13:02:24 -080066 Box(const Box &other) : Box(*other) {}
67 Box(Box &&other) noexcept : repr(other.repr) { other.repr = 0; }
68 Box(const T &val) {
David Tolnay7db73692019-10-20 14:51:12 -040069 this->uninit();
David Tolnay90838582020-02-23 00:57:03 -080070 ::new (this->deref_mut()) T(val);
David Tolnay7db73692019-10-20 14:51:12 -040071 }
David Tolnay324437a2020-03-01 13:02:24 -080072 Box &operator=(const Box &other) {
David Tolnay7db73692019-10-20 14:51:12 -040073 if (this != &other) {
74 if (this->repr) {
75 **this = *other;
76 } else {
77 this->uninit();
David Tolnay90838582020-02-23 00:57:03 -080078 ::new (this->deref_mut()) T(*other);
David Tolnay7db73692019-10-20 14:51:12 -040079 }
80 }
81 return *this;
82 }
David Tolnay324437a2020-03-01 13:02:24 -080083 Box &operator=(Box &&other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040084 if (this->repr) {
85 this->drop();
86 }
87 this->repr = other.repr;
88 other.repr = 0;
89 return *this;
90 }
David Tolnay324437a2020-03-01 13:02:24 -080091 ~Box() noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040092 if (this->repr) {
93 this->drop();
94 }
95 }
96
97 const T *operator->() const noexcept { return this->deref(); }
98 const T &operator*() const noexcept { return *this->deref(); }
99 T *operator->() noexcept { return this->deref_mut(); }
100 T &operator*() noexcept { return *this->deref_mut(); }
101
102 // Important: requires that `raw` came from an into_raw call. Do not pass a
103 // pointer from `new` or any other source.
David Tolnay324437a2020-03-01 13:02:24 -0800104 static Box from_raw(T *raw) noexcept {
105 Box box;
David Tolnay7db73692019-10-20 14:51:12 -0400106 box.set_raw(raw);
107 return box;
108 }
109
110 T *into_raw() noexcept {
111 T *raw = this->deref_mut();
112 this->repr = 0;
113 return raw;
114 }
115
116private:
David Tolnay324437a2020-03-01 13:02:24 -0800117 Box() noexcept {}
David Tolnay7db73692019-10-20 14:51:12 -0400118 void uninit() noexcept;
119 void set_raw(T *) noexcept;
120 T *get_raw() noexcept;
121 void drop() noexcept;
122 const T *deref() const noexcept;
123 T *deref_mut() noexcept;
124 uintptr_t repr;
125};
David Tolnaye43b7372020-01-08 08:46:20 -0800126#endif // CXXBRIDGE01_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400127
David Tolnay56082162020-03-01 12:57:33 -0800128std::ostream &operator<<(std::ostream &os, const String &s);
David Tolnay09dbe752020-03-01 13:00:40 -0800129std::ostream &operator<<(std::ostream &os, const Str &s);
David Tolnay7db73692019-10-20 14:51:12 -0400130
David Tolnay750755e2020-03-01 13:04:08 -0800131} // inline namespace cxxbridge01
132} // namespace rust