Skip to content

Commit

Permalink
Add support for DataView
Browse files Browse the repository at this point in the history
  • Loading branch information
lxsmnsyc committed Apr 8, 2023
1 parent 8ae80f4 commit 28fd1ac
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 1 deletion.
3 changes: 3 additions & 0 deletions packages/seroval/src/tree/async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
UNDEFINED_NODE,
createReferenceNode,
createArrayBufferNode,
createDataViewNode,
} from './primitives';
import { hasReferenceID } from './reference';
import {
Expand Down Expand Up @@ -408,6 +409,8 @@ async function parse<T>(
case BigInt64Array:
case BigUint64Array:
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
case DataView:
return createDataViewNode(ctx, id, current as unknown as DataView);
case Map:
return generateMapNode(
ctx,
Expand Down
16 changes: 16 additions & 0 deletions packages/seroval/src/tree/deserialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
SerovalArrayBufferNode,
SerovalArrayNode,
SerovalBigIntTypedArrayNode,
SerovalDataViewNode,
SerovalErrorNode,
SerovalIterableNode,
SerovalMapNode,
Expand Down Expand Up @@ -240,6 +241,19 @@ function deserializeIterable(
return deserializeDictionary(ctx, node, result);
}

function deserializeDataView(
ctx: SerializationContext,
node: SerovalDataViewNode,
) {
const source = deserializeTree(ctx, node.f) as ArrayBuffer;
const result = assignIndexedValue(ctx, node.i, new DataView(
source,
node.b,
node.l,
));
return result;
}

export default function deserializeTree(
ctx: SerializationContext,
node: SerovalNode,
Expand Down Expand Up @@ -285,6 +299,8 @@ export default function deserializeTree(
case SerovalNodeType.BigIntTypedArray:
case SerovalNodeType.TypedArray:
return deserializeTypedArray(ctx, node);
case SerovalNodeType.DataView:
return deserializeDataView(ctx, node);
case SerovalNodeType.AggregateError:
return deserializeAggregateError(ctx, node);
case SerovalNodeType.Error:
Expand Down
20 changes: 20 additions & 0 deletions packages/seroval/src/tree/primitives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
SerovalWKSymbolNode,
SerovalReferenceNode,
SerovalArrayBufferNode,
SerovalDataViewNode,
} from './types';

export const TRUE_NODE: SerovalBooleanNode = {
Expand Down Expand Up @@ -338,3 +339,22 @@ export function createReferenceNode<T>(
b: undefined,
};
}

export function createDataViewNode(
ctx: ParserContext,
id: number,
current: DataView,
): SerovalDataViewNode {
return {
t: SerovalNodeType.DataView,
i: id,
s: undefined,
l: current.byteLength,
c: undefined,
m: undefined,
d: undefined,
a: undefined,
f: serializeArrayBuffer(ctx, current.buffer),
b: current.byteOffset,
};
}
11 changes: 11 additions & 0 deletions packages/seroval/src/tree/serialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
SerovalSetNode,
SerovalTypedArrayNode,
SerovalArrayBufferNode,
SerovalDataViewNode,
} from './types';

function getAssignmentExpression(assignment: Assignment): string {
Expand Down Expand Up @@ -570,6 +571,14 @@ function serializeIterable(
return serializeDictionary(ctx, node.i, node.d, serialized);
}

function serializeDataView(
ctx: SerializationContext,
node: SerovalDataViewNode,
) {
const args = serializeTree(ctx, node.f) + ',' + node.b + ',' + node.l;
return assignIndexedValue(ctx, node.i, 'new DataView(' + args + ')');
}

export default function serializeTree(
ctx: SerializationContext,
node: SerovalNode,
Expand Down Expand Up @@ -616,6 +625,8 @@ export default function serializeTree(
case SerovalNodeType.BigIntTypedArray:
case SerovalNodeType.TypedArray:
return serializeTypedArray(ctx, node);
case SerovalNodeType.DataView:
return serializeDataView(ctx, node);
case SerovalNodeType.AggregateError:
return serializeAggregateError(ctx, node);
case SerovalNodeType.Error:
Expand Down
3 changes: 3 additions & 0 deletions packages/seroval/src/tree/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
UNDEFINED_NODE,
createReferenceNode,
createArrayBufferNode,
createDataViewNode,
} from './primitives';
import {
hasReferenceID,
Expand Down Expand Up @@ -367,6 +368,8 @@ function parse<T>(
case BigInt64Array:
case BigUint64Array:
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
case DataView:
return createDataViewNode(ctx, id, current as unknown as DataView);
case Map:
return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
case Set:
Expand Down
12 changes: 11 additions & 1 deletion packages/seroval/src/tree/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const enum SerovalNodeType {
URLSearchParams,
Reference,
ArrayBuffer,
DataView,
}

export interface SerovalBaseNode {
Expand Down Expand Up @@ -263,6 +264,14 @@ export interface SerovalReferenceNode extends SerovalBaseNode {
s: string;
}

export interface SerovalDataViewNode extends SerovalBaseNode {
t: SerovalNodeType.DataView;
i: number;
l: number;
f: SerovalNode;
b: number;
}

export type SerovalNode =
| SerovalPrimitiveNode
| SerovalIndexedValueNode
Expand All @@ -280,4 +289,5 @@ export type SerovalNode =
| SerovalURLNode
| SerovalURLSearchParamsNode
| SerovalReferenceNode
| SerovalArrayBufferNode;
| SerovalArrayBufferNode
| SerovalDataViewNode;
9 changes: 9 additions & 0 deletions packages/seroval/test/__snapshots__/data-view.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Vitest Snapshot v1

exports[`DataView > serialize > supports DataView 1`] = `"new DataView(new Uint8Array([0,0,42,0,0,0,0,0,0,0,0,0,0,0,0,0]).buffer,0,16)"`;

exports[`DataView > serializeAsync > supports DataView 1`] = `"Promise.resolve(new DataView(new Uint8Array([0,0,42,0,0,0,0,0,0,0,0,0,0,0,0,0]).buffer,0,16))"`;

exports[`DataView > toJSON > supports DataView 1`] = `"{\\"t\\":{\\"t\\":29,\\"i\\":0,\\"l\\":16,\\"f\\":{\\"t\\":28,\\"i\\":1,\\"s\\":[0,0,42,0,0,0,0,0,0,0,0,0,0,0,0,0]},\\"b\\":0},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;

exports[`DataView > toJSONAsync > supports DataView 1`] = `"{\\"t\\":{\\"t\\":18,\\"i\\":0,\\"f\\":{\\"t\\":29,\\"i\\":1,\\"l\\":16,\\"f\\":{\\"t\\":28,\\"i\\":2,\\"s\\":[0,0,42,0,0,0,0,0,0,0,0,0,0,0,0,0]},\\"b\\":0}},\\"r\\":0,\\"i\\":false,\\"f\\":16383,\\"m\\":[]}"`;
60 changes: 60 additions & 0 deletions packages/seroval/test/data-view.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { describe, it, expect } from 'vitest';
import {
deserialize,
fromJSON,
serialize,
serializeAsync,
toJSONAsync,
toJSON,
} from '../src';

describe('DataView', () => {
describe('serialize', () => {
it('supports DataView', () => {
const buffer = new ArrayBuffer(16);
const example = new DataView(buffer, 0);
example.setInt16(1, 42);
const result = serialize(example);
expect(result).toMatchSnapshot();
const back = deserialize<DataView>(result);
expect(back).toBeInstanceOf(DataView);
expect(back.getInt16(1)).toBe(example.getInt16(1));
});
});
describe('serializeAsync', () => {
it('supports DataView', async () => {
const buffer = new ArrayBuffer(16);
const example = new DataView(buffer, 0);
example.setInt16(1, 42);
const result = await serializeAsync(Promise.resolve(example));
expect(result).toMatchSnapshot();
const back = await deserialize<Promise<DataView>>(result);
expect(back).toBeInstanceOf(DataView);
expect(back.getInt16(1)).toBe(example.getInt16(1));
});
});
describe('toJSON', () => {
it('supports DataView', () => {
const buffer = new ArrayBuffer(16);
const example = new DataView(buffer, 0);
example.setInt16(1, 42);
const result = toJSON(example);
expect(JSON.stringify(result)).toMatchSnapshot();
const back = fromJSON<DataView>(result);
expect(back).toBeInstanceOf(DataView);
expect(back.getInt16(1)).toBe(example.getInt16(1));
});
});
describe('toJSONAsync', () => {
it('supports DataView', async () => {
const buffer = new ArrayBuffer(16);
const example = new DataView(buffer, 0);
example.setInt16(1, 42);
const result = await toJSONAsync(Promise.resolve(example));
expect(JSON.stringify(result)).toMatchSnapshot();
const back = await fromJSON<Promise<DataView>>(result);
expect(back).toBeInstanceOf(DataView);
expect(back.getInt16(1)).toBe(example.getInt16(1));
});
});
});

0 comments on commit 28fd1ac

Please sign in to comment.