Skip to content

Commit

Permalink
Merge pull request #279 from betwixt-labs/binary-schema-raw
Browse files Browse the repository at this point in the history
feat: enable access to raw binary schema
  • Loading branch information
andrewmd5 authored Jul 18, 2023
2 parents 01868e8 + 426d6e4 commit 2333a76
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 12 deletions.
4 changes: 2 additions & 2 deletions .env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION="2.8.6"
VERSION="2.8.7"
MAJOR=2
MINOR=8
PATCH=6
PATCH=7
64 changes: 56 additions & 8 deletions Runtime/TypeScript/binary.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { BebopRuntimeError, BebopTypeGuard, BebopView, Guid, GuidMap } from "./index";
import {
BebopRuntimeError,
BebopTypeGuard,
BebopView,
Guid,
GuidMap,
} from "./index";

const decoder = new TextDecoder();

Expand Down Expand Up @@ -218,7 +224,9 @@ export class RecordReader {
case "map":
return this.readMap(field.fieldProperties, view);
default:
throw new BebopRuntimeError(`Unknown field type: ${field.fieldProperties}`);
throw new BebopRuntimeError(
`Unknown field type: ${field.fieldProperties}`
);
}
}

Expand Down Expand Up @@ -359,7 +367,9 @@ export class RecordReader {
case WireBaseType.Int64:
return view.readInt64();
default:
throw new BebopRuntimeError(`Unknown enum base type: ${definition.baseType}`);
throw new BebopRuntimeError(
`Unknown enum base type: ${definition.baseType}`
);
}
}

Expand Down Expand Up @@ -472,7 +482,9 @@ export class RecordWriter {
const start = view.length;
Object.values(definition.fields).forEach((field) => {
if (field.constantValue === undefined || field.constantValue === null) {
throw new BebopRuntimeError(`Missing constant value for field: ${field.name}`);
throw new BebopRuntimeError(
`Missing constant value for field: ${field.name}`
);
}
if (typeof field.constantValue !== "number") {
throw new BebopRuntimeError(
Expand All @@ -499,7 +511,9 @@ export class RecordWriter {
value: unknown
): void {
if (typeof value !== "number" && typeof value !== "bigint") {
throw new BebopRuntimeError(`Expected number or bigint, got ${typeof value}`);
throw new BebopRuntimeError(
`Expected number or bigint, got ${typeof value}`
);
}
if (
(definition.baseType === WireBaseType.Int64 ||
Expand Down Expand Up @@ -550,7 +564,9 @@ export class RecordWriter {
view.writeInt64(value as bigint);
break;
default:
throw new BebopRuntimeError(`Unknown enum base type: ${definition.baseType}`);
throw new BebopRuntimeError(
`Unknown enum base type: ${definition.baseType}`
);
}
}

Expand Down Expand Up @@ -619,7 +635,9 @@ export class RecordWriter {
this.writeMap(field.fieldProperties, view, value);
break;
default:
throw new BebopRuntimeError(`Unknown field type: ${field.fieldProperties}`);
throw new BebopRuntimeError(
`Unknown field type: ${field.fieldProperties}`
);
}
}

Expand Down Expand Up @@ -784,6 +802,7 @@ export class RecordWriter {
*/
export class BinarySchema {
private readonly view: DataView;
private readonly dataProxy: Uint8Array;
private pos: number;
private readonly ArrayType = -14;
private readonly MapType = -15;
Expand All @@ -798,12 +817,35 @@ export class BinarySchema {
* @param data - The binary data array.
*/
constructor(private readonly data: Uint8Array) {
this.view = new DataView(data.buffer);
// copy the data to prevent modification
//this.data = data.subarray(0, data.length);
this.view = new DataView(this.data.buffer);
this.pos = 0;
//@ts-expect-error
this.reader = new RecordReader(this);
//@ts-expect-error
this.writer = new RecordWriter(this);
this.dataProxy = new Proxy(this.data, {
get: (target: Uint8Array, prop: PropertyKey): any => {
// If prop is 'length', return the length of the Uint8Array
if (prop === "length") {
return target.length;
}
// If prop is a number-like string, convert it to a number and return the element at that index in the Uint8Array
if (typeof prop === "string" && !isNaN(Number(prop))) {
return target[Number(prop)];
}
// If prop is the name of a method of Uint8Array, return the function
if (typeof prop === 'string' && typeof (target as any)[prop] === 'function') {
return (target as any)[prop].bind(target);
}
// Optionally, you can throw an error or return undefined for all other properties
throw new BebopRuntimeError(`Cannot access property ${String(prop)}`);
},
set: (_: Uint8Array, __: PropertyKey, ___: any): boolean => {
throw new BebopRuntimeError("Cannot modify schema data");
},
});
}

/**
Expand Down Expand Up @@ -846,6 +888,12 @@ export class BinarySchema {
}
return this.parsedSchema!;
}
/**
* Returns the raw binary data of the schema wrapped in an immutable Uint8Array.
*/
public get raw(): Uint8Array {
return this.dataProxy;
}

/**
* Get a Definition by its index or name.
Expand Down
10 changes: 8 additions & 2 deletions Runtime/TypeScript/bs.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BinarySchema, Guid } from "./index";
import { BebopRuntimeError, BinarySchema, Guid } from "./index";

import { describe, expect, it } from "vitest";

Expand All @@ -14,7 +14,7 @@ const schemaData = new Uint8Array([
255, 255, 0, 2, 110, 101, 115, 116, 101, 100, 0, 241, 255, 255, 255, 245, 255,
255, 255, 241, 255, 255, 255, 245, 255, 255, 255, 242, 255, 255, 255, 1, 245,
255, 255, 255, 0, 3, 80, 111, 119, 101, 114, 0, 3, 0, 2, 1, 1, 0, 0, 0, 2, 2,
0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0,
]);

const recordData = new Uint8Array([
Expand Down Expand Up @@ -64,4 +64,10 @@ describe("binary schema", () => {
const read = schema.reader.read("Power", data);
expect(read).toEqual(record);
});

it("cannot modify schema data", () => {
expect(() => {
schema.raw[0] = 0;
}).toThrow(BebopRuntimeError);
});
});

0 comments on commit 2333a76

Please sign in to comment.