list.h 20.1 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

Kenton Varda's avatar
Kenton Varda committed
22 23
#ifndef CAPNP_LIST_H_
#define CAPNP_LIST_H_
24

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

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

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

39 40 41 42 43 44 45 46
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
47
  TemporaryPointer(T&& value): value(kj::mv(value)) {}
48 49 50 51 52 53 54
  TemporaryPointer(const T& value): value(value) {}

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

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

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

  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
72 73 74 75
  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); }
76

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

  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
86 87 88 89 90 91
  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; }
92 93

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

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

102
}  // namespace _ (private)
103 104

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

108 109
  List() = delete;

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

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

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

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

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

  class Builder {
  public:
140 141
    typedef List<T> Builds;

142
    inline Builder(): builder(_::elementSizeForType<T>()) {}
143
    inline Builder(decltype(nullptr)) {}
144
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}
145

146 147 148
    inline operator Reader() { return Reader(builder.asReader()); }
    inline Reader asReader() { return Reader(builder.asReader()); }

149
    inline uint size() const { return builder.size() / ELEMENTS; }
150
    inline T operator[](uint index) {
151
      KJ_IREQUIRE(index < size());
Kenton Varda's avatar
Kenton Varda committed
152 153 154 155 156 157 158 159 160 161 162
      return builder.template getDataElement<T>(index * ELEMENTS);
    }
    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").

      builder.template setDataElement<T>(index * ELEMENTS, value);
    }
163

164
    typedef _::IndexingIterator<Builder, T> Iterator;
165 166
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }
167

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

177 178
  class Pipeline {};

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

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

template <typename T>
198 199 200 201
struct List<T, Kind::ENUM>: public List<T, Kind::PRIMITIVE> {};

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

204 205
  List() = delete;

Kenton Varda's avatar
Kenton Varda committed
206 207
  class Reader {
  public:
208 209
    typedef List<T> Reads;

210
    inline Reader(): reader(ElementSize::INLINE_COMPOSITE) {}
211
    inline explicit Reader(_::ListReader reader): reader(reader) {}
Kenton Varda's avatar
Kenton Varda committed
212

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

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

Kenton Varda's avatar
Kenton Varda committed
223
  private:
224
    _::ListReader reader;
225
    template <typename U, Kind K>
226
    friend struct _::PointerHelpers;
227 228
    template <typename U, Kind K>
    friend struct List;
229 230 231
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
232
  };
233

Kenton Varda's avatar
Kenton Varda committed
234 235
  class Builder {
  public:
236 237
    typedef List<T> Builds;

238
    inline Builder(): builder(ElementSize::INLINE_COMPOSITE) {}
239
    inline Builder(decltype(nullptr)) {}
240
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}
241

242 243 244
    inline operator Reader() { return Reader(builder.asReader()); }
    inline Reader asReader() { return Reader(builder.asReader()); }

245
    inline uint size() const { return builder.size() / ELEMENTS; }
246
    inline typename T::Builder operator[](uint index) {
247
      KJ_IREQUIRE(index < size());
Kenton Varda's avatar
Kenton Varda committed
248
      return typename T::Builder(builder.getStructElement(index * ELEMENTS));
Kenton Varda's avatar
Kenton Varda committed
249
    }
250

251 252 253 254 255 256 257 258 259 260
    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.

261 262
      KJ_IREQUIRE(index < size());

263 264 265 266
      // 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.
      builder.getStructElement(index * ELEMENTS).transferContentFrom(
267
          orphan.builder.asStruct(_::StructSize(0 * WORDS, 0 * POINTERS)));
268
    }
269 270 271 272 273 274
    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.
275 276 277 278
      //
      // 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.)
279

280
      KJ_IREQUIRE(index < size());
281 282
      builder.getStructElement(index * ELEMENTS).copyContentFrom(reader._reader);
    }
283

284 285 286 287
    // 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.
288

289
    typedef _::IndexingIterator<Builder, typename T::Builder> Iterator;
290 291
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }
292 293

  private:
294
    _::ListBuilder builder;
295 296
    template <typename U, Kind K>
    friend struct _::PointerHelpers;
297 298 299
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
300
  };
301

302 303
  class Pipeline {};

304
private:
305 306
  inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
    return builder.initStructList(size * ELEMENTS, _::structSize<T>());
307
  }
308 309
  inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
    return builder.getStructList(_::structSize<T>(), defaultValue);
310
  }
311 312
  inline static _::ListReader getFromPointer(
      const _::PointerReader& reader, const word* defaultValue) {
313
    return reader.getList(ElementSize::INLINE_COMPOSITE, defaultValue);
314 315
  }

316
  template <typename U, Kind k>
Kenton Varda's avatar
Kenton Varda committed
317
  friend struct List;
318
  template <typename U, Kind K>
319
  friend struct _::PointerHelpers;
320 321 322
};

template <typename T>
323
struct List<List<T>, Kind::LIST> {
324 325
  // List of lists.

326 327
  List() = delete;

328 329
  class Reader {
  public:
330 331
    typedef List<List<T>> Reads;

332
    inline Reader(): reader(ElementSize::POINTER) {}
333
    inline explicit Reader(_::ListReader reader): reader(reader) {}
334

335 336
    inline uint size() const { return reader.size() / ELEMENTS; }
    inline typename List<T>::Reader operator[](uint index) const {
337
      KJ_IREQUIRE(index < size());
338 339
      return typename List<T>::Reader(
          _::PointerHelpers<List<T>>::get(reader.getPointerElement(index * ELEMENTS)));
Kenton Varda's avatar
Kenton Varda committed
340
    }
341

342
    typedef _::IndexingIterator<const Reader, typename List<T>::Reader> Iterator;
343 344
    inline Iterator begin() const { return Iterator(this, 0); }
    inline Iterator end() const { return Iterator(this, size()); }
345 346

  private:
347
    _::ListReader reader;
348
    template <typename U, Kind K>
349
    friend struct _::PointerHelpers;
350 351
    template <typename U, Kind K>
    friend struct List;
352 353 354
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
355 356 357 358
  };

  class Builder {
  public:
359 360
    typedef List<List<T>> Builds;

361
    inline Builder(): builder(ElementSize::POINTER) {}
362
    inline Builder(decltype(nullptr)) {}
363
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}
364

365 366 367
    inline operator Reader() { return Reader(builder.asReader()); }
    inline Reader asReader() { return Reader(builder.asReader()); }

368
    inline uint size() const { return builder.size() / ELEMENTS; }
369
    inline typename List<T>::Builder operator[](uint index) {
370
      KJ_IREQUIRE(index < size());
371 372
      return typename List<T>::Builder(
          _::PointerHelpers<List<T>>::get(builder.getPointerElement(index * ELEMENTS)));
Kenton Varda's avatar
Kenton Varda committed
373 374
    }
    inline typename List<T>::Builder init(uint index, uint size) {
375
      KJ_IREQUIRE(index < this->size());
376 377
      return typename List<T>::Builder(
          _::PointerHelpers<List<T>>::init(builder.getPointerElement(index * ELEMENTS), size));
Kenton Varda's avatar
Kenton Varda committed
378
    }
379
    inline void set(uint index, typename List<T>::Reader value) {
380
      KJ_IREQUIRE(index < size());
381
      builder.getPointerElement(index * ELEMENTS).setList(value.reader);
382 383
    }
    void set(uint index, std::initializer_list<ReaderFor<T>> value) {
384
      KJ_IREQUIRE(index < size());
385 386 387 388 389 390
      auto l = init(index, value.size());
      uint i = 0;
      for (auto& element: value) {
        l.set(i++, element);
      }
    }
391
    inline void adopt(uint index, Orphan<T>&& value) {
392
      KJ_IREQUIRE(index < size());
393
      builder.getPointerElement(index * ELEMENTS).adopt(kj::mv(value.builder));
394 395
    }
    inline Orphan<T> disown(uint index) {
396
      KJ_IREQUIRE(index < size());
397
      return Orphan<T>(builder.getPointerElement(index * ELEMENTS).disown());
398
    }
399

400
    typedef _::IndexingIterator<Builder, typename List<T>::Builder> Iterator;
401 402
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }
403

Kenton Varda's avatar
Kenton Varda committed
404
  private:
405
    _::ListBuilder builder;
406 407
    template <typename U, Kind K>
    friend struct _::PointerHelpers;
408 409 410
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
411
  };
412

413 414
  class Pipeline {};

415
private:
416
  inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
417
    return builder.initList(ElementSize::POINTER, size * ELEMENTS);
418
  }
419
  inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
420
    return builder.getList(ElementSize::POINTER, defaultValue);
421
  }
422 423
  inline static _::ListReader getFromPointer(
      const _::PointerReader& reader, const word* defaultValue) {
424
    return reader.getList(ElementSize::POINTER, defaultValue);
425 426
  }

427
  template <typename U, Kind k>
Kenton Varda's avatar
Kenton Varda committed
428
  friend struct List;
429
  template <typename U, Kind K>
430
  friend struct _::PointerHelpers;
Kenton Varda's avatar
Kenton Varda committed
431 432
};

433 434
template <typename T>
struct List<T, Kind::BLOB> {
435 436
  List() = delete;

Kenton Varda's avatar
Kenton Varda committed
437 438
  class Reader {
  public:
439 440
    typedef List<T> Reads;

441
    inline Reader(): reader(ElementSize::POINTER) {}
442
    inline explicit Reader(_::ListReader reader): reader(reader) {}
Kenton Varda's avatar
Kenton Varda committed
443

444 445
    inline uint size() const { return reader.size() / ELEMENTS; }
    inline typename T::Reader operator[](uint index) const {
446
      KJ_IREQUIRE(index < size());
447
      return reader.getPointerElement(index * ELEMENTS).template getBlob<T>(nullptr, 0 * BYTES);
Kenton Varda's avatar
Kenton Varda committed
448 449
    }

450
    typedef _::IndexingIterator<const Reader, typename T::Reader> Iterator;
451 452
    inline Iterator begin() const { return Iterator(this, 0); }
    inline Iterator end() const { return Iterator(this, size()); }
Kenton Varda's avatar
Kenton Varda committed
453 454

  private:
455
    _::ListReader reader;
456
    template <typename U, Kind K>
457
    friend struct _::PointerHelpers;
458 459
    template <typename U, Kind K>
    friend struct List;
460 461 462
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
463 464 465 466
  };

  class Builder {
  public:
467 468
    typedef List<T> Builds;

469
    inline Builder(): builder(ElementSize::POINTER) {}
470
    inline Builder(decltype(nullptr)) {}
471
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}
Kenton Varda's avatar
Kenton Varda committed
472

473 474 475
    inline operator Reader() { return Reader(builder.asReader()); }
    inline Reader asReader() { return Reader(builder.asReader()); }

476
    inline uint size() const { return builder.size() / ELEMENTS; }
477
    inline typename T::Builder operator[](uint index) {
478
      KJ_IREQUIRE(index < size());
479
      return builder.getPointerElement(index * ELEMENTS).template getBlob<T>(nullptr, 0 * BYTES);
Kenton Varda's avatar
Kenton Varda committed
480
    }
481
    inline void set(uint index, typename T::Reader value) {
482
      KJ_IREQUIRE(index < size());
483
      builder.getPointerElement(index * ELEMENTS).template setBlob<T>(value);
484
    }
485
    inline typename T::Builder init(uint index, uint size) {
486
      KJ_IREQUIRE(index < this->size());
487
      return builder.getPointerElement(index * ELEMENTS).template initBlob<T>(size * BYTES);
Kenton Varda's avatar
Kenton Varda committed
488
    }
489
    inline void adopt(uint index, Orphan<T>&& value) {
490
      KJ_IREQUIRE(index < size());
491
      builder.getPointerElement(index * ELEMENTS).adopt(kj::mv(value.builder));
492 493
    }
    inline Orphan<T> disown(uint index) {
494
      KJ_IREQUIRE(index < size());
495
      return Orphan<T>(builder.getPointerElement(index * ELEMENTS).disown());
496
    }
Kenton Varda's avatar
Kenton Varda committed
497

498
    typedef _::IndexingIterator<Builder, typename T::Builder> Iterator;
499 500
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }
Kenton Varda's avatar
Kenton Varda committed
501 502

  private:
503
    _::ListBuilder builder;
504 505
    template <typename U, Kind K>
    friend struct _::PointerHelpers;
506 507 508
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
Kenton Varda's avatar
Kenton Varda committed
509
  };
510

511 512
  class Pipeline {};

513
private:
514
  inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
515
    return builder.initList(ElementSize::POINTER, size * ELEMENTS);
516
  }
517
  inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
518
    return builder.getList(ElementSize::POINTER, defaultValue);
519
  }
520 521
  inline static _::ListReader getFromPointer(
      const _::PointerReader& reader, const word* defaultValue) {
522
    return reader.getList(ElementSize::POINTER, defaultValue);
523 524
  }

525
  template <typename U, Kind k>
Kenton Varda's avatar
Kenton Varda committed
526
  friend struct List;
527
  template <typename U, Kind K>
528
  friend struct _::PointerHelpers;
Kenton Varda's avatar
Kenton Varda committed
529 530
};

531
}  // namespace capnp
532

533 534 535 536 537 538 539 540 541 542
#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

Kenton Varda's avatar
Kenton Varda committed
543
#endif  // CAPNP_LIST_H_