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#pragma once
23
24#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
25#pragma GCC system_header
26#endif
27
28#include "layout.h"
29#include "pointer-helpers.h"
30#include "orphan.h"
31#include "list.h"
32#include <kj/windows-sanity.h> // work-around macro conflict with `VOID`
33
34namespace capnp {
35
36class StructSchema;
37class ListSchema;
38class InterfaceSchema;
39class Orphanage;
40class ClientHook;
41class PipelineHook;
42struct PipelineOp;
43struct AnyPointer;
44
45struct AnyList {
46 AnyList() = delete;
47
48 class Reader;
49 class Builder;
50};
51
52struct AnyStruct {
53 AnyStruct() = delete;
54
55 class Reader;
56 class Builder;
57 class Pipeline;
58};
59
60template<>
61struct List<AnyStruct, Kind::OTHER> {
62 List() = delete;
63
64 class Reader;
65 class Builder;
66};
67
68namespace _ { // private
69template <> struct Kind_<AnyPointer> { static constexpr Kind kind = Kind::OTHER; };
70template <> struct Kind_<AnyStruct> { static constexpr Kind kind = Kind::OTHER; };
71template <> struct Kind_<AnyList> { static constexpr Kind kind = Kind::OTHER; };
72} // namespace _ (private)
73
74// =======================================================================================
75// AnyPointer!
76
77enum class Equality {
78 NOT_EQUAL,
79 EQUAL,
80 UNKNOWN_CONTAINS_CAPS
81};
82
83kj::StringPtr KJ_STRINGIFY(Equality res);
84
85struct 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) const;
109 bool operator==(AnyPointer::Reader right) const;
110 inline bool operator!=(AnyPointer::Reader right) const {
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) const {
163 return asReader().equals(right);
164 }
165 inline bool operator==(AnyPointer::Reader right) const {
166 return asReader() == right;
167 }
168 inline bool operator!=(AnyPointer::Reader right) const {
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 uint16_t dataWordCount, uint16_t pointerCount, uint elementCount);
212
213 inline AnyStruct::Builder initAsAnyStruct(uint16_t dataWordCount, uint16_t 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
305template <>
306class Orphan<AnyPointer> {
307 // An orphaned object of unknown type.
308
309public:
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
358private:
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
369template <Kind k> struct AnyTypeFor_;
370template <> struct AnyTypeFor_<Kind::STRUCT> { typedef AnyStruct Type; };
371template <> struct AnyTypeFor_<Kind::LIST> { typedef AnyList Type; };
372
373template <typename T>
374using AnyTypeFor = typename AnyTypeFor_<CAPNP_KIND(T)>::Type;
375
376template <typename T>
377inline ReaderFor<AnyTypeFor<FromReader<T>>> toAny(T&& value) {
378 return ReaderFor<AnyTypeFor<FromReader<T>>>(
379 _::PointerHelpers<FromReader<T>>::getInternalReader(value));
380}
381template <typename T>
382inline BuilderFor<AnyTypeFor<FromBuilder<T>>> toAny(T&& value) {
383 return BuilderFor<AnyTypeFor<FromBuilder<T>>>(
384 _::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::mv(value)));
385}
386
387template <>
388struct 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 unbound(reader.size() / ELEMENTS); }
402 inline AnyPointer::Reader operator[](uint index) const {
403 KJ_IREQUIRE(index < size());
404 return AnyPointer::Reader(reader.getPointerElement(bounded(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 inline MessageSize totalSize() const {
412 return reader.totalSize().asPublic();
413 }
414
415 private:
416 _::ListReader reader;
417 template <typename U, Kind K>
418 friend struct _::PointerHelpers;
419 template <typename U, Kind K>
420 friend struct List;
421 friend class Orphanage;
422 template <typename U, Kind K>
423 friend struct ToDynamic_;
424 };
425
426 class Builder {
427 public:
428 typedef List<AnyPointer> Builds;
429
430 Builder() = delete;
431 inline Builder(decltype(nullptr)): builder(ElementSize::POINTER) {}
432 inline explicit Builder(_::ListBuilder builder): builder(builder) {}
433
434 inline operator Reader() const { return Reader(builder.asReader()); }
435 inline Reader asReader() const { return Reader(builder.asReader()); }
436
437 inline uint size() const { return unbound(builder.size() / ELEMENTS); }
438 inline AnyPointer::Builder operator[](uint index) {
439 KJ_IREQUIRE(index < size());
440 return AnyPointer::Builder(builder.getPointerElement(bounded(index) * ELEMENTS));
441 }
442
443 typedef _::IndexingIterator<Builder, typename AnyPointer::Builder> Iterator;
444 inline Iterator begin() { return Iterator(this, 0); }
445 inline Iterator end() { return Iterator(this, size()); }
446
447 private:
448 _::ListBuilder builder;
449 template <typename, Kind>
450 friend struct _::PointerHelpers;
451 friend class Orphanage;
452 template <typename, Kind>
453 friend struct ToDynamic_;
454 };
455};
456
457class AnyStruct::Reader {
458public:
459 typedef AnyStruct Reads;
460
461 Reader() = default;
462 inline Reader(_::StructReader reader): _reader(reader) {}
463
464 template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromReader<T>) == Kind::STRUCT>>
465 inline Reader(T&& value)
466 : _reader(_::PointerHelpers<FromReader<T>>::getInternalReader(kj::fwd<T>(value))) {}
467
468 inline MessageSize totalSize() const { return _reader.totalSize().asPublic(); }
469
470 kj::ArrayPtr<const byte> getDataSection() const {
471 return _reader.getDataSectionAsBlob();
472 }
473 List<AnyPointer>::Reader getPointerSection() const {
474 return List<AnyPointer>::Reader(_reader.getPointerSectionAsList());
475 }
476
477 kj::Array<word> canonicalize() {
478 return _reader.canonicalize();
479 }
480
481 Equality equals(AnyStruct::Reader right) const;
482 bool operator==(AnyStruct::Reader right) const;
483 inline bool operator!=(AnyStruct::Reader right) const {
484 return !(*this == right);
485 }
486
487 template <typename T>
488 ReaderFor<T> as() const {
489 // T must be a struct type.
490 return typename T::Reader(_reader);
491 }
492
493 template <typename T>
494 ReaderFor<T> as(StructSchema schema) const;
495 // T must be DynamicStruct. Defined in dynamic.h.
496
497private:
498 _::StructReader _reader;
499
500 template <typename, Kind>
501 friend struct _::PointerHelpers;
502 friend class Orphanage;
503};
504
505class AnyStruct::Builder {
506public:
507 typedef AnyStruct Builds;
508
509 inline Builder(decltype(nullptr)) {}
510 inline Builder(_::StructBuilder builder): _builder(builder) {}
511
512#if !_MSC_VER // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves.
513 template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromBuilder<T>) == Kind::STRUCT>>
514 inline Builder(T&& value)
515 : _builder(_::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::fwd<T>(value))) {}
516#endif
517
518 inline kj::ArrayPtr<byte> getDataSection() {
519 return _builder.getDataSectionAsBlob();
520 }
521 List<AnyPointer>::Builder getPointerSection() {
522 return List<AnyPointer>::Builder(_builder.getPointerSectionAsList());
523 }
524
525 inline Equality equals(AnyStruct::Reader right) const {
526 return asReader().equals(right);
527 }
528 inline bool operator==(AnyStruct::Reader right) const {
529 return asReader() == right;
530 }
531 inline bool operator!=(AnyStruct::Reader right) const {
532 return !(*this == right);
533 }
534
535 inline operator Reader() const { return Reader(_builder.asReader()); }
536 inline Reader asReader() const { return Reader(_builder.asReader()); }
537
538 template <typename T>
539 BuilderFor<T> as() {
540 // T must be a struct type.
541 return typename T::Builder(_builder);
542 }
543
544 template <typename T>
545 BuilderFor<T> as(StructSchema schema);
546 // T must be DynamicStruct. Defined in dynamic.h.
547
548private:
549 _::StructBuilder _builder;
550 friend class Orphanage;
551 friend class CapBuilderContext;
552};
553
554#if !CAPNP_LITE
555class AnyStruct::Pipeline {
556public:
557 inline Pipeline(decltype(nullptr)): typeless(nullptr) {}
558 inline explicit Pipeline(AnyPointer::Pipeline&& typeless)
559 : typeless(kj::mv(typeless)) {}
560
561 inline AnyPointer::Pipeline getPointerField(uint16_t pointerIndex) {
562 // Return a new Promise representing a sub-object of the result. `pointerIndex` is the index
563 // of the sub-object within the pointer section of the result (the result must be a struct).
564 //
565 // TODO(perf): On GCC 4.8 / Clang 3.3, use rvalue qualifiers to avoid the need for copies.
566 // Also make `ops` into a Vector to optimize this.
567 return typeless.getPointerField(pointerIndex);
568 }
569
570private:
571 AnyPointer::Pipeline typeless;
572};
573#endif // !CAPNP_LITE
574
575class List<AnyStruct, Kind::OTHER>::Reader {
576public:
577 typedef List<AnyStruct> Reads;
578
579 inline Reader(): reader(ElementSize::INLINE_COMPOSITE) {}
580 inline explicit Reader(_::ListReader reader): reader(reader) {}
581
582 inline uint size() const { return unbound(reader.size() / ELEMENTS); }
583 inline AnyStruct::Reader operator[](uint index) const {
584 KJ_IREQUIRE(index < size());
585 return AnyStruct::Reader(reader.getStructElement(bounded(index) * ELEMENTS));
586 }
587
588 typedef _::IndexingIterator<const Reader, typename AnyStruct::Reader> Iterator;
589 inline Iterator begin() const { return Iterator(this, 0); }
590 inline Iterator end() const { return Iterator(this, size()); }
591
592 inline MessageSize totalSize() const {
593 return reader.totalSize().asPublic();
594 }
595
596private:
597 _::ListReader reader;
598 template <typename U, Kind K>
599 friend struct _::PointerHelpers;
600 template <typename U, Kind K>
601 friend struct List;
602 friend class Orphanage;
603 template <typename U, Kind K>
604 friend struct ToDynamic_;
605};
606
607class List<AnyStruct, Kind::OTHER>::Builder {
608public:
609 typedef List<AnyStruct> Builds;
610
611 Builder() = delete;
612 inline Builder(decltype(nullptr)): builder(ElementSize::INLINE_COMPOSITE) {}
613 inline explicit Builder(_::ListBuilder builder): builder(builder) {}
614
615 inline operator Reader() const { return Reader(builder.asReader()); }
616 inline Reader asReader() const { return Reader(builder.asReader()); }
617
618 inline uint size() const { return unbound(builder.size() / ELEMENTS); }
619 inline AnyStruct::Builder operator[](uint index) {
620 KJ_IREQUIRE(index < size());
621 return AnyStruct::Builder(builder.getStructElement(bounded(index) * ELEMENTS));
622 }
623
624 typedef _::IndexingIterator<Builder, typename AnyStruct::Builder> Iterator;
625 inline Iterator begin() { return Iterator(this, 0); }
626 inline Iterator end() { return Iterator(this, size()); }
627
628private:
629 _::ListBuilder builder;
630 template <typename U, Kind K>
631 friend struct _::PointerHelpers;
632 friend class Orphanage;
633 template <typename U, Kind K>
634 friend struct ToDynamic_;
635};
636
637class AnyList::Reader {
638public:
639 typedef AnyList Reads;
640
641 inline Reader(): _reader(ElementSize::VOID) {}
642 inline Reader(_::ListReader reader): _reader(reader) {}
643
644#if !_MSC_VER // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves.
645 template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromReader<T>) == Kind::LIST>>
646 inline Reader(T&& value)
647 : _reader(_::PointerHelpers<FromReader<T>>::getInternalReader(kj::fwd<T>(value))) {}
648#endif
649
650 inline ElementSize getElementSize() const { return _reader.getElementSize(); }
651 inline uint size() const { return unbound(_reader.size() / ELEMENTS); }
652
653 inline kj::ArrayPtr<const byte> getRawBytes() const { return _reader.asRawBytes(); }
654
655 Equality equals(AnyList::Reader right) const;
656 bool operator==(AnyList::Reader right) const;
657 inline bool operator!=(AnyList::Reader right) const {
658 return !(*this == right);
659 }
660
661 inline MessageSize totalSize() const {
662 return _reader.totalSize().asPublic();
663 }
664
665 template <typename T> ReaderFor<T> as() const {
666 // T must be List<U>.
667 return ReaderFor<T>(_reader);
668 }
669private:
670 _::ListReader _reader;
671
672 template <typename, Kind>
673 friend struct _::PointerHelpers;
674 friend class Orphanage;
675};
676
677class AnyList::Builder {
678public:
679 typedef AnyList Builds;
680
681 inline Builder(decltype(nullptr)): _builder(ElementSize::VOID) {}
682 inline Builder(_::ListBuilder builder): _builder(builder) {}
683
684#if !_MSC_VER // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves.
685 template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromBuilder<T>) == Kind::LIST>>
686 inline Builder(T&& value)
687 : _builder(_::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::fwd<T>(value))) {}
688#endif
689
690 inline ElementSize getElementSize() { return _builder.getElementSize(); }
691 inline uint size() { return unbound(_builder.size() / ELEMENTS); }
692
693 Equality equals(AnyList::Reader right) const;
694 inline bool operator==(AnyList::Reader right) const{
695 return asReader() == right;
696 }
697 inline bool operator!=(AnyList::Reader right) const{
698 return !(*this == right);
699 }
700
701 template <typename T> BuilderFor<T> as() {
702 // T must be List<U>.
703 return BuilderFor<T>(_builder);
704 }
705
706 inline operator Reader() const { return Reader(_builder.asReader()); }
707 inline Reader asReader() const { return Reader(_builder.asReader()); }
708
709private:
710 _::ListBuilder _builder;
711
712 friend class Orphanage;
713};
714
715// =======================================================================================
716// Pipeline helpers
717//
718// These relate to capabilities, but we don't declare them in capability.h because generated code
719// for structs needs to know about these, even in files that contain no interfaces.
720
721#if !CAPNP_LITE
722
723struct PipelineOp {
724 // Corresponds to rpc.capnp's PromisedAnswer.Op.
725
726 enum Type {
727 NOOP, // for convenience
728
729 GET_POINTER_FIELD
730
731 // There may be other types in the future...
732 };
733
734 Type type;
735 union {
736 uint16_t pointerIndex; // for GET_POINTER_FIELD
737 };
738};
739
740class PipelineHook {
741 // Represents a currently-running call, and implements pipelined requests on its result.
742
743public:
744 virtual kj::Own<PipelineHook> addRef() = 0;
745 // Increment this object's reference count.
746
747 virtual kj::Own<ClientHook> getPipelinedCap(kj::ArrayPtr<const PipelineOp> ops) = 0;
748 // Extract a promised Capability from the results.
749
750 virtual kj::Own<ClientHook> getPipelinedCap(kj::Array<PipelineOp>&& ops);
751 // Version of getPipelinedCap() passing the array by move. May avoid a copy in some cases.
752 // Default implementation just calls the other version.
753
754 template <typename Pipeline, typename = FromPipeline<Pipeline>>
755 static inline kj::Own<PipelineHook> from(Pipeline&& pipeline);
756
757private:
758 template <typename T> struct FromImpl;
759};
760
761#endif // !CAPNP_LITE
762
763// =======================================================================================
764// Inline implementation details
765
766inline MessageSize AnyPointer::Reader::targetSize() const {
767 return reader.targetSize().asPublic();
768}
769
770inline PointerType AnyPointer::Reader::getPointerType() const {
771 return reader.getPointerType();
772}
773
774template <typename T>
775inline ReaderFor<T> AnyPointer::Reader::getAs() const {
776 return _::PointerHelpers<T>::get(reader);
777}
778
779inline MessageSize AnyPointer::Builder::targetSize() const {
780 return asReader().targetSize();
781}
782
783inline PointerType AnyPointer::Builder::getPointerType() {
784 return builder.getPointerType();
785}
786
787inline void AnyPointer::Builder::clear() {
788 return builder.clear();
789}
790
791template <typename T>
792inline BuilderFor<T> AnyPointer::Builder::getAs() {
793 return _::PointerHelpers<T>::get(builder);
794}
795
796template <typename T>
797inline BuilderFor<T> AnyPointer::Builder::initAs() {
798 return _::PointerHelpers<T>::init(builder);
799}
800
801template <typename T>
802inline BuilderFor<T> AnyPointer::Builder::initAs(uint elementCount) {
803 return _::PointerHelpers<T>::init(builder, elementCount);
804}
805
806inline AnyList::Builder AnyPointer::Builder::initAsAnyList(
807 ElementSize elementSize, uint elementCount) {
808 return AnyList::Builder(builder.initList(elementSize, bounded(elementCount) * ELEMENTS));
809}
810
811inline List<AnyStruct>::Builder AnyPointer::Builder::initAsListOfAnyStruct(
812 uint16_t dataWordCount, uint16_t pointerCount, uint elementCount) {
813 return List<AnyStruct>::Builder(builder.initStructList(bounded(elementCount) * ELEMENTS,
814 _::StructSize(bounded(dataWordCount) * WORDS,
815 bounded(pointerCount) * POINTERS)));
816}
817
818inline AnyStruct::Builder AnyPointer::Builder::initAsAnyStruct(
819 uint16_t dataWordCount, uint16_t pointerCount) {
820 return AnyStruct::Builder(builder.initStruct(
821 _::StructSize(bounded(dataWordCount) * WORDS,
822 bounded(pointerCount) * POINTERS)));
823}
824
825template <typename T>
826inline void AnyPointer::Builder::setAs(ReaderFor<T> value) {
827 return _::PointerHelpers<T>::set(builder, value);
828}
829
830template <typename T>
831inline void AnyPointer::Builder::setCanonicalAs(ReaderFor<T> value) {
832 return _::PointerHelpers<T>::setCanonical(builder, value);
833}
834
835template <typename T>
836inline void AnyPointer::Builder::setAs(
837 std::initializer_list<ReaderFor<ListElementType<T>>> list) {
838 return _::PointerHelpers<T>::set(builder, list);
839}
840
841template <typename T>
842inline void AnyPointer::Builder::adopt(Orphan<T>&& orphan) {
843 _::PointerHelpers<T>::adopt(builder, kj::mv(orphan));
844}
845
846template <typename T>
847inline Orphan<T> AnyPointer::Builder::disownAs() {
848 return _::PointerHelpers<T>::disown(builder);
849}
850
851inline Orphan<AnyPointer> AnyPointer::Builder::disown() {
852 return Orphan<AnyPointer>(builder.disown());
853}
854
855template <> struct ReaderFor_ <AnyPointer, Kind::OTHER> { typedef AnyPointer::Reader Type; };
856template <> struct BuilderFor_<AnyPointer, Kind::OTHER> { typedef AnyPointer::Builder Type; };
857template <> struct ReaderFor_ <AnyStruct, Kind::OTHER> { typedef AnyStruct::Reader Type; };
858template <> struct BuilderFor_<AnyStruct, Kind::OTHER> { typedef AnyStruct::Builder Type; };
859
860template <>
861struct Orphanage::GetInnerReader<AnyPointer, Kind::OTHER> {
862 static inline _::PointerReader apply(const AnyPointer::Reader& t) {
863 return t.reader;
864 }
865};
866
867template <>
868struct Orphanage::GetInnerBuilder<AnyPointer, Kind::OTHER> {
869 static inline _::PointerBuilder apply(AnyPointer::Builder& t) {
870 return t.builder;
871 }
872};
873
874template <>
875struct Orphanage::GetInnerReader<AnyStruct, Kind::OTHER> {
876 static inline _::StructReader apply(const AnyStruct::Reader& t) {
877 return t._reader;
878 }
879};
880
881template <>
882struct Orphanage::GetInnerBuilder<AnyStruct, Kind::OTHER> {
883 static inline _::StructBuilder apply(AnyStruct::Builder& t) {
884 return t._builder;
885 }
886};
887
888template <>
889struct Orphanage::GetInnerReader<AnyList, Kind::OTHER> {
890 static inline _::ListReader apply(const AnyList::Reader& t) {
891 return t._reader;
892 }
893};
894
895template <>
896struct Orphanage::GetInnerBuilder<AnyList, Kind::OTHER> {
897 static inline _::ListBuilder apply(AnyList::Builder& t) {
898 return t._builder;
899 }
900};
901
902template <typename T>
903inline BuilderFor<T> Orphan<AnyPointer>::getAs() {
904 return _::OrphanGetImpl<T>::apply(builder);
905}
906template <typename T>
907inline ReaderFor<T> Orphan<AnyPointer>::getAsReader() const {
908 return _::OrphanGetImpl<T>::applyReader(builder);
909}
910template <typename T>
911inline Orphan<T> Orphan<AnyPointer>::releaseAs() {
912 return Orphan<T>(kj::mv(builder));
913}
914
915// Using AnyPointer as the template type should work...
916
917template <>
918inline typename AnyPointer::Reader AnyPointer::Reader::getAs<AnyPointer>() const {
919 return *this;
920}
921template <>
922inline typename AnyPointer::Builder AnyPointer::Builder::getAs<AnyPointer>() {
923 return *this;
924}
925template <>
926inline typename AnyPointer::Builder AnyPointer::Builder::initAs<AnyPointer>() {
927 clear();
928 return *this;
929}
930template <>
931inline void AnyPointer::Builder::setAs<AnyPointer>(AnyPointer::Reader value) {
932 return builder.copyFrom(value.reader);
933}
934template <>
935inline void AnyPointer::Builder::adopt<AnyPointer>(Orphan<AnyPointer>&& orphan) {
936 builder.adopt(kj::mv(orphan.builder));
937}
938template <>
939inline Orphan<AnyPointer> AnyPointer::Builder::disownAs<AnyPointer>() {
940 return Orphan<AnyPointer>(builder.disown());
941}
942template <>
943inline Orphan<AnyPointer> Orphan<AnyPointer>::releaseAs() {
944 return kj::mv(*this);
945}
946
947namespace _ { // private
948
949// Specialize PointerHelpers for AnyPointer.
950
951template <>
952struct PointerHelpers<AnyPointer, Kind::OTHER> {
953 static inline AnyPointer::Reader get(PointerReader reader,
954 const void* defaultValue = nullptr,
955 uint defaultBytes = 0) {
956 return AnyPointer::Reader(reader);
957 }
958 static inline AnyPointer::Builder get(PointerBuilder builder,
959 const void* defaultValue = nullptr,
960 uint defaultBytes = 0) {
961 return AnyPointer::Builder(builder);
962 }
963 static inline void set(PointerBuilder builder, AnyPointer::Reader value) {
964 AnyPointer::Builder(builder).set(value);
965 }
966 static inline void adopt(PointerBuilder builder, Orphan<AnyPointer>&& value) {
967 builder.adopt(kj::mv(value.builder));
968 }
969 static inline Orphan<AnyPointer> disown(PointerBuilder builder) {
970 return Orphan<AnyPointer>(builder.disown());
971 }
972 static inline _::PointerReader getInternalReader(const AnyPointer::Reader& reader) {
973 return reader.reader;
974 }
975 static inline _::PointerBuilder getInternalBuilder(AnyPointer::Builder&& builder) {
976 return builder.builder;
977 }
978};
979
980template <>
981struct PointerHelpers<AnyStruct, Kind::OTHER> {
982 static inline AnyStruct::Reader get(
983 PointerReader reader, const word* defaultValue = nullptr) {
984 return AnyStruct::Reader(reader.getStruct(defaultValue));
985 }
986 static inline AnyStruct::Builder get(
987 PointerBuilder builder, const word* defaultValue = nullptr) {
988 // TODO(someday): Allow specifying the size somehow?
989 return AnyStruct::Builder(builder.getStruct(
990 _::StructSize(ZERO * WORDS, ZERO * POINTERS), defaultValue));
991 }
992 static inline void set(PointerBuilder builder, AnyStruct::Reader value) {
993 builder.setStruct(value._reader);
994 }
995 static inline AnyStruct::Builder init(
996 PointerBuilder builder, uint16_t dataWordCount, uint16_t pointerCount) {
997 return AnyStruct::Builder(builder.initStruct(
998 StructSize(bounded(dataWordCount) * WORDS,
999 bounded(pointerCount) * POINTERS)));
1000 }
1001
1002 static void adopt(PointerBuilder builder, Orphan<AnyStruct>&& value) {
1003 builder.adopt(kj::mv(value.builder));
1004 }
1005 static Orphan<AnyStruct> disown(PointerBuilder builder) {
1006 return Orphan<AnyStruct>(builder.disown());
1007 }
1008};
1009
1010template <>
1011struct PointerHelpers<AnyList, Kind::OTHER> {
1012 static inline AnyList::Reader get(
1013 PointerReader reader, const word* defaultValue = nullptr) {
1014 return AnyList::Reader(reader.getListAnySize(defaultValue));
1015 }
1016 static inline AnyList::Builder get(
1017 PointerBuilder builder, const word* defaultValue = nullptr) {
1018 return AnyList::Builder(builder.getListAnySize(defaultValue));
1019 }
1020 static inline void set(PointerBuilder builder, AnyList::Reader value) {
1021 builder.setList(value._reader);
1022 }
1023 static inline AnyList::Builder init(
1024 PointerBuilder builder, ElementSize elementSize, uint elementCount) {
1025 return AnyList::Builder(builder.initList(
1026 elementSize, bounded(elementCount) * ELEMENTS));
1027 }
1028 static inline AnyList::Builder init(
1029 PointerBuilder builder, uint16_t dataWordCount, uint16_t pointerCount, uint elementCount) {
1030 return AnyList::Builder(builder.initStructList(
1031 bounded(elementCount) * ELEMENTS,
1032 StructSize(bounded(dataWordCount) * WORDS,
1033 bounded(pointerCount) * POINTERS)));
1034 }
1035
1036 static void adopt(PointerBuilder builder, Orphan<AnyList>&& value) {
1037 builder.adopt(kj::mv(value.builder));
1038 }
1039 static Orphan<AnyList> disown(PointerBuilder builder) {
1040 return Orphan<AnyList>(builder.disown());
1041 }
1042};
1043
1044template <>
1045struct OrphanGetImpl<AnyStruct, Kind::OTHER> {
1046 static inline AnyStruct::Builder apply(_::OrphanBuilder& builder) {
1047 return AnyStruct::Builder(builder.asStruct(_::StructSize(ZERO * WORDS, ZERO * POINTERS)));
1048 }
1049 static inline AnyStruct::Reader applyReader(const _::OrphanBuilder& builder) {
1050 return AnyStruct::Reader(builder.asStructReader(_::StructSize(ZERO * WORDS, ZERO * POINTERS)));
1051 }
1052 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
1053 builder.truncate(size, _::StructSize(ZERO * WORDS, ZERO * POINTERS));
1054 }
1055};
1056
1057template <>
1058struct OrphanGetImpl<AnyList, Kind::OTHER> {
1059 static inline AnyList::Builder apply(_::OrphanBuilder& builder) {
1060 return AnyList::Builder(builder.asListAnySize());
1061 }
1062 static inline AnyList::Reader applyReader(const _::OrphanBuilder& builder) {
1063 return AnyList::Reader(builder.asListReaderAnySize());
1064 }
1065 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
1066 builder.truncate(size, ElementSize::POINTER);
1067 }
1068};
1069
1070} // namespace _ (private)
1071
1072#if !CAPNP_LITE
1073
1074template <typename T>
1075struct PipelineHook::FromImpl {
1076 static inline kj::Own<PipelineHook> apply(typename T::Pipeline&& pipeline) {
1077 return from(kj::mv(pipeline._typeless));
1078 }
1079};
1080
1081template <>
1082struct PipelineHook::FromImpl<AnyPointer> {
1083 static inline kj::Own<PipelineHook> apply(AnyPointer::Pipeline&& pipeline) {
1084 return kj::mv(pipeline.hook);
1085 }
1086};
1087
1088template <typename Pipeline, typename T>
1089inline kj::Own<PipelineHook> PipelineHook::from(Pipeline&& pipeline) {
1090 return FromImpl<T>::apply(kj::fwd<Pipeline>(pipeline));
1091}
1092
1093#endif // !CAPNP_LITE
1094
1095} // namespace capnp
1096