|  | // 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 "core_patch.dart"; | 
|  |  | 
|  | /// Immutable map class for compiler generated map literals. | 
|  | // TODO(lrn): Extend MapBase with UnmodifiableMapMixin when mixins | 
|  | // support forwarding const constructors. | 
|  | @pragma("vm:entry-point") | 
|  | class _ImmutableMap<K, V> implements Map<K, V> { | 
|  | final _ImmutableList _kvPairs; | 
|  |  | 
|  | @pragma("vm:entry-point") | 
|  | const _ImmutableMap._create(_ImmutableList keyValuePairs) | 
|  | : _kvPairs = keyValuePairs; | 
|  |  | 
|  | Map<K2, V2> cast<K2, V2>() => Map.castFrom<K, V, K2, V2>(this); | 
|  | V operator [](Object key) { | 
|  | // To preserve the key-value order of the map literal, the keys are | 
|  | // not sorted. Need to do linear search or implement an additional | 
|  | // lookup table. | 
|  | for (int i = 0; i < _kvPairs.length - 1; i += 2) { | 
|  | if (key == _kvPairs[i]) { | 
|  | return _kvPairs[i + 1]; | 
|  | } | 
|  | } | 
|  | return null; | 
|  | } | 
|  |  | 
|  | bool get isEmpty { | 
|  | return _kvPairs.length == 0; | 
|  | } | 
|  |  | 
|  | bool get isNotEmpty => !isEmpty; | 
|  |  | 
|  | int get length { | 
|  | return _kvPairs.length ~/ 2; | 
|  | } | 
|  |  | 
|  | void forEach(void f(K key, V value)) { | 
|  | for (int i = 0; i < _kvPairs.length; i += 2) { | 
|  | f(_kvPairs[i], _kvPairs[i + 1]); | 
|  | } | 
|  | } | 
|  |  | 
|  | Iterable<K> get keys { | 
|  | return new _ImmutableMapKeyIterable<K>(this); | 
|  | } | 
|  |  | 
|  | Iterable<V> get values { | 
|  | return new _ImmutableMapValueIterable<V>(this); | 
|  | } | 
|  |  | 
|  | bool containsKey(Object key) { | 
|  | for (int i = 0; i < _kvPairs.length; i += 2) { | 
|  | if (key == _kvPairs[i]) { | 
|  | return true; | 
|  | } | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool containsValue(Object value) { | 
|  | for (int i = 1; i < _kvPairs.length; i += 2) { | 
|  | if (value == _kvPairs[i]) { | 
|  | return true; | 
|  | } | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | void operator []=(K key, V value) { | 
|  | throw new UnsupportedError("Cannot set value in unmodifiable Map"); | 
|  | } | 
|  |  | 
|  | void addAll(Map<K, V> other) { | 
|  | throw new UnsupportedError("Cannot set value in unmodifiable Map"); | 
|  | } | 
|  |  | 
|  | V putIfAbsent(K key, V ifAbsent()) { | 
|  | throw new UnsupportedError("Cannot set value in unmodifiable Map"); | 
|  | } | 
|  |  | 
|  | void clear() { | 
|  | throw new UnsupportedError("Cannot clear unmodifiable Map"); | 
|  | } | 
|  |  | 
|  | V remove(Object key) { | 
|  | throw new UnsupportedError("Cannot remove from unmodifiable Map"); | 
|  | } | 
|  |  | 
|  | Iterable<MapEntry<K, V>> get entries => | 
|  | new _ImmutableMapEntryIterable<K, V>(this); | 
|  |  | 
|  | Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> f(K key, V value)) { | 
|  | var result = <K2, V2>{}; | 
|  | for (int i = 0; i < _kvPairs.length; i += 2) { | 
|  | var entry = f(_kvPairs[i], _kvPairs[i + 1]); | 
|  | result[entry.key] = entry.value; | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | void addEntries(Iterable<MapEntry<K, V>> newEntries) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable Map"); | 
|  | } | 
|  |  | 
|  | V update(K key, V update(V value), {V ifAbsent()}) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable Map"); | 
|  | } | 
|  |  | 
|  | void updateAll(V update(K key, V value)) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable Map"); | 
|  | } | 
|  |  | 
|  | void removeWhere(bool predicate(K key, V value)) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable Map"); | 
|  | } | 
|  |  | 
|  | String toString() => MapBase.mapToString(this); | 
|  | } | 
|  |  | 
|  | class _ImmutableMapKeyIterable<E> extends EfficientLengthIterable<E> { | 
|  | final _ImmutableMap _map; | 
|  | _ImmutableMapKeyIterable(this._map); | 
|  |  | 
|  | Iterator<E> get iterator { | 
|  | return new _ImmutableMapKeyIterator<E>(_map); | 
|  | } | 
|  |  | 
|  | int get length => _map.length; | 
|  | } | 
|  |  | 
|  | class _ImmutableMapValueIterable<E> extends EfficientLengthIterable<E> { | 
|  | final _ImmutableMap _map; | 
|  | _ImmutableMapValueIterable(this._map); | 
|  |  | 
|  | Iterator<E> get iterator { | 
|  | return new _ImmutableMapValueIterator<E>(_map); | 
|  | } | 
|  |  | 
|  | int get length => _map.length; | 
|  | } | 
|  |  | 
|  | class _ImmutableMapEntryIterable<K, V> | 
|  | extends EfficientLengthIterable<MapEntry<K, V>> { | 
|  | final _ImmutableMap _map; | 
|  | _ImmutableMapEntryIterable(this._map); | 
|  |  | 
|  | Iterator<MapEntry<K, V>> get iterator { | 
|  | return new _ImmutableMapEntryIterator<K, V>(_map); | 
|  | } | 
|  |  | 
|  | int get length => _map.length; | 
|  | } | 
|  |  | 
|  | class _ImmutableMapKeyIterator<E> implements Iterator<E> { | 
|  | _ImmutableMap _map; | 
|  | int _nextIndex = 0; | 
|  | E _current; | 
|  |  | 
|  | _ImmutableMapKeyIterator(this._map); | 
|  |  | 
|  | bool moveNext() { | 
|  | int newIndex = _nextIndex; | 
|  | if (newIndex < _map.length) { | 
|  | _nextIndex = newIndex + 1; | 
|  | _current = _map._kvPairs[newIndex * 2]; | 
|  | return true; | 
|  | } | 
|  | _current = null; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | E get current => _current; | 
|  | } | 
|  |  | 
|  | class _ImmutableMapValueIterator<E> implements Iterator<E> { | 
|  | _ImmutableMap _map; | 
|  | int _nextIndex = 0; | 
|  | E _current; | 
|  |  | 
|  | _ImmutableMapValueIterator(this._map); | 
|  |  | 
|  | bool moveNext() { | 
|  | int newIndex = _nextIndex; | 
|  | if (newIndex < _map.length) { | 
|  | _nextIndex = newIndex + 1; | 
|  | _current = _map._kvPairs[newIndex * 2 + 1]; | 
|  | return true; | 
|  | } | 
|  | _current = null; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | E get current => _current; | 
|  | } | 
|  |  | 
|  | class _ImmutableMapEntryIterator<K, V> implements Iterator<MapEntry<K, V>> { | 
|  | _ImmutableMap _map; | 
|  | int _nextIndex = 0; | 
|  | MapEntry<K, V> _current; | 
|  |  | 
|  | _ImmutableMapEntryIterator(this._map); | 
|  |  | 
|  | bool moveNext() { | 
|  | int newIndex = _nextIndex; | 
|  | if (newIndex < _map.length) { | 
|  | _nextIndex = newIndex + 1; | 
|  | _current = new MapEntry<K, V>( | 
|  | _map._kvPairs[newIndex * 2], _map._kvPairs[newIndex * 2 + 1]); | 
|  | return true; | 
|  | } | 
|  | _current = null; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | MapEntry<K, V> get current => _current; | 
|  | } |