| Index: packages/collection/lib/src/combined_wrappers/combined_iterable.dart
|
| diff --git a/packages/collection/lib/src/combined_wrappers/combined_iterable.dart b/packages/collection/lib/src/combined_wrappers/combined_iterable.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..511876ed5bd0345daf8339cce21a9fa5635b9e55
|
| --- /dev/null
|
| +++ b/packages/collection/lib/src/combined_wrappers/combined_iterable.dart
|
| @@ -0,0 +1,55 @@
|
| +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +import 'dart:collection';
|
| +
|
| +/// A view of several iterables combined sequentially into a single iterable.
|
| +///
|
| +/// All methods and accessors treat the [CombinedIterableView] as if it were a
|
| +/// single concatenated iterable, but the underlying implementation is based on
|
| +/// lazily accessing individual iterable instances. This means that if the
|
| +/// underlying iterables change, the [CombinedIterableView] will reflect those
|
| +/// changes.
|
| +class CombinedIterableView<T> extends IterableBase<T> {
|
| + /// The iterables that this combines.
|
| + final Iterable<Iterable<T>> _iterables;
|
| +
|
| + /// Creates a combined view of [iterables].
|
| + const CombinedIterableView(this._iterables);
|
| +
|
| + Iterator<T> get iterator =>
|
| + new _CombinedIterator<T>(_iterables.map((i) => i.iterator).iterator);
|
| +
|
| + // Special cased contains/isEmpty/length since many iterables have an
|
| + // efficient implementation instead of running through the entire iterator.
|
| +
|
| + bool contains(Object element) => _iterables.any((i) => i.contains(element));
|
| +
|
| + bool get isEmpty => _iterables.every((i) => i.isEmpty);
|
| +
|
| + int get length => _iterables.fold(0, (length, i) => length + i.length);
|
| +}
|
| +
|
| +/// The iterator for [CombinedIterableView].
|
| +///
|
| +/// This moves through each iterable's iterators in sequence.
|
| +class _CombinedIterator<T> implements Iterator<T> {
|
| + /// The iterators that this combines.
|
| + ///
|
| + /// Because this comes from a call to [Iterable.map], it's lazy and will
|
| + /// avoid instantiating unnecessary iterators.
|
| + final Iterator<Iterator<T>> _iterators;
|
| +
|
| + _CombinedIterator(this._iterators);
|
| +
|
| + T get current => _iterators.current?.current;
|
| +
|
| + bool moveNext() {
|
| + var current = _iterators.current;
|
| + if (current != null && current.moveNext()) {
|
| + return true;
|
| + }
|
| + return _iterators.moveNext() && moveNext();
|
| + }
|
| +}
|
|
|