|  | // 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.collection; | 
|  |  | 
|  | /// Base class for implementing a [Map]. | 
|  | /// | 
|  | /// This class has a basic implementation of all but five of the members of | 
|  | /// [Map]. | 
|  | /// A basic `Map` class can be implemented by extending this class and | 
|  | /// implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`. | 
|  | /// The remaining operations are implemented in terms of these five. | 
|  | /// | 
|  | /// The `keys` iterable should have efficient [Iterable.length] and | 
|  | /// [Iterable.contains] operations, and it should catch concurrent modifications | 
|  | /// of the keys while iterating. | 
|  | /// | 
|  | /// A more efficient implementation is usually possible by overriding | 
|  | /// some of the other members as well. | 
|  | abstract mixin class MapBase<K, V> implements Map<K, V> { | 
|  | const MapBase(); | 
|  |  | 
|  | Iterable<K> get keys; | 
|  | V? operator [](Object? key); | 
|  | operator []=(K key, V value); | 
|  | V? remove(Object? key); | 
|  | // The `clear` operation should not be based on `remove`. | 
|  | // It should clear the map even if some keys are not equal to themselves. | 
|  | void clear(); | 
|  |  | 
|  | Map<RK, RV> cast<RK, RV>() => Map.castFrom<K, V, RK, RV>(this); | 
|  | void forEach(void action(K key, V value)) { | 
|  | for (K key in keys) { | 
|  | action(key, this[key] as V); | 
|  | } | 
|  | } | 
|  |  | 
|  | void addAll(Map<K, V> other) { | 
|  | other.forEach((K key, V value) { | 
|  | this[key] = value; | 
|  | }); | 
|  | } | 
|  |  | 
|  | bool containsValue(Object? value) { | 
|  | for (K key in keys) { | 
|  | if (this[key] == value) return true; | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | V putIfAbsent(K key, V ifAbsent()) { | 
|  | if (containsKey(key)) { | 
|  | return this[key] as V; | 
|  | } | 
|  | return this[key] = ifAbsent(); | 
|  | } | 
|  |  | 
|  | V update(K key, V update(V value), {V Function()? ifAbsent}) { | 
|  | if (this.containsKey(key)) { | 
|  | return this[key] = update(this[key] as V); | 
|  | } | 
|  | if (ifAbsent != null) { | 
|  | return this[key] = ifAbsent(); | 
|  | } | 
|  | throw ArgumentError.value(key, "key", "Key not in map."); | 
|  | } | 
|  |  | 
|  | void updateAll(V update(K key, V value)) { | 
|  | for (var key in this.keys) { | 
|  | this[key] = update(key, this[key] as V); | 
|  | } | 
|  | } | 
|  |  | 
|  | Iterable<MapEntry<K, V>> get entries { | 
|  | return keys.map((K key) => MapEntry<K, V>(key, this[key] as V)); | 
|  | } | 
|  |  | 
|  | Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> transform(K key, V value)) { | 
|  | var result = <K2, V2>{}; | 
|  | for (var key in this.keys) { | 
|  | var entry = transform(key, this[key] as V); | 
|  | result[entry.key] = entry.value; | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | void addEntries(Iterable<MapEntry<K, V>> newEntries) { | 
|  | for (var entry in newEntries) { | 
|  | this[entry.key] = entry.value; | 
|  | } | 
|  | } | 
|  |  | 
|  | void removeWhere(bool test(K key, V value)) { | 
|  | var keysToRemove = <K>[]; | 
|  | for (var key in keys) { | 
|  | if (test(key, this[key] as V)) keysToRemove.add(key); | 
|  | } | 
|  | for (var key in keysToRemove) { | 
|  | this.remove(key); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool containsKey(Object? key) => keys.contains(key); | 
|  | int get length => keys.length; | 
|  | bool get isEmpty => keys.isEmpty; | 
|  | bool get isNotEmpty => keys.isNotEmpty; | 
|  | Iterable<V> get values => _MapBaseValueIterable<K, V>(this); | 
|  | String toString() => mapToString(this); | 
|  |  | 
|  | static String mapToString(Map<Object?, Object?> m) { | 
|  | // Reuses the list used by Iterable for detecting toString cycles. | 
|  | if (isToStringVisiting(m)) { | 
|  | return '{...}'; | 
|  | } | 
|  |  | 
|  | var result = StringBuffer(); | 
|  | try { | 
|  | toStringVisiting.add(m); | 
|  | result.write('{'); | 
|  | bool first = true; | 
|  | m.forEach((Object? k, Object? v) { | 
|  | if (!first) { | 
|  | result.write(', '); | 
|  | } | 
|  | first = false; | 
|  | result.write(k); | 
|  | result.write(': '); | 
|  | result.write(v); | 
|  | }); | 
|  | result.write('}'); | 
|  | } finally { | 
|  | assert(identical(toStringVisiting.last, m)); | 
|  | toStringVisiting.removeLast(); | 
|  | } | 
|  |  | 
|  | return result.toString(); | 
|  | } | 
|  |  | 
|  | /// Fills a [Map] with key/value pairs computed from [iterable]. | 
|  | /// | 
|  | /// This method is used by [Map] classes in the named constructor | 
|  | /// `fromIterable`. | 
|  | static void _fillMapWithMappedIterable( | 
|  | Map<Object?, Object?> map, | 
|  | Iterable<Object?> iterable, | 
|  | Object? Function(Object? element)? key, | 
|  | Object? Function(Object? element)? value, | 
|  | ) { | 
|  | key ??= _id; | 
|  | value ??= _id; | 
|  |  | 
|  | for (var element in iterable) { | 
|  | map[key(element)] = value(element); | 
|  | } | 
|  | } | 
|  |  | 
|  | static Object? _id(Object? x) => x; | 
|  |  | 
|  | /// Fills a map by associating the [keys] to [values]. | 
|  | /// | 
|  | /// This method is used by [Map] classes in the named constructor | 
|  | /// `fromIterables`. | 
|  | static void _fillMapWithIterables( | 
|  | Map<Object?, Object?> map, | 
|  | Iterable<Object?> keys, | 
|  | Iterable<Object?> values, | 
|  | ) { | 
|  | Iterator<Object?> keyIterator = keys.iterator; | 
|  | Iterator<Object?> valueIterator = values.iterator; | 
|  |  | 
|  | bool hasNextKey = keyIterator.moveNext(); | 
|  | bool hasNextValue = valueIterator.moveNext(); | 
|  |  | 
|  | while (hasNextKey && hasNextValue) { | 
|  | map[keyIterator.current] = valueIterator.current; | 
|  | hasNextKey = keyIterator.moveNext(); | 
|  | hasNextValue = valueIterator.moveNext(); | 
|  | } | 
|  |  | 
|  | if (hasNextKey || hasNextValue) { | 
|  | throw ArgumentError("Iterables do not have same length."); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Mixin implementing a [Map]. | 
|  | /// | 
|  | /// This mixin has a basic implementation of all but five of the members of | 
|  | /// [Map]. | 
|  | /// A basic `Map` class can be implemented by mixin in this class and | 
|  | /// implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`. | 
|  | /// The remaining operations are implemented in terms of these five. | 
|  | /// | 
|  | /// The `keys` iterable should have efficient [Iterable.length] and | 
|  | /// [Iterable.contains] operations, and it should catch concurrent modifications | 
|  | /// of the keys while iterating. | 
|  | /// | 
|  | /// A more efficient implementation is usually possible by overriding | 
|  | /// some of the other members as well. | 
|  | // TODO: @Deprecated("Use MapBase instead") | 
|  | // Longer term: Deprecate `Map` unnamed constructor, to allow using `Map` | 
|  | // as skeleton class and replace `MapBase`. | 
|  | typedef MapMixin<K, V> = MapBase<K, V>; | 
|  |  | 
|  | /// Basic implementation of an unmodifiable [Map]. | 
|  | /// | 
|  | /// This class has a basic implementation of all but two of the members of | 
|  | /// an unmodifiable [Map]. | 
|  | /// A simple unmodifiable `Map` class can be implemented by extending this | 
|  | /// class and implementing `keys` and `operator[]`. | 
|  | /// | 
|  | /// Modifying operations throw when used. | 
|  | /// The remaining non-modifying operations are implemented in terms of `keys` | 
|  | /// and `operator[]`. | 
|  | /// | 
|  | /// The `keys` iterable should have efficient [Iterable.length] and | 
|  | /// [Iterable.contains] operations, and it should catch concurrent modifications | 
|  | /// of the keys while iterating. | 
|  | /// | 
|  | /// A more efficient implementation is usually possible by overriding | 
|  | /// some of the other members as well. | 
|  | abstract class UnmodifiableMapBase<K, V> = MapBase<K, V> | 
|  | with _UnmodifiableMapMixin<K, V>; | 
|  |  | 
|  | /// Implementation of [Map.values] based on the map and its [Map.keys] iterable. | 
|  | /// | 
|  | /// Iterable that iterates over the values of a `Map`. | 
|  | /// It accesses the values by iterating over the keys of the map, and using the | 
|  | /// map's `operator[]` to lookup the keys. | 
|  | class _MapBaseValueIterable<K, V> extends EfficientLengthIterable<V> | 
|  | implements HideEfficientLengthIterable<V> { | 
|  | final Map<K, V> _map; | 
|  | _MapBaseValueIterable(this._map); | 
|  |  | 
|  | int get length => _map.length; | 
|  | bool get isEmpty => _map.isEmpty; | 
|  | bool get isNotEmpty => _map.isNotEmpty; | 
|  | V get first => _map[_map.keys.first] as V; | 
|  | V get single => _map[_map.keys.single] as V; | 
|  | V get last => _map[_map.keys.last] as V; | 
|  |  | 
|  | Iterator<V> get iterator => _MapBaseValueIterator<K, V>(_map); | 
|  | } | 
|  |  | 
|  | /// Iterator created by [_MapBaseValueIterable]. | 
|  | /// | 
|  | /// Iterates over the values of a map by iterating its keys and lookup up the | 
|  | /// values. | 
|  | class _MapBaseValueIterator<K, V> implements Iterator<V> { | 
|  | final Iterator<K> _keys; | 
|  | final Map<K, V> _map; | 
|  | V? _current; | 
|  |  | 
|  | _MapBaseValueIterator(Map<K, V> map) : _map = map, _keys = map.keys.iterator; | 
|  |  | 
|  | bool moveNext() { | 
|  | if (_keys.moveNext()) { | 
|  | _current = _map[_keys.current]; | 
|  | return true; | 
|  | } | 
|  | _current = null; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | V get current => _current as V; | 
|  | } | 
|  |  | 
|  | /// Mixin that overrides mutating map operations with implementations that | 
|  | /// throw. | 
|  | mixin _UnmodifiableMapMixin<K, V> implements Map<K, V> { | 
|  | /// This operation is not supported by an unmodifiable map. | 
|  | void operator []=(K key, V value) { | 
|  | throw UnsupportedError("Cannot modify unmodifiable map"); | 
|  | } | 
|  |  | 
|  | /// This operation is not supported by an unmodifiable map. | 
|  | void addAll(Map<K, V> other) { | 
|  | throw UnsupportedError("Cannot modify unmodifiable map"); | 
|  | } | 
|  |  | 
|  | /// This operation is not supported by an unmodifiable map. | 
|  | void addEntries(Iterable<MapEntry<K, V>> entries) { | 
|  | throw UnsupportedError("Cannot modify unmodifiable map"); | 
|  | } | 
|  |  | 
|  | /// This operation is not supported by an unmodifiable map. | 
|  | void clear() { | 
|  | throw UnsupportedError("Cannot modify unmodifiable map"); | 
|  | } | 
|  |  | 
|  | /// This operation is not supported by an unmodifiable map. | 
|  | V? remove(Object? key) { | 
|  | throw UnsupportedError("Cannot modify unmodifiable map"); | 
|  | } | 
|  |  | 
|  | /// This operation is not supported by an unmodifiable map. | 
|  | void removeWhere(bool test(K key, V value)) { | 
|  | throw UnsupportedError("Cannot modify unmodifiable map"); | 
|  | } | 
|  |  | 
|  | /// This operation is not supported by an unmodifiable map. | 
|  | V putIfAbsent(K key, V ifAbsent()) { | 
|  | throw UnsupportedError("Cannot modify unmodifiable map"); | 
|  | } | 
|  |  | 
|  | /// This operation is not supported by an unmodifiable map. | 
|  | V update(K key, V update(V value), {V Function()? ifAbsent}) { | 
|  | throw UnsupportedError("Cannot modify unmodifiable map"); | 
|  | } | 
|  |  | 
|  | /// This operation is not supported by an unmodifiable map. | 
|  | void updateAll(V update(K key, V value)) { | 
|  | throw UnsupportedError("Cannot modify unmodifiable map"); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Wrapper around a class that implements [Map] that only exposes `Map` | 
|  | /// members. | 
|  | /// | 
|  | /// A simple wrapper that delegates all `Map` members to the map provided in the | 
|  | /// constructor. | 
|  | /// | 
|  | /// Base for delegating map implementations like [UnmodifiableMapView]. | 
|  | class MapView<K, V> implements Map<K, V> { | 
|  | final Map<K, V> _map; | 
|  |  | 
|  | /// Creates a view which forwards operations to [map]. | 
|  | const MapView(Map<K, V> map) : _map = map; | 
|  |  | 
|  | Map<RK, RV> cast<RK, RV>() => _map.cast<RK, RV>(); | 
|  | V? operator [](Object? key) => _map[key]; | 
|  | void operator []=(K key, V value) { | 
|  | _map[key] = value; | 
|  | } | 
|  |  | 
|  | void addAll(Map<K, V> other) { | 
|  | _map.addAll(other); | 
|  | } | 
|  |  | 
|  | void clear() { | 
|  | _map.clear(); | 
|  | } | 
|  |  | 
|  | V putIfAbsent(K key, V ifAbsent()) => _map.putIfAbsent(key, ifAbsent); | 
|  | bool containsKey(Object? key) => _map.containsKey(key); | 
|  | bool containsValue(Object? value) => _map.containsValue(value); | 
|  | void forEach(void action(K key, V value)) { | 
|  | _map.forEach(action); | 
|  | } | 
|  |  | 
|  | bool get isEmpty => _map.isEmpty; | 
|  | bool get isNotEmpty => _map.isNotEmpty; | 
|  | int get length => _map.length; | 
|  | Iterable<K> get keys => _map.keys; | 
|  | V? remove(Object? key) => _map.remove(key); | 
|  | String toString() => _map.toString(); | 
|  | Iterable<V> get values => _map.values; | 
|  |  | 
|  | Iterable<MapEntry<K, V>> get entries => _map.entries; | 
|  |  | 
|  | void addEntries(Iterable<MapEntry<K, V>> entries) { | 
|  | _map.addEntries(entries); | 
|  | } | 
|  |  | 
|  | Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> transform(K key, V value)) => | 
|  | _map.map<K2, V2>(transform); | 
|  |  | 
|  | V update(K key, V update(V value), {V Function()? ifAbsent}) => | 
|  | _map.update(key, update, ifAbsent: ifAbsent); | 
|  |  | 
|  | void updateAll(V update(K key, V value)) { | 
|  | _map.updateAll(update); | 
|  | } | 
|  |  | 
|  | void removeWhere(bool test(K key, V value)) { | 
|  | _map.removeWhere(test); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// View of a [Map] that disallow modifying the map. | 
|  | /// | 
|  | /// A wrapper around a `Map` that forwards all members to the map provided in | 
|  | /// the constructor, except for operations that modify the map. | 
|  | /// Modifying operations throw instead. | 
|  | /// | 
|  | /// ```dart | 
|  | /// final baseMap = <int, String>{1: 'Mars', 2: 'Mercury', 3: 'Venus'}; | 
|  | /// final unmodifiableMapView = UnmodifiableMapView(baseMap); | 
|  | /// | 
|  | /// // Remove an entry from the original map. | 
|  | /// baseMap.remove(3); | 
|  | /// print(unmodifiableMapView); // {1: Mars, 2: Mercury} | 
|  | /// | 
|  | /// unmodifiableMapView.remove(1); // Throws. | 
|  | /// ``` | 
|  | class UnmodifiableMapView<K, V> extends MapView<K, V> | 
|  | with _UnmodifiableMapMixin<K, V> { | 
|  | UnmodifiableMapView(Map<K, V> map) : super(map); | 
|  |  | 
|  | Map<RK, RV> cast<RK, RV>() => | 
|  | UnmodifiableMapView<RK, RV>(_map.cast<RK, RV>()); | 
|  | } |