Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 2 additions & 19 deletions src/encoding/StringEncoder.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,18 @@
import Serializable from "./Serializable";

export default class StringEncoder implements Serializable<string> {
// Default size of the decoder buffer that's always reused (in bytes)
private static readonly ENCODER_BUFFER_SIZE = 16384

private textEncoder = new TextEncoder();
private textDecoder = new TextDecoder();

private encoderBuffer: ArrayBuffer = new ArrayBuffer(StringEncoder.ENCODER_BUFFER_SIZE);
private encoderArray: Uint8Array = new Uint8Array(this.encoderBuffer);
private currentDecoderBufferSize: number = StringEncoder.ENCODER_BUFFER_SIZE;

decode(buffer: Uint8Array): string {
return this.textDecoder.decode(buffer);
}

encode(stringValue: string, destination: Uint8Array): number {
// Safari does not support the encodeInto function
if (this.textEncoder.encodeInto !== undefined) {
const maxStringLength = stringValue.length * 3;

if (this.currentDecoderBufferSize < maxStringLength) {
this.encoderBuffer = new ArrayBuffer(maxStringLength);
this.encoderArray = new Uint8Array(this.encoderBuffer);
this.currentDecoderBufferSize = maxStringLength;
}

const writeResult = this.textEncoder.encodeInto(stringValue, this.encoderArray);
const writeLength = writeResult.written || 0;
destination.set(this.encoderArray.subarray(0, writeLength));
return writeLength;
const writeResult = this.textEncoder.encodeInto(stringValue, destination);
return writeResult.written || 0;
} else {
const encodedString = this.textEncoder.encode(stringValue);
destination.set(encodedString);
Expand Down
32 changes: 32 additions & 0 deletions src/encoding/__tests__/StringEncoder.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import StringEncoder from "../StringEncoder";

describe("StringEncoder", () => {
it("should correctly encode a string into a Uint8Array view", () => {
const encoder = new StringEncoder();
const str = "Hello World! €";

// Use SharedArrayBuffer if available, otherwise ArrayBuffer
const bufferType = typeof SharedArrayBuffer !== 'undefined' ? SharedArrayBuffer : ArrayBuffer;
const buffer = new bufferType(1024);
const view = new Uint8Array(buffer);

// Create a view at an offset
const offset = 100;
const dest = view.subarray(offset, offset + 100);

const written = encoder.encode(str, dest);

// Verify return value
const expectedEncoded = new TextEncoder().encode(str);
expect(written).toBe(expectedEncoded.length);

// Verify content
const result = dest.subarray(0, written);
expect(result).toEqual(expectedEncoded);

// Verify original buffer content at offset
const fullView = new Uint8Array(buffer);
const writtenSlice = fullView.subarray(offset, offset + written);
expect(writtenSlice).toEqual(expectedEncoded);
});
});