blob: b4c8a9c8b85f30b3d9719d9c66871639dd993411 [file] [log] [blame]
// Copyright (c) 2011, 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 protobuf;
typedef CheckFunc(x);
class PbList<E> extends Object with ListMixin<E> implements List<E> {
final List<E> _wrappedList;
final CheckFunc check;
PbList({this.check: _checkNotNull}) : _wrappedList = <E>[] {
assert(check != null);
}
PbList.from(List from)
// TODO(sra): Should this be validated?
: _wrappedList = new List<E>.from(from),
check = _checkNotNull;
factory PbList.forFieldType(int fieldType) =>
new PbList(check: getCheckFunction(fieldType));
bool operator ==(other) => (other is PbList) && _areListsEqual(other, this);
int get hashCode {
int hash = 0;
for (final value in _wrappedList) {
hash = (hash + value.hashCode) & 0x3fffffff;
hash = (hash + hash << 10) & 0x3fffffff;
hash = (hash ^ hash >> 6) & 0x3fffffff;
}
hash = (hash + hash << 3) & 0x3fffffff;
hash = (hash ^ hash >> 11) & 0x3fffffff;
hash = (hash + hash << 15) & 0x3fffffff;
return hash;
}
/// Returns an [Iterator] for the list.
Iterator<E> get iterator => _wrappedList.iterator;
/// Returns a new lazy [Iterable] with elements that are created by calling
/// `f` on each element of this `PbList` in iteration order.
Iterable<T> map<T>(T f(E e)) => _wrappedList.map<T>(f);
/// Applies the function [f] to each element of this list in iteration order.
void forEach(void f(E element)) {
_wrappedList.forEach(f);
}
/// Returns the element at the given [index] in the list or throws an
/// [IndexOutOfRangeException] if [index] is out of bounds.
E operator [](int index) => _wrappedList[index];
/// Sets the entry at the given [index] in the list to [value].
/// Throws an [IndexOutOfRangeException] if [index] is out of bounds.
void operator []=(int index, E value) {
_validate(value);
_wrappedList[index] = value;
}
/// Unsupported -- violated non-null constraint imposed by protobufs.
///
/// Changes the length of the list. If [newLength] is greater than the current
/// [length], entries are initialized to [:null:]. Throws an
/// [UnsupportedError] if the list is not extendable.
void set length(int newLength) {
if (newLength > length) {
throw new ArgumentError('Extending protobuf lists is not supported');
}
_wrappedList.length = newLength;
}
/// Adds [value] at the end of the list, extending the length by one.
/// Throws an [UnsupportedError] if the list is not extendable.
void add(E value) {
_validate(value);
_wrappedList.add(value);
}
/// Appends all elements of the [collection] to the end of list.
/// Extends the length of the list by the length of [collection].
/// Throws an [UnsupportedError] if the list is not extendable.
void addAll(Iterable<E> collection) {
collection.forEach(_validate);
_wrappedList.addAll(collection);
}
/// Copies [:end - start:] elements of the [from] array, starting from
/// [skipCount], into [:this:], starting at [start].
/// Throws an [UnsupportedError] if the list is not extendable.
void setRange(int start, int end, Iterable<E> from, [int skipCount = 0]) {
// NOTE: In case `take()` returns less than `end - start` elements, the
// _wrappedList will fail with a `StateError`.
from.skip(skipCount).take(end - start).forEach(_validate);
_wrappedList.setRange(start, end, from, skipCount);
}
/// Inserts a new element in the list.
/// The element must be valid (and not nullable) for the PbList type.
void insert(int index, E element) {
_validate(element);
_wrappedList.insert(index, element);
}
/// Inserts all elements of [iterable] at position [index] in the list.
///
/// Elements in [iterable] must be valid and not nullable for the PbList type.
void insertAll(int index, Iterable<E> iterable) {
iterable.forEach(_validate);
_wrappedList.insertAll(index, iterable);
}
/// Overwrites elements of `this` with elements of [iterable] starting at
/// position [index] in the list.
///
/// Elements in [iterable] must be valid and not nullable for the PbList type.
void setAll(int index, Iterable<E> iterable) {
iterable.forEach(_validate);
_wrappedList.setAll(index, iterable);
}
/// Returns the number of elements in this collection.
int get length => _wrappedList.length;
void _validate(E val) {
check(val);
// TODO: remove after migration to check functions is finished
if (val is! E) {
throw new ArgumentError('Value ($val) is not of the correct type');
}
}
}