// 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 extends Iterable { Iterable get _source; Iterator get iterator => CastIterator(_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 skip(int count) => CastIterable(_source.skip(count)); Iterable take(int count) => CastIterable(_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 implements Iterator { Iterator _source; CastIterator(this._source); bool moveNext() => _source.moveNext(); T get current => _source.current as T; } class CastIterable extends _CastIterableBase { final Iterable _source; CastIterable._(this._source); factory CastIterable(Iterable source) { if (source is EfficientLengthIterable) { return _EfficientLengthCastIterable(source); } return CastIterable._(source); } Iterable cast() => CastIterable(_source); } class _EfficientLengthCastIterable extends CastIterable implements EfficientLengthIterable, HideEfficientLengthIterable { _EfficientLengthCastIterable(EfficientLengthIterable source) : super._(source); } abstract class _CastListBase extends _CastIterableBase with ListMixin { List 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 values) { _source.addAll(CastIterable(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 elements) { _source.insertAll(index, CastIterable(elements)); } void setAll(int index, Iterable elements) { _source.setAll(index, CastIterable(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 getRange(int start, int end) => CastIterable(_source.getRange(start, end)); void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { _source.setRange(start, end, CastIterable(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 replacement) { _source.replaceRange(start, end, CastIterable(replacement)); } } class CastList extends _CastListBase { final List _source; CastList(this._source); List cast() => CastList(_source); } class CastSet extends _CastIterableBase implements Set { final Set _source; /// Creates a new empty set of the same *kind* as [_source], /// but with `` as type argument. /// Used by [toSet] and [union]. final Set Function()? _emptySet; CastSet(this._source, this._emptySet); Set cast() => CastSet(_source, _emptySet); bool add(T value) => _source.add(value as S); void addAll(Iterable elements) { _source.addAll(CastIterable(elements)); } bool remove(Object? object) => _source.remove(object); void removeAll(Iterable objects) { _source.removeAll(objects); } void retainAll(Iterable 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 objects) => _source.containsAll(objects); Set intersection(Set other) { if (_emptySet != null) return _conditionalAdd(other, true); return CastSet(_source.intersection(other), null); } Set difference(Set other) { if (_emptySet != null) return _conditionalAdd(other, false); return CastSet(_source.difference(other), null); } Set _conditionalAdd(Set other, bool otherContains) { var emptySet = _emptySet; Set result = (emptySet == null) ? Set() : emptySet(); for (var element in _source) { T castElement = element as T; if (otherContains == other.contains(castElement)) result.add(castElement); } return result; } Set union(Set other) => _clone()..addAll(other); void clear() { _source.clear(); } Set _clone() { var emptySet = _emptySet; Set result = (emptySet == null) ? Set() : emptySet(); result.addAll(this); return result; } Set toSet() => _clone(); T lookup(Object? key) => _source.lookup(key) as T; } class CastMap extends MapBase { final Map _source; CastMap(this._source); Map cast() => CastMap(_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 other) { _source.addAll(CastMap(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 get keys => CastIterable(_source.keys); Iterable get values => CastIterable(_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> get entries { return _source.entries.map>( (MapEntry e) => MapEntry(e.key as K, e.value as V), ); } void addEntries(Iterable> 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 extends _CastIterableBase implements Queue { final Queue _source; CastQueue(this._source); Queue cast() => CastQueue(_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 elements) { _source.addAll(CastIterable(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(); } }