Mercurial > hg > sv-dependency-builds
comparison osx/include/capnp/any.h @ 49:3ab5a40c4e3b
Add Capnp and KJ builds for OSX
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 25 Oct 2016 14:48:23 +0100 |
parents | |
children | 0994c39f1e94 |
comparison
equal
deleted
inserted
replaced
48:9530b331f8c1 | 49:3ab5a40c4e3b |
---|---|
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors | |
2 // Licensed under the MIT License: | |
3 // | |
4 // Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 // of this software and associated documentation files (the "Software"), to deal | |
6 // in the Software without restriction, including without limitation the rights | |
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 // copies of the Software, and to permit persons to whom the Software is | |
9 // furnished to do so, subject to the following conditions: | |
10 // | |
11 // The above copyright notice and this permission notice shall be included in | |
12 // all copies or substantial portions of the Software. | |
13 // | |
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
20 // THE SOFTWARE. | |
21 | |
22 #ifndef CAPNP_ANY_H_ | |
23 #define CAPNP_ANY_H_ | |
24 | |
25 #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) | |
26 #pragma GCC system_header | |
27 #endif | |
28 | |
29 #include "layout.h" | |
30 #include "pointer-helpers.h" | |
31 #include "orphan.h" | |
32 #include "list.h" | |
33 | |
34 namespace capnp { | |
35 | |
36 class StructSchema; | |
37 class ListSchema; | |
38 class InterfaceSchema; | |
39 class Orphanage; | |
40 class ClientHook; | |
41 class PipelineHook; | |
42 struct PipelineOp; | |
43 struct AnyPointer; | |
44 | |
45 struct AnyList { | |
46 AnyList() = delete; | |
47 | |
48 class Reader; | |
49 class Builder; | |
50 }; | |
51 | |
52 struct AnyStruct { | |
53 AnyStruct() = delete; | |
54 | |
55 class Reader; | |
56 class Builder; | |
57 class Pipeline; | |
58 }; | |
59 | |
60 template<> | |
61 struct List<AnyStruct, Kind::OTHER> { | |
62 List() = delete; | |
63 | |
64 class Reader; | |
65 class Builder; | |
66 }; | |
67 | |
68 namespace _ { // private | |
69 template <> struct Kind_<AnyPointer> { static constexpr Kind kind = Kind::OTHER; }; | |
70 template <> struct Kind_<AnyStruct> { static constexpr Kind kind = Kind::OTHER; }; | |
71 template <> struct Kind_<AnyList> { static constexpr Kind kind = Kind::OTHER; }; | |
72 } // namespace _ (private) | |
73 | |
74 // ======================================================================================= | |
75 // AnyPointer! | |
76 | |
77 enum class Equality { | |
78 NOT_EQUAL, | |
79 EQUAL, | |
80 UNKNOWN_CONTAINS_CAPS | |
81 }; | |
82 | |
83 kj::StringPtr KJ_STRINGIFY(Equality res); | |
84 | |
85 struct AnyPointer { | |
86 // Reader/Builder for the `AnyPointer` field type, i.e. a pointer that can point to an arbitrary | |
87 // object. | |
88 | |
89 AnyPointer() = delete; | |
90 | |
91 class Reader { | |
92 public: | |
93 typedef AnyPointer Reads; | |
94 | |
95 Reader() = default; | |
96 inline Reader(_::PointerReader reader): reader(reader) {} | |
97 | |
98 inline MessageSize targetSize() const; | |
99 // Get the total size of the target object and all its children. | |
100 | |
101 inline PointerType getPointerType() const; | |
102 | |
103 inline bool isNull() const { return getPointerType() == PointerType::NULL_; } | |
104 inline bool isStruct() const { return getPointerType() == PointerType::STRUCT; } | |
105 inline bool isList() const { return getPointerType() == PointerType::LIST; } | |
106 inline bool isCapability() const { return getPointerType() == PointerType::CAPABILITY; } | |
107 | |
108 Equality equals(AnyPointer::Reader right); | |
109 bool operator==(AnyPointer::Reader right); | |
110 inline bool operator!=(AnyPointer::Reader right) { | |
111 return !(*this == right); | |
112 } | |
113 | |
114 template <typename T> | |
115 inline ReaderFor<T> getAs() const; | |
116 // Valid for T = any generated struct type, interface type, List<U>, Text, or Data. | |
117 | |
118 template <typename T> | |
119 inline ReaderFor<T> getAs(StructSchema schema) const; | |
120 // Only valid for T = DynamicStruct. Requires `#include <capnp/dynamic.h>`. | |
121 | |
122 template <typename T> | |
123 inline ReaderFor<T> getAs(ListSchema schema) const; | |
124 // Only valid for T = DynamicList. Requires `#include <capnp/dynamic.h>`. | |
125 | |
126 template <typename T> | |
127 inline ReaderFor<T> getAs(InterfaceSchema schema) const; | |
128 // Only valid for T = DynamicCapability. Requires `#include <capnp/dynamic.h>`. | |
129 | |
130 #if !CAPNP_LITE | |
131 kj::Own<ClientHook> getPipelinedCap(kj::ArrayPtr<const PipelineOp> ops) const; | |
132 // Used by RPC system to implement pipelining. Applications generally shouldn't use this | |
133 // directly. | |
134 #endif // !CAPNP_LITE | |
135 | |
136 private: | |
137 _::PointerReader reader; | |
138 friend struct AnyPointer; | |
139 friend class Orphanage; | |
140 friend class CapReaderContext; | |
141 friend struct _::PointerHelpers<AnyPointer>; | |
142 }; | |
143 | |
144 class Builder { | |
145 public: | |
146 typedef AnyPointer Builds; | |
147 | |
148 Builder() = delete; | |
149 inline Builder(decltype(nullptr)) {} | |
150 inline Builder(_::PointerBuilder builder): builder(builder) {} | |
151 | |
152 inline MessageSize targetSize() const; | |
153 // Get the total size of the target object and all its children. | |
154 | |
155 inline PointerType getPointerType(); | |
156 | |
157 inline bool isNull() { return getPointerType() == PointerType::NULL_; } | |
158 inline bool isStruct() { return getPointerType() == PointerType::STRUCT; } | |
159 inline bool isList() { return getPointerType() == PointerType::LIST; } | |
160 inline bool isCapability() { return getPointerType() == PointerType::CAPABILITY; } | |
161 | |
162 inline Equality equals(AnyPointer::Reader right) { | |
163 return asReader().equals(right); | |
164 } | |
165 inline bool operator==(AnyPointer::Reader right) { | |
166 return asReader() == right; | |
167 } | |
168 inline bool operator!=(AnyPointer::Reader right) { | |
169 return !(*this == right); | |
170 } | |
171 | |
172 inline void clear(); | |
173 // Set to null. | |
174 | |
175 template <typename T> | |
176 inline BuilderFor<T> getAs(); | |
177 // Valid for T = any generated struct type, List<U>, Text, or Data. | |
178 | |
179 template <typename T> | |
180 inline BuilderFor<T> getAs(StructSchema schema); | |
181 // Only valid for T = DynamicStruct. Requires `#include <capnp/dynamic.h>`. | |
182 | |
183 template <typename T> | |
184 inline BuilderFor<T> getAs(ListSchema schema); | |
185 // Only valid for T = DynamicList. Requires `#include <capnp/dynamic.h>`. | |
186 | |
187 template <typename T> | |
188 inline BuilderFor<T> getAs(InterfaceSchema schema); | |
189 // Only valid for T = DynamicCapability. Requires `#include <capnp/dynamic.h>`. | |
190 | |
191 template <typename T> | |
192 inline BuilderFor<T> initAs(); | |
193 // Valid for T = any generated struct type. | |
194 | |
195 template <typename T> | |
196 inline BuilderFor<T> initAs(uint elementCount); | |
197 // Valid for T = List<U>, Text, or Data. | |
198 | |
199 template <typename T> | |
200 inline BuilderFor<T> initAs(StructSchema schema); | |
201 // Only valid for T = DynamicStruct. Requires `#include <capnp/dynamic.h>`. | |
202 | |
203 template <typename T> | |
204 inline BuilderFor<T> initAs(ListSchema schema, uint elementCount); | |
205 // Only valid for T = DynamicList. Requires `#include <capnp/dynamic.h>`. | |
206 | |
207 inline AnyList::Builder initAsAnyList(ElementSize elementSize, uint elementCount); | |
208 // Note: Does not accept INLINE_COMPOSITE for elementSize. | |
209 | |
210 inline List<AnyStruct>::Builder initAsListOfAnyStruct( | |
211 uint dataWordCount, uint pointerCount, uint elementCount); | |
212 | |
213 inline AnyStruct::Builder initAsAnyStruct(uint dataWordCount, uint pointerCount); | |
214 | |
215 template <typename T> | |
216 inline void setAs(ReaderFor<T> value); | |
217 // Valid for ReaderType = T::Reader for T = any generated struct type, List<U>, Text, Data, | |
218 // DynamicStruct, or DynamicList (the dynamic types require `#include <capnp/dynamic.h>`). | |
219 | |
220 template <typename T> | |
221 inline void setAs(std::initializer_list<ReaderFor<ListElementType<T>>> list); | |
222 // Valid for T = List<?>. | |
223 | |
224 template <typename T> | |
225 inline void setCanonicalAs(ReaderFor<T> value); | |
226 | |
227 inline void set(Reader value) { builder.copyFrom(value.reader); } | |
228 // Set to a copy of another AnyPointer. | |
229 | |
230 inline void setCanonical(Reader value) { builder.copyFrom(value.reader, true); } | |
231 | |
232 template <typename T> | |
233 inline void adopt(Orphan<T>&& orphan); | |
234 // Valid for T = any generated struct type, List<U>, Text, Data, DynamicList, DynamicStruct, | |
235 // or DynamicValue (the dynamic types require `#include <capnp/dynamic.h>`). | |
236 | |
237 template <typename T> | |
238 inline Orphan<T> disownAs(); | |
239 // Valid for T = any generated struct type, List<U>, Text, Data. | |
240 | |
241 template <typename T> | |
242 inline Orphan<T> disownAs(StructSchema schema); | |
243 // Only valid for T = DynamicStruct. Requires `#include <capnp/dynamic.h>`. | |
244 | |
245 template <typename T> | |
246 inline Orphan<T> disownAs(ListSchema schema); | |
247 // Only valid for T = DynamicList. Requires `#include <capnp/dynamic.h>`. | |
248 | |
249 template <typename T> | |
250 inline Orphan<T> disownAs(InterfaceSchema schema); | |
251 // Only valid for T = DynamicCapability. Requires `#include <capnp/dynamic.h>`. | |
252 | |
253 inline Orphan<AnyPointer> disown(); | |
254 // Disown without a type. | |
255 | |
256 inline Reader asReader() const { return Reader(builder.asReader()); } | |
257 inline operator Reader() const { return Reader(builder.asReader()); } | |
258 | |
259 private: | |
260 _::PointerBuilder builder; | |
261 friend class Orphanage; | |
262 friend class CapBuilderContext; | |
263 friend struct _::PointerHelpers<AnyPointer>; | |
264 }; | |
265 | |
266 #if !CAPNP_LITE | |
267 class Pipeline { | |
268 public: | |
269 typedef AnyPointer Pipelines; | |
270 | |
271 inline Pipeline(decltype(nullptr)) {} | |
272 inline explicit Pipeline(kj::Own<PipelineHook>&& hook): hook(kj::mv(hook)) {} | |
273 | |
274 Pipeline noop(); | |
275 // Just make a copy. | |
276 | |
277 Pipeline getPointerField(uint16_t pointerIndex); | |
278 // Deprecated. In the future, we should use .asAnyStruct.getPointerField. | |
279 | |
280 inline AnyStruct::Pipeline asAnyStruct(); | |
281 | |
282 kj::Own<ClientHook> asCap(); | |
283 // Expect that the result is a capability and construct a pipelined version of it now. | |
284 | |
285 inline kj::Own<PipelineHook> releasePipelineHook() { return kj::mv(hook); } | |
286 // For use by RPC implementations. | |
287 | |
288 template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromClient<T>) == Kind::INTERFACE>> | |
289 inline operator T() { return T(asCap()); } | |
290 | |
291 private: | |
292 kj::Own<PipelineHook> hook; | |
293 kj::Array<PipelineOp> ops; | |
294 | |
295 inline Pipeline(kj::Own<PipelineHook>&& hook, kj::Array<PipelineOp>&& ops) | |
296 : hook(kj::mv(hook)), ops(kj::mv(ops)) {} | |
297 | |
298 friend class LocalClient; | |
299 friend class PipelineHook; | |
300 friend class AnyStruct::Pipeline; | |
301 }; | |
302 #endif // !CAPNP_LITE | |
303 }; | |
304 | |
305 template <> | |
306 class Orphan<AnyPointer> { | |
307 // An orphaned object of unknown type. | |
308 | |
309 public: | |
310 Orphan() = default; | |
311 KJ_DISALLOW_COPY(Orphan); | |
312 Orphan(Orphan&&) = default; | |
313 inline Orphan(_::OrphanBuilder&& builder) | |
314 : builder(kj::mv(builder)) {} | |
315 | |
316 Orphan& operator=(Orphan&&) = default; | |
317 | |
318 template <typename T> | |
319 inline Orphan(Orphan<T>&& other): builder(kj::mv(other.builder)) {} | |
320 template <typename T> | |
321 inline Orphan& operator=(Orphan<T>&& other) { builder = kj::mv(other.builder); return *this; } | |
322 // Cast from typed orphan. | |
323 | |
324 // It's not possible to get an AnyPointer::{Reader,Builder} directly since there is no | |
325 // underlying pointer (the pointer would normally live in the parent, but this object is | |
326 // orphaned). It is possible, however, to request typed readers/builders. | |
327 | |
328 template <typename T> | |
329 inline BuilderFor<T> getAs(); | |
330 template <typename T> | |
331 inline BuilderFor<T> getAs(StructSchema schema); | |
332 template <typename T> | |
333 inline BuilderFor<T> getAs(ListSchema schema); | |
334 template <typename T> | |
335 inline typename T::Client getAs(InterfaceSchema schema); | |
336 template <typename T> | |
337 inline ReaderFor<T> getAsReader() const; | |
338 template <typename T> | |
339 inline ReaderFor<T> getAsReader(StructSchema schema) const; | |
340 template <typename T> | |
341 inline ReaderFor<T> getAsReader(ListSchema schema) const; | |
342 template <typename T> | |
343 inline typename T::Client getAsReader(InterfaceSchema schema) const; | |
344 | |
345 template <typename T> | |
346 inline Orphan<T> releaseAs(); | |
347 template <typename T> | |
348 inline Orphan<T> releaseAs(StructSchema schema); | |
349 template <typename T> | |
350 inline Orphan<T> releaseAs(ListSchema schema); | |
351 template <typename T> | |
352 inline Orphan<T> releaseAs(InterfaceSchema schema); | |
353 // Down-cast the orphan to a specific type. | |
354 | |
355 inline bool operator==(decltype(nullptr)) const { return builder == nullptr; } | |
356 inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; } | |
357 | |
358 private: | |
359 _::OrphanBuilder builder; | |
360 | |
361 template <typename, Kind> | |
362 friend struct _::PointerHelpers; | |
363 friend class Orphanage; | |
364 template <typename U> | |
365 friend class Orphan; | |
366 friend class AnyPointer::Builder; | |
367 }; | |
368 | |
369 template <Kind k> struct AnyTypeFor_; | |
370 template <> struct AnyTypeFor_<Kind::STRUCT> { typedef AnyStruct Type; }; | |
371 template <> struct AnyTypeFor_<Kind::LIST> { typedef AnyList Type; }; | |
372 | |
373 template <typename T> | |
374 using AnyTypeFor = typename AnyTypeFor_<CAPNP_KIND(T)>::Type; | |
375 | |
376 template <typename T> | |
377 inline ReaderFor<AnyTypeFor<FromReader<T>>> toAny(T&& value) { | |
378 return ReaderFor<AnyTypeFor<FromReader<T>>>( | |
379 _::PointerHelpers<FromReader<T>>::getInternalReader(value)); | |
380 } | |
381 template <typename T> | |
382 inline BuilderFor<AnyTypeFor<FromBuilder<T>>> toAny(T&& value) { | |
383 return BuilderFor<AnyTypeFor<FromBuilder<T>>>( | |
384 _::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::mv(value))); | |
385 } | |
386 | |
387 template <> | |
388 struct List<AnyPointer, Kind::OTHER> { | |
389 // Note: This cannot be used for a list of structs, since such lists are not encoded as pointer | |
390 // lists! Use List<AnyStruct>. | |
391 | |
392 List() = delete; | |
393 | |
394 class Reader { | |
395 public: | |
396 typedef List<AnyPointer> Reads; | |
397 | |
398 inline Reader(): reader(ElementSize::POINTER) {} | |
399 inline explicit Reader(_::ListReader reader): reader(reader) {} | |
400 | |
401 inline uint size() const { return reader.size() / ELEMENTS; } | |
402 inline AnyPointer::Reader operator[](uint index) const { | |
403 KJ_IREQUIRE(index < size()); | |
404 return AnyPointer::Reader(reader.getPointerElement(index * ELEMENTS)); | |
405 } | |
406 | |
407 typedef _::IndexingIterator<const Reader, typename AnyPointer::Reader> Iterator; | |
408 inline Iterator begin() const { return Iterator(this, 0); } | |
409 inline Iterator end() const { return Iterator(this, size()); } | |
410 | |
411 private: | |
412 _::ListReader reader; | |
413 template <typename U, Kind K> | |
414 friend struct _::PointerHelpers; | |
415 template <typename U, Kind K> | |
416 friend struct List; | |
417 friend class Orphanage; | |
418 template <typename U, Kind K> | |
419 friend struct ToDynamic_; | |
420 }; | |
421 | |
422 class Builder { | |
423 public: | |
424 typedef List<AnyPointer> Builds; | |
425 | |
426 Builder() = delete; | |
427 inline Builder(decltype(nullptr)): builder(ElementSize::POINTER) {} | |
428 inline explicit Builder(_::ListBuilder builder): builder(builder) {} | |
429 | |
430 inline operator Reader() const { return Reader(builder.asReader()); } | |
431 inline Reader asReader() const { return Reader(builder.asReader()); } | |
432 | |
433 inline uint size() const { return builder.size() / ELEMENTS; } | |
434 inline AnyPointer::Builder operator[](uint index) { | |
435 KJ_IREQUIRE(index < size()); | |
436 return AnyPointer::Builder(builder.getPointerElement(index * ELEMENTS)); | |
437 } | |
438 | |
439 typedef _::IndexingIterator<Builder, typename AnyPointer::Builder> Iterator; | |
440 inline Iterator begin() { return Iterator(this, 0); } | |
441 inline Iterator end() { return Iterator(this, size()); } | |
442 | |
443 private: | |
444 _::ListBuilder builder; | |
445 template <typename, Kind> | |
446 friend struct _::PointerHelpers; | |
447 friend class Orphanage; | |
448 template <typename, Kind> | |
449 friend struct ToDynamic_; | |
450 }; | |
451 }; | |
452 | |
453 class AnyStruct::Reader { | |
454 public: | |
455 typedef AnyStruct Reads; | |
456 | |
457 Reader() = default; | |
458 inline Reader(_::StructReader reader): _reader(reader) {} | |
459 | |
460 template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromReader<T>) == Kind::STRUCT>> | |
461 inline Reader(T&& value) | |
462 : _reader(_::PointerHelpers<FromReader<T>>::getInternalReader(kj::fwd<T>(value))) {} | |
463 | |
464 kj::ArrayPtr<const byte> getDataSection() { | |
465 return _reader.getDataSectionAsBlob(); | |
466 } | |
467 List<AnyPointer>::Reader getPointerSection() { | |
468 return List<AnyPointer>::Reader(_reader.getPointerSectionAsList()); | |
469 } | |
470 | |
471 kj::Array<word> canonicalize() { | |
472 return _reader.canonicalize(); | |
473 } | |
474 | |
475 Equality equals(AnyStruct::Reader right); | |
476 bool operator==(AnyStruct::Reader right); | |
477 inline bool operator!=(AnyStruct::Reader right) { | |
478 return !(*this == right); | |
479 } | |
480 | |
481 template <typename T> | |
482 ReaderFor<T> as() const { | |
483 // T must be a struct type. | |
484 return typename T::Reader(_reader); | |
485 } | |
486 private: | |
487 _::StructReader _reader; | |
488 | |
489 template <typename, Kind> | |
490 friend struct _::PointerHelpers; | |
491 friend class Orphanage; | |
492 }; | |
493 | |
494 class AnyStruct::Builder { | |
495 public: | |
496 typedef AnyStruct Builds; | |
497 | |
498 inline Builder(decltype(nullptr)) {} | |
499 inline Builder(_::StructBuilder builder): _builder(builder) {} | |
500 | |
501 #if !_MSC_VER // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves. | |
502 template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromBuilder<T>) == Kind::STRUCT>> | |
503 inline Builder(T&& value) | |
504 : _builder(_::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::fwd<T>(value))) {} | |
505 #endif | |
506 | |
507 inline kj::ArrayPtr<byte> getDataSection() { | |
508 return _builder.getDataSectionAsBlob(); | |
509 } | |
510 List<AnyPointer>::Builder getPointerSection() { | |
511 return List<AnyPointer>::Builder(_builder.getPointerSectionAsList()); | |
512 } | |
513 | |
514 inline Equality equals(AnyStruct::Reader right) { | |
515 return asReader().equals(right); | |
516 } | |
517 inline bool operator==(AnyStruct::Reader right) { | |
518 return asReader() == right; | |
519 } | |
520 inline bool operator!=(AnyStruct::Reader right) { | |
521 return !(*this == right); | |
522 } | |
523 | |
524 inline operator Reader() const { return Reader(_builder.asReader()); } | |
525 inline Reader asReader() const { return Reader(_builder.asReader()); } | |
526 | |
527 template <typename T> | |
528 BuilderFor<T> as() { | |
529 // T must be a struct type. | |
530 return typename T::Builder(_builder); | |
531 } | |
532 private: | |
533 _::StructBuilder _builder; | |
534 friend class Orphanage; | |
535 friend class CapBuilderContext; | |
536 }; | |
537 | |
538 #if !CAPNP_LITE | |
539 class AnyStruct::Pipeline { | |
540 public: | |
541 inline Pipeline(decltype(nullptr)): typeless(nullptr) {} | |
542 inline explicit Pipeline(AnyPointer::Pipeline&& typeless) | |
543 : typeless(kj::mv(typeless)) {} | |
544 | |
545 inline AnyPointer::Pipeline getPointerField(uint16_t pointerIndex) { | |
546 // Return a new Promise representing a sub-object of the result. `pointerIndex` is the index | |
547 // of the sub-object within the pointer section of the result (the result must be a struct). | |
548 // | |
549 // TODO(perf): On GCC 4.8 / Clang 3.3, use rvalue qualifiers to avoid the need for copies. | |
550 // Also make `ops` into a Vector to optimize this. | |
551 return typeless.getPointerField(pointerIndex); | |
552 } | |
553 | |
554 private: | |
555 AnyPointer::Pipeline typeless; | |
556 }; | |
557 #endif // !CAPNP_LITE | |
558 | |
559 class List<AnyStruct, Kind::OTHER>::Reader { | |
560 public: | |
561 typedef List<AnyStruct> Reads; | |
562 | |
563 inline Reader(): reader(ElementSize::INLINE_COMPOSITE) {} | |
564 inline explicit Reader(_::ListReader reader): reader(reader) {} | |
565 | |
566 inline uint size() const { return reader.size() / ELEMENTS; } | |
567 inline AnyStruct::Reader operator[](uint index) const { | |
568 KJ_IREQUIRE(index < size()); | |
569 return AnyStruct::Reader(reader.getStructElement(index * ELEMENTS)); | |
570 } | |
571 | |
572 typedef _::IndexingIterator<const Reader, typename AnyStruct::Reader> Iterator; | |
573 inline Iterator begin() const { return Iterator(this, 0); } | |
574 inline Iterator end() const { return Iterator(this, size()); } | |
575 | |
576 private: | |
577 _::ListReader reader; | |
578 template <typename U, Kind K> | |
579 friend struct _::PointerHelpers; | |
580 template <typename U, Kind K> | |
581 friend struct List; | |
582 friend class Orphanage; | |
583 template <typename U, Kind K> | |
584 friend struct ToDynamic_; | |
585 }; | |
586 | |
587 class List<AnyStruct, Kind::OTHER>::Builder { | |
588 public: | |
589 typedef List<AnyStruct> Builds; | |
590 | |
591 Builder() = delete; | |
592 inline Builder(decltype(nullptr)): builder(ElementSize::INLINE_COMPOSITE) {} | |
593 inline explicit Builder(_::ListBuilder builder): builder(builder) {} | |
594 | |
595 inline operator Reader() const { return Reader(builder.asReader()); } | |
596 inline Reader asReader() const { return Reader(builder.asReader()); } | |
597 | |
598 inline uint size() const { return builder.size() / ELEMENTS; } | |
599 inline AnyStruct::Builder operator[](uint index) { | |
600 KJ_IREQUIRE(index < size()); | |
601 return AnyStruct::Builder(builder.getStructElement(index * ELEMENTS)); | |
602 } | |
603 | |
604 typedef _::IndexingIterator<Builder, typename AnyStruct::Builder> Iterator; | |
605 inline Iterator begin() { return Iterator(this, 0); } | |
606 inline Iterator end() { return Iterator(this, size()); } | |
607 | |
608 private: | |
609 _::ListBuilder builder; | |
610 template <typename U, Kind K> | |
611 friend struct _::PointerHelpers; | |
612 friend class Orphanage; | |
613 template <typename U, Kind K> | |
614 friend struct ToDynamic_; | |
615 }; | |
616 | |
617 class AnyList::Reader { | |
618 public: | |
619 typedef AnyList Reads; | |
620 | |
621 inline Reader(): _reader(ElementSize::VOID) {} | |
622 inline Reader(_::ListReader reader): _reader(reader) {} | |
623 | |
624 #if !_MSC_VER // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves. | |
625 template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromReader<T>) == Kind::LIST>> | |
626 inline Reader(T&& value) | |
627 : _reader(_::PointerHelpers<FromReader<T>>::getInternalReader(kj::fwd<T>(value))) {} | |
628 #endif | |
629 | |
630 inline ElementSize getElementSize() { return _reader.getElementSize(); } | |
631 inline uint size() { return _reader.size() / ELEMENTS; } | |
632 | |
633 inline kj::ArrayPtr<const byte> getRawBytes() { return _reader.asRawBytes(); } | |
634 | |
635 Equality equals(AnyList::Reader right); | |
636 bool operator==(AnyList::Reader right); | |
637 inline bool operator!=(AnyList::Reader right) { | |
638 return !(*this == right); | |
639 } | |
640 | |
641 template <typename T> ReaderFor<T> as() { | |
642 // T must be List<U>. | |
643 return ReaderFor<T>(_reader); | |
644 } | |
645 private: | |
646 _::ListReader _reader; | |
647 | |
648 template <typename, Kind> | |
649 friend struct _::PointerHelpers; | |
650 friend class Orphanage; | |
651 }; | |
652 | |
653 class AnyList::Builder { | |
654 public: | |
655 typedef AnyList Builds; | |
656 | |
657 inline Builder(decltype(nullptr)): _builder(ElementSize::VOID) {} | |
658 inline Builder(_::ListBuilder builder): _builder(builder) {} | |
659 | |
660 #if !_MSC_VER // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves. | |
661 template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromBuilder<T>) == Kind::LIST>> | |
662 inline Builder(T&& value) | |
663 : _builder(_::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::fwd<T>(value))) {} | |
664 #endif | |
665 | |
666 inline ElementSize getElementSize() { return _builder.getElementSize(); } | |
667 inline uint size() { return _builder.size() / ELEMENTS; } | |
668 | |
669 Equality equals(AnyList::Reader right); | |
670 inline bool operator==(AnyList::Reader right) { | |
671 return asReader() == right; | |
672 } | |
673 inline bool operator!=(AnyList::Reader right) { | |
674 return !(*this == right); | |
675 } | |
676 | |
677 template <typename T> BuilderFor<T> as() { | |
678 // T must be List<U>. | |
679 return BuilderFor<T>(_builder); | |
680 } | |
681 | |
682 inline operator Reader() const { return Reader(_builder.asReader()); } | |
683 inline Reader asReader() const { return Reader(_builder.asReader()); } | |
684 | |
685 private: | |
686 _::ListBuilder _builder; | |
687 | |
688 friend class Orphanage; | |
689 }; | |
690 | |
691 // ======================================================================================= | |
692 // Pipeline helpers | |
693 // | |
694 // These relate to capabilities, but we don't declare them in capability.h because generated code | |
695 // for structs needs to know about these, even in files that contain no interfaces. | |
696 | |
697 #if !CAPNP_LITE | |
698 | |
699 struct PipelineOp { | |
700 // Corresponds to rpc.capnp's PromisedAnswer.Op. | |
701 | |
702 enum Type { | |
703 NOOP, // for convenience | |
704 | |
705 GET_POINTER_FIELD | |
706 | |
707 // There may be other types in the future... | |
708 }; | |
709 | |
710 Type type; | |
711 union { | |
712 uint16_t pointerIndex; // for GET_POINTER_FIELD | |
713 }; | |
714 }; | |
715 | |
716 class PipelineHook { | |
717 // Represents a currently-running call, and implements pipelined requests on its result. | |
718 | |
719 public: | |
720 virtual kj::Own<PipelineHook> addRef() = 0; | |
721 // Increment this object's reference count. | |
722 | |
723 virtual kj::Own<ClientHook> getPipelinedCap(kj::ArrayPtr<const PipelineOp> ops) = 0; | |
724 // Extract a promised Capability from the results. | |
725 | |
726 virtual kj::Own<ClientHook> getPipelinedCap(kj::Array<PipelineOp>&& ops); | |
727 // Version of getPipelinedCap() passing the array by move. May avoid a copy in some cases. | |
728 // Default implementation just calls the other version. | |
729 | |
730 template <typename Pipeline, typename = FromPipeline<Pipeline>> | |
731 static inline kj::Own<PipelineHook> from(Pipeline&& pipeline); | |
732 | |
733 private: | |
734 template <typename T> struct FromImpl; | |
735 }; | |
736 | |
737 #endif // !CAPNP_LITE | |
738 | |
739 // ======================================================================================= | |
740 // Inline implementation details | |
741 | |
742 inline MessageSize AnyPointer::Reader::targetSize() const { | |
743 return reader.targetSize().asPublic(); | |
744 } | |
745 | |
746 inline PointerType AnyPointer::Reader::getPointerType() const { | |
747 return reader.getPointerType(); | |
748 } | |
749 | |
750 template <typename T> | |
751 inline ReaderFor<T> AnyPointer::Reader::getAs() const { | |
752 return _::PointerHelpers<T>::get(reader); | |
753 } | |
754 | |
755 inline MessageSize AnyPointer::Builder::targetSize() const { | |
756 return asReader().targetSize(); | |
757 } | |
758 | |
759 inline PointerType AnyPointer::Builder::getPointerType() { | |
760 return builder.getPointerType(); | |
761 } | |
762 | |
763 inline void AnyPointer::Builder::clear() { | |
764 return builder.clear(); | |
765 } | |
766 | |
767 template <typename T> | |
768 inline BuilderFor<T> AnyPointer::Builder::getAs() { | |
769 return _::PointerHelpers<T>::get(builder); | |
770 } | |
771 | |
772 template <typename T> | |
773 inline BuilderFor<T> AnyPointer::Builder::initAs() { | |
774 return _::PointerHelpers<T>::init(builder); | |
775 } | |
776 | |
777 template <typename T> | |
778 inline BuilderFor<T> AnyPointer::Builder::initAs(uint elementCount) { | |
779 return _::PointerHelpers<T>::init(builder, elementCount); | |
780 } | |
781 | |
782 inline AnyList::Builder AnyPointer::Builder::initAsAnyList( | |
783 ElementSize elementSize, uint elementCount) { | |
784 return AnyList::Builder(builder.initList(elementSize, elementCount * ELEMENTS)); | |
785 } | |
786 | |
787 inline List<AnyStruct>::Builder AnyPointer::Builder::initAsListOfAnyStruct( | |
788 uint dataWordCount, uint pointerCount, uint elementCount) { | |
789 return List<AnyStruct>::Builder(builder.initStructList(elementCount * ELEMENTS, | |
790 _::StructSize(dataWordCount * WORDS, pointerCount * POINTERS))); | |
791 } | |
792 | |
793 inline AnyStruct::Builder AnyPointer::Builder::initAsAnyStruct(uint dataWordCount, uint pointerCount) { | |
794 return AnyStruct::Builder(builder.initStruct( | |
795 _::StructSize(dataWordCount * WORDS, pointerCount * POINTERS))); | |
796 } | |
797 | |
798 template <typename T> | |
799 inline void AnyPointer::Builder::setAs(ReaderFor<T> value) { | |
800 return _::PointerHelpers<T>::set(builder, value); | |
801 } | |
802 | |
803 template <typename T> | |
804 inline void AnyPointer::Builder::setCanonicalAs(ReaderFor<T> value) { | |
805 return _::PointerHelpers<T>::setCanonical(builder, value); | |
806 } | |
807 | |
808 template <typename T> | |
809 inline void AnyPointer::Builder::setAs( | |
810 std::initializer_list<ReaderFor<ListElementType<T>>> list) { | |
811 return _::PointerHelpers<T>::set(builder, list); | |
812 } | |
813 | |
814 template <typename T> | |
815 inline void AnyPointer::Builder::adopt(Orphan<T>&& orphan) { | |
816 _::PointerHelpers<T>::adopt(builder, kj::mv(orphan)); | |
817 } | |
818 | |
819 template <typename T> | |
820 inline Orphan<T> AnyPointer::Builder::disownAs() { | |
821 return _::PointerHelpers<T>::disown(builder); | |
822 } | |
823 | |
824 inline Orphan<AnyPointer> AnyPointer::Builder::disown() { | |
825 return Orphan<AnyPointer>(builder.disown()); | |
826 } | |
827 | |
828 template <> struct ReaderFor_ <AnyPointer, Kind::OTHER> { typedef AnyPointer::Reader Type; }; | |
829 template <> struct BuilderFor_<AnyPointer, Kind::OTHER> { typedef AnyPointer::Builder Type; }; | |
830 template <> struct ReaderFor_ <AnyStruct, Kind::OTHER> { typedef AnyStruct::Reader Type; }; | |
831 template <> struct BuilderFor_<AnyStruct, Kind::OTHER> { typedef AnyStruct::Builder Type; }; | |
832 | |
833 template <> | |
834 struct Orphanage::GetInnerReader<AnyPointer, Kind::OTHER> { | |
835 static inline _::PointerReader apply(const AnyPointer::Reader& t) { | |
836 return t.reader; | |
837 } | |
838 }; | |
839 | |
840 template <> | |
841 struct Orphanage::GetInnerBuilder<AnyPointer, Kind::OTHER> { | |
842 static inline _::PointerBuilder apply(AnyPointer::Builder& t) { | |
843 return t.builder; | |
844 } | |
845 }; | |
846 | |
847 template <> | |
848 struct Orphanage::GetInnerReader<AnyStruct, Kind::OTHER> { | |
849 static inline _::StructReader apply(const AnyStruct::Reader& t) { | |
850 return t._reader; | |
851 } | |
852 }; | |
853 | |
854 template <> | |
855 struct Orphanage::GetInnerBuilder<AnyStruct, Kind::OTHER> { | |
856 static inline _::StructBuilder apply(AnyStruct::Builder& t) { | |
857 return t._builder; | |
858 } | |
859 }; | |
860 | |
861 template <> | |
862 struct Orphanage::GetInnerReader<AnyList, Kind::OTHER> { | |
863 static inline _::ListReader apply(const AnyList::Reader& t) { | |
864 return t._reader; | |
865 } | |
866 }; | |
867 | |
868 template <> | |
869 struct Orphanage::GetInnerBuilder<AnyList, Kind::OTHER> { | |
870 static inline _::ListBuilder apply(AnyList::Builder& t) { | |
871 return t._builder; | |
872 } | |
873 }; | |
874 | |
875 template <typename T> | |
876 inline BuilderFor<T> Orphan<AnyPointer>::getAs() { | |
877 return _::OrphanGetImpl<T>::apply(builder); | |
878 } | |
879 template <typename T> | |
880 inline ReaderFor<T> Orphan<AnyPointer>::getAsReader() const { | |
881 return _::OrphanGetImpl<T>::applyReader(builder); | |
882 } | |
883 template <typename T> | |
884 inline Orphan<T> Orphan<AnyPointer>::releaseAs() { | |
885 return Orphan<T>(kj::mv(builder)); | |
886 } | |
887 | |
888 // Using AnyPointer as the template type should work... | |
889 | |
890 template <> | |
891 inline typename AnyPointer::Reader AnyPointer::Reader::getAs<AnyPointer>() const { | |
892 return *this; | |
893 } | |
894 template <> | |
895 inline typename AnyPointer::Builder AnyPointer::Builder::getAs<AnyPointer>() { | |
896 return *this; | |
897 } | |
898 template <> | |
899 inline typename AnyPointer::Builder AnyPointer::Builder::initAs<AnyPointer>() { | |
900 clear(); | |
901 return *this; | |
902 } | |
903 template <> | |
904 inline void AnyPointer::Builder::setAs<AnyPointer>(AnyPointer::Reader value) { | |
905 return builder.copyFrom(value.reader); | |
906 } | |
907 template <> | |
908 inline void AnyPointer::Builder::adopt<AnyPointer>(Orphan<AnyPointer>&& orphan) { | |
909 builder.adopt(kj::mv(orphan.builder)); | |
910 } | |
911 template <> | |
912 inline Orphan<AnyPointer> AnyPointer::Builder::disownAs<AnyPointer>() { | |
913 return Orphan<AnyPointer>(builder.disown()); | |
914 } | |
915 template <> | |
916 inline Orphan<AnyPointer> Orphan<AnyPointer>::releaseAs() { | |
917 return kj::mv(*this); | |
918 } | |
919 | |
920 namespace _ { // private | |
921 | |
922 // Specialize PointerHelpers for AnyPointer. | |
923 | |
924 template <> | |
925 struct PointerHelpers<AnyPointer, Kind::OTHER> { | |
926 static inline AnyPointer::Reader get(PointerReader reader, | |
927 const void* defaultValue = nullptr, | |
928 uint defaultBytes = 0) { | |
929 return AnyPointer::Reader(reader); | |
930 } | |
931 static inline AnyPointer::Builder get(PointerBuilder builder, | |
932 const void* defaultValue = nullptr, | |
933 uint defaultBytes = 0) { | |
934 return AnyPointer::Builder(builder); | |
935 } | |
936 static inline void set(PointerBuilder builder, AnyPointer::Reader value) { | |
937 AnyPointer::Builder(builder).set(value); | |
938 } | |
939 static inline void adopt(PointerBuilder builder, Orphan<AnyPointer>&& value) { | |
940 builder.adopt(kj::mv(value.builder)); | |
941 } | |
942 static inline Orphan<AnyPointer> disown(PointerBuilder builder) { | |
943 return Orphan<AnyPointer>(builder.disown()); | |
944 } | |
945 static inline _::PointerReader getInternalReader(const AnyPointer::Reader& reader) { | |
946 return reader.reader; | |
947 } | |
948 static inline _::PointerBuilder getInternalBuilder(AnyPointer::Builder&& builder) { | |
949 return builder.builder; | |
950 } | |
951 }; | |
952 | |
953 template <> | |
954 struct PointerHelpers<AnyStruct, Kind::OTHER> { | |
955 static inline AnyStruct::Reader get( | |
956 PointerReader reader, const word* defaultValue = nullptr) { | |
957 return AnyStruct::Reader(reader.getStruct(defaultValue)); | |
958 } | |
959 static inline AnyStruct::Builder get( | |
960 PointerBuilder builder, const word* defaultValue = nullptr) { | |
961 // TODO(someday): Allow specifying the size somehow? | |
962 return AnyStruct::Builder(builder.getStruct( | |
963 _::StructSize(0 * WORDS, 0 * POINTERS), defaultValue)); | |
964 } | |
965 static inline void set(PointerBuilder builder, AnyStruct::Reader value) { | |
966 builder.setStruct(value._reader); | |
967 } | |
968 static inline AnyStruct::Builder init( | |
969 PointerBuilder builder, uint dataWordCount, uint pointerCount) { | |
970 return AnyStruct::Builder(builder.initStruct( | |
971 StructSize(dataWordCount * WORDS, pointerCount * POINTERS))); | |
972 } | |
973 | |
974 // TODO(soon): implement these | |
975 static void adopt(PointerBuilder builder, Orphan<AnyStruct>&& value); | |
976 static Orphan<AnyStruct> disown(PointerBuilder builder); | |
977 }; | |
978 | |
979 template <> | |
980 struct PointerHelpers<AnyList, Kind::OTHER> { | |
981 static inline AnyList::Reader get( | |
982 PointerReader reader, const word* defaultValue = nullptr) { | |
983 return AnyList::Reader(reader.getListAnySize(defaultValue)); | |
984 } | |
985 static inline AnyList::Builder get( | |
986 PointerBuilder builder, const word* defaultValue = nullptr) { | |
987 return AnyList::Builder(builder.getListAnySize(defaultValue)); | |
988 } | |
989 static inline void set(PointerBuilder builder, AnyList::Reader value) { | |
990 builder.setList(value._reader); | |
991 } | |
992 static inline AnyList::Builder init( | |
993 PointerBuilder builder, ElementSize elementSize, uint elementCount) { | |
994 return AnyList::Builder(builder.initList(elementSize, elementCount * ELEMENTS)); | |
995 } | |
996 static inline AnyList::Builder init( | |
997 PointerBuilder builder, uint dataWordCount, uint pointerCount, uint elementCount) { | |
998 return AnyList::Builder(builder.initStructList( | |
999 elementCount * ELEMENTS, StructSize(dataWordCount * WORDS, pointerCount * POINTERS))); | |
1000 } | |
1001 | |
1002 // TODO(soon): implement these | |
1003 static void adopt(PointerBuilder builder, Orphan<AnyList>&& value); | |
1004 static Orphan<AnyList> disown(PointerBuilder builder); | |
1005 }; | |
1006 | |
1007 template <> | |
1008 struct OrphanGetImpl<AnyStruct, Kind::OTHER> { | |
1009 static inline AnyStruct::Builder apply(_::OrphanBuilder& builder) { | |
1010 return AnyStruct::Builder(builder.asStruct(_::StructSize(0 * WORDS, 0 * POINTERS))); | |
1011 } | |
1012 static inline AnyStruct::Reader applyReader(const _::OrphanBuilder& builder) { | |
1013 return AnyStruct::Reader(builder.asStructReader(_::StructSize(0 * WORDS, 0 * POINTERS))); | |
1014 } | |
1015 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { | |
1016 builder.truncate(size, _::StructSize(0 * WORDS, 0 * POINTERS)); | |
1017 } | |
1018 }; | |
1019 | |
1020 } // namespace _ (private) | |
1021 | |
1022 #if !CAPNP_LITE | |
1023 | |
1024 template <typename T> | |
1025 struct PipelineHook::FromImpl { | |
1026 static inline kj::Own<PipelineHook> apply(typename T::Pipeline&& pipeline) { | |
1027 return from(kj::mv(pipeline._typeless)); | |
1028 } | |
1029 }; | |
1030 | |
1031 template <> | |
1032 struct PipelineHook::FromImpl<AnyPointer> { | |
1033 static inline kj::Own<PipelineHook> apply(AnyPointer::Pipeline&& pipeline) { | |
1034 return kj::mv(pipeline.hook); | |
1035 } | |
1036 }; | |
1037 | |
1038 template <typename Pipeline, typename T> | |
1039 inline kj::Own<PipelineHook> PipelineHook::from(Pipeline&& pipeline) { | |
1040 return FromImpl<T>::apply(kj::fwd<Pipeline>(pipeline)); | |
1041 } | |
1042 | |
1043 #endif // !CAPNP_LITE | |
1044 | |
1045 } // namespace capnp | |
1046 | |
1047 #endif // CAPNP_ANY_H_ |