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