1
+ #pragma once
2
+
3
+ // kj-rs/convert.h - Rust/C++ Interoperability Utilities for KJ
4
+ //
5
+ // This header provides seamless integration between Rust types and KJ (Cap'n Proto's C++ library)
6
+ // types, enabling efficient and safe data exchange across the language boundary.
7
+ //
8
+ // ============================================================================
9
+ // USAGE OVERVIEW
10
+ // ============================================================================
11
+ //
12
+ // Converting C++ kj arrays, strings, etc to Rust:
13
+ // - kjObject.as<Rust>() - creates zero-copy read-only Rust view
14
+ // - kjObject.as<RustMutable>() - creates zero-copy mutable Rust view
15
+ // - kjObject.as<RustCopy>() - creates owned Rust copy
16
+ //
17
+ // Converting Rust to C++ kj objects:
18
+ // - from<Rust>(rustObject) - creates zero-copy C++ view
19
+ // - from<RustCopy>(rustObject) - creates owned C++ copy
20
+ // - kj::str(rustString) - automatic conversion (via KJ_STRINGIFY)
21
+ // - kj::hashCode(rustString) - automatic hash computation (via KJ_HASHCODE)
22
+ //
23
+ // ============================================================================
24
+ // CONVERSION FUNCTIONS
25
+ // ============================================================================
26
+ //
27
+ // Zero-copy conversions from Rust to C++:
28
+ // - from<Rust>(rust::Vec<T>) -> kj::ArrayPtr<const T>
29
+ // - from<Rust>(rust::Slice<T>) -> kj::ArrayPtr<T>
30
+ // - from<Rust>(rust::String) -> kj::ArrayPtr<const char>
31
+ // - from<Rust>(rust::str) -> kj::ArrayPtr<const char>
32
+ //
33
+ // Owned conversions from Rust to C++:
34
+ // - from<RustCopy>(rust::Slice<rust::str>) -> kj::Array<kj::String>
35
+ // - from<RustCopy>(rust::Vec<rust::String>) -> kj::Array<kj::String>
36
+ //
37
+ // Zero-copy conversions from C++ to Rust (read-only):
38
+ // - kjArray.as<Rust>() -> rust::Slice<const T>
39
+ // - kjString.as<Rust>() -> rust::String
40
+ // - kjStringPtr.as<Rust>() -> rust::str
41
+ // - kjConstString.as<Rust>() -> rust::str
42
+ //
43
+ // Zero-copy conversions from C++ to Rust (mutable):
44
+ // - kjArray.as<RustMutable>() -> rust::Slice<T>
45
+ // - kjArrayPtr.as<RustMutable>() -> rust::Slice<T>
46
+ //
47
+ // Owned conversions from C++ to Rust (copying):
48
+ // - kjStringPtr.as<RustCopy>() -> rust::String
49
+ // - kjConstString.as<RustCopy>() -> rust::String
50
+ // - kjArrayPtr.as<RustCopy>() -> rust::Vec<T>
51
+ //
52
+ // Automatic conversions (via ADL):
53
+ // - kj::str(rust::String) - uses KJ_STRINGIFY for seamless string conversion
54
+ // - kj::hashCode(rust::String) - uses KJ_HASHCODE for hash computation
55
+ //
56
+ // ============================================================================
57
+ // EXAMPLES
58
+ // ============================================================================
59
+ //
60
+ // Basic usage patterns:
61
+ //
62
+ // // Convert Rust to C++:
63
+ // kj::ArrayPtr<const int> cppView = from<Rust>(rustVec);
64
+ //
65
+ // // Convert C++ to Rust (read-only):
66
+ // rust::Slice<const int> rustView = cppArray.as<Rust>();
67
+ //
68
+ // // Convert C++ to Rust (mutable):
69
+ // rust::Slice<int> rustMutableView = cppArray.as<RustMutable>();
70
+ //
71
+ // // Convert C++ to Rust (copying):
72
+ // rust::String rustOwnedStr = cppStr.as<RustCopy>();
73
+ //
74
+ // // Automatic string conversion:
75
+ // kj::String cppStr = kj::str(rustStr); // via KJ_STRINGIFY
76
+ //
77
+
78
+ #include < rust/cxx.h>
79
+
80
+ #include < kj/common.h>
81
+ #include < kj/hash.h>
82
+ #include < kj/string.h>
83
+
84
+ namespace rust {
85
+
86
+ // Automatic KJ Integration Functions - enable ADL for kj::str() and kj::hashCode()
87
+
88
+ // / Converts rust::String to kj::ArrayPtr - called by kj::str(rustString)
89
+ inline auto KJ_STRINGIFY (const ::rust::String& str) {
90
+ // HACK: rust::String is not null-terminated, so we use kj::ArrayPtr instead
91
+ // which usually acts like kj::StringPtr but does not rely on null
92
+ // termination.
93
+ return kj::ArrayPtr<const char >(str.data (), str.size ());
94
+ }
95
+
96
+ // / Converts rust::str to kj::ArrayPtr - called by kj::str(rustStr)
97
+ inline auto KJ_STRINGIFY (const ::rust::str& str) {
98
+ // HACK: rust::str is not null-terminated, so we use kj::ArrayPtr instead
99
+ // which usually acts like kj::StringPtr but does not rely on null
100
+ // termination.
101
+ return kj::ArrayPtr<const char >(str.data (), str.size ());
102
+ }
103
+
104
+ // / Hash code for rust::String - called by kj::hashCode(rustString)
105
+ inline auto KJ_HASHCODE (const ::rust::String& str) {
106
+ return kj::hashCode (kj::toCharSequence (str));
107
+ }
108
+
109
+ // / Hash code for rust::str - called by kj::hashCode(rustStr)
110
+ inline auto KJ_HASHCODE (const ::rust::str& str) {
111
+ return kj::hashCode (kj::toCharSequence (str));
112
+ }
113
+
114
+ } // namespace rust
115
+
116
+ namespace kj_rs {
117
+
118
+ // KJ to Rust conversion utilities with different ownership semantics
119
+
120
+ // / Template function for nicer syntax: from<Rust>(rustObject) instead of fromRust(rustObject)
121
+ template <typename T, typename U>
122
+ inline auto from (U&& rustObject) {
123
+ return T::into (std::forward<U>(rustObject));
124
+ }
125
+
126
+ // / Zero-copy read-only Rust views: kjObject.as<Rust>() and from<Rust>(kjObject)
127
+ struct Rust {
128
+ // / kjArrayPtr.as<Rust>() - via Rust::from(&kjArrayPtr)
129
+ template <typename T>
130
+ static ::rust::Slice<const T> from (const kj::ArrayPtr<T>* arr) {
131
+ return ::rust::Slice<const T>(arr->begin (), arr->size ());
132
+ }
133
+
134
+ // / kjArray.as<Rust>() - via Rust::from(&kjArray)
135
+ template <typename T>
136
+ static ::rust::Slice<const T> from (const kj::Array<T>* arr) {
137
+ return ::rust::Slice<const T>(arr->begin (), arr->size ());
138
+ }
139
+
140
+ // / kjString.as<Rust>() - via Rust::from(&kjString)
141
+ static ::rust::String from (const kj::String* str) {
142
+ return ::rust::String (str->begin (), str->size ());
143
+ }
144
+
145
+ // / kjStringPtr.as<Rust>() - via Rust::from(&kjStringPtr)
146
+ static ::rust::Str from (const kj::StringPtr* str) {
147
+ return ::rust::Str (str->begin (), str->size ());
148
+ }
149
+
150
+ // / kjConstString.as<Rust>() - via Rust::from(&kjConstString)
151
+ static ::rust::Str from (const kj::ConstString* str) {
152
+ return ::rust::Str (str->begin (), str->size ());
153
+ }
154
+
155
+ // into() methods for from<Rust>(rustObject) - converting Rust to KJ
156
+
157
+ // / from<Rust>(rustVec) - Zero-copy read-only view
158
+ template <typename T>
159
+ static kj::ArrayPtr<const T> into (const ::rust::Vec<T>& vec) {
160
+ return kj::ArrayPtr<const T>(vec.data (), vec.size ());
161
+ }
162
+
163
+ // / from<Rust>(rustSlice) - Zero-copy slice view
164
+ template <typename T>
165
+ static kj::ArrayPtr<T> into (const ::rust::Slice<T>& slice) {
166
+ return kj::ArrayPtr<T>(slice.data (), slice.size ());
167
+ }
168
+
169
+ // / from<Rust>(rustString) - Zero-copy string chars (not null-terminated)
170
+ static kj::ArrayPtr<const char > into (const ::rust::String& str) {
171
+ return kj::ArrayPtr<const char >(str.data (), str.size ());
172
+ }
173
+
174
+ // / from<Rust>(rustStr) - Zero-copy string slice chars (not null-terminated)
175
+ static kj::ArrayPtr<const char > into (const ::rust::Str& str) {
176
+ return kj::ArrayPtr<const char >(str.data (), str.size ());
177
+ }
178
+ };
179
+
180
+ // / Owned Rust copies: kjObject.as<RustCopy>() and from<RustCopy>(kjObject)
181
+ struct RustCopy {
182
+ // / kjStringPtr.as<RustCopy>() - via RustCopy::from(&kjStringPtr)
183
+ static ::rust::String from (const kj::StringPtr* str) {
184
+ return ::rust::String (str->begin (), str->size ());
185
+ }
186
+
187
+ // / kjConstString.as<RustCopy>() - via RustCopy::from(&kjConstString)
188
+ static ::rust::String from (const kj::ConstString* str) {
189
+ return ::rust::String (str->begin (), str->size ());
190
+ }
191
+
192
+ // / kjArrayPtr.as<RustCopy>() - via RustCopy::from(&kjArrayPtr)
193
+ template <typename T>
194
+ static ::rust::Vec<T> from (kj::ArrayPtr<const T>* arr) {
195
+ ::rust::Vec<T> result;
196
+ result.reserve (arr->size ());
197
+ for (auto & t: *arr) {
198
+ result.push_back (t);
199
+ }
200
+ return result;
201
+ }
202
+
203
+ // / from<RustCopy>(rustSliceOfStrs) - Copy slice of strs to null-terminated KJ strings
204
+ static kj::Array<kj::String> into (::rust::Slice<::rust::str> slice) {
205
+ auto res = kj::heapArrayBuilder<kj::String>(slice.size ());
206
+ for (auto & entry: slice) {
207
+ res.add (kj::str (entry));
208
+ }
209
+ return res.finish ();
210
+ }
211
+
212
+ // / from<RustCopy>(rustVecOfStrings) - Copy string vector to null-terminated KJ strings
213
+ static kj::Array<kj::String> into (const ::rust::Vec<::rust::String>& vec) {
214
+ auto res = kj::heapArrayBuilder<kj::String>(vec.size ());
215
+ for (auto & entry: vec) {
216
+ res.add (kj::str (entry));
217
+ }
218
+ return res.finish ();
219
+ }
220
+ };
221
+
222
+ // / Mutable Rust views: kjObject.as<RustMutable>() and from<RustMutable>(kjObject)
223
+ struct RustMutable {
224
+ // / kjArrayPtr.as<RustMutable>() - via RustMutable::from(&kjArrayPtr)
225
+ template <typename T>
226
+ static ::rust::Slice<T> from (kj::ArrayPtr<T>* arr) {
227
+ return ::rust::Slice<T>(arr->begin (), arr->size ());
228
+ }
229
+
230
+ // / kjArray.as<RustMutable>() - via RustMutable::from(&kjArray)
231
+ template <typename T>
232
+ static ::rust::Slice<T> from (kj::Array<T>* arr) {
233
+ return ::rust::Slice<T>(arr->begin (), arr->size ());
234
+ }
235
+ };
236
+
237
+ } // namespace kj_rs
0 commit comments