blob: 2ff3d20c1e779445a4b47a822fdcd8ffd1c89425 [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
David Tolnay09dbe752020-03-01 13:00:40 -080034class Str final {
David Tolnay7db73692019-10-20 14:51:12 -040035public:
David Tolnay09dbe752020-03-01 13:00:40 -080036 Str() noexcept;
37 Str(const char *s);
38 Str(const std::string &s);
39 Str(std::string &&s) = delete;
40 Str(const Str &other) noexcept;
41 Str &operator=(Str other) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040042 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 };
David Tolnay09dbe752020-03-01 13:00:40 -080057 Str(Repr repr) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040058 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 Tolnay324437a2020-03-01 13:02:24 -080066template <typename T> class Box final {
David Tolnay7db73692019-10-20 14:51:12 -040067public:
David Tolnay324437a2020-03-01 13:02:24 -080068 Box(const Box &other) : Box(*other) {}
69 Box(Box &&other) noexcept : repr(other.repr) { other.repr = 0; }
70 Box(const T &val) {
David Tolnay7db73692019-10-20 14:51:12 -040071 this->uninit();
David Tolnay90838582020-02-23 00:57:03 -080072 ::new (this->deref_mut()) T(val);
David Tolnay7db73692019-10-20 14:51:12 -040073 }
David Tolnay324437a2020-03-01 13:02:24 -080074 Box &operator=(const Box &other) {
David Tolnay7db73692019-10-20 14:51:12 -040075 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 }
David Tolnay324437a2020-03-01 13:02:24 -080085 Box &operator=(Box &&other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040086 if (this->repr) {
87 this->drop();
88 }
89 this->repr = other.repr;
90 other.repr = 0;
91 return *this;
92 }
David Tolnay324437a2020-03-01 13:02:24 -080093 ~Box() noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040094 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.
David Tolnay324437a2020-03-01 13:02:24 -0800106 static Box from_raw(T *raw) noexcept {
107 Box box;
David Tolnay7db73692019-10-20 14:51:12 -0400108 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:
David Tolnay324437a2020-03-01 13:02:24 -0800119 Box() noexcept {}
David Tolnay7db73692019-10-20 14:51:12 -0400120 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 Tolnay09dbe752020-03-01 13:00:40 -0800131std::ostream &operator<<(std::ostream &os, const Str &s);
David Tolnay7db73692019-10-20 14:51:12 -0400132
David Tolnaye43b7372020-01-08 08:46:20 -0800133} // namespace cxxbridge01