From 328e9e6eddecaf78e35c48821da667d9cedad0e4 Mon Sep 17 00:00:00 2001 From: "lijiacheng.ljc" Date: Sun, 18 Feb 2024 18:05:12 +0800 Subject: [PATCH] feat(JavaScript): Make PlatformBuffer available if has Buffer polyfill --- javascript/packages/fury/lib/gen/any.ts | 2 +- .../packages/fury/lib/gen/serializer.ts | 6 +-- .../packages/fury/lib/platformBuffer.ts | 39 ++++++++++---- javascript/packages/fury/lib/reader/index.ts | 6 +-- javascript/packages/fury/lib/reader/string.ts | 2 +- javascript/packages/fury/lib/util.ts | 2 + javascript/packages/fury/lib/writer.ts | 6 +-- javascript/test/platformBuffer.test.ts | 51 ++++++++++++++++--- javascript/test/reader.test.ts | 2 +- 9 files changed, 87 insertions(+), 29 deletions(-) diff --git a/javascript/packages/fury/lib/gen/any.ts b/javascript/packages/fury/lib/gen/any.ts index e0335f9b22..91a5f68081 100644 --- a/javascript/packages/fury/lib/gen/any.ts +++ b/javascript/packages/fury/lib/gen/any.ts @@ -45,7 +45,7 @@ export class AnySerializer { const typeId = this.fury.binaryReader.int16(); let serializer: Serializer; if (typeId === InternalSerializerType.FURY_TYPE_TAG) { - const tag = this.fury.classResolver.readTag(this.fury.binaryReader)(); + const tag = this.fury.classResolver.readTag(this.fury.binaryReader)()!; serializer = this.fury.classResolver.getSerializerByTag(tag); } else { serializer = this.fury.classResolver.getSerializerById(typeId); diff --git a/javascript/packages/fury/lib/gen/serializer.ts b/javascript/packages/fury/lib/gen/serializer.ts index 16d7020efb..36cbc011b4 100644 --- a/javascript/packages/fury/lib/gen/serializer.ts +++ b/javascript/packages/fury/lib/gen/serializer.ts @@ -25,9 +25,9 @@ import { Scope } from "./scope"; import { TypeDescription, ObjectTypeDescription } from "../description"; export interface SerializerGenerator { - toSerializer(): string; - toWriteEmbed(accessor: string, excludeHead?: boolean): string; - toReadEmbed(accessor: (expr: string) => string, excludeHead?: boolean, refState?: RefState): string; + toSerializer(): string + toWriteEmbed(accessor: string, excludeHead?: boolean): string + toReadEmbed(accessor: (expr: string) => string, excludeHead?: boolean, refState?: RefState): string } export enum RefStateType { diff --git a/javascript/packages/fury/lib/platformBuffer.ts b/javascript/packages/fury/lib/platformBuffer.ts index 9c82a02352..25a87f0e56 100644 --- a/javascript/packages/fury/lib/platformBuffer.ts +++ b/javascript/packages/fury/lib/platformBuffer.ts @@ -17,23 +17,40 @@ * under the License. */ -import { isNodeEnv } from "./util"; +import { hasBuffer } from "./util"; + +export type SupportedEncodings = "latin1" | "utf8"; export interface PlatformBuffer extends Uint8Array { - latin1Slice(start: number, end: number): string; - utf8Slice(start: number, end: number): string; - latin1Write(v: string, offset: number): void; - utf8Write(v: string, offset: number): void; - copy(target: Uint8Array, targetStart?: number, sourceStart?: number, sourceEnd?: number): void; + toString(encoding?: SupportedEncodings, start?: number, end?: number,): string + write(string: string, offset: number, encoding?: SupportedEncodings): void + copy(target: Uint8Array, targetStart?: number, sourceStart?: number, sourceEnd?: number): void } export class BrowserBuffer extends Uint8Array implements PlatformBuffer { + write(string: string, offset: number, encoding: SupportedEncodings = "utf8"): void { + if (encoding === "latin1") { + return this.latin1Write(string, offset); + } + return this.utf8Write(string, offset); + } + + toString(encoding: SupportedEncodings = "utf8", start = 0, end?: number): string { + end = end || this.length; + + if (encoding === "latin1") { + return this.latin1Slice(start, end); + } + return this.utf8Slice(start, end); + } + static alloc(size: number) { return new BrowserBuffer(new Uint8Array(size)); } latin1Write(string: string, offset: number) { - for (let index = 0; index < string.length; index++) { + let index = 0; + for (; index < string.length; index++) { this[offset++] = string.charCodeAt(index); } } @@ -122,7 +139,7 @@ export class BrowserBuffer extends Uint8Array implements PlatformBuffer { } } -export const fromUint8Array = isNodeEnv +export const fromUint8Array = hasBuffer ? (ab: Buffer | Uint8Array) => { if (!Buffer.isBuffer(ab)) { return (Buffer.from(ab) as unknown as PlatformBuffer); @@ -132,14 +149,14 @@ export const fromUint8Array = isNodeEnv } : (ab: Buffer | Uint8Array) => new BrowserBuffer(ab); -export const alloc = (isNodeEnv ? Buffer.allocUnsafe : BrowserBuffer.alloc) as unknown as (size: number) => PlatformBuffer; +export const alloc = (hasBuffer ? Buffer.allocUnsafe : BrowserBuffer.alloc) as unknown as (size: number) => PlatformBuffer; -export const strByteLength = isNodeEnv ? Buffer.byteLength : BrowserBuffer.byteLength; +export const strByteLength = hasBuffer ? Buffer.byteLength : BrowserBuffer.byteLength; let utf8Encoder: TextEncoder | null; export const fromString -= isNodeEnv += hasBuffer ? (str: string) => Buffer.from(str) as unknown as PlatformBuffer : (str: string) => { if (!utf8Encoder) { diff --git a/javascript/packages/fury/lib/reader/index.ts b/javascript/packages/fury/lib/reader/index.ts index b12bf12133..ef308e79d7 100644 --- a/javascript/packages/fury/lib/reader/index.ts +++ b/javascript/packages/fury/lib/reader/index.ts @@ -37,7 +37,7 @@ export const BinaryReader = (config: Config) => { byteLength = buffer.byteLength; dataView = new DataView(buffer.buffer, buffer.byteOffset); if (sliceStringEnable) { - bigString = buffer.latin1Slice(0, byteLength); + bigString = buffer.toString("latin1", 0, byteLength); } cursor = 0; } @@ -113,11 +113,11 @@ export const BinaryReader = (config: Config) => { } function stringUtf8At(start: number, len: number) { - return buffer.utf8Slice(start, start + len); + return buffer.toString("utf8", start, start + len); } function stringUtf8(len: number) { - const result = buffer.utf8Slice(cursor, cursor + len); + const result = buffer.toString("utf8", cursor, cursor + len); cursor += len; return result; } diff --git a/javascript/packages/fury/lib/reader/string.ts b/javascript/packages/fury/lib/reader/string.ts index 8b9c78c6fa..c8bc4869cf 100644 --- a/javascript/packages/fury/lib/reader/string.ts +++ b/javascript/packages/fury/lib/reader/string.ts @@ -100,6 +100,6 @@ export const readLatin1String = (buffer: PlatformBuffer, len: number, cursor: nu case 15: return read15(buffer, cursor); default: - return buffer.latin1Slice(cursor, cursor + len); + return buffer.toString("latin1", cursor, cursor + len,); } }; diff --git a/javascript/packages/fury/lib/util.ts b/javascript/packages/fury/lib/util.ts index d78445e2dd..b7e45a1247 100644 --- a/javascript/packages/fury/lib/util.ts +++ b/javascript/packages/fury/lib/util.ts @@ -22,3 +22,5 @@ export const isNodeEnv: boolean && process.versions != null && process.env.ECMA_ONLY !== "true" && process.versions.node != null; + +export const hasBuffer = isNodeEnv && typeof Buffer !== "undefined"; diff --git a/javascript/packages/fury/lib/writer.ts b/javascript/packages/fury/lib/writer.ts index c88f53bcce..e329f69ed3 100644 --- a/javascript/packages/fury/lib/writer.ts +++ b/javascript/packages/fury/lib/writer.ts @@ -194,7 +194,7 @@ export const BinaryWriter = (config: Config) => { if (len < 40) { fastWriteStringUtf8(v, arrayBuffer, cursor); } else { - arrayBuffer.utf8Write(v, cursor); + arrayBuffer.write(v, cursor, "utf8"); } } cursor += len; @@ -213,13 +213,13 @@ export const BinaryWriter = (config: Config) => { arrayBuffer[cursor + index] = v.charCodeAt(index); } } else { - arrayBuffer.latin1Write(v, cursor); + arrayBuffer.write(v, cursor, "latin1"); } } else { if (len < 40) { fastWriteStringUtf8(v, arrayBuffer, cursor); } else { - arrayBuffer.utf8Write(v, cursor); + arrayBuffer.write(v, cursor, "utf8"); } } cursor += len; diff --git a/javascript/test/platformBuffer.test.ts b/javascript/test/platformBuffer.test.ts index 5e9d136774..cc633fc436 100644 --- a/javascript/test/platformBuffer.test.ts +++ b/javascript/test/platformBuffer.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { fromUint8Array, alloc, BrowserBuffer } from '../packages/fury/lib/platformBuffer'; +import { fromUint8Array, alloc, BrowserBuffer, PlatformBuffer } from '../packages/fury/lib/platformBuffer'; import { describe, expect, test } from '@jest/globals'; describe('platformBuffer', () => { @@ -38,22 +38,54 @@ describe('platformBuffer', () => { }); - test('should latin1 work', () => { + test('should latin1Write work', () => { const bb = BrowserBuffer.alloc(100); bb.latin1Write("hello, world", 0); const str = bb.latin1Slice(0, 12); expect(str).toBe("hello, world"); + + const str2 = bb.toString('latin1', 0, 12); + expect(str2).toBe("hello, world"); + }); + + test('should write latin1 work', () => { + const bb = BrowserBuffer.alloc(100); + bb.write("hello, world", 0, 'latin1'); + + const str = bb.latin1Slice(0, 12); + expect(str).toBe("hello, world"); + + const str2 = bb.toString('latin1', 0, 12); + expect(str2).toBe("hello, world"); + }); + + + test('should utf8Write work', () => { + const rawStr = "我是Fury, 你好!😁א"; + const bb = BrowserBuffer.alloc(100); + bb.utf8Write(rawStr, 0); + + const str = bb.utf8Slice(0, 27); + expect(str).toBe(rawStr); + + const str2 = bb.toString('utf8', 0, 27); + expect(str2).toBe(rawStr); }); test('should utf8 work', () => { + const rawStr = "我是Fury, 你好!😁א"; const bb = BrowserBuffer.alloc(100); - bb.utf8Write("我是Fury, 你好!😁א", 0); + bb.write(rawStr, 0, 'utf8'); const str = bb.utf8Slice(0, 27); - expect(str).toBe("我是Fury, 你好!😁א"); + expect(str).toBe(rawStr); + + const str2 = bb.toString('utf8', 0, 27); + expect(str2).toBe(rawStr); }); + test('should byteLength work', () => { expect(BrowserBuffer.byteLength("hello, world")).toBe(12); expect(BrowserBuffer.byteLength("我是Fury, 你好!😁א")).toBe(27); @@ -66,6 +98,13 @@ describe('platformBuffer', () => { bb.copy(target, 0, 0, 5); expect([...target]).toEqual([ 104, 101, 108, 108, 111 ]) }); -}); - + test('Buffer can be assigned to PlatformBuffer', () => { + const cc = Buffer.alloc(20); + cc.write("hello", 0, "latin1"); + const bb: PlatformBuffer = cc; + expect(bb.toString('latin1', 0 , 5)).toBe("hello"); + bb.write("world", 5, "latin1"); + expect(bb.toString('latin1', 0, 10)).toBe("helloworld"); + }) +}); diff --git a/javascript/test/reader.test.ts b/javascript/test/reader.test.ts index a707d3937d..d753aec33d 100644 --- a/javascript/test/reader.test.ts +++ b/javascript/test/reader.test.ts @@ -50,7 +50,7 @@ describe('reader', () => { test('should bufferRef work', () => { const bb = alloc(100); - bb.latin1Write("hello", 0); + bb.write("hello", 0, 'latin1'); const target = new Uint8Array(5); bb.copy(target, 0, 0, 5); expect([...target]).toEqual([ 104, 101, 108, 108, 111 ])