Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
surma committed Apr 7, 2020
1 parent bf1c456 commit 3fa23a8
Show file tree
Hide file tree
Showing 5 changed files with 11,043 additions and 4,176 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
coverage
dist
node_modules
75 changes: 51 additions & 24 deletions aosv.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
/**
* Copyright 2020 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// Like `isNaN` but returns `true` for symbols.
function betterIsNaN(s) {
if (typeof s === "symbol") {
Expand All @@ -14,21 +27,20 @@ export function ArrayOfStructsView(buffer, descriptors) {
descriptors = Object.assign({}, descriptors);
for (const [name, descriptor] of Object.entries(descriptors)) {
// Copy second layer and add offset property
descriptors[name] = Object.assign({}, descriptor, {offset: stride})
descriptors[name] = Object.assign({}, descriptor, { offset: stride });
stride += descriptor.size;
}

const length = Math.floor(buffer.byteLength / stride);
return new Proxy(new Array(length), {
get(target, prop, proxy) {
switch (prop) {
case 'buffer':
case "buffer":
return buffer;
case 'toJSON':
return JSON.stringify(
Array.from({ length }, (_, i) => proxy[i])
);
case 'length': return length;
case "toJSON":
return JSON.stringify(Array.from({ length }, (_, i) => proxy[i]));
case "length":
return length;
}
// If it wasn’t handled by the switch-case above
// and is not a number, than it’s a prop we don’t support yet.
Expand All @@ -40,45 +52,60 @@ export function ArrayOfStructsView(buffer, descriptors) {
if (!target[idx]) {
target[idx] = {};
for (const [name, descriptor] of Object.entries(descriptors)) {
if (!('get' in descriptor)) {
if (!("get" in descriptor)) {
continue;
}
Object.defineProperty(target[idx], name, {
enumerable: true,
get() {
return descriptor.get(dataView, itemOffset + descriptor.offset)
return descriptor.get(dataView, itemOffset + descriptor.offset);
},
set(value) {
return descriptor.set(dataView, itemOffset + descriptor.offset, value)
return descriptor.set(
dataView,
itemOffset + descriptor.offset,
value
);
}
})
});
}
}
return target[idx];
}
})
});
}

["Uint16", "Uint32", "Int16", "Int32", "Float32", "Float64", "BigInt64", "BigUint64"].forEach(name => {
ArrayOfStructsView[name] = ({ endianess = 'big' } = {}) => {
if (endianess !== 'big' && endianess !== 'little') {
[
"Uint16",
"Uint32",
"Int16",
"Int32",
"Float32",
"Float64",
"BigInt64",
"BigUint64"
].forEach(name => {
ArrayOfStructsView[name] = ({ endianess = "big" } = {}) => {
if (endianess !== "big" && endianess !== "little") {
throw Error("Endianess needs to be either 'big' or 'little'");
}
const littleEndian = endianess === 'little';
const littleEndian = endianess === "little";
return {
size: self[`${name}Array`].BYTES_PER_ELEMENT,
get: (dataView, byteOffset) => dataView[`get${name}`](byteOffset, littleEndian),
set: (dataView, byteOffset, value) => dataView[`set${name}`](byteOffset, value, littleEndian)
}
}
})
get: (dataView, byteOffset) =>
dataView[`get${name}`](byteOffset, littleEndian),
set: (dataView, byteOffset, value) =>
dataView[`set${name}`](byteOffset, value, littleEndian)
};
};
});

ArrayOfStructsView.Uint8 = () => ({
size: 1,
get: (dataView, byteOffset) => dataView.getUint8(byteOffset),
set: (dataView, byteOffset, value) => dataView.setUint8(byteOffset, value),
set: (dataView, byteOffset, value) => dataView.setUint8(byteOffset, value)
});

ArrayOfStructsView.reserved = (size) => ({ size });
ArrayOfStructsView.reserved = size => ({ size });

export default ArrayOfStructsView;
export default ArrayOfStructsView;
87 changes: 87 additions & 0 deletions aosv.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* Copyright 2020 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { ArrayOfStructsView } from "./aosv.js";

describe("ArrayOfStructsView", function() {
it("calculates length correctly", function() {
// Add one stray byte
const { buffer } = new Uint8Array([0, 0, 1, 0, 2, 0, 1]);
const aosv = new ArrayOfStructsView(buffer, {
id: ArrayOfStructsView.Uint8(),
_: ArrayOfStructsView.reserved(1)
});
expect(aosv.length).toBe(3);
});

it("decodes items correctly", function() {
const buffer = new ArrayBuffer(22 * 2);
const dataView = new DataView(buffer);
dataView.setUint8(0 + 0, 1);
dataView.setUint8(22 + 0, 2);
dataView.setFloat64(0 + 1, 20, false);
dataView.setFloat64(0 + 9, 30, true);
dataView.setFloat64(22 + 1, 40, false);
dataView.setFloat64(22 + 9, 50, true);
dataView.setInt32(0 + 17, 9);
dataView.setInt32(22 + 17, 10);
const aosv = new ArrayOfStructsView(buffer, {
id: ArrayOfStructsView.Uint8(),
x: ArrayOfStructsView.Float64({ endianess: "big" }),
y: ArrayOfStructsView.Float64({ endianess: "little" }),
texture: ArrayOfStructsView.Int32(),
_: ArrayOfStructsView.reserved(1)
});
expect(aosv[0].id).toBe(1);
expect(aosv[1].id).toBe(2);
expect(aosv[0].x).toBe(20);
expect(aosv[1].x).toBe(40);
expect(aosv[0].y).toBe(30);
expect(aosv[1].y).toBe(50);
expect(aosv[0].texture).toBe(9);
expect(aosv[1].texture).toBe(10);
});

it("can return the buffer", function() {
const buffer = new ArrayBuffer(22);
const aosv = new ArrayOfStructsView(buffer, {
x: ArrayOfStructsView.Uint8()
});
expect(aosv.buffer).toBe(buffer);
});

it("can decode to JSON", function() {
const { buffer } = new Uint8Array([0, 0, 1, 0, 2, 0, 1]);
const aosv = new ArrayOfStructsView(buffer, {
id: ArrayOfStructsView.Uint8(),
_: ArrayOfStructsView.reserved(1)
});
expect(JSON.stringify(aosv)).toBe(
JSON.stringify([{ id: 0 }, { id: 1 }, { id: 2 }])
);
});

it("can write items", function() {
const buffer = new ArrayBuffer(10 * 2);
const dataView = new DataView(buffer);
const aosv = new ArrayOfStructsView(buffer, {
id: ArrayOfStructsView.Uint8(),
x: ArrayOfStructsView.Float64(),
_: ArrayOfStructsView.reserved(1)
});
aosv[0].x = 10;
aosv[1].x = 20;
expect(dataView.getFloat64(1)).toBe(10);
expect(dataView.getFloat64(11)).toBe(20);
});
});
Loading

0 comments on commit 3fa23a8

Please sign in to comment.