Add new constructors to TypedData classes.

The new constructor creates a view of a (sub range) of the elements of another TypedData object.
It works for both typed lists and ByteData.

The advantage over the .view constructors is that it handles other views properly, including their
offsetInBytes in the start computation, which it is easy to forget to do when you call

  SomethingList.view(other.buffer)

directly, and that constructor cannot compensate for the information because it only existed on the object
that the buffer was extracted from, not on the buffer itself.

Change-Id: I8abafbf2a81a32ea67f5d4c0f65dcfea08b49bb7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/127321
Commit-Queue: Lasse R.H. Nielsen <lrn@google.com>
Reviewed-by: Jake Macdonald <jakemac@google.com>
Reviewed-by: Jonas Termansen <sortie@google.com>
This commit is contained in:
Lasse R.H. Nielsen 2020-01-22 14:39:48 +00:00 committed by commit-bot@chromium.org
parent a9ea9365ad
commit 0c71fb2d95
4 changed files with 1731 additions and 2 deletions

View file

@ -171,6 +171,12 @@ even when imported with a prefix.
* **Breaking change**: Added `IOOverrides.serverSocketBind` to aid in writing
tests that wish to mock `ServerSocket.bind`.
#### `dart:typed_data`
* Added new constructors, `.sublistView(TypedData, [start, end])` to all
`TypedData` classes. The constructor makes it easier, and less error-prone,
to create a view of (a slice of) another `TypedData` object.
### Dart VM
* New fields added to existing instances by a reload will now be initialized

View file

@ -14,7 +14,7 @@
/// {@category Core}
library dart.typed_data;
import "dart:_internal" show UnmodifiableListBase;
import "dart:_internal" show Since, UnmodifiableListBase;
part "unmodifiable_typed_data.dart";
@ -473,12 +473,56 @@ abstract class ByteData implements TypedData {
* Throws [RangeError] if [offsetInBytes] or [length] are negative, or
* if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than
* the length of [buffer].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `ByteData.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* ByteData.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [ByteData.sublistView]
* which includes this computation.
* ```dart
* ByteData.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory ByteData.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asByteData(offsetInBytes, length);
}
/**
* Creates a [ByteData] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*/
@Since("2.8")
factory ByteData.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
return data.buffer.asByteData(
data.offsetInBytes + start * elementSize, (end - start) * elementSize);
}
/**
* Returns the (possibly negative) integer represented by the byte at the
* specified [byteOffset] in this object, in two's complement binary
@ -768,12 +812,56 @@ abstract class Int8List implements List<int>, _TypedIntList {
* Throws [RangeError] if [offsetInBytes] or [length] are negative, or
* if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than
* the length of [buffer].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Int8List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Int8List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Int8List.sublistView]
* which includes this computation.
* ```dart
* Int8List.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Int8List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asInt8List(offsetInBytes, length);
}
/**
* Creates an [Int8List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*/
@Since("2.8")
factory Int8List.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
return data.buffer.asInt8List(
data.offsetInBytes + start * elementSize, (end - start) * elementSize);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -841,12 +929,56 @@ abstract class Uint8List implements List<int>, _TypedIntList {
* Throws [RangeError] if [offsetInBytes] or [length] are negative, or
* if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than
* the length of [buffer].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Uint8List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Uint8List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Uint8List.sublistView]
* which includes this computation.
* ```dart
* Uint8List.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Uint8List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asUint8List(offsetInBytes, length);
}
/**
* Creates a [Uint8List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*/
@Since("2.8")
factory Uint8List.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
return data.buffer.asUint8List(
data.offsetInBytes + start * elementSize, (end - start) * elementSize);
}
/**
* Returns a concatenation of this list and [other].
*
@ -924,12 +1056,57 @@ abstract class Uint8ClampedList implements List<int>, _TypedIntList {
* Throws [RangeError] if [offsetInBytes] or [length] are negative, or
* if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than
* the length of [buffer].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Uint8ClampedList.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Uint8ClampedList.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Uint8ClampedList.sublistView]
* which includes this computation.
* ```dart
* Uint8ClampedList.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Uint8ClampedList.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asUint8ClampedList(offsetInBytes, length);
}
/**
* Creates a [Uint8ClampedList] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*/
@Since("2.8")
factory Uint8ClampedList.sublistView(TypedData data,
[int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
return data.buffer.asUint8ClampedList(
data.offsetInBytes + start * elementSize, (end - start) * elementSize);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1001,12 +1178,64 @@ abstract class Int16List implements List<int>, _TypedIntList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Int16List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Int16List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Int16List.sublistView]
* which includes this computation.
* ```dart
* Int16List.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Int16List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asInt16List(offsetInBytes, length);
}
/**
* Creates an [Int16List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of two.
*/
@Since("2.8")
factory Int16List.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asInt16List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1079,12 +1308,64 @@ abstract class Uint16List implements List<int>, _TypedIntList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Uint16List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Uint16List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Uint16List.sublistView]
* which includes this computation.
* ```dart
* Uint16List.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Uint16List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asUint16List(offsetInBytes, length);
}
/**
* Creates a [Uint16List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of two.
*/
@Since("2.8")
factory Uint16List.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asUint16List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1156,12 +1437,64 @@ abstract class Int32List implements List<int>, _TypedIntList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Int32List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Int32List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Int32List.sublistView]
* which includes this computation.
* ```dart
* Int32List.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Int32List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asInt32List(offsetInBytes, length);
}
/**
* Creates an [Int32List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of four.
*/
@Since("2.8")
factory Int32List.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asInt32List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1234,12 +1567,64 @@ abstract class Uint32List implements List<int>, _TypedIntList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Uint32List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Uint32List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Uint32List.sublistView]
* which includes this computation.
* ```dart
* Uint32List.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Uint32List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asUint32List(offsetInBytes, length);
}
/**
* Creates a [Uint32List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of four.
*/
@Since("2.8")
factory Uint32List.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asUint32List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1311,12 +1696,64 @@ abstract class Int64List implements List<int>, _TypedIntList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Int64List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Int64List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Int64List.sublistView]
* which includes this computation.
* ```dart
* Int64List.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Int64List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asInt64List(offsetInBytes, length);
}
/**
* Creates an [Int64List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of eight.
*/
@Since("2.8")
factory Int64List.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asInt64List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1389,12 +1826,64 @@ abstract class Uint64List implements List<int>, _TypedIntList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Uint64List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Uint64List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Uint64List.sublistView]
* which includes this computation.
* ```dart
* Uint64List.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Uint64List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asUint64List(offsetInBytes, length);
}
/**
* Creates a [Uint64List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of eight.
*/
@Since("2.8")
factory Uint64List.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asUint64List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1467,12 +1956,64 @@ abstract class Float32List implements List<double>, _TypedFloatList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Float32List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Float32List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Float32List.sublistView]
* which includes this computation.
* ```dart
* Float32List.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Float32List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asFloat32List(offsetInBytes, length);
}
/**
* Creates an [Float32List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of four.
*/
@Since("2.8")
factory Float32List.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asFloat32List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1538,12 +2079,64 @@ abstract class Float64List implements List<double>, _TypedFloatList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Float64List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Float64List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Float64List.sublistView]
* which includes this computation.
* ```dart
* Float64List.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Float64List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asFloat64List(offsetInBytes, length);
}
/**
* Creates a [Float64List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of eight.
*/
@Since("2.8")
factory Float64List.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asFloat64List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1608,12 +2201,64 @@ abstract class Float32x4List implements List<Float32x4>, TypedData {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Float32x4List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Float32x4List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Float32x4List.sublistView]
* which includes this computation.
* ```dart
* Float32x4List.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Float32x4List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asFloat32x4List(offsetInBytes, length);
}
/**
* Creates a [Float32x4List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of sixteen.
*/
@Since("2.8")
factory Float32x4List.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asFloat32x4List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns the concatenation of this list and [other].
*
@ -1686,12 +2331,64 @@ abstract class Int32x4List implements List<Int32x4>, TypedData {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Int32x4List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Int32x4List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Int32x4List.sublistView]
* which includes this computation.
* ```dart
* Int32x4List.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Int32x4List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asInt32x4List(offsetInBytes, length);
}
/**
* Creates an [Int32x4List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of sixteen.
*/
@Since("2.8")
factory Int32x4List.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asInt32x4List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns the concatenation of this list and [other].
*
@ -1772,12 +2469,64 @@ abstract class Float64x2List implements List<Float64x2>, TypedData {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Float64x2List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Float64x2List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Float64x2List.sublistView]
* which includes this computation.
* ```dart
* Float64x2List.sublistView(other, 0, count)
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Float64x2List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int length]) {
return buffer.asFloat64x2List(offsetInBytes, length);
}
/**
* Creates an [Float64x2List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of sixteen.
*/
@Since("2.8")
factory Float64x2List.sublistView(TypedData data, [int start = 0, int end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asFloat64x2List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*

View file

@ -12,7 +12,7 @@
/// {@category Core}
library dart.typed_data;
import "dart:_internal" show UnmodifiableListBase;
import "dart:_internal" show Since, UnmodifiableListBase;
part "unmodifiable_typed_data.dart";
@ -471,12 +471,58 @@ abstract class ByteData implements TypedData {
* Throws [RangeError] if [offsetInBytes] or [length] are negative, or
* if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than
* the length of [buffer].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `ByteData.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* ByteData.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [ByteData.sublistView]
* which includes this computation:
* ```dart
* ByteData.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory ByteData.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asByteData(offsetInBytes, length);
}
/**
* Creates a [ByteData] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*/
@Since("2.8")
factory ByteData.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null)
throw "unreachable"; // TODO(38725): Remove when promotion works.
return data.buffer.asByteData(
data.offsetInBytes + start * elementSize, (end - start) * elementSize);
}
/**
* Returns the (possibly negative) integer represented by the byte at the
* specified [byteOffset] in this object, in two's complement binary
@ -766,12 +812,57 @@ abstract class Int8List implements List<int>, _TypedIntList {
* Throws [RangeError] if [offsetInBytes] or [length] are negative, or
* if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than
* the length of [buffer].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Int8List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Int8List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Int8List.sublistView]
* which includes this computation:
* ```dart
* Int8List.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Int8List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asInt8List(offsetInBytes, length);
}
/**
* Creates an [Int8List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*/
@Since("2.8")
factory Int8List.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
return data.buffer.asInt8List(
data.offsetInBytes + start * elementSize, (end - start) * elementSize);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -839,12 +930,57 @@ abstract class Uint8List implements List<int>, _TypedIntList {
* Throws [RangeError] if [offsetInBytes] or [length] are negative, or
* if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than
* the length of [buffer].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Uint8List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Uint8List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Uint8List.sublistView]
* which includes this computation:
* ```dart
* Uint8List.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Uint8List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asUint8List(offsetInBytes, length);
}
/**
* Creates a [Uint8List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*/
@Since("2.8")
factory Uint8List.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
return data.buffer.asUint8List(
data.offsetInBytes + start * elementSize, (end - start) * elementSize);
}
/**
* Returns a concatenation of this list and [other].
*
@ -922,12 +1058,58 @@ abstract class Uint8ClampedList implements List<int>, _TypedIntList {
* Throws [RangeError] if [offsetInBytes] or [length] are negative, or
* if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than
* the length of [buffer].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Uint8ClampedList.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Uint8ClampedList.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Uint8ClampedList.sublistView]
* which includes this computation:
* ```dart
* Uint8ClampedList.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Uint8ClampedList.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asUint8ClampedList(offsetInBytes, length);
}
/**
* Creates a [Uint8ClampedList] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*/
@Since("2.8")
factory Uint8ClampedList.sublistView(TypedData data,
[int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
return data.buffer.asUint8ClampedList(
data.offsetInBytes + start * elementSize, (end - start) * elementSize);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -999,12 +1181,65 @@ abstract class Int16List implements List<int>, _TypedIntList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Int16List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Int16List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Int16List.sublistView]
* which includes this computation:
* ```dart
* Int16List.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Int16List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asInt16List(offsetInBytes, length);
}
/**
* Creates an [Int16List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of two.
*/
@Since("2.8")
factory Int16List.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asInt16List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1077,12 +1312,65 @@ abstract class Uint16List implements List<int>, _TypedIntList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Uint16List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Uint16List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Uint16List.sublistView]
* which includes this computation:
* ```dart
* Uint16List.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Uint16List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asUint16List(offsetInBytes, length);
}
/**
* Creates a [Uint16List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of two.
*/
@Since("2.8")
factory Uint16List.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asUint16List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1154,12 +1442,65 @@ abstract class Int32List implements List<int>, _TypedIntList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Int32List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Int32List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Int32List.sublistView]
* which includes this computation:
* ```dart
* Int32List.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Int32List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asInt32List(offsetInBytes, length);
}
/**
* Creates an [Int32List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of four.
*/
@Since("2.8")
factory Int32List.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asInt32List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1232,12 +1573,65 @@ abstract class Uint32List implements List<int>, _TypedIntList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Uint32List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Uint32List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Uint32List.sublistView]
* which includes this computation:
* ```dart
* Uint32List.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Uint32List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asUint32List(offsetInBytes, length);
}
/**
* Creates a [Uint32List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of four.
*/
@Since("2.8")
factory Uint32List.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asUint32List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1309,12 +1703,65 @@ abstract class Int64List implements List<int>, _TypedIntList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Int64List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Int64List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Int64List.sublistView]
* which includes this computation:
* ```dart
* Int64List.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Int64List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asInt64List(offsetInBytes, length);
}
/**
* Creates an [Int64List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of eight.
*/
@Since("2.8")
factory Int64List.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asInt64List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1387,12 +1834,65 @@ abstract class Uint64List implements List<int>, _TypedIntList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Uint64List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Uint64List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Uint64List.sublistView]
* which includes this computation:
* ```dart
* Uint64List.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Uint64List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asUint64List(offsetInBytes, length);
}
/**
* Creates a [Uint64List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of eight.
*/
@Since("2.8")
factory Uint64List.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asUint64List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1465,12 +1965,65 @@ abstract class Float32List implements List<double>, _TypedFloatList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Float32List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Float32List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Float32List.sublistView]
* which includes this computation:
* ```dart
* Float32List.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Float32List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asFloat32List(offsetInBytes, length);
}
/**
* Creates an [Float32List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of four.
*/
@Since("2.8")
factory Float32List.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asFloat32List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1536,12 +2089,65 @@ abstract class Float64List implements List<double>, _TypedFloatList {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Float64List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Float64List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Float64List.sublistView]
* which includes this computation:
* ```dart
* Float64List.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Float64List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asFloat64List(offsetInBytes, length);
}
/**
* Creates a [Float64List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of eight.
*/
@Since("2.8")
factory Float64List.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asFloat64List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*
@ -1606,12 +2212,65 @@ abstract class Float32x4List implements List<Float32x4>, TypedData {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Float32x4List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Float32x4List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Float32x4List.sublistView]
* which includes this computation:
* ```dart
* Float32x4List.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Float32x4List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asFloat32x4List(offsetInBytes, length);
}
/**
* Creates a [Float32x4List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of sixteen.
*/
@Since("2.8")
factory Float32x4List.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asFloat32x4List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns the concatenation of this list and [other].
*
@ -1684,12 +2343,65 @@ abstract class Int32x4List implements List<Int32x4>, TypedData {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Int32x4List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Int32x4List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Int32x4List.sublistView]
* which includes this computation:
* ```dart
* Int32x4List.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Int32x4List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asInt32x4List(offsetInBytes, length);
}
/**
* Creates an [Int32x4List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of sixteen.
*/
@Since("2.8")
factory Int32x4List.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asInt32x4List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns the concatenation of this list and [other].
*
@ -1770,12 +2482,65 @@ abstract class Float64x2List implements List<Float64x2>, TypedData {
*
* Throws [ArgumentError] if [offsetInBytes] is not a multiple of
* [bytesPerElement].
*
* Note that when creating a view from a [TypedData] list or byte data,
* that list or byte data may itself be a view on a larger buffer
* with a [TypedData.offsetInBytes] greater than zero.
* Merely doing `Float64x2List.view(other.buffer, 0, count)` may not
* point to the bytes you intended. Instead you may need to do:
* ```dart
* Float64x2List.view(other.buffer, other.offsetInBytes, count)
* ```
* Alternatively, use [Float64x2List.sublistView]
* which includes this computation:
* ```dart
* Float64x2List.sublistView(other, 0, count);
* ```
* (The third argument is an end index rather than a length, so if
* you start from a position greater than zero, you need not
* reduce the count correspondingly).
*/
factory Float64x2List.view(ByteBuffer buffer,
[int offsetInBytes = 0, int? length]) {
return buffer.asFloat64x2List(offsetInBytes, length);
}
/**
* Creates an [Float64x2List] view on a range of elements of [data].
*
* Creates a view on the range of `data.buffer` which corresponds
* to the elements of [data] from [start] until [end].
* If [data] is a typed data list, like [Uint16List], then the view is on
* the bytes of the elements with indices from [start] until [end].
* If [data] is a [ByteData], it's treated like a list of bytes.
*
* If provided, [start] and [end] must satisfy
*
* 0 &le; `start` &le; `end` &le; *elementCount*
*
* where *elementCount* is the number of elements in [data], which
* is the same as the [List.length] of a typed data list.
*
* If omitted, [start] defaults to zero and [end] to *elementCount*.
*
* The start and end indices of the range of bytes being viewed must be
* multiples of sixteen.
*/
@Since("2.8")
factory Float64x2List.sublistView(TypedData data, [int start = 0, int? end]) {
int elementSize = data.elementSizeInBytes;
end = RangeError.checkValidRange(
start, end, data.lengthInBytes ~/ elementSize);
if (end == null) throw "unreachable"; // TODO(38725)
int byteLength = (end - start) * elementSize;
if (byteLength % bytesPerElement != 0) {
throw ArgumentError("The number of bytes to view must be a multiple of " +
"$bytesPerElement");
}
return data.buffer.asFloat64x2List(data.offsetInBytes + start * elementSize,
byteLength ~/ bytesPerElement);
}
/**
* Returns a new list containing the elements between [start] and [end].
*

View file

@ -0,0 +1,209 @@
// Copyright (c) 2018, 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.
import 'dart:typed_data';
import 'package:expect/expect.dart';
const bool isJS = identical(1, 1.0); // Implies no 64-bit integers.
void main() {
testViews();
testErrors();
}
void testViews() {
var bytes = Uint8List.fromList([for (int i = 0; i < 256; i++) i]);
// Non-view classes.
var bd = () {
var bd = ByteData(256);
for (int i = 0; i < 256; i++) bd.setUint8(i, i);
return bd;
}();
var u8 = Uint8List.fromList(bytes);
var i8 = Int8List.fromList(bytes);
var c8 = Uint8ClampedList.fromList(bytes);
var u16 = Uint16List.fromList(Uint16List.view(bytes.buffer));
var i16 = Int16List.fromList(Int16List.view(bytes.buffer));
var u32 = Uint32List.fromList(Uint32List.view(bytes.buffer));
var i32 = Int32List.fromList(Int32List.view(bytes.buffer));
var u64 = isJS ? null : Uint64List.fromList(Uint64List.view(bytes.buffer));
var i64 = isJS ? null : Int64List.fromList(Int64List.view(bytes.buffer));
var f32 = Float32List.fromList(Float32List.view(bytes.buffer));
var f64 = Float64List.fromList(Float64List.view(bytes.buffer));
var f32x4 = Float32x4List.fromList(Float32x4List.view(bytes.buffer));
var i32x4 = Int32x4List.fromList(Int32x4List.view(bytes.buffer));
var f64x2 = Float64x2List.fromList(Float64x2List.view(bytes.buffer));
// View classes. A buffer with the right data in the middle.
var doubleBuffer = Uint8List(512)..setRange(128, 384, bytes);
var bdv = ByteData.view(doubleBuffer.buffer, 128, 256);
var u8v = Uint8List.view(doubleBuffer.buffer, 128, 256);
var i8v = Int8List.view(doubleBuffer.buffer, 128, 256);
var c8v = Uint8ClampedList.view(doubleBuffer.buffer, 128, 256);
var u16v = Uint16List.view(doubleBuffer.buffer, 128, 128);
var i16v = Int16List.view(doubleBuffer.buffer, 128, 128);
var u32v = Uint32List.view(doubleBuffer.buffer, 128, 64);
var i32v = Int32List.view(doubleBuffer.buffer, 128, 64);
var u64v = isJS ? null : Uint64List.view(doubleBuffer.buffer, 128, 32);
var i64v = isJS ? null : Int64List.view(doubleBuffer.buffer, 128, 32);
var f32v = Float32List.view(doubleBuffer.buffer, 128, 64);
var f64v = Float64List.view(doubleBuffer.buffer, 128, 32);
var f32x4v = Float32x4List.view(doubleBuffer.buffer, 128, 16);
var i32x4v = Int32x4List.view(doubleBuffer.buffer, 128, 16);
var f64x2v = Float64x2List.view(doubleBuffer.buffer, 128, 16);
var allTypedData = <TypedData>[
bd,
u8,
i8,
c8,
u16,
i16,
u32,
i32,
if (!isJS) u64,
if (!isJS) i64,
f32,
f64,
f32x4,
i32x4,
f64x2,
u8v,
i8v,
c8v,
u16v,
i16v,
u32v,
i32v,
if (!isJS) u64v,
if (!isJS) i64v,
f32v,
f64v,
f32x4v,
i32x4v,
f64x2v,
];
for (var td in allTypedData) {
var tdType = td.runtimeType.toString();
testSame(TypedData data) {
expectBuffer(td.buffer, data.buffer);
Expect.equals(td.lengthInBytes, data.lengthInBytes);
Expect.equals(td.offsetInBytes, data.offsetInBytes);
}
testSame(ByteData.sublistView(td));
testSame(Int8List.sublistView(td));
testSame(Uint8List.sublistView(td));
testSame(Uint8ClampedList.sublistView(td));
testSame(Int16List.sublistView(td));
testSame(Uint16List.sublistView(td));
testSame(Int32List.sublistView(td));
testSame(Uint32List.sublistView(td));
if (!isJS) testSame(Int64List.sublistView(td));
if (!isJS) testSame(Uint64List.sublistView(td));
testSame(Float32List.sublistView(td));
testSame(Float64List.sublistView(td));
testSame(Float32x4List.sublistView(td));
testSame(Int32x4List.sublistView(td));
testSame(Float64x2List.sublistView(td));
var length = td.lengthInBytes ~/ td.elementSizeInBytes;
for (int start = 0; start < length; start += 16) {
for (int end = start; end < length; end += 16) {
void testSlice(TypedData data) {
var name = "$tdType -> ${data.runtimeType} $start..$end";
expectBuffer(td.buffer, data.buffer, name);
int offsetInBytes = td.offsetInBytes + start * td.elementSizeInBytes;
int lengthInBytes = (end - start) * td.elementSizeInBytes;
Expect.equals(lengthInBytes, data.lengthInBytes, name);
Expect.equals(offsetInBytes, data.offsetInBytes, name);
}
testSlice(ByteData.sublistView(td, start, end));
testSlice(Int8List.sublistView(td, start, end));
testSlice(Uint8List.sublistView(td, start, end));
testSlice(Uint8ClampedList.sublistView(td, start, end));
testSlice(Int16List.sublistView(td, start, end));
testSlice(Uint16List.sublistView(td, start, end));
testSlice(Int32List.sublistView(td, start, end));
testSlice(Uint32List.sublistView(td, start, end));
if (!isJS) testSlice(Int64List.sublistView(td, start, end));
if (!isJS) testSlice(Uint64List.sublistView(td, start, end));
testSlice(Float32List.sublistView(td, start, end));
testSlice(Float64List.sublistView(td, start, end));
testSlice(Float32x4List.sublistView(td, start, end));
testSlice(Int32x4List.sublistView(td, start, end));
testSlice(Float64x2List.sublistView(td, start, end));
}
}
}
}
void testErrors() {
// Alignment must be right for non-byte-sized results.
// offsetInBytes offset must be a multiple of the element size.
// lengthInBytes must be a multiple of the element size.
var bytes = Uint8List.fromList([for (int i = 0; i < 256; i++) i]);
var oddStartView = Uint8List.view(bytes.buffer, 1, 32);
var oddLengthView = Uint8List.view(bytes.buffer, 0, 33);
void testThrows(void Function() operation) {
Expect.throws<ArgumentError>(operation);
}
testThrows(() => Uint16List.sublistView(oddStartView));
testThrows(() => Int16List.sublistView(oddStartView));
testThrows(() => Uint32List.sublistView(oddStartView));
testThrows(() => Int32List.sublistView(oddStartView));
if (!isJS) testThrows(() => Uint64List.sublistView(oddStartView));
if (!isJS) testThrows(() => Int64List.sublistView(oddStartView));
testThrows(() => Float32List.sublistView(oddStartView));
testThrows(() => Float64List.sublistView(oddStartView));
testThrows(() => Float32x4List.sublistView(oddStartView));
testThrows(() => Int32x4List.sublistView(oddStartView));
testThrows(() => Float64x2List.sublistView(oddStartView));
testThrows(() => Uint16List.sublistView(oddLengthView));
testThrows(() => Int16List.sublistView(oddLengthView));
testThrows(() => Uint32List.sublistView(oddLengthView));
testThrows(() => Int32List.sublistView(oddLengthView));
if (!isJS) testThrows(() => Uint64List.sublistView(oddLengthView));
if (!isJS) testThrows(() => Int64List.sublistView(oddLengthView));
testThrows(() => Float32List.sublistView(oddLengthView));
testThrows(() => Float64List.sublistView(oddLengthView));
testThrows(() => Float32x4List.sublistView(oddLengthView));
testThrows(() => Int32x4List.sublistView(oddLengthView));
testThrows(() => Float64x2List.sublistView(oddLengthView));
}
void expectBuffer(ByteBuffer buffer, ByteBuffer dataBuffer, [String name]) {
// Buffer objects are not necessarily *identical* even though they
// represent the same underlying data. The VM allocates buffer objects
// lazily for inline typed data objects.
if (identical(buffer, dataBuffer)) return;
if (buffer.lengthInBytes != dataBuffer.lengthInBytes) {
Expect.fail("Different buffers${name == null ? "" : ": $name"}");
}
// Cannot distinguish empty buffers.
if (buffer.lengthInBytes == 0) return;
// Contains the same value now.
var l1 = Uint8List.view(buffer);
var l2 = Uint8List.view(dataBuffer);
var byte1 = l1[0];
var byte2 = l2[0];
if (byte1 != byte2) {
Expect.fail("Different buffers${name == null ? "" : ": $name"}");
}
// Byte written to one buffer can be read from the other.
var newByte1 = byte1 ^ 1;
l1[0] = newByte1;
var newByte2 = l2[0];
l1[0] = byte1;
if (newByte1 != newByte2) {
Expect.fail("Different buffers${name == null ? "" : ": $name"}");
}
}