Skip to content

Commit 1afee21

Browse files
committed
v1.8.5 encodeInto()
1 parent 25c4cde commit 1afee21

9 files changed

Lines changed: 106 additions & 24 deletions

File tree

dist/index.cjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

dist/index.cjs.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.d.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,6 @@ export declare class BufferFormat<EncoderType extends EncoderDefinition, HeaderT
232232
* @see {peekHeaderStr(...)}
233233
*/
234234
header: HeaderType;
235-
get encodingBuffer(): DataView | undefined;
236235
constructor(def: EncoderType, header?: HeaderType | null);
237236
/**
238237
* Read the header of a buffer as a number.
@@ -248,6 +247,13 @@ export declare class BufferFormat<EncoderType extends EncoderDefinition, HeaderT
248247
* @throws {RangeError} if buffer size < 2
249248
*/
250249
static peekHeaderStr: typeof peekHeaderStr;
250+
/**
251+
* Encode an object into an existing byte array.
252+
*
253+
* **Warning:** Returns an unsafe view into the encoding buffer. Pass this reference to preserve
254+
* performance, and to minimize memory allocation and fragmentation.
255+
*/
256+
encodeInto<TDecodedType extends DecodedType<EncoderType>>(data: TDecodedType, bytes: Uint8Array): Uint8Array;
251257
/**
252258
* Encode an object to bytes.
253259
*
@@ -263,11 +269,20 @@ export declare class BufferFormat<EncoderType extends EncoderDefinition, HeaderT
263269
* @throws if fails to encode value to schema
264270
*/
265271
encode<TDecodedType extends DecodedType<EncoderType>>(data: TDecodedType, preserveBytes?: boolean): Uint8Array;
272+
/**
273+
* Decode binary data into an existing object instance.
274+
* @throws if fails to decode bytes to schema.
275+
*/
276+
decodeInto<TDecodedType = DecodedType<EncoderType>>(bytes: Uint8Array | ArrayBufferView | ArrayBuffer, obj: Partial<TDecodedType>): TDecodedType;
266277
/**
267278
* Decode binary data to an object.
268279
* @throws if fails to decode bytes to schema.
269280
*/
270-
decode<TDecodedType = DecodedType<EncoderType>>(bytes: Uint8Array | ArrayBufferView | ArrayBuffer, decodeInto?: Partial<TDecodedType>): TDecodedType;
281+
decode<TDecodedType = DecodedType<EncoderType>>(bytes: Uint8Array | ArrayBufferView | ArrayBuffer): TDecodedType;
282+
/**
283+
* @deprecated use decodeInto() instead
284+
*/
285+
decode<TDecodedType = DecodedType<EncoderType>>(bytes: Uint8Array | ArrayBufferView | ArrayBuffer, decodeInto: Partial<TDecodedType>): TDecodedType;
271286
/**
272287
* Set additional transform functions to apply before encoding and after decoding.
273288
*/

dist/index.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

dist/index.mjs.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tinybuf",
3-
"version": "1.8.3",
3+
"version": "1.8.5",
44
"author": "Reece Como <reece.como@gmail.com>",
55
"authors": [
66
"Reece Como <reece.como@gmail.com>",

src/__tests__/BufferFormat.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,25 @@ describe("BufferFormat", () => {
333333
expect(() => defineFormat("bigint128" as any)).toThrow(TypeError);
334334
});
335335

336+
it("encodeInto()", () => {
337+
const data = new Uint8Array(32);
338+
const input = {
339+
a: 100,
340+
b: [100, 200],
341+
c: [
342+
{ d: undefined },
343+
{ d: "lol" }
344+
]
345+
};
346+
347+
expect(data.toString()).toBe("0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
348+
const result = MyBufferFormat.encodeInto(input, data);
349+
expect(data.toString()).not.toBe("0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
350+
351+
const reversed = MyBufferFormat.decode(result);
352+
expect(reversed).toStrictEqual(input);
353+
});
354+
336355
it("decode() emits output that is valid input for encode()", () => {
337356
const Example = defineFormat({
338357
integer: Type.UInt16,

src/core/BufferFormat.ts

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable @typescript-eslint/unified-signatures */
12
import { writers, readers } from "./lib/coders";
23
import * as coders from "./lib/coders";
34
import { $hashCode, $strToHashCode } from "./lib/hashCode";
@@ -104,10 +105,6 @@ export class BufferFormat<EncoderType extends EncoderDefinition, HeaderType exte
104105
/** @internal */
105106
private _$writer?: BufferWriter;
106107

107-
public get encodingBuffer(): DataView | undefined {
108-
return this._$writer?._$dataView;
109-
}
110-
111108
public constructor(
112109
def: EncoderType,
113110
header?: HeaderType | null,
@@ -199,6 +196,27 @@ export class BufferFormat<EncoderType extends EncoderDefinition, HeaderType exte
199196
return new BufferWriter(cfg.encodingBufferInitialSize);
200197
}
201198

199+
/**
200+
* Encode an object into an existing byte array.
201+
*
202+
* **Warning:** Returns an unsafe view into the encoding buffer. Pass this reference to preserve
203+
* performance, and to minimize memory allocation and fragmentation.
204+
*/
205+
public encodeInto<TDecodedType extends DecodedType<EncoderType>>(
206+
data: TDecodedType,
207+
bytes: Uint8Array,
208+
): Uint8Array {
209+
const writer = new BufferWriter(bytes);
210+
211+
if (this._$hasValidationOrTransforms) {
212+
data = this._$preprocess(data);
213+
}
214+
215+
this._$write(data, writer);
216+
217+
return writer.$viewBytes();
218+
}
219+
202220
/**
203221
* Encode an object to bytes.
204222
*
@@ -236,13 +254,37 @@ export class BufferFormat<EncoderType extends EncoderDefinition, HeaderType exte
236254
: this._$writer.$viewBytes();
237255
}
238256

257+
/**
258+
* Decode binary data into an existing object instance.
259+
* @throws if fails to decode bytes to schema.
260+
*/
261+
public decodeInto<TDecodedType = DecodedType<EncoderType>>(
262+
bytes: Uint8Array | ArrayBufferView | ArrayBuffer,
263+
obj: Partial<TDecodedType>,
264+
): TDecodedType {
265+
return this._$read(new BufferReader(bytes, this.header === undefined ? 0 : 2), obj);
266+
}
267+
/**
268+
* Decode binary data to an object.
269+
* @throws if fails to decode bytes to schema.
270+
*/
271+
public decode<TDecodedType = DecodedType<EncoderType>>(
272+
bytes: Uint8Array | ArrayBufferView | ArrayBuffer
273+
): TDecodedType;
274+
/**
275+
* @deprecated use decodeInto() instead
276+
*/
277+
public decode<TDecodedType = DecodedType<EncoderType>>(
278+
bytes: Uint8Array | ArrayBufferView | ArrayBuffer,
279+
decodeInto: Partial<TDecodedType>,
280+
): TDecodedType;
239281
/**
240282
* Decode binary data to an object.
241283
* @throws if fails to decode bytes to schema.
242284
*/
243285
public decode<TDecodedType = DecodedType<EncoderType>>(
244286
bytes: Uint8Array | ArrayBufferView | ArrayBuffer,
245-
decodeInto?: Partial<TDecodedType>,
287+
decodeInto?: Partial<TDecodedType> | undefined,
246288
): TDecodedType {
247289
return this._$read(new BufferReader(bytes, this.header === undefined ? 0 : 2), decodeInto);
248290
}

src/core/lib/BufferWriter.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,26 @@ import { TinybufError } from "./errors";
88
*/
99
export class BufferWriter {
1010
public $byteLength: number = 0;
11-
public _$dataView: DataView;
11+
private _$dataView: DataView;
12+
private _$bytes: Uint8Array;
1213
private _$writeHead: number = 0;
14+
private _$resizable: boolean;
1315

14-
public constructor(initialSize: number) {
15-
this._$dataView = new DataView(new ArrayBuffer(initialSize));
16+
public constructor($0: number | Uint8Array) {
17+
this._$resizable = typeof $0 === "number";
18+
let b = $0 instanceof Uint8Array ? $0 : new Uint8Array($0);
19+
this._$bytes = b;
20+
this._$dataView = new DataView(b.buffer, b.byteOffset, b.byteLength);
1621
}
1722

1823
public $viewBytes(): Uint8Array {
19-
return new Uint8Array(this._$dataView.buffer, this._$dataView.byteOffset, this.$byteLength);
24+
return this._$bytes.subarray(this._$bytes.byteOffset, this._$bytes.byteOffset + this.$byteLength);
2025
}
2126

2227
public $copyBytes(): Uint8Array {
23-
return new Uint8Array(this._$dataView.buffer.slice(0, this.$byteLength));
28+
const buf = new Uint8Array(this.$byteLength);
29+
buf.set(this.$viewBytes());
30+
return buf;
2431
}
2532

2633
// ----- Writers: -----
@@ -81,6 +88,7 @@ export class BufferWriter {
8188
if (this.$byteLength + bytes > this._$dataView.byteLength) {
8289
const minBytesNeeded = this.$byteLength + bytes - this._$dataView.byteLength;
8390
const requestedNewBytes = Math.ceil(minBytesNeeded / cfg.encodingBufferIncrement) * cfg.encodingBufferIncrement;
91+
if (!this._$resizable) throw new TinybufError("exceeded buffer length: " + this._$dataView.byteLength);
8492
this._$resizeBuffer(this._$dataView.byteLength + requestedNewBytes);
8593
}
8694

@@ -96,13 +104,11 @@ export class BufferWriter {
96104
throw new TinybufError(`exceeded encodingBufferMaxSize: ${cfg.encodingBufferMaxSize}`);
97105
}
98106

99-
const newBuf = new ArrayBuffer(newSize);
107+
const buf = new Uint8Array(newSize);
108+
buf.set(this._$bytes); // copy bytes
100109

101-
// copy bytes
102-
const oldView = new Uint8Array(this._$dataView.buffer, this._$dataView.byteOffset, this._$dataView.byteLength);
103-
new Uint8Array(newBuf).set(oldView);
104-
105-
// update ref
106-
this._$dataView = new DataView(newBuf);
110+
// update refs
111+
this._$dataView = new DataView(buf.buffer);
112+
this._$bytes = buf;
107113
}
108114
}

0 commit comments

Comments
 (0)