General clean-up and tweaks. (#157)
* General clean-up and tweaks.
Fixes some null-safety issues, usees some newer features (const classes can use mixins now),
and replaces unnecessary `late` with a dual constructor.
Fixes the `CombinedList.iterator` having potentially quadratic complexity
since the default list iterator does repeated indexing.
Ensure that interfaces returning an `Iterable` does not return a `Set` instead.
diff --git a/lib/src/algorithms.dart b/lib/src/algorithms.dart
index fc7aed3..44a2b3b 100644
--- a/lib/src/algorithms.dart
+++ b/lib/src/algorithms.dart
@@ -199,7 +199,7 @@
var max = targetOffset + i;
while (min < max) {
var mid = min + ((max - min) >> 1);
- if (compare(element, target[mid]!) < 0) {
+ if (compare(element, target[mid]) < 0) {
max = mid;
} else {
min = mid + 1;
@@ -262,7 +262,7 @@
var cursor1 = firstStart;
var cursor2 = secondStart;
var firstElement = firstList[cursor1++];
- var secondElement = secondList[cursor2++]!;
+ var secondElement = secondList[cursor2++];
while (true) {
if (compare(firstElement, secondElement) <= 0) {
target[targetOffset++] = firstElement;
@@ -271,7 +271,7 @@
} else {
target[targetOffset++] = secondElement;
if (cursor2 != secondEnd) {
- secondElement = secondList[cursor2++]!;
+ secondElement = secondList[cursor2++];
continue;
}
// Second list empties first. Flushing first list here.
diff --git a/lib/src/canonicalized_map.dart b/lib/src/canonicalized_map.dart
index 280050c..5f97b25 100644
--- a/lib/src/canonicalized_map.dart
+++ b/lib/src/canonicalized_map.dart
@@ -4,8 +4,6 @@
import 'dart:collection';
-import 'utils.dart';
-
/// A map whose keys are converted to canonical values of type `C`.
///
/// This is useful for using case-insensitive String keys, for example. It's
@@ -17,7 +15,7 @@
final bool Function(K)? _isValidKeyFn;
- final _base = <C, Pair<K, V>>{};
+ final _base = <C, MapEntry<K, V>>{};
/// Creates an empty canonicalized map.
///
@@ -52,13 +50,13 @@
V? operator [](Object? key) {
if (!_isValidKey(key)) return null;
var pair = _base[_canonicalize(key as K)];
- return pair == null ? null : pair.last;
+ return pair == null ? null : pair.value;
}
@override
void operator []=(K key, V value) {
if (!_isValidKey(key)) return;
- _base[_canonicalize(key)] = Pair(key, value);
+ _base[_canonicalize(key)] = MapEntry(key, value);
}
@override
@@ -67,8 +65,8 @@
}
@override
- void addEntries(Iterable<MapEntry<K, V>> entries) => _base.addEntries(
- entries.map((e) => MapEntry(_canonicalize(e.key), Pair(e.key, e.value))));
+ void addEntries(Iterable<MapEntry<K, V>> entries) => _base.addEntries(entries
+ .map((e) => MapEntry(_canonicalize(e.key), MapEntry(e.key, e.value))));
@override
Map<K2, V2> cast<K2, V2>() => _base.cast<K2, V2>();
@@ -86,15 +84,15 @@
@override
bool containsValue(Object? value) =>
- _base.values.any((pair) => pair.last == value);
+ _base.values.any((pair) => pair.value == value);
@override
Iterable<MapEntry<K, V>> get entries =>
- _base.entries.map((e) => MapEntry(e.value.first, e.value.last));
+ _base.entries.map((e) => MapEntry(e.value.key, e.value.value));
@override
void forEach(void Function(K, V) f) {
- _base.forEach((key, pair) => f(pair.first, pair.last));
+ _base.forEach((key, pair) => f(pair.key, pair.value));
}
@override
@@ -104,83 +102,63 @@
bool get isNotEmpty => _base.isNotEmpty;
@override
- Iterable<K> get keys => _base.values.map((pair) => pair.first);
+ Iterable<K> get keys => _base.values.map((pair) => pair.key);
@override
int get length => _base.length;
@override
Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> Function(K, V) transform) =>
- _base.map((_, pair) => transform(pair.first, pair.last));
+ _base.map((_, pair) => transform(pair.key, pair.value));
@override
V putIfAbsent(K key, V Function() ifAbsent) {
return _base
- .putIfAbsent(_canonicalize(key), () => Pair(key, ifAbsent()))
- .last;
+ .putIfAbsent(_canonicalize(key), () => MapEntry(key, ifAbsent()))
+ .value;
}
@override
V? remove(Object? key) {
if (!_isValidKey(key)) return null;
var pair = _base.remove(_canonicalize(key as K));
- return pair == null ? null : pair.last;
+ return pair?.value;
}
@override
void removeWhere(bool Function(K key, V value) test) =>
- _base.removeWhere((_, pair) => test(pair.first, pair.last));
+ _base.removeWhere((_, pair) => test(pair.key, pair.value));
@deprecated
Map<K2, V2> retype<K2, V2>() => cast<K2, V2>();
@override
- V update(K key, V Function(V) update, {V Function()? ifAbsent}) => _base
- .update(_canonicalize(key), (pair) => Pair(key, update(pair.last)),
- ifAbsent: ifAbsent == null ? null : () => Pair(key, ifAbsent()))
- .last;
+ V update(K key, V Function(V) update, {V Function()? ifAbsent}) =>
+ _base.update(_canonicalize(key), (pair) {
+ var value = pair.value;
+ var newValue = update(value);
+ if (identical(newValue, value)) return pair;
+ return MapEntry(key, newValue);
+ },
+ ifAbsent:
+ ifAbsent == null ? null : () => MapEntry(key, ifAbsent())).value;
@override
- void updateAll(V Function(K key, V value) update) => _base
- .updateAll((_, pair) => Pair(pair.first, update(pair.first, pair.last)));
-
- @override
- Iterable<V> get values => _base.values.map((pair) => pair.last);
-
- @override
- String toString() {
- // Detect toString() cycles.
- if (_isToStringVisiting(this)) {
- return '{...}';
- }
-
- var result = StringBuffer();
- try {
- _toStringVisiting.add(this);
- result.write('{');
- var first = true;
- forEach((k, v) {
- if (!first) {
- result.write(', ');
- }
- first = false;
- result.write('$k: $v');
+ void updateAll(V Function(K key, V value) update) =>
+ _base.updateAll((_, pair) {
+ var value = pair.value;
+ var key = pair.key;
+ var newValue = update(key, value);
+ if (identical(value, newValue)) return pair;
+ return MapEntry(key, newValue);
});
- result.write('}');
- } finally {
- assert(identical(_toStringVisiting.last, this));
- _toStringVisiting.removeLast();
- }
- return result.toString();
- }
+ @override
+ Iterable<V> get values => _base.values.map((pair) => pair.value);
+
+ @override
+ String toString() => MapBase.mapToString(this);
bool _isValidKey(Object? key) =>
(key is K) && (_isValidKeyFn == null || _isValidKeyFn!(key));
}
-
-/// A collection used to identify cyclic maps during toString() calls.
-final List _toStringVisiting = [];
-
-/// Check if we are currently visiting `o` in a toString() call.
-bool _isToStringVisiting(o) => _toStringVisiting.any((e) => identical(o, e));
diff --git a/lib/src/combined_wrappers/combined_iterable.dart b/lib/src/combined_wrappers/combined_iterable.dart
index 8c5f091..97d843f 100644
--- a/lib/src/combined_wrappers/combined_iterable.dart
+++ b/lib/src/combined_wrappers/combined_iterable.dart
@@ -4,6 +4,8 @@
import 'dart:collection';
+import 'combined_iterator.dart';
+
/// A view of several iterables combined sequentially into a single iterable.
///
/// All methods and accessors treat the [CombinedIterableView] as if it were a
@@ -20,7 +22,7 @@
@override
Iterator<T> get iterator =>
- _CombinedIterator<T>(_iterables.map((i) => i.iterator).iterator);
+ 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.
@@ -34,41 +36,3 @@
@override
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;
-
- /// The current iterator in [_iterators], or `null` if done iterating.
- Iterator<T>? _currentItr;
-
- _CombinedIterator(this._iterators) {
- _advance();
- }
-
- @override
- T get current => _iterators.current.current;
-
- @override
- bool moveNext() {
- if (_currentItr == null) return false;
- if (_currentItr!.moveNext()) {
- return true;
- } else {
- _advance();
- }
- return moveNext();
- }
-
- /// Advances [_currentItr] or sets it to `null` if there are no more entries
- /// in [_iterators].
- void _advance() {
- _currentItr = _iterators.moveNext() ? _iterators.current : null;
- }
-}
diff --git a/lib/src/combined_wrappers/combined_iterator.dart b/lib/src/combined_wrappers/combined_iterator.dart
new file mode 100644
index 0000000..0d6088a
--- /dev/null
+++ b/lib/src/combined_wrappers/combined_iterator.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2020, 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.
+
+/// The iterator for `CombinedIterableView` and `CombinedListView`.
+///
+/// Moves through each iterable's iterator in sequence.
+class CombinedIterator<T> implements Iterator<T> {
+ /// The iterators that this combines, or `null` if done iterating.
+ ///
+ /// Because this comes from a call to [Iterable.map], it's lazy and will
+ /// avoid instantiating unnecessary iterators.
+ Iterator<Iterator<T>>? _iterators;
+
+ CombinedIterator(Iterator<Iterator<T>> iterators) : _iterators = iterators {
+ if (!iterators.moveNext()) _iterators = null;
+ }
+
+ @override
+ T get current {
+ var iterators = _iterators;
+ if (iterators != null) return iterators.current.current;
+ return null as T;
+ }
+
+ @override
+ bool moveNext() {
+ var iterators = _iterators;
+ if (iterators != null) {
+ do {
+ if (iterators.current.moveNext()) {
+ return true;
+ }
+ } while (iterators.moveNext());
+ _iterators = null;
+ }
+ return false;
+ }
+}
diff --git a/lib/src/combined_wrappers/combined_list.dart b/lib/src/combined_wrappers/combined_list.dart
index e341be4..c9a2eb8 100644
--- a/lib/src/combined_wrappers/combined_list.dart
+++ b/lib/src/combined_wrappers/combined_list.dart
@@ -4,6 +4,8 @@
import 'dart:collection';
+import 'combined_iterator.dart';
+
/// A view of several lists combined into a single list.
///
/// All methods and accessors treat the [CombinedListView] list as if it were a
@@ -26,6 +28,10 @@
CombinedListView(this._lists);
@override
+ Iterator<T> get iterator =>
+ CombinedIterator<T>(_lists.map((i) => i.iterator).iterator);
+
+ @override
set length(int length) {
_throw();
}
diff --git a/lib/src/empty_unmodifiable_set.dart b/lib/src/empty_unmodifiable_set.dart
index 6d7f03c..44bd5ef 100644
--- a/lib/src/empty_unmodifiable_set.dart
+++ b/lib/src/empty_unmodifiable_set.dart
@@ -4,24 +4,20 @@
import 'dart:collection';
+import 'package:collection/collection.dart';
+
import 'unmodifiable_wrappers.dart';
-// Unfortunately, we can't use UnmodifiableSetMixin here, since const classes
-// can't use mixins.
-/// An unmodifiable, empty set that can have a const constructor.
+/// An unmodifiable, empty set which can be constant.
class EmptyUnmodifiableSet<E> extends IterableBase<E>
+ with UnmodifiableSetMixin<E>
implements UnmodifiableSetView<E> {
- static T _throw<T>() {
- throw UnsupportedError('Cannot modify an unmodifiable Set');
- }
+ const EmptyUnmodifiableSet();
@override
Iterator<E> get iterator => Iterable<E>.empty().iterator;
@override
int get length => 0;
-
- const EmptyUnmodifiableSet();
-
@override
EmptyUnmodifiableSet<T> cast<T>() => EmptyUnmodifiableSet<T>();
@override
@@ -29,7 +25,7 @@
@override
bool containsAll(Iterable<Object?> other) => other.isEmpty;
@override
- Iterable<E> followedBy(Iterable<E> other) => Set.from(other);
+ Iterable<E> followedBy(Iterable<E> other) => DelegatingIterable(other);
@override
E? lookup(Object? element) => null;
@deprecated
@@ -37,32 +33,15 @@
EmptyUnmodifiableSet<T> retype<T>() => EmptyUnmodifiableSet<T>();
@override
E singleWhere(bool Function(E) test, {E Function()? orElse}) =>
- super.singleWhere(test);
+ orElse != null ? orElse() : throw StateError('No element');
@override
- Iterable<T> whereType<T>() => EmptyUnmodifiableSet<T>();
+ Iterable<T> whereType<T>() => Iterable.empty();
@override
Set<E> toSet() => {};
@override
- Set<E> union(Set<E> other) => Set.from(other);
+ Set<E> union(Set<E> other) => Set.of(other);
@override
Set<E> intersection(Set<Object?> other) => {};
@override
Set<E> difference(Set<Object?> other) => {};
-
- @override
- bool add(E value) => _throw();
- @override
- void addAll(Iterable<E> elements) => _throw();
- @override
- void clear() => _throw();
- @override
- bool remove(Object? element) => _throw();
- @override
- void removeAll(Iterable<Object?> elements) => _throw();
- @override
- void removeWhere(bool Function(E) test) => _throw();
- @override
- void retainWhere(bool Function(E) test) => _throw();
- @override
- void retainAll(Iterable<Object?> elements) => _throw();
}
diff --git a/lib/src/functions.dart b/lib/src/functions.dart
index 8f401d4..07c8d4b 100644
--- a/lib/src/functions.dart
+++ b/lib/src/functions.dart
@@ -31,7 +31,7 @@
/// values. If [value] is omitted, the value from [map2] is used.
Map<K, V> mergeMaps<K, V>(Map<K, V> map1, Map<K, V> map2,
{V Function(V, V)? value}) {
- var result = Map<K, V>.from(map1);
+ var result = Map<K, V>.of(map1);
if (value == null) return result..addAll(map2);
map2.forEach((key, mapValue) {
diff --git a/lib/src/iterable_zip.dart b/lib/src/iterable_zip.dart
index 940b5e7..9671eaf 100644
--- a/lib/src/iterable_zip.dart
+++ b/lib/src/iterable_zip.dart
@@ -23,7 +23,6 @@
@override
Iterator<List<T>> get iterator {
var iterators = _iterables.map((x) => x.iterator).toList(growable: false);
- // TODO(lrn): Return an empty iterator directly if iterators is empty?
return _IteratorZip<T>(iterators);
}
}
@@ -49,5 +48,5 @@
}
@override
- List<T> get current => _current!;
+ List<T> get current => _current ?? (throw StateError('No element'));
}
diff --git a/lib/src/queue_list.dart b/lib/src/queue_list.dart
index 14b696e..3bf13f2 100644
--- a/lib/src/queue_list.dart
+++ b/lib/src/queue_list.dart
@@ -25,26 +25,25 @@
return _CastQueueList<S, T>(source);
}
- static const int _INITIAL_CAPACITY = 8;
- late List<E?> _table;
+ /// Default and minimal initial capacity of the queue-list.
+ static const int _initialCapacity = 8;
+ List<E?> _table;
int _head;
int _tail;
- /// Create an empty queue.
+ /// Creates an empty queue.
///
/// If [initialCapacity] is given, prepare the queue for at least that many
/// elements.
QueueList([int? initialCapacity])
- : _head = 0,
- _tail = 0 {
- if (initialCapacity == null || initialCapacity < _INITIAL_CAPACITY) {
- initialCapacity = _INITIAL_CAPACITY;
- } else if (!_isPowerOf2(initialCapacity)) {
- initialCapacity = _nextPowerOf2(initialCapacity);
- }
- assert(_isPowerOf2(initialCapacity));
- _table = List<E?>.filled(initialCapacity, null);
- }
+ : this._init(_computeInitialCapacity(initialCapacity));
+
+ /// Creates an empty queue with the specific initial capacity.
+ QueueList._init(int initialCapacity)
+ : assert(_isPowerOf2(initialCapacity)),
+ _table = List<E?>.filled(initialCapacity, null),
+ _head = 0,
+ _tail = 0;
/// An internal constructor for use by [_CastQueueList].
QueueList._(this._head, this._tail, this._table);
@@ -64,6 +63,18 @@
}
}
+ /// Computes the actual initial capacity based on the constructor parameter.
+ static int _computeInitialCapacity(int? initialCapacity) {
+ if (initialCapacity == null || initialCapacity < _initialCapacity) {
+ return _initialCapacity;
+ }
+ initialCapacity += 1;
+ if (_isPowerOf2(initialCapacity)) {
+ return initialCapacity;
+ }
+ return _nextPowerOf2(initialCapacity);
+ }
+
// Collection interface.
@override
@@ -137,7 +148,7 @@
E removeLast() {
if (_head == _tail) throw StateError('No element');
_tail = (_tail - 1) & (_table.length - 1);
- var result = _table[_tail]!;
+ var result = _table[_tail] as E;
_table[_tail] = null;
return result;
}
diff --git a/lib/src/union_set.dart b/lib/src/union_set.dart
index 2fe6e3e..37aee48 100644
--- a/lib/src/union_set.dart
+++ b/lib/src/union_set.dart
@@ -29,7 +29,9 @@
/// is, that they contain no elements in common. This makes many operations
/// including [length] more efficient. If the component sets turn out not to
/// be disjoint, some operations may behave inconsistently.
- UnionSet(this._sets, {bool disjoint = false}) : _disjoint = disjoint;
+ UnionSet(Set<Set<E>> sets, {bool disjoint = false})
+ : _sets = sets,
+ _disjoint = disjoint;
/// Creates a new set that's a view of the union of all sets in [sets].
///
@@ -66,20 +68,13 @@
@override
E? lookup(Object? element) {
- if (element == null) return null;
for (var set in _sets) {
var result = set.lookup(element);
- if (result != null) return result;
+ if (result != null || set.contains(null)) return result;
}
return null;
}
@override
- Set<E> toSet() {
- var result = <E>{};
- for (var set in _sets) {
- result.addAll(set);
- }
- return result;
- }
+ Set<E> toSet() => <E>{for (var set in _sets) ...set};
}
diff --git a/lib/src/union_set_controller.dart b/lib/src/union_set_controller.dart
index 245081d..ea3622a 100644
--- a/lib/src/union_set_controller.dart
+++ b/lib/src/union_set_controller.dart
@@ -23,20 +23,21 @@
/// ```
class UnionSetController<E> {
/// The [UnionSet] that provides a view of the union of sets in [this].
- UnionSet<E> get set => _set;
- late final UnionSet<E> _set;
+ final UnionSet<E> set;
/// The sets whose union is exposed through [set].
- final _sets = <Set<E>>{};
+ final Set<Set<E>> _sets;
/// Creates a set of sets that provides a view of the union of those sets.
///
/// If [disjoint] is `true`, this assumes that all component sets are
/// disjoint—that is, that they contain no elements in common. This makes
/// many operations including [length] more efficient.
- UnionSetController({bool disjoint = false}) {
- _set = UnionSet<E>(_sets, disjoint: disjoint);
- }
+ UnionSetController({bool disjoint = false}) : this._(<Set<E>>{}, disjoint);
+
+ /// Creates a controller with the provided [_sets].
+ UnionSetController._(this._sets, bool disjoint)
+ : set = UnionSet<E>(_sets, disjoint: disjoint);
/// Adds the contents of [component] to [set].
///
diff --git a/lib/src/unmodifiable_wrappers.dart b/lib/src/unmodifiable_wrappers.dart
index 96551e8..c6cf2cd 100644
--- a/lib/src/unmodifiable_wrappers.dart
+++ b/lib/src/unmodifiable_wrappers.dart
@@ -26,7 +26,7 @@
/// Mixin class that implements a throwing version of all list operations that
/// change the List's length.
abstract class NonGrowableListMixin<E> implements List<E> {
- static T _throw<T>() {
+ static Never _throw() {
throw UnsupportedError('Cannot change the length of a fixed-length list');
}
@@ -98,9 +98,9 @@
/// An unmodifiable set.
///
-/// An UnmodifiableSetView contains a [Set] object and ensures
-/// that it does not change.
-/// Methods that would change the set,
+/// An [UnmodifiableSetView] contains a [Set],
+/// and prevents that set from being changed through the view.
+/// Methods that could change the set,
/// such as [add] and [remove], throw an [UnsupportedError].
/// Permitted operations defer to the wrapped set.
class UnmodifiableSetView<E> extends DelegatingSet<E>
@@ -117,7 +117,7 @@
/// Mixin class that implements a throwing version of all set operations that
/// change the Set.
abstract class UnmodifiableSetMixin<E> implements Set<E> {
- static T _throw<T>() {
+ static Never _throw() {
throw UnsupportedError('Cannot modify an unmodifiable Set');
}
@@ -165,7 +165,7 @@
/// Mixin class that implements a throwing version of all map operations that
/// change the Map.
abstract class UnmodifiableMapMixin<K, V> implements Map<K, V> {
- static T _throw<T>() {
+ static Never _throw() {
throw UnsupportedError('Cannot modify an unmodifiable Map');
}
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 194f99c..00ea932 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -2,14 +2,6 @@
// 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.
-/// A pair of values.
-class Pair<E, F> {
- E first;
- F last;
-
- Pair(this.first, this.last);
-}
-
/// Returns a [Comparator] that asserts that its first argument is comparable.
Comparator<T> defaultCompare<T>() =>
(value1, value2) => (value1 as Comparable).compareTo(value2);
diff --git a/lib/src/wrappers.dart b/lib/src/wrappers.dart
index 14e2d8c..b5b61e3 100644
--- a/lib/src/wrappers.dart
+++ b/lib/src/wrappers.dart
@@ -148,8 +148,11 @@
/// This class can be used to hide non-`List` methods of a list object, or it
/// can be extended to add extra functionality on top of an existing list
/// object.
-class DelegatingList<E> extends DelegatingIterable<E> implements List<E> {
- const DelegatingList(List<E> base) : super(base);
+class DelegatingList<E> extends _DelegatingIterableBase<E> implements List<E> {
+ @override
+ final List<E> _base;
+
+ const DelegatingList(List<E> base) : _base = base;
/// Creates a wrapper that asserts the types of values in [base].
///
@@ -165,43 +168,41 @@
@Deprecated('Use list.cast<E> instead.')
static List<E> typed<E>(List base) => base.cast<E>();
- List<E> get _listBase => _base as List<E>;
-
@override
- E operator [](int index) => _listBase[index];
+ E operator [](int index) => _base[index];
@override
void operator []=(int index, E value) {
- _listBase[index] = value;
+ _base[index] = value;
}
@override
- List<E> operator +(List<E> other) => _listBase + other;
+ List<E> operator +(List<E> other) => _base + other;
@override
void add(E value) {
- _listBase.add(value);
+ _base.add(value);
}
@override
void addAll(Iterable<E> iterable) {
- _listBase.addAll(iterable);
+ _base.addAll(iterable);
}
@override
- Map<int, E> asMap() => _listBase.asMap();
+ Map<int, E> asMap() => _base.asMap();
@override
- List<T> cast<T>() => _listBase.cast<T>();
+ List<T> cast<T>() => _base.cast<T>();
@override
void clear() {
- _listBase.clear();
+ _base.clear();
}
@override
void fillRange(int start, int end, [E? fillValue]) {
- _listBase.fillRange(start, end, fillValue);
+ _base.fillRange(start, end, fillValue);
}
@override
@@ -211,23 +212,23 @@
}
@override
- Iterable<E> getRange(int start, int end) => _listBase.getRange(start, end);
+ Iterable<E> getRange(int start, int end) => _base.getRange(start, end);
@override
- int indexOf(E element, [int start = 0]) => _listBase.indexOf(element, start);
+ int indexOf(E element, [int start = 0]) => _base.indexOf(element, start);
@override
int indexWhere(bool Function(E) test, [int start = 0]) =>
- _listBase.indexWhere(test, start);
+ _base.indexWhere(test, start);
@override
void insert(int index, E element) {
- _listBase.insert(index, element);
+ _base.insert(index, element);
}
@override
void insertAll(int index, Iterable<E> iterable) {
- _listBase.insertAll(index, iterable);
+ _base.insertAll(index, iterable);
}
@override
@@ -237,45 +238,44 @@
}
@override
- int lastIndexOf(E element, [int? start]) =>
- _listBase.lastIndexOf(element, start);
+ int lastIndexOf(E element, [int? start]) => _base.lastIndexOf(element, start);
@override
int lastIndexWhere(bool Function(E) test, [int? start]) =>
- _listBase.lastIndexWhere(test, start);
+ _base.lastIndexWhere(test, start);
@override
set length(int newLength) {
- _listBase.length = newLength;
+ _base.length = newLength;
}
@override
- bool remove(Object? value) => _listBase.remove(value);
+ bool remove(Object? value) => _base.remove(value);
@override
- E removeAt(int index) => _listBase.removeAt(index);
+ E removeAt(int index) => _base.removeAt(index);
@override
- E removeLast() => _listBase.removeLast();
+ E removeLast() => _base.removeLast();
@override
void removeRange(int start, int end) {
- _listBase.removeRange(start, end);
+ _base.removeRange(start, end);
}
@override
void removeWhere(bool Function(E) test) {
- _listBase.removeWhere(test);
+ _base.removeWhere(test);
}
@override
void replaceRange(int start, int end, Iterable<E> iterable) {
- _listBase.replaceRange(start, end, iterable);
+ _base.replaceRange(start, end, iterable);
}
@override
void retainWhere(bool Function(E) test) {
- _listBase.retainWhere(test);
+ _base.retainWhere(test);
}
@deprecated
@@ -283,38 +283,41 @@
List<T> retype<T>() => cast<T>();
@override
- Iterable<E> get reversed => _listBase.reversed;
+ Iterable<E> get reversed => _base.reversed;
@override
void setAll(int index, Iterable<E> iterable) {
- _listBase.setAll(index, iterable);
+ _base.setAll(index, iterable);
}
@override
void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
- _listBase.setRange(start, end, iterable, skipCount);
+ _base.setRange(start, end, iterable, skipCount);
}
@override
void shuffle([math.Random? random]) {
- _listBase.shuffle(random);
+ _base.shuffle(random);
}
@override
void sort([int Function(E, E)? compare]) {
- _listBase.sort(compare);
+ _base.sort(compare);
}
@override
- List<E> sublist(int start, [int? end]) => _listBase.sublist(start, end);
+ List<E> sublist(int start, [int? end]) => _base.sublist(start, end);
}
/// A [Set] that delegates all operations to a base set.
///
/// This class can be used to hide non-`Set` methods of a set object, or it can
/// be extended to add extra functionality on top of an existing set object.
-class DelegatingSet<E> extends DelegatingIterable<E> implements Set<E> {
- const DelegatingSet(Set<E> base) : super(base);
+class DelegatingSet<E> extends _DelegatingIterableBase<E> implements Set<E> {
+ @override
+ final Set<E> _base;
+
+ const DelegatingSet(Set<E> base) : _base = base;
/// Creates a wrapper that asserts the types of values in [base].
///
@@ -330,52 +333,50 @@
@Deprecated('Use set.cast<E> instead.')
static Set<E> typed<E>(Set base) => base.cast<E>();
- Set<E> get _setBase => _base as Set<E>;
-
@override
- bool add(E value) => _setBase.add(value);
+ bool add(E value) => _base.add(value);
@override
void addAll(Iterable<E> elements) {
- _setBase.addAll(elements);
+ _base.addAll(elements);
}
@override
- Set<T> cast<T>() => _setBase.cast<T>();
+ Set<T> cast<T>() => _base.cast<T>();
@override
void clear() {
- _setBase.clear();
+ _base.clear();
}
@override
- bool containsAll(Iterable<Object?> other) => _setBase.containsAll(other);
+ bool containsAll(Iterable<Object?> other) => _base.containsAll(other);
@override
- Set<E> difference(Set<Object?> other) => _setBase.difference(other);
+ Set<E> difference(Set<Object?> other) => _base.difference(other);
@override
- Set<E> intersection(Set<Object?> other) => _setBase.intersection(other);
+ Set<E> intersection(Set<Object?> other) => _base.intersection(other);
@override
- E? lookup(Object? element) => _setBase.lookup(element);
+ E? lookup(Object? element) => _base.lookup(element);
@override
- bool remove(Object? value) => _setBase.remove(value);
+ bool remove(Object? value) => _base.remove(value);
@override
void removeAll(Iterable<Object?> elements) {
- _setBase.removeAll(elements);
+ _base.removeAll(elements);
}
@override
void removeWhere(bool Function(E) test) {
- _setBase.removeWhere(test);
+ _base.removeWhere(test);
}
@override
void retainAll(Iterable<Object?> elements) {
- _setBase.retainAll(elements);
+ _base.retainAll(elements);
}
@deprecated
@@ -384,14 +385,14 @@
@override
void retainWhere(bool Function(E) test) {
- _setBase.retainWhere(test);
+ _base.retainWhere(test);
}
@override
- Set<E> union(Set<E> other) => _setBase.union(other);
+ Set<E> union(Set<E> other) => _base.union(other);
@override
- Set<E> toSet() => DelegatingSet<E>(_setBase.toSet());
+ Set<E> toSet() => DelegatingSet<E>(_base.toSet());
}
/// A [Queue] that delegates all operations to a base queue.
@@ -399,8 +400,12 @@
/// This class can be used to hide non-`Queue` methods of a queue object, or it
/// can be extended to add extra functionality on top of an existing queue
/// object.
-class DelegatingQueue<E> extends DelegatingIterable<E> implements Queue<E> {
- const DelegatingQueue(Queue<E> queue) : super(queue);
+class DelegatingQueue<E> extends _DelegatingIterableBase<E>
+ implements Queue<E> {
+ @override
+ final Queue<E> _base;
+
+ const DelegatingQueue(Queue<E> queue) : _base = queue;
/// Creates a wrapper that asserts the types of values in [base].
///
@@ -416,47 +421,45 @@
@Deprecated('Use queue.cast<E> instead.')
static Queue<E> typed<E>(Queue base) => base.cast<E>();
- Queue<E> get _baseQueue => _base as Queue<E>;
-
@override
void add(E value) {
- _baseQueue.add(value);
+ _base.add(value);
}
@override
void addAll(Iterable<E> iterable) {
- _baseQueue.addAll(iterable);
+ _base.addAll(iterable);
}
@override
void addFirst(E value) {
- _baseQueue.addFirst(value);
+ _base.addFirst(value);
}
@override
void addLast(E value) {
- _baseQueue.addLast(value);
+ _base.addLast(value);
}
@override
- Queue<T> cast<T>() => _baseQueue.cast<T>();
+ Queue<T> cast<T>() => _base.cast<T>();
@override
void clear() {
- _baseQueue.clear();
+ _base.clear();
}
@override
- bool remove(Object? object) => _baseQueue.remove(object);
+ bool remove(Object? object) => _base.remove(object);
@override
void removeWhere(bool Function(E) test) {
- _baseQueue.removeWhere(test);
+ _base.removeWhere(test);
}
@override
void retainWhere(bool Function(E) test) {
- _baseQueue.retainWhere(test);
+ _base.retainWhere(test);
}
@deprecated
@@ -464,10 +467,10 @@
Queue<T> retype<T>() => cast<T>();
@override
- E removeFirst() => _baseQueue.removeFirst();
+ E removeFirst() => _base.removeFirst();
@override
- E removeLast() => _baseQueue.removeLast();
+ E removeLast() => _base.removeLast();
}
/// A [Map] that delegates all operations to a base map.
@@ -616,7 +619,7 @@
int get length => _baseMap.length;
@override
- String toString() => "{${_base.join(', ')}}";
+ String toString() => SetBase.setToString(this);
@override
bool containsAll(Iterable<Object?> other) => other.every(contains);
@@ -805,7 +808,7 @@
var key = _keyForValue(element);
if (!_baseMap.containsKey(key)) continue;
- valuesToRetain.add(_baseMap[key]!);
+ valuesToRetain.add(_baseMap[key] ?? null as V);
}
var keysToRemove = [];