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