annotate win64-msvc/include/capnp/orphan.h @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 0f2d93caa50c
children
rev   line source
Chris@63 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
Chris@63 2 // Licensed under the MIT License:
Chris@63 3 //
Chris@63 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
Chris@63 5 // of this software and associated documentation files (the "Software"), to deal
Chris@63 6 // in the Software without restriction, including without limitation the rights
Chris@63 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Chris@63 8 // copies of the Software, and to permit persons to whom the Software is
Chris@63 9 // furnished to do so, subject to the following conditions:
Chris@63 10 //
Chris@63 11 // The above copyright notice and this permission notice shall be included in
Chris@63 12 // all copies or substantial portions of the Software.
Chris@63 13 //
Chris@63 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Chris@63 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Chris@63 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Chris@63 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Chris@63 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Chris@63 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Chris@63 20 // THE SOFTWARE.
Chris@63 21
Chris@63 22 #ifndef CAPNP_ORPHAN_H_
Chris@63 23 #define CAPNP_ORPHAN_H_
Chris@63 24
Chris@63 25 #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
Chris@63 26 #pragma GCC system_header
Chris@63 27 #endif
Chris@63 28
Chris@63 29 #include "layout.h"
Chris@63 30
Chris@63 31 namespace capnp {
Chris@63 32
Chris@63 33 class StructSchema;
Chris@63 34 class ListSchema;
Chris@63 35 struct DynamicStruct;
Chris@63 36 struct DynamicList;
Chris@63 37 namespace _ { struct OrphanageInternal; }
Chris@63 38
Chris@63 39 template <typename T>
Chris@63 40 class Orphan {
Chris@63 41 // Represents an object which is allocated within some message builder but has no pointers
Chris@63 42 // pointing at it. An Orphan can later be "adopted" by some other object as one of that object's
Chris@63 43 // fields, without having to copy the orphan. For a field `foo` of pointer type, the generated
Chris@63 44 // code will define builder methods `void adoptFoo(Orphan<T>)` and `Orphan<T> disownFoo()`.
Chris@63 45 // Orphans can also be created independently of any parent using an Orphanage.
Chris@63 46 //
Chris@63 47 // `Orphan<T>` can be moved but not copied, like `Own<T>`, so that it is impossible for one
Chris@63 48 // orphan to be adopted multiple times. If an orphan is destroyed without being adopted, its
Chris@63 49 // contents are zero'd out (and possibly reused, if we ever implement the ability to reuse space
Chris@63 50 // in a message arena).
Chris@63 51
Chris@63 52 public:
Chris@63 53 Orphan() = default;
Chris@63 54 KJ_DISALLOW_COPY(Orphan);
Chris@63 55 Orphan(Orphan&&) = default;
Chris@63 56 Orphan& operator=(Orphan&&) = default;
Chris@63 57 inline Orphan(_::OrphanBuilder&& builder): builder(kj::mv(builder)) {}
Chris@63 58
Chris@63 59 inline BuilderFor<T> get();
Chris@63 60 // Get the underlying builder. If the orphan is null, this will allocate and return a default
Chris@63 61 // object rather than crash. This is done for security -- otherwise, you might enable a DoS
Chris@63 62 // attack any time you disown a field and fail to check if it is null. In the case of structs,
Chris@63 63 // this means that the orphan is no longer null after get() returns. In the case of lists,
Chris@63 64 // no actual object is allocated since a simple empty ListBuilder can be returned.
Chris@63 65
Chris@63 66 inline ReaderFor<T> getReader() const;
Chris@63 67
Chris@63 68 inline bool operator==(decltype(nullptr)) const { return builder == nullptr; }
Chris@63 69 inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; }
Chris@63 70
Chris@63 71 inline void truncate(uint size);
Chris@63 72 // Resize an object (which must be a list or a blob) to the given size.
Chris@63 73 //
Chris@63 74 // If the new size is less than the original, the remaining elements will be discarded. The
Chris@63 75 // list is never moved in this case. If the list happens to be located at the end of its segment
Chris@63 76 // (which is always true if the list was the last thing allocated), the removed memory will be
Chris@63 77 // reclaimed (reducing the messag size), otherwise it is simply zeroed. The reclaiming behavior
Chris@63 78 // is particularly useful for allocating buffer space when you aren't sure how much space you
Chris@63 79 // actually need: you can pre-allocate, say, a 4k byte array, read() from a file into it, and
Chris@63 80 // then truncate it back to the amount of space actually used.
Chris@63 81 //
Chris@63 82 // If the new size is greater than the original, the list is extended with default values. If
Chris@63 83 // the list is the last object in its segment *and* there is enough space left in the segment to
Chris@63 84 // extend it to cover the new values, then the list is extended in-place. Otherwise, it must be
Chris@63 85 // moved to a new location, leaving a zero'd hole in the previous space that won't be filled.
Chris@63 86 // This copy is shallow; sub-objects will simply be reparented, not copied.
Chris@63 87 //
Chris@63 88 // Any existing readers or builders pointing at the object are invalidated by this call (even if
Chris@63 89 // it doesn't move). You must call `get()` or `getReader()` again to get the new, valid pointer.
Chris@63 90
Chris@63 91 private:
Chris@63 92 _::OrphanBuilder builder;
Chris@63 93
Chris@63 94 template <typename, Kind>
Chris@63 95 friend struct _::PointerHelpers;
Chris@63 96 template <typename, Kind>
Chris@63 97 friend struct List;
Chris@63 98 template <typename U>
Chris@63 99 friend class Orphan;
Chris@63 100 friend class Orphanage;
Chris@63 101 friend class MessageBuilder;
Chris@63 102 };
Chris@63 103
Chris@63 104 class Orphanage: private kj::DisallowConstCopy {
Chris@63 105 // Use to directly allocate Orphan objects, without having a parent object allocate and then
Chris@63 106 // disown the object.
Chris@63 107
Chris@63 108 public:
Chris@63 109 inline Orphanage(): arena(nullptr) {}
Chris@63 110
Chris@63 111 template <typename BuilderType>
Chris@63 112 static Orphanage getForMessageContaining(BuilderType builder);
Chris@63 113 // Construct an Orphanage that allocates within the message containing the given Builder. This
Chris@63 114 // allows the constructed Orphans to be adopted by objects within said message.
Chris@63 115 //
Chris@63 116 // This constructor takes the builder rather than having the builder have a getOrphanage() method
Chris@63 117 // because this is an advanced feature and we don't want to pollute the builder APIs with it.
Chris@63 118 //
Chris@63 119 // Note that if you have a direct pointer to the `MessageBuilder`, you can simply call its
Chris@63 120 // `getOrphanage()` method.
Chris@63 121
Chris@63 122 template <typename RootType>
Chris@63 123 Orphan<RootType> newOrphan() const;
Chris@63 124 // Allocate a new orphaned struct.
Chris@63 125
Chris@63 126 template <typename RootType>
Chris@63 127 Orphan<RootType> newOrphan(uint size) const;
Chris@63 128 // Allocate a new orphaned list or blob.
Chris@63 129
Chris@63 130 Orphan<DynamicStruct> newOrphan(StructSchema schema) const;
Chris@63 131 // Dynamically create an orphan struct with the given schema. You must
Chris@63 132 // #include <capnp/dynamic.h> to use this.
Chris@63 133
Chris@63 134 Orphan<DynamicList> newOrphan(ListSchema schema, uint size) const;
Chris@63 135 // Dynamically create an orphan list with the given schema. You must #include <capnp/dynamic.h>
Chris@63 136 // to use this.
Chris@63 137
Chris@63 138 template <typename Reader>
Chris@63 139 Orphan<FromReader<Reader>> newOrphanCopy(Reader copyFrom) const;
Chris@63 140 // Allocate a new orphaned object (struct, list, or blob) and initialize it as a copy of the
Chris@63 141 // given object.
Chris@63 142
Chris@63 143 template <typename T>
Chris@63 144 Orphan<List<ListElementType<FromReader<T>>>> newOrphanConcat(kj::ArrayPtr<T> lists) const;
Chris@63 145 template <typename T>
Chris@63 146 Orphan<List<ListElementType<FromReader<T>>>> newOrphanConcat(kj::ArrayPtr<const T> lists) const;
Chris@63 147 // Given an array of List readers, copy and concatenate the lists, creating a new Orphan.
Chris@63 148 //
Chris@63 149 // Note that compared to allocating the list yourself and using `setWithCaveats()` to set each
Chris@63 150 // item, this method avoids the "caveats": the new list will be allocated with the element size
Chris@63 151 // being the maximum of that from all the input lists. This is particularly important when
Chris@63 152 // concatenating struct lists: if the lists were created using a newer version of the protocol
Chris@63 153 // in which some new fields had been added to the struct, using `setWithCaveats()` would
Chris@63 154 // truncate off those new fields.
Chris@63 155
Chris@63 156 Orphan<Data> referenceExternalData(Data::Reader data) const;
Chris@63 157 // Creates an Orphan<Data> that points at an existing region of memory (e.g. from another message)
Chris@63 158 // without copying it. There are some SEVERE restrictions on how this can be used:
Chris@63 159 // - The memory must remain valid until the `MessageBuilder` is destroyed (even if the orphan is
Chris@63 160 // abandoned).
Chris@63 161 // - Because the data is const, you will not be allowed to obtain a `Data::Builder`
Chris@63 162 // for this blob. Any call which would return such a builder will throw an exception. You
Chris@63 163 // can, however, obtain a Reader, e.g. via orphan.getReader() or from a parent Reader (once
Chris@63 164 // the orphan is adopted). It is your responsibility to make sure your code can deal with
Chris@63 165 // these problems when using this optimization; if you can't, allocate a copy instead.
Chris@63 166 // - `data.begin()` must be aligned to a machine word boundary (32-bit or 64-bit depending on
Chris@63 167 // the CPU). Any pointer returned by malloc() as well as any data blob obtained from another
Chris@63 168 // Cap'n Proto message satisfies this.
Chris@63 169 // - If `data.size()` is not a multiple of 8, extra bytes past data.end() up until the next 8-byte
Chris@63 170 // boundary will be visible in the raw message when it is written out. Thus, there must be no
Chris@63 171 // secrets in these bytes. Data blobs obtained from other Cap'n Proto messages should be safe
Chris@63 172 // as these bytes should be zero (unless the sender had the same problem).
Chris@63 173 //
Chris@63 174 // The array will actually become one of the message's segments. The data can thus be adopted
Chris@63 175 // into the message tree without copying it. This is particularly useful when referencing very
Chris@63 176 // large blobs, such as whole mmap'd files.
Chris@63 177
Chris@63 178 private:
Chris@63 179 _::BuilderArena* arena;
Chris@63 180 _::CapTableBuilder* capTable;
Chris@63 181
Chris@63 182 inline explicit Orphanage(_::BuilderArena* arena, _::CapTableBuilder* capTable)
Chris@63 183 : arena(arena), capTable(capTable) {}
Chris@63 184
Chris@63 185 template <typename T, Kind = CAPNP_KIND(T)>
Chris@63 186 struct GetInnerBuilder;
Chris@63 187 template <typename T, Kind = CAPNP_KIND(T)>
Chris@63 188 struct GetInnerReader;
Chris@63 189 template <typename T>
Chris@63 190 struct NewOrphanListImpl;
Chris@63 191
Chris@63 192 friend class MessageBuilder;
Chris@63 193 friend struct _::OrphanageInternal;
Chris@63 194 };
Chris@63 195
Chris@63 196 // =======================================================================================
Chris@63 197 // Inline implementation details.
Chris@63 198
Chris@63 199 namespace _ { // private
Chris@63 200
Chris@63 201 template <typename T, Kind = CAPNP_KIND(T)>
Chris@63 202 struct OrphanGetImpl;
Chris@63 203
Chris@63 204 template <typename T>
Chris@63 205 struct OrphanGetImpl<T, Kind::PRIMITIVE> {
Chris@63 206 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
Chris@63 207 builder.truncate(size, _::elementSizeForType<T>());
Chris@63 208 }
Chris@63 209 };
Chris@63 210
Chris@63 211 template <typename T>
Chris@63 212 struct OrphanGetImpl<T, Kind::STRUCT> {
Chris@63 213 static inline typename T::Builder apply(_::OrphanBuilder& builder) {
Chris@63 214 return typename T::Builder(builder.asStruct(_::structSize<T>()));
Chris@63 215 }
Chris@63 216 static inline typename T::Reader applyReader(const _::OrphanBuilder& builder) {
Chris@63 217 return typename T::Reader(builder.asStructReader(_::structSize<T>()));
Chris@63 218 }
Chris@63 219 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
Chris@63 220 builder.truncate(size, _::structSize<T>());
Chris@63 221 }
Chris@63 222 };
Chris@63 223
Chris@63 224 #if !CAPNP_LITE
Chris@63 225 template <typename T>
Chris@63 226 struct OrphanGetImpl<T, Kind::INTERFACE> {
Chris@63 227 static inline typename T::Client apply(_::OrphanBuilder& builder) {
Chris@63 228 return typename T::Client(builder.asCapability());
Chris@63 229 }
Chris@63 230 static inline typename T::Client applyReader(const _::OrphanBuilder& builder) {
Chris@63 231 return typename T::Client(builder.asCapability());
Chris@63 232 }
Chris@63 233 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
Chris@63 234 builder.truncate(size, ElementSize::POINTER);
Chris@63 235 }
Chris@63 236 };
Chris@63 237 #endif // !CAPNP_LITE
Chris@63 238
Chris@63 239 template <typename T, Kind k>
Chris@63 240 struct OrphanGetImpl<List<T, k>, Kind::LIST> {
Chris@63 241 static inline typename List<T>::Builder apply(_::OrphanBuilder& builder) {
Chris@63 242 return typename List<T>::Builder(builder.asList(_::ElementSizeForType<T>::value));
Chris@63 243 }
Chris@63 244 static inline typename List<T>::Reader applyReader(const _::OrphanBuilder& builder) {
Chris@63 245 return typename List<T>::Reader(builder.asListReader(_::ElementSizeForType<T>::value));
Chris@63 246 }
Chris@63 247 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
Chris@63 248 builder.truncate(size, ElementSize::POINTER);
Chris@63 249 }
Chris@63 250 };
Chris@63 251
Chris@63 252 template <typename T>
Chris@63 253 struct OrphanGetImpl<List<T, Kind::STRUCT>, Kind::LIST> {
Chris@63 254 static inline typename List<T>::Builder apply(_::OrphanBuilder& builder) {
Chris@63 255 return typename List<T>::Builder(builder.asStructList(_::structSize<T>()));
Chris@63 256 }
Chris@63 257 static inline typename List<T>::Reader applyReader(const _::OrphanBuilder& builder) {
Chris@63 258 return typename List<T>::Reader(builder.asListReader(_::ElementSizeForType<T>::value));
Chris@63 259 }
Chris@63 260 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
Chris@63 261 builder.truncate(size, ElementSize::POINTER);
Chris@63 262 }
Chris@63 263 };
Chris@63 264
Chris@63 265 template <>
Chris@63 266 struct OrphanGetImpl<Text, Kind::BLOB> {
Chris@63 267 static inline Text::Builder apply(_::OrphanBuilder& builder) {
Chris@63 268 return Text::Builder(builder.asText());
Chris@63 269 }
Chris@63 270 static inline Text::Reader applyReader(const _::OrphanBuilder& builder) {
Chris@63 271 return Text::Reader(builder.asTextReader());
Chris@63 272 }
Chris@63 273 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
Chris@63 274 builder.truncate(size, ElementSize::POINTER);
Chris@63 275 }
Chris@63 276 };
Chris@63 277
Chris@63 278 template <>
Chris@63 279 struct OrphanGetImpl<Data, Kind::BLOB> {
Chris@63 280 static inline Data::Builder apply(_::OrphanBuilder& builder) {
Chris@63 281 return Data::Builder(builder.asData());
Chris@63 282 }
Chris@63 283 static inline Data::Reader applyReader(const _::OrphanBuilder& builder) {
Chris@63 284 return Data::Reader(builder.asDataReader());
Chris@63 285 }
Chris@63 286 static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
Chris@63 287 builder.truncate(size, ElementSize::POINTER);
Chris@63 288 }
Chris@63 289 };
Chris@63 290
Chris@63 291 struct OrphanageInternal {
Chris@63 292 static inline _::BuilderArena* getArena(Orphanage orphanage) { return orphanage.arena; }
Chris@63 293 static inline _::CapTableBuilder* getCapTable(Orphanage orphanage) { return orphanage.capTable; }
Chris@63 294 };
Chris@63 295
Chris@63 296 } // namespace _ (private)
Chris@63 297
Chris@63 298 template <typename T>
Chris@63 299 inline BuilderFor<T> Orphan<T>::get() {
Chris@63 300 return _::OrphanGetImpl<T>::apply(builder);
Chris@63 301 }
Chris@63 302
Chris@63 303 template <typename T>
Chris@63 304 inline ReaderFor<T> Orphan<T>::getReader() const {
Chris@63 305 return _::OrphanGetImpl<T>::applyReader(builder);
Chris@63 306 }
Chris@63 307
Chris@63 308 template <typename T>
Chris@63 309 inline void Orphan<T>::truncate(uint size) {
Chris@63 310 _::OrphanGetImpl<ListElementType<T>>::truncateListOf(builder, bounded(size) * ELEMENTS);
Chris@63 311 }
Chris@63 312
Chris@63 313 template <>
Chris@63 314 inline void Orphan<Text>::truncate(uint size) {
Chris@63 315 builder.truncateText(bounded(size) * ELEMENTS);
Chris@63 316 }
Chris@63 317
Chris@63 318 template <>
Chris@63 319 inline void Orphan<Data>::truncate(uint size) {
Chris@63 320 builder.truncate(bounded(size) * ELEMENTS, ElementSize::BYTE);
Chris@63 321 }
Chris@63 322
Chris@63 323 template <typename T>
Chris@63 324 struct Orphanage::GetInnerBuilder<T, Kind::STRUCT> {
Chris@63 325 static inline _::StructBuilder apply(typename T::Builder& t) {
Chris@63 326 return t._builder;
Chris@63 327 }
Chris@63 328 };
Chris@63 329
Chris@63 330 template <typename T>
Chris@63 331 struct Orphanage::GetInnerBuilder<T, Kind::LIST> {
Chris@63 332 static inline _::ListBuilder apply(typename T::Builder& t) {
Chris@63 333 return t.builder;
Chris@63 334 }
Chris@63 335 };
Chris@63 336
Chris@63 337 template <typename BuilderType>
Chris@63 338 Orphanage Orphanage::getForMessageContaining(BuilderType builder) {
Chris@63 339 auto inner = GetInnerBuilder<FromBuilder<BuilderType>>::apply(builder);
Chris@63 340 return Orphanage(inner.getArena(), inner.getCapTable());
Chris@63 341 }
Chris@63 342
Chris@63 343 template <typename RootType>
Chris@63 344 Orphan<RootType> Orphanage::newOrphan() const {
Chris@63 345 return Orphan<RootType>(_::OrphanBuilder::initStruct(arena, capTable, _::structSize<RootType>()));
Chris@63 346 }
Chris@63 347
Chris@63 348 template <typename T, Kind k>
Chris@63 349 struct Orphanage::NewOrphanListImpl<List<T, k>> {
Chris@63 350 static inline _::OrphanBuilder apply(
Chris@63 351 _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) {
Chris@63 352 return _::OrphanBuilder::initList(
Chris@63 353 arena, capTable, bounded(size) * ELEMENTS, _::ElementSizeForType<T>::value);
Chris@63 354 }
Chris@63 355 };
Chris@63 356
Chris@63 357 template <typename T>
Chris@63 358 struct Orphanage::NewOrphanListImpl<List<T, Kind::STRUCT>> {
Chris@63 359 static inline _::OrphanBuilder apply(
Chris@63 360 _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) {
Chris@63 361 return _::OrphanBuilder::initStructList(
Chris@63 362 arena, capTable, bounded(size) * ELEMENTS, _::structSize<T>());
Chris@63 363 }
Chris@63 364 };
Chris@63 365
Chris@63 366 template <>
Chris@63 367 struct Orphanage::NewOrphanListImpl<Text> {
Chris@63 368 static inline _::OrphanBuilder apply(
Chris@63 369 _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) {
Chris@63 370 return _::OrphanBuilder::initText(arena, capTable, bounded(size) * BYTES);
Chris@63 371 }
Chris@63 372 };
Chris@63 373
Chris@63 374 template <>
Chris@63 375 struct Orphanage::NewOrphanListImpl<Data> {
Chris@63 376 static inline _::OrphanBuilder apply(
Chris@63 377 _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) {
Chris@63 378 return _::OrphanBuilder::initData(arena, capTable, bounded(size) * BYTES);
Chris@63 379 }
Chris@63 380 };
Chris@63 381
Chris@63 382 template <typename RootType>
Chris@63 383 Orphan<RootType> Orphanage::newOrphan(uint size) const {
Chris@63 384 return Orphan<RootType>(NewOrphanListImpl<RootType>::apply(arena, capTable, size));
Chris@63 385 }
Chris@63 386
Chris@63 387 template <typename T>
Chris@63 388 struct Orphanage::GetInnerReader<T, Kind::STRUCT> {
Chris@63 389 static inline _::StructReader apply(const typename T::Reader& t) {
Chris@63 390 return t._reader;
Chris@63 391 }
Chris@63 392 };
Chris@63 393
Chris@63 394 template <typename T>
Chris@63 395 struct Orphanage::GetInnerReader<T, Kind::LIST> {
Chris@63 396 static inline _::ListReader apply(const typename T::Reader& t) {
Chris@63 397 return t.reader;
Chris@63 398 }
Chris@63 399 };
Chris@63 400
Chris@63 401 template <typename T>
Chris@63 402 struct Orphanage::GetInnerReader<T, Kind::BLOB> {
Chris@63 403 static inline const typename T::Reader& apply(const typename T::Reader& t) {
Chris@63 404 return t;
Chris@63 405 }
Chris@63 406 };
Chris@63 407
Chris@63 408 template <typename Reader>
Chris@63 409 inline Orphan<FromReader<Reader>> Orphanage::newOrphanCopy(Reader copyFrom) const {
Chris@63 410 return Orphan<FromReader<Reader>>(_::OrphanBuilder::copy(
Chris@63 411 arena, capTable, GetInnerReader<FromReader<Reader>>::apply(copyFrom)));
Chris@63 412 }
Chris@63 413
Chris@63 414 template <typename T>
Chris@63 415 inline Orphan<List<ListElementType<FromReader<T>>>>
Chris@63 416 Orphanage::newOrphanConcat(kj::ArrayPtr<T> lists) const {
Chris@63 417 return newOrphanConcat(kj::implicitCast<kj::ArrayPtr<const T>>(lists));
Chris@63 418 }
Chris@63 419 template <typename T>
Chris@63 420 inline Orphan<List<ListElementType<FromReader<T>>>>
Chris@63 421 Orphanage::newOrphanConcat(kj::ArrayPtr<const T> lists) const {
Chris@63 422 // Optimization / simplification: Rely on List<T>::Reader containing nothing except a
Chris@63 423 // _::ListReader.
Chris@63 424 static_assert(sizeof(T) == sizeof(_::ListReader), "lists are not bare readers?");
Chris@63 425 kj::ArrayPtr<const _::ListReader> raw(
Chris@63 426 reinterpret_cast<const _::ListReader*>(lists.begin()), lists.size());
Chris@63 427 typedef ListElementType<FromReader<T>> Element;
Chris@63 428 return Orphan<List<Element>>(
Chris@63 429 _::OrphanBuilder::concat(arena, capTable,
Chris@63 430 _::elementSizeForType<Element>(),
Chris@63 431 _::minStructSizeForElement<Element>(), raw));
Chris@63 432 }
Chris@63 433
Chris@63 434 inline Orphan<Data> Orphanage::referenceExternalData(Data::Reader data) const {
Chris@63 435 return Orphan<Data>(_::OrphanBuilder::referenceExternalData(arena, data));
Chris@63 436 }
Chris@63 437
Chris@63 438 } // namespace capnp
Chris@63 439
Chris@63 440 #endif // CAPNP_ORPHAN_H_