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_