blob: 5b8aeb541088bf2612d5ef78a3cb681e589b1053 [file] [log] [blame]
// 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.
// @dart = 2.9
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"}");
}
}