list.h 20.8 KB
Newer Older
Kenton Varda's avatar
Kenton Varda committed
1 2
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
3
//
Kenton Varda's avatar
Kenton Varda committed
4 5 6 7 8 9
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
10
//
Kenton Varda's avatar
Kenton Varda committed
11 12
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
13
//
Kenton Varda's avatar
Kenton Varda committed
14 15 16 17 18 19 20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
21

22
#pragma once
23

24
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
25 26 27
#pragma GCC system_header
#endif

28
#include "layout.h"
29
#include "orphan.h"
30
#include <initializer_list>
31
#ifdef KJ_STD_COMPAT
32
#include <iterator>
33
#endif  // KJ_STD_COMPAT
34

35
namespace capnp {
36
namespace _ {  // private
37

38 39 40 41 42 43 44 45
template <typename T>
class TemporaryPointer {
  // This class is a little hack which lets us define operator->() in cases where it needs to
  // return a pointer to a temporary value.  We instead construct a TemporaryPointer and return that
  // (by value).  The compiler then invokes operator->() on the TemporaryPointer, which itself is
  // able to return a real pointer to its member.

public:
Kenton Varda's avatar
Kenton Varda committed
46
  TemporaryPointer(T&& value): value(kj::mv(value)) {}
47 48 49 50 51 52 53
  TemporaryPointer(const T& value): value(value) {}

  inline T* operator->() { return &value; }
private:
  T value;
};

Kenton Varda's avatar
Kenton Varda committed
54
template <typename Container, typename Element>
55
class IndexingIterator {
56 57 58
public:
  IndexingIterator() = default;

Kenton Varda's avatar
Kenton Varda committed
59 60
  inline Element operator*() const { return (*container)[index]; }
  inline TemporaryPointer<Element> operator->() const {
Kenton Varda's avatar
Kenton Varda committed
61 62
    return TemporaryPointer<Element>((*container)[index]);
  }
Kenton Varda's avatar
Kenton Varda committed
63 64
  inline Element operator[]( int off) const { return (*container)[index]; }
  inline Element operator[](uint off) const { return (*container)[index]; }
65 66 67 68 69 70

  inline IndexingIterator& operator++() { ++index; return *this; }
  inline IndexingIterator operator++(int) { IndexingIterator other = *this; ++index; return other; }
  inline IndexingIterator& operator--() { --index; return *this; }
  inline IndexingIterator operator--(int) { IndexingIterator other = *this; --index; return other; }

Kenton Varda's avatar
Kenton Varda committed
71 72 73 74
  inline IndexingIterator operator+(uint amount) const { return IndexingIterator(container, index + amount); }
  inline IndexingIterator operator-(uint amount) const { return IndexingIterator(container, index - amount); }
  inline IndexingIterator operator+( int amount) const { return IndexingIterator(container, index + amount); }
  inline IndexingIterator operator-( int amount) const { return IndexingIterator(container, index - amount); }
75

Kenton Varda's avatar
Kenton Varda committed
76
  inline int operator-(const IndexingIterator& other) const { return index - other.index; }
77 78 79 80 81 82 83 84

  inline IndexingIterator& operator+=(uint amount) { index += amount; return *this; }
  inline IndexingIterator& operator-=(uint amount) { index -= amount; return *this; }
  inline IndexingIterator& operator+=( int amount) { index += amount; return *this; }
  inline IndexingIterator& operator-=( int amount) { index -= amount; return *this; }

  // STL says comparing iterators of different containers is not allowed, so we only compare
  // indices here.
Kenton Varda's avatar
Kenton Varda committed
85 86 87 88 89 90
  inline bool operator==(const IndexingIterator& other) const { return index == other.index; }
  inline bool operator!=(const IndexingIterator& other) const { return index != other.index; }
  inline bool operator<=(const IndexingIterator& other) const { return index <= other.index; }
  inline bool operator>=(const IndexingIterator& other) const { return index >= other.index; }
  inline bool operator< (const IndexingIterator& other) const { return index <  other.index; }
  inline bool operator> (const IndexingIterator& other) const { return index >  other.index; }
91 92

private:
93
  Container* container;
94 95 96
  uint index;

  friend Container;
97
  inline IndexingIterator(Container* container, uint index)
98
      : container(container), index(index) {}
99 100
};

101
}  // namespace _ (private)
102 103

template <typename T>
104
struct List<T, Kind::PRIMITIVE> {
105 106
  // List of primitives.

107 108
  List() = delete;

109 110
  class Reader {
  public:
111 112
    typedef List<T> Reads;

113
    inline Reader(): reader(_::elementSizeForType<T>()) {}
114
    inline explicit Reader(_::ListReader reader): reader(reader) {}
115

116
    inline uint size() const { return unbound(reader.size() / ELEMENTS); }
117
    inline T operator[](uint index) const {
118
      KJ_IREQUIRE(index < size());
119
      return reader.template getDataElement<T>(bounded(index) * ELEMENTS);
120
    }
121

122
    typedef _::IndexingIterator<const Reader, T> Iterator;
123 124
    inline Iterator begin() const { return Iterator(this, 0); }
    inline Iterator end() const { return Iterator(this, size()); }
125

126 127 128 129
    inline MessageSize totalSize() const {
      return reader.totalSize().asPublic();
    }

130
  private:
131
    _::ListReader reader;
132
    template <typename U, Kind K>
133
    friend struct _::PointerHelpers;
134 135
    template <typename U, Kind K>
    friend struct List;
136 137 138
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
139 140 141 142
  };

  class Builder {
  public:
143 144
    typedef List<T> Builds;

145
    inline Builder(): builder(_::elementSizeForType<T>()) {}
Kenton Varda's avatar
Kenton Varda committed
146
    inline Builder(decltype(nullptr)): Builder() {}
147
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}
148

149 150
    inline operator Reader() const { return Reader(builder.asReader()); }
    inline Reader asReader() const { return Reader(builder.asReader()); }
151

152
    inline uint size() const { return unbound(builder.size() / ELEMENTS); }
153
    inline T operator[](uint index) {
154
      KJ_IREQUIRE(index < size());
155
      return builder.template getDataElement<T>(bounded(index) * ELEMENTS);
Kenton Varda's avatar
Kenton Varda committed
156 157 158 159 160 161 162 163
    }
    inline void set(uint index, T value) {
      // Alas, it is not possible to make operator[] return a reference to which you can assign,
      // since the encoded representation does not necessarily match the compiler's representation
      // of the type.  We can't even return a clever class that implements operator T() and
      // operator=() because it will lead to surprising behavior when using type inference (e.g.
      // calling a template function with inferred argument types, or using "auto" or "decltype").

164
      builder.template setDataElement<T>(bounded(index) * ELEMENTS, value);
Kenton Varda's avatar
Kenton Varda committed
165
    }
166

167
    typedef _::IndexingIterator<Builder, T> Iterator;
168 169
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }
170

Kenton Varda's avatar
Kenton Varda committed
171
  private:
172
    _::ListBuilder builder;
173 174
    template <typename U, Kind K>
    friend struct _::PointerHelpers;
175 176 177
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
178
  };
179

180 181
  class Pipeline {};

182
private:
183
  inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
184
    return builder.initList(_::elementSizeForType<T>(), bounded(size) * ELEMENTS);
185
  }
186 187
  inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
    return builder.getList(_::elementSizeForType<T>(), defaultValue);
188
  }
189 190 191
  inline static _::ListReader getFromPointer(
      const _::PointerReader& reader, const word* defaultValue) {
    return reader.getList(_::elementSizeForType<T>(), defaultValue);
192 193
  }

194
  template <typename U, Kind k>
Kenton Varda's avatar
Kenton Varda committed
195
  friend struct List;
196
  template <typename U, Kind K>
197
  friend struct _::PointerHelpers;
Kenton Varda's avatar
Kenton Varda committed
198 199 200
};

template <typename T>
201 202 203 204
struct List<T, Kind::ENUM>: public List<T, Kind::PRIMITIVE> {};

template <typename T>
struct List<T, Kind::STRUCT> {
205 206
  // List of structs.

207 208
  List() = delete;

Kenton Varda's avatar
Kenton Varda committed
209 210
  class Reader {
  public:
211 212
    typedef List<T> Reads;

213
    inline Reader(): reader(ElementSize::INLINE_COMPOSITE) {}
214
    inline explicit Reader(_::ListReader reader): reader(reader) {}
Kenton Varda's avatar
Kenton Varda committed
215

216
    inline uint size() const { return unbound(reader.size() / ELEMENTS); }
217
    inline typename T::Reader operator[](uint index) const {
218
      KJ_IREQUIRE(index < size());
219
      return typename T::Reader(reader.getStructElement(bounded(index) * ELEMENTS));
Kenton Varda's avatar
Kenton Varda committed
220
    }
221

222
    typedef _::IndexingIterator<const Reader, typename T::Reader> Iterator;
223 224
    inline Iterator begin() const { return Iterator(this, 0); }
    inline Iterator end() const { return Iterator(this, size()); }
225

226 227 228 229
    inline MessageSize totalSize() const {
      return reader.totalSize().asPublic();
    }

Kenton Varda's avatar
Kenton Varda committed
230
  private:
231
    _::ListReader reader;
232
    template <typename U, Kind K>
233
    friend struct _::PointerHelpers;
234 235
    template <typename U, Kind K>
    friend struct List;
236 237 238
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
239
  };
240

Kenton Varda's avatar
Kenton Varda committed
241 242
  class Builder {
  public:
243 244
    typedef List<T> Builds;

245
    inline Builder(): builder(ElementSize::INLINE_COMPOSITE) {}
Kenton Varda's avatar
Kenton Varda committed
246
    inline Builder(decltype(nullptr)): Builder() {}
247
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}
248

249 250
    inline operator Reader() const { return Reader(builder.asReader()); }
    inline Reader asReader() const { return Reader(builder.asReader()); }
251

252
    inline uint size() const { return unbound(builder.size() / ELEMENTS); }
253
    inline typename T::Builder operator[](uint index) {
254
      KJ_IREQUIRE(index < size());
255
      return typename T::Builder(builder.getStructElement(bounded(index) * ELEMENTS));
Kenton Varda's avatar
Kenton Varda committed
256
    }
257

258 259 260 261 262 263 264 265 266 267
    inline void adoptWithCaveats(uint index, Orphan<T>&& orphan) {
      // Mostly behaves like you'd expect `adopt` to behave, but with two caveats originating from
      // the fact that structs in a struct list are allocated inline rather than by pointer:
      // * This actually performs a shallow copy, effectively adopting each of the orphan's
      //   children rather than adopting the orphan itself.  The orphan ends up being discarded,
      //   possibly wasting space in the message object.
      // * If the orphan is larger than the target struct -- say, because the orphan was built
      //   using a newer version of the schema that has additional fields -- it will be truncated,
      //   losing data.

268 269
      KJ_IREQUIRE(index < size());

270 271 272
      // We pass a zero-valued StructSize to asStruct() because we do not want the struct to be
      // expanded under any circumstances.  We're just going to throw it away anyway, and
      // transferContentFrom() already carefully compares the struct sizes before transferring.
273
      builder.getStructElement(bounded(index) * ELEMENTS).transferContentFrom(
274
          orphan.builder.asStruct(_::StructSize(ZERO * WORDS, ZERO * POINTERS)));
275
    }
276 277 278 279 280 281
    inline void setWithCaveats(uint index, const typename T::Reader& reader) {
      // Mostly behaves like you'd expect `set` to behave, but with a caveat originating from
      // the fact that structs in a struct list are allocated inline rather than by pointer:
      // If the source struct is larger than the target struct -- say, because the source was built
      // using a newer version of the schema that has additional fields -- it will be truncated,
      // losing data.
282 283 284 285
      //
      // Note: If you are trying to concatenate some lists, use Orphanage::newOrphanConcat() to
      //   do it without losing any data in case the source lists come from a newer version of the
      //   protocol. (Plus, it's easier to use anyhow.)
286

287
      KJ_IREQUIRE(index < size());
288
      builder.getStructElement(bounded(index) * ELEMENTS).copyContentFrom(reader._reader);
289
    }
290

291 292 293 294
    // There are no init(), set(), adopt(), or disown() methods for lists of structs because the
    // elements of the list are inlined and are initialized when the list is initialized.  This
    // means that init() would be redundant, and set() would risk data loss if the input struct
    // were from a newer version of the protocol.
295

296
    typedef _::IndexingIterator<Builder, typename T::Builder> Iterator;
297 298
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }
299 300

  private:
301
    _::ListBuilder builder;
302 303
    template <typename U, Kind K>
    friend struct _::PointerHelpers;
304 305 306
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
307
  };
308

309 310
  class Pipeline {};

311
private:
312
  inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
313
    return builder.initStructList(bounded(size) * ELEMENTS, _::structSize<T>());
314
  }
315 316
  inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
    return builder.getStructList(_::structSize<T>(), defaultValue);
317
  }
318 319
  inline static _::ListReader getFromPointer(
      const _::PointerReader& reader, const word* defaultValue) {
320
    return reader.getList(ElementSize::INLINE_COMPOSITE, defaultValue);
321 322
  }

323
  template <typename U, Kind k>
Kenton Varda's avatar
Kenton Varda committed
324
  friend struct List;
325
  template <typename U, Kind K>
326
  friend struct _::PointerHelpers;
327 328 329
};

template <typename T>
330
struct List<List<T>, Kind::LIST> {
331 332
  // List of lists.

333 334
  List() = delete;

335 336
  class Reader {
  public:
337 338
    typedef List<List<T>> Reads;

339
    inline Reader(): reader(ElementSize::POINTER) {}
340
    inline explicit Reader(_::ListReader reader): reader(reader) {}
341

342
    inline uint size() const { return unbound(reader.size() / ELEMENTS); }
343
    inline typename List<T>::Reader operator[](uint index) const {
344
      KJ_IREQUIRE(index < size());
345
      return typename List<T>::Reader(_::PointerHelpers<List<T>>::get(
346
          reader.getPointerElement(bounded(index) * ELEMENTS)));
Kenton Varda's avatar
Kenton Varda committed
347
    }
348

349
    typedef _::IndexingIterator<const Reader, typename List<T>::Reader> Iterator;
350 351
    inline Iterator begin() const { return Iterator(this, 0); }
    inline Iterator end() const { return Iterator(this, size()); }
352

353 354 355 356
    inline MessageSize totalSize() const {
      return reader.totalSize().asPublic();
    }

357
  private:
358
    _::ListReader reader;
359
    template <typename U, Kind K>
360
    friend struct _::PointerHelpers;
361 362
    template <typename U, Kind K>
    friend struct List;
363 364 365
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
366 367 368 369
  };

  class Builder {
  public:
370 371
    typedef List<List<T>> Builds;

372
    inline Builder(): builder(ElementSize::POINTER) {}
Kenton Varda's avatar
Kenton Varda committed
373
    inline Builder(decltype(nullptr)): Builder() {}
374
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}
375

376 377
    inline operator Reader() const { return Reader(builder.asReader()); }
    inline Reader asReader() const { return Reader(builder.asReader()); }
378

379
    inline uint size() const { return unbound(builder.size() / ELEMENTS); }
380
    inline typename List<T>::Builder operator[](uint index) {
381
      KJ_IREQUIRE(index < size());
382
      return typename List<T>::Builder(_::PointerHelpers<List<T>>::get(
383
          builder.getPointerElement(bounded(index) * ELEMENTS)));
Kenton Varda's avatar
Kenton Varda committed
384 385
    }
    inline typename List<T>::Builder init(uint index, uint size) {
386
      KJ_IREQUIRE(index < this->size());
387
      return typename List<T>::Builder(_::PointerHelpers<List<T>>::init(
388
          builder.getPointerElement(bounded(index) * ELEMENTS), size));
Kenton Varda's avatar
Kenton Varda committed
389
    }
390
    inline void set(uint index, typename List<T>::Reader value) {
391
      KJ_IREQUIRE(index < size());
392
      builder.getPointerElement(bounded(index) * ELEMENTS).setList(value.reader);
393 394
    }
    void set(uint index, std::initializer_list<ReaderFor<T>> value) {
395
      KJ_IREQUIRE(index < size());
396 397 398 399 400 401
      auto l = init(index, value.size());
      uint i = 0;
      for (auto& element: value) {
        l.set(i++, element);
      }
    }
402
    inline void adopt(uint index, Orphan<T>&& value) {
403
      KJ_IREQUIRE(index < size());
404
      builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder));
405 406
    }
    inline Orphan<T> disown(uint index) {
407
      KJ_IREQUIRE(index < size());
408
      return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown());
409
    }
410

411
    typedef _::IndexingIterator<Builder, typename List<T>::Builder> Iterator;
412 413
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }
414

Kenton Varda's avatar
Kenton Varda committed
415
  private:
416
    _::ListBuilder builder;
417 418
    template <typename U, Kind K>
    friend struct _::PointerHelpers;
419 420 421
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
422
  };
423

424 425
  class Pipeline {};

426
private:
427
  inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
428
    return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS);
429
  }
430
  inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
431
    return builder.getList(ElementSize::POINTER, defaultValue);
432
  }
433 434
  inline static _::ListReader getFromPointer(
      const _::PointerReader& reader, const word* defaultValue) {
435
    return reader.getList(ElementSize::POINTER, defaultValue);
436 437
  }

438
  template <typename U, Kind k>
Kenton Varda's avatar
Kenton Varda committed
439
  friend struct List;
440
  template <typename U, Kind K>
441
  friend struct _::PointerHelpers;
Kenton Varda's avatar
Kenton Varda committed
442 443
};

444 445
template <typename T>
struct List<T, Kind::BLOB> {
446 447
  List() = delete;

Kenton Varda's avatar
Kenton Varda committed
448 449
  class Reader {
  public:
450 451
    typedef List<T> Reads;

452
    inline Reader(): reader(ElementSize::POINTER) {}
453
    inline explicit Reader(_::ListReader reader): reader(reader) {}
Kenton Varda's avatar
Kenton Varda committed
454

455
    inline uint size() const { return unbound(reader.size() / ELEMENTS); }
456
    inline typename T::Reader operator[](uint index) const {
457
      KJ_IREQUIRE(index < size());
458
      return reader.getPointerElement(bounded(index) * ELEMENTS)
459
          .template getBlob<T>(nullptr, ZERO * BYTES);
Kenton Varda's avatar
Kenton Varda committed
460 461
    }

462
    typedef _::IndexingIterator<const Reader, typename T::Reader> Iterator;
463 464
    inline Iterator begin() const { return Iterator(this, 0); }
    inline Iterator end() const { return Iterator(this, size()); }
Kenton Varda's avatar
Kenton Varda committed
465

466 467 468 469
    inline MessageSize totalSize() const {
      return reader.totalSize().asPublic();
    }

Kenton Varda's avatar
Kenton Varda committed
470
  private:
471
    _::ListReader reader;
472
    template <typename U, Kind K>
473
    friend struct _::PointerHelpers;
474 475
    template <typename U, Kind K>
    friend struct List;
476 477 478
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
479 480 481 482
  };

  class Builder {
  public:
483 484
    typedef List<T> Builds;

485
    inline Builder(): builder(ElementSize::POINTER) {}
Kenton Varda's avatar
Kenton Varda committed
486
    inline Builder(decltype(nullptr)): Builder() {}
487
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}
Kenton Varda's avatar
Kenton Varda committed
488

489 490
    inline operator Reader() const { return Reader(builder.asReader()); }
    inline Reader asReader() const { return Reader(builder.asReader()); }
491

492
    inline uint size() const { return unbound(builder.size() / ELEMENTS); }
493
    inline typename T::Builder operator[](uint index) {
494
      KJ_IREQUIRE(index < size());
495
      return builder.getPointerElement(bounded(index) * ELEMENTS)
496
          .template getBlob<T>(nullptr, ZERO * BYTES);
Kenton Varda's avatar
Kenton Varda committed
497
    }
498
    inline void set(uint index, typename T::Reader value) {
499
      KJ_IREQUIRE(index < size());
500
      builder.getPointerElement(bounded(index) * ELEMENTS).template setBlob<T>(value);
501
    }
502
    inline typename T::Builder init(uint index, uint size) {
503
      KJ_IREQUIRE(index < this->size());
504 505
      return builder.getPointerElement(bounded(index) * ELEMENTS)
          .template initBlob<T>(bounded(size) * BYTES);
Kenton Varda's avatar
Kenton Varda committed
506
    }
507
    inline void adopt(uint index, Orphan<T>&& value) {
508
      KJ_IREQUIRE(index < size());
509
      builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder));
510 511
    }
    inline Orphan<T> disown(uint index) {
512
      KJ_IREQUIRE(index < size());
513
      return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown());
514
    }
Kenton Varda's avatar
Kenton Varda committed
515

516
    typedef _::IndexingIterator<Builder, typename T::Builder> Iterator;
517 518
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }
Kenton Varda's avatar
Kenton Varda committed
519 520

  private:
521
    _::ListBuilder builder;
522 523
    template <typename U, Kind K>
    friend struct _::PointerHelpers;
524 525 526
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
527
  };
528

529 530
  class Pipeline {};

531
private:
532
  inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
533
    return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS);
534
  }
535
  inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
536
    return builder.getList(ElementSize::POINTER, defaultValue);
537
  }
538 539
  inline static _::ListReader getFromPointer(
      const _::PointerReader& reader, const word* defaultValue) {
540
    return reader.getList(ElementSize::POINTER, defaultValue);
541 542
  }

543
  template <typename U, Kind k>
Kenton Varda's avatar
Kenton Varda committed
544
  friend struct List;
545
  template <typename U, Kind K>
546
  friend struct _::PointerHelpers;
Kenton Varda's avatar
Kenton Varda committed
547 548
};

549
}  // namespace capnp
550

551 552 553 554 555 556 557 558 559
#ifdef KJ_STD_COMPAT
namespace std {

template <typename Container, typename Element>
struct iterator_traits<capnp::_::IndexingIterator<Container, Element>>
      : public std::iterator<std::random_access_iterator_tag, Element, int> {};

}  // namespace std
#endif  // KJ_STD_COMPAT