mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
bef857b6cb
Change-Id: Id4a5e5b100ca1c429070263555ab730622644d19 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/127161 Reviewed-by: Leaf Petersen <leafp@google.com> Commit-Queue: Nicholas Shahan <nshahan@google.com>
363 lines
9.7 KiB
Dart
363 lines
9.7 KiB
Dart
// Copyright (c) 2012, 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.
|
|
|
|
part of dart._internal;
|
|
|
|
// Casting wrappers for collection classes.
|
|
|
|
abstract class _CastIterableBase<S, T> extends Iterable<T> {
|
|
Iterable<S> get _source;
|
|
|
|
Iterator<T> get iterator => new CastIterator<S, T>(_source.iterator);
|
|
|
|
// The following members use the default implementation on the
|
|
// throwing iterator. These are all operations that have no more efficient
|
|
// implementation than visiting every element in order,
|
|
// or that has no more efficient way to get the correct type (toList, toSet).
|
|
//
|
|
// * map
|
|
// * where
|
|
// * expand
|
|
// * forEach
|
|
// * reduce
|
|
// * fold
|
|
// * every
|
|
// * any
|
|
// * join
|
|
// * toList
|
|
// * toSet
|
|
// * skipWhile
|
|
// * takeWhile
|
|
// * firstWhere
|
|
// * singleWhere
|
|
|
|
int get length => _source.length;
|
|
bool get isEmpty => _source.isEmpty;
|
|
bool get isNotEmpty => _source.isNotEmpty;
|
|
|
|
Iterable<T> skip(int count) => new CastIterable<S, T>(_source.skip(count));
|
|
Iterable<T> take(int count) => new CastIterable<S, T>(_source.take(count));
|
|
|
|
T elementAt(int index) => _source.elementAt(index) as T;
|
|
T get first => _source.first as T;
|
|
T get last => _source.last as T;
|
|
T get single => _source.single as T;
|
|
|
|
bool contains(Object? other) => _source.contains(other);
|
|
|
|
// Might be implemented by testing backwards from the end,
|
|
// so use the _source's implementation.
|
|
T lastWhere(bool test(T element), {T Function()? orElse}) =>
|
|
_source.lastWhere((S element) => test(element as T),
|
|
orElse: (orElse == null) ? null : () => orElse() as S) as T;
|
|
|
|
String toString() => _source.toString();
|
|
}
|
|
|
|
class CastIterator<S, T> implements Iterator<T> {
|
|
Iterator<S> _source;
|
|
CastIterator(this._source);
|
|
bool moveNext() => _source.moveNext();
|
|
T get current => _source.current as T;
|
|
}
|
|
|
|
class CastIterable<S, T> extends _CastIterableBase<S, T> {
|
|
final Iterable<S> _source;
|
|
|
|
CastIterable._(this._source);
|
|
|
|
factory CastIterable(Iterable<S> source) {
|
|
if (source is EfficientLengthIterable<S>) {
|
|
return new _EfficientLengthCastIterable<S, T>(source);
|
|
}
|
|
return new CastIterable<S, T>._(source);
|
|
}
|
|
|
|
Iterable<R> cast<R>() => new CastIterable<S, R>(_source);
|
|
}
|
|
|
|
class _EfficientLengthCastIterable<S, T> extends CastIterable<S, T>
|
|
implements EfficientLengthIterable<T> {
|
|
_EfficientLengthCastIterable(EfficientLengthIterable<S> source)
|
|
: super._(source);
|
|
}
|
|
|
|
abstract class _CastListBase<S, T> extends _CastIterableBase<S, T>
|
|
with ListMixin<T> {
|
|
List<S> get _source;
|
|
|
|
// Using the default implementation from ListMixin:
|
|
// * reversed
|
|
// * shuffle
|
|
// * indexOf
|
|
// * lastIndexOf
|
|
// * clear
|
|
// * sublist
|
|
// * asMap
|
|
|
|
T operator [](int index) => _source[index] as T;
|
|
|
|
void operator []=(int index, T value) {
|
|
_source[index] = value as S;
|
|
}
|
|
|
|
void set length(int length) {
|
|
_source.length = length;
|
|
}
|
|
|
|
void add(T value) {
|
|
_source.add(value as S);
|
|
}
|
|
|
|
void addAll(Iterable<T> values) {
|
|
_source.addAll(new CastIterable<T, S>(values));
|
|
}
|
|
|
|
void sort([int Function(T v1, T v2)? compare]) {
|
|
_source.sort(
|
|
compare == null ? null : (S v1, S v2) => compare(v1 as T, v2 as T));
|
|
}
|
|
|
|
void shuffle([Random? random]) {
|
|
_source.shuffle(random);
|
|
}
|
|
|
|
void insert(int index, T element) {
|
|
_source.insert(index, element as S);
|
|
}
|
|
|
|
void insertAll(int index, Iterable<T> elements) {
|
|
_source.insertAll(index, new CastIterable<T, S>(elements));
|
|
}
|
|
|
|
void setAll(int index, Iterable<T> elements) {
|
|
_source.setAll(index, new CastIterable<T, S>(elements));
|
|
}
|
|
|
|
bool remove(Object? value) => _source.remove(value);
|
|
|
|
T removeAt(int index) => _source.removeAt(index) as T;
|
|
|
|
T removeLast() => _source.removeLast() as T;
|
|
|
|
void removeWhere(bool test(T element)) {
|
|
_source.removeWhere((S element) => test(element as T));
|
|
}
|
|
|
|
void retainWhere(bool test(T element)) {
|
|
_source.retainWhere((S element) => test(element as T));
|
|
}
|
|
|
|
Iterable<T> getRange(int start, int end) =>
|
|
new CastIterable<S, T>(_source.getRange(start, end));
|
|
|
|
void setRange(int start, int end, Iterable<T> iterable, [int skipCount = 0]) {
|
|
_source.setRange(start, end, new CastIterable<T, S>(iterable), skipCount);
|
|
}
|
|
|
|
void removeRange(int start, int end) {
|
|
_source.removeRange(start, end);
|
|
}
|
|
|
|
void fillRange(int start, int end, [T? fillValue]) {
|
|
_source.fillRange(start, end, fillValue as S);
|
|
}
|
|
|
|
void replaceRange(int start, int end, Iterable<T> replacement) {
|
|
_source.replaceRange(start, end, new CastIterable<T, S>(replacement));
|
|
}
|
|
}
|
|
|
|
class CastList<S, T> extends _CastListBase<S, T> {
|
|
final List<S> _source;
|
|
CastList(this._source);
|
|
|
|
List<R> cast<R>() => new CastList<S, R>(_source);
|
|
}
|
|
|
|
class CastSet<S, T> extends _CastIterableBase<S, T> implements Set<T> {
|
|
final Set<S> _source;
|
|
|
|
/// Creates a new empty set of the same *kind* as [_source],
|
|
/// but with `<R>` as type argument.
|
|
/// Used by [toSet] and [union].
|
|
final Set<R> Function<R>()? _emptySet;
|
|
|
|
CastSet(this._source, this._emptySet);
|
|
|
|
static Set<R> _defaultEmptySet<R>() => new Set<R>();
|
|
|
|
Set<R> cast<R>() => new CastSet<S, R>(_source, _emptySet);
|
|
bool add(T value) => _source.add(value as S);
|
|
|
|
void addAll(Iterable<T> elements) {
|
|
_source.addAll(new CastIterable<T, S>(elements));
|
|
}
|
|
|
|
bool remove(Object? object) => _source.remove(object);
|
|
|
|
void removeAll(Iterable<Object?> objects) {
|
|
_source.removeAll(objects);
|
|
}
|
|
|
|
void retainAll(Iterable<Object?> objects) {
|
|
_source.retainAll(objects);
|
|
}
|
|
|
|
void removeWhere(bool test(T element)) {
|
|
_source.removeWhere((S element) => test(element as T));
|
|
}
|
|
|
|
void retainWhere(bool test(T element)) {
|
|
_source.retainWhere((S element) => test(element as T));
|
|
}
|
|
|
|
bool containsAll(Iterable<Object?> objects) => _source.containsAll(objects);
|
|
|
|
Set<T> intersection(Set<Object?> other) {
|
|
if (_emptySet != null) return _conditionalAdd(other, true);
|
|
return new CastSet<S, T>(_source.intersection(other), null);
|
|
}
|
|
|
|
Set<T> difference(Set<Object?> other) {
|
|
if (_emptySet != null) return _conditionalAdd(other, false);
|
|
return new CastSet<S, T>(_source.difference(other), null);
|
|
}
|
|
|
|
Set<T> _conditionalAdd(Set<Object?> other, bool otherContains) {
|
|
var emptySet = _emptySet;
|
|
Set<T> result = (emptySet == null) ? new Set<T>() : emptySet<T>();
|
|
for (var element in _source) {
|
|
T castElement = element as T;
|
|
if (otherContains == other.contains(castElement)) result.add(castElement);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Set<T> union(Set<T> other) => _clone()..addAll(other);
|
|
|
|
void clear() {
|
|
_source.clear();
|
|
}
|
|
|
|
Set<T> _clone() {
|
|
var emptySet = _emptySet;
|
|
Set<T> result = (emptySet == null) ? new Set<T>() : emptySet<T>();
|
|
result.addAll(this);
|
|
return result;
|
|
}
|
|
|
|
Set<T> toSet() => _clone();
|
|
|
|
T lookup(Object? key) => _source.lookup(key) as T;
|
|
}
|
|
|
|
class CastMap<SK, SV, K, V> extends MapBase<K, V> {
|
|
final Map<SK, SV> _source;
|
|
|
|
CastMap(this._source);
|
|
|
|
Map<RK, RV> cast<RK, RV>() => new CastMap<SK, SV, RK, RV>(_source);
|
|
|
|
bool containsValue(Object? value) => _source.containsValue(value);
|
|
|
|
bool containsKey(Object? key) => _source.containsKey(key);
|
|
|
|
V? operator [](Object? key) => _source[key] as V?;
|
|
|
|
void operator []=(K key, V value) {
|
|
_source[key as SK] = value as SV;
|
|
}
|
|
|
|
V putIfAbsent(K key, V Function() ifAbsent) =>
|
|
_source.putIfAbsent(key as SK, () => ifAbsent() as SV) as V;
|
|
|
|
void addAll(Map<K, V> other) {
|
|
_source.addAll(new CastMap<K, V, SK, SV>(other));
|
|
}
|
|
|
|
V remove(Object? key) => _source.remove(key) as V;
|
|
|
|
void clear() {
|
|
_source.clear();
|
|
}
|
|
|
|
void forEach(void f(K key, V value)) {
|
|
_source.forEach((SK key, SV value) {
|
|
f(key as K, value as V);
|
|
});
|
|
}
|
|
|
|
Iterable<K> get keys => new CastIterable<SK, K>(_source.keys);
|
|
|
|
Iterable<V> get values => new CastIterable<SV, V>(_source.values);
|
|
|
|
int get length => _source.length;
|
|
|
|
bool get isEmpty => _source.isEmpty;
|
|
|
|
bool get isNotEmpty => _source.isNotEmpty;
|
|
|
|
V update(K key, V update(V value), {V Function()? ifAbsent}) {
|
|
return _source.update(key as SK, (SV value) => update(value as V) as SV,
|
|
ifAbsent: (ifAbsent == null) ? null : () => ifAbsent() as SV) as V;
|
|
}
|
|
|
|
void updateAll(V update(K key, V value)) {
|
|
_source.updateAll((SK key, SV value) => update(key as K, value as V) as SV);
|
|
}
|
|
|
|
Iterable<MapEntry<K, V>> get entries {
|
|
return _source.entries.map<MapEntry<K, V>>(
|
|
(MapEntry<SK, SV> e) => new MapEntry<K, V>(e.key as K, e.value as V));
|
|
}
|
|
|
|
void addEntries(Iterable<MapEntry<K, V>> entries) {
|
|
for (var entry in entries) {
|
|
_source[entry.key as SK] = entry.value as SV;
|
|
}
|
|
}
|
|
|
|
void removeWhere(bool test(K key, V value)) {
|
|
_source.removeWhere((SK key, SV value) => test(key as K, value as V));
|
|
}
|
|
}
|
|
|
|
class CastQueue<S, T> extends _CastIterableBase<S, T> implements Queue<T> {
|
|
final Queue<S> _source;
|
|
CastQueue(this._source);
|
|
Queue<R> cast<R>() => new CastQueue<S, R>(_source);
|
|
|
|
T removeFirst() => _source.removeFirst() as T;
|
|
T removeLast() => _source.removeLast() as T;
|
|
|
|
void add(T value) {
|
|
_source.add(value as S);
|
|
}
|
|
|
|
void addFirst(T value) {
|
|
_source.addFirst(value as S);
|
|
}
|
|
|
|
void addLast(T value) {
|
|
_source.addLast(value as S);
|
|
}
|
|
|
|
bool remove(Object? other) => _source.remove(other);
|
|
void addAll(Iterable<T> elements) {
|
|
_source.addAll(new CastIterable<T, S>(elements));
|
|
}
|
|
|
|
void removeWhere(bool test(T element)) {
|
|
_source.removeWhere((S element) => test(element as T));
|
|
}
|
|
|
|
void retainWhere(bool test(T element)) {
|
|
_source.retainWhere((S element) => test(element as T));
|
|
}
|
|
|
|
void clear() {
|
|
_source.clear();
|
|
}
|
|
}
|