|  | // Copyright (c) 2013, 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; | 
|  |  | 
|  | /** | 
|  | * Mixin that throws on the length changing operations of [List]. | 
|  | * | 
|  | * Intended to mix-in on top of [ListMixin] for fixed-length lists. | 
|  | */ | 
|  | abstract class FixedLengthListMixin<E> { | 
|  | /** This operation is not supported by a fixed length list. */ | 
|  | set length(int newLength) { | 
|  | throw new UnsupportedError( | 
|  | "Cannot change the length of a fixed-length list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by a fixed length list. */ | 
|  | void add(E value) { | 
|  | throw new UnsupportedError("Cannot add to a fixed-length list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by a fixed length list. */ | 
|  | void insert(int index, E value) { | 
|  | throw new UnsupportedError("Cannot add to a fixed-length list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by a fixed length list. */ | 
|  | void insertAll(int at, Iterable<E> iterable) { | 
|  | throw new UnsupportedError("Cannot add to a fixed-length list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by a fixed length list. */ | 
|  | void addAll(Iterable<E> iterable) { | 
|  | throw new UnsupportedError("Cannot add to a fixed-length list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by a fixed length list. */ | 
|  | bool remove(Object element) { | 
|  | throw new UnsupportedError("Cannot remove from a fixed-length list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by a fixed length list. */ | 
|  | void removeWhere(bool test(E element)) { | 
|  | throw new UnsupportedError("Cannot remove from a fixed-length list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by a fixed length list. */ | 
|  | void retainWhere(bool test(E element)) { | 
|  | throw new UnsupportedError("Cannot remove from a fixed-length list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by a fixed length list. */ | 
|  | void clear() { | 
|  | throw new UnsupportedError("Cannot clear a fixed-length list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by a fixed length list. */ | 
|  | E removeAt(int index) { | 
|  | throw new UnsupportedError("Cannot remove from a fixed-length list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by a fixed length list. */ | 
|  | E removeLast() { | 
|  | throw new UnsupportedError("Cannot remove from a fixed-length list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by a fixed length list. */ | 
|  | void removeRange(int start, int end) { | 
|  | throw new UnsupportedError("Cannot remove from a fixed-length list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by a fixed length list. */ | 
|  | void replaceRange(int start, int end, Iterable<E> iterable) { | 
|  | throw new UnsupportedError("Cannot remove from a fixed-length list"); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Mixin for an unmodifiable [List] class. | 
|  | * | 
|  | * This overrides all mutating methods with methods that throw. | 
|  | * This mixin is intended to be mixed in on top of [ListMixin] on | 
|  | * unmodifiable lists. | 
|  | */ | 
|  | abstract class UnmodifiableListMixin<E> implements List<E> { | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void operator []=(int index, E value) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | set length(int newLength) { | 
|  | throw new UnsupportedError( | 
|  | "Cannot change the length of an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void setAll(int at, Iterable<E> iterable) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void add(E value) { | 
|  | throw new UnsupportedError("Cannot add to an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void insert(int index, E element) { | 
|  | throw new UnsupportedError("Cannot add to an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void insertAll(int at, Iterable<E> iterable) { | 
|  | throw new UnsupportedError("Cannot add to an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void addAll(Iterable<E> iterable) { | 
|  | throw new UnsupportedError("Cannot add to an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | bool remove(Object element) { | 
|  | throw new UnsupportedError("Cannot remove from an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void removeWhere(bool test(E element)) { | 
|  | throw new UnsupportedError("Cannot remove from an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void retainWhere(bool test(E element)) { | 
|  | throw new UnsupportedError("Cannot remove from an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void sort([Comparator<E> compare]) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void shuffle([Random random]) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void clear() { | 
|  | throw new UnsupportedError("Cannot clear an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | E removeAt(int index) { | 
|  | throw new UnsupportedError("Cannot remove from an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | E removeLast() { | 
|  | throw new UnsupportedError("Cannot remove from an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void removeRange(int start, int end) { | 
|  | throw new UnsupportedError("Cannot remove from an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void replaceRange(int start, int end, Iterable<E> iterable) { | 
|  | throw new UnsupportedError("Cannot remove from an unmodifiable list"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable list. */ | 
|  | void fillRange(int start, int end, [E fillValue]) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable list"); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Abstract implementation of a fixed-length list. | 
|  | * | 
|  | * All operations are defined in terms of `length`, `operator[]` and | 
|  | * `operator[]=`, which need to be implemented. | 
|  | */ | 
|  | abstract class FixedLengthListBase<E> = ListBase<E> | 
|  | with FixedLengthListMixin<E>; | 
|  |  | 
|  | /** | 
|  | * Abstract implementation of an unmodifiable list. | 
|  | * | 
|  | * All operations are defined in terms of `length` and `operator[]`, | 
|  | * which need to be implemented. | 
|  | */ | 
|  | abstract class UnmodifiableListBase<E> = ListBase<E> | 
|  | with UnmodifiableListMixin<E>; | 
|  |  | 
|  | class _ListIndicesIterable extends ListIterable<int> { | 
|  | List _backedList; | 
|  |  | 
|  | _ListIndicesIterable(this._backedList); | 
|  |  | 
|  | int get length => _backedList.length; | 
|  | int elementAt(int index) { | 
|  | RangeError.checkValidIndex(index, this); | 
|  | return index; | 
|  | } | 
|  | } | 
|  |  | 
|  | class ListMapView<E> implements Map<int, E> { | 
|  | List<E> _values; | 
|  |  | 
|  | ListMapView(this._values); | 
|  |  | 
|  | E operator [](Object key) => containsKey(key) ? _values[key] : null; | 
|  | int get length => _values.length; | 
|  |  | 
|  | Iterable<E> get values => new SubListIterable<E>(_values, 0, null); | 
|  | Iterable<int> get keys => new _ListIndicesIterable(_values); | 
|  |  | 
|  | bool get isEmpty => _values.isEmpty; | 
|  | bool get isNotEmpty => _values.isNotEmpty; | 
|  | bool containsValue(Object value) => _values.contains(value); | 
|  | bool containsKey(Object key) => key is int && key >= 0 && key < length; | 
|  |  | 
|  | void forEach(void f(int key, E value)) { | 
|  | int length = _values.length; | 
|  | for (int i = 0; i < length; i++) { | 
|  | f(i, _values[i]); | 
|  | if (length != _values.length) { | 
|  | throw new ConcurrentModificationError(_values); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable map. */ | 
|  | void operator []=(int key, E value) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable map"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable map. */ | 
|  | E putIfAbsent(int key, E ifAbsent()) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable map"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable map. */ | 
|  | E remove(Object key) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable map"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable map. */ | 
|  | void clear() { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable map"); | 
|  | } | 
|  |  | 
|  | /** This operation is not supported by an unmodifiable map. */ | 
|  | void addAll(Map<int, E> other) { | 
|  | throw new UnsupportedError("Cannot modify an unmodifiable map"); | 
|  | } | 
|  |  | 
|  | String toString() => Maps.mapToString(this); | 
|  | } | 
|  |  | 
|  | class ReversedListIterable<E> extends ListIterable<E> { | 
|  | Iterable<E> _source; | 
|  | ReversedListIterable(this._source); | 
|  |  | 
|  | int get length => _source.length; | 
|  |  | 
|  | E elementAt(int index) => _source.elementAt(_source.length - 1 - index); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Creates errors thrown by unmodifiable lists when they are attempted modified. | 
|  | * | 
|  | * This class creates [UnsupportedError]s with specialized messages. | 
|  | */ | 
|  | abstract class UnmodifiableListError { | 
|  | /** Error thrown when trying to add elements to an unmodifiable list. */ | 
|  | static UnsupportedError add() => | 
|  | new UnsupportedError("Cannot add to unmodifiable List"); | 
|  |  | 
|  | /** Error thrown when trying to add elements to an unmodifiable list. */ | 
|  | static UnsupportedError change() => | 
|  | new UnsupportedError("Cannot change the content of an unmodifiable List"); | 
|  |  | 
|  | /** Error thrown when trying to change the length of an unmodifiable list. */ | 
|  | static UnsupportedError length() => | 
|  | new UnsupportedError("Cannot change length of unmodifiable List"); | 
|  |  | 
|  | /** Error thrown when trying to remove elements from an unmodifiable list. */ | 
|  | static UnsupportedError remove() => | 
|  | new UnsupportedError("Cannot remove from unmodifiable List"); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Creates errors thrown by non-growable lists when they are attempted modified. | 
|  | * | 
|  | * This class creates [UnsupportedError]s with specialized messages. | 
|  | */ | 
|  | abstract class NonGrowableListError { | 
|  | /** Error thrown when trying to add elements to an non-growable list. */ | 
|  | static UnsupportedError add() => | 
|  | new UnsupportedError("Cannot add to non-growable List"); | 
|  |  | 
|  | /** Error thrown when trying to change the length of an non-growable list. */ | 
|  | static UnsupportedError length() => | 
|  | new UnsupportedError("Cannot change length of non-growable List"); | 
|  |  | 
|  | /** Error thrown when trying to remove elements from an non-growable list. */ | 
|  | static UnsupportedError remove() => | 
|  | new UnsupportedError("Cannot remove from non-growable List"); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Converts a growable list to a fixed length list with the same elements. | 
|  | * | 
|  | * For internal use only. | 
|  | * Only works on growable lists as created by `[]` or `new List()`. | 
|  | * May throw on any other list. | 
|  | * | 
|  | * The operation is efficient. It doesn't copy the elements, but converts | 
|  | * the existing list directly to a fixed length list. | 
|  | * That means that it is a destructive conversion. | 
|  | * The original list should not be used afterwards. | 
|  | * | 
|  | * The returned list may be the same list as the original, | 
|  | * or it may be a different list (according to [identical]). | 
|  | * The original list may have changed type to be a fixed list, | 
|  | * or become empty or been otherwise modified. | 
|  | * It will still be a valid object, so references to it will not, e.g., crash | 
|  | * the runtime if accessed, but no promises are made wrt. its contents. | 
|  | * | 
|  | * This unspecified behavior is the reason the function is not exposed to | 
|  | * users. We allow the underlying implementation to make the most efficient | 
|  | * conversion, at the cost of leaving the original list in an unspecified | 
|  | * state. | 
|  | */ | 
|  | external List makeListFixedLength(List growableList); | 
|  |  | 
|  | /** | 
|  | * Converts a fixed-length list to an unmodifiable list. | 
|  | * | 
|  | * For internal use only. | 
|  | * Only works for core fixed-length lists as created by `new List(length)`, | 
|  | * or as returned by [makeListFixedLength]. | 
|  | * | 
|  | * The operation is efficient. It doesn't copy the elements, but converts | 
|  | * the existing list directly to a fixed length list. | 
|  | * That means that it is a destructive conversion. | 
|  | * The original list should not be used afterwards. | 
|  | * | 
|  | * The unmodifiable list type is similar to the one used by const lists. | 
|  | */ | 
|  | external List makeFixedListUnmodifiable(List fixedLengthList); |