// 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. */ mixin FixedLengthListMixin { /** This operation is not supported by a fixed length list. */ set length(int newLength) { throw 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 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 UnsupportedError("Cannot add to a fixed-length list"); } /** This operation is not supported by a fixed length list. */ void insertAll(int at, Iterable iterable) { throw UnsupportedError("Cannot add to a fixed-length list"); } /** This operation is not supported by a fixed length list. */ void addAll(Iterable iterable) { throw UnsupportedError("Cannot add to a fixed-length list"); } /** This operation is not supported by a fixed length list. */ bool remove(Object? element) { throw 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 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 UnsupportedError("Cannot remove from a fixed-length list"); } /** This operation is not supported by a fixed length list. */ void clear() { throw UnsupportedError("Cannot clear a fixed-length list"); } /** This operation is not supported by a fixed length list. */ E removeAt(int index) { throw UnsupportedError("Cannot remove from a fixed-length list"); } /** This operation is not supported by a fixed length list. */ E removeLast() { throw 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 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 iterable) { throw 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. */ mixin UnmodifiableListMixin implements List { /** This operation is not supported by an unmodifiable list. */ void operator []=(int index, E value) { throw UnsupportedError("Cannot modify an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ set length(int newLength) { throw UnsupportedError("Cannot change the length of an unmodifiable list"); } set first(E element) { throw UnsupportedError("Cannot modify an unmodifiable list"); } set last(E element) { throw UnsupportedError("Cannot modify an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ void setAll(int at, Iterable iterable) { throw UnsupportedError("Cannot modify an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ void add(E value) { throw UnsupportedError("Cannot add to an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ void insert(int index, E element) { throw UnsupportedError("Cannot add to an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ void insertAll(int at, Iterable iterable) { throw UnsupportedError("Cannot add to an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ void addAll(Iterable iterable) { throw UnsupportedError("Cannot add to an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ bool remove(Object? element) { throw UnsupportedError("Cannot remove from an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ void removeWhere(bool test(E element)) { throw UnsupportedError("Cannot remove from an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ void retainWhere(bool test(E element)) { throw UnsupportedError("Cannot remove from an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ void sort([Comparator? compare]) { throw UnsupportedError("Cannot modify an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ void shuffle([Random? random]) { throw UnsupportedError("Cannot modify an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ void clear() { throw UnsupportedError("Cannot clear an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ E removeAt(int index) { throw UnsupportedError("Cannot remove from an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ E removeLast() { throw UnsupportedError("Cannot remove from an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { throw UnsupportedError("Cannot modify an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ void removeRange(int start, int end) { throw UnsupportedError("Cannot remove from an unmodifiable list"); } /** This operation is not supported by an unmodifiable list. */ void replaceRange(int start, int end, Iterable iterable) { throw 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 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 = ListBase with FixedLengthListMixin; /** * Abstract implementation of an unmodifiable list. * * All operations are defined in terms of `length` and `operator[]`, * which need to be implemented. */ abstract class UnmodifiableListBase = ListBase with UnmodifiableListMixin; final class _ListIndicesIterable extends ListIterable { List _backedList; _ListIndicesIterable(this._backedList); int get length => _backedList.length; int elementAt(int index) { IndexError.check(index, length, indexable: this); return index; } } class ListMapView extends UnmodifiableMapBase { List _values; ListMapView(this._values); E? operator [](Object? key) => containsKey(key) ? _values[key as int] : null; int get length => _values.length; Iterable get values => SubListIterable(_values, 0, null); Iterable get keys => _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 ConcurrentModificationError(_values); } } } } final class ReversedListIterable extends ListIterable { Iterable _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() => UnsupportedError("Cannot add to unmodifiable List"); /** Error thrown when trying to add elements to an unmodifiable list. */ static UnsupportedError change() => UnsupportedError("Cannot change the content of an unmodifiable List"); /** Error thrown when trying to change the length of an unmodifiable list. */ static UnsupportedError length() => UnsupportedError("Cannot change length of unmodifiable List"); /** Error thrown when trying to remove elements from an unmodifiable list. */ static UnsupportedError remove() => 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() => UnsupportedError("Cannot add to non-growable List"); /** Error thrown when trying to change the length of an non-growable list. */ static UnsupportedError length() => UnsupportedError("Cannot change length of non-growable List"); /** Error thrown when trying to remove elements from an non-growable list. */ static UnsupportedError remove() => 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 like the one created by `[]`. * 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 * `List.filled(length)`/`List.empty()`, * 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 reference should not be used afterwards. * * The unmodifiable list type is similar to the one used by const lists. */ external List makeFixedListUnmodifiable(List fixedLengthList);