This is an automated email from the ASF dual-hosted git repository.
wangweipeng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git
The following commit(s) were added to refs/heads/main by this push:
new 8db5f00cb feat(JavaScript): impl the xlang string (#3197)
8db5f00cb is described below
commit 8db5f00cb74d9662e6d6795aeb2c0340cc3241b1
Author: weipeng <[email protected]>
AuthorDate: Sun Jan 25 23:05:32 2026 +0800
feat(JavaScript): impl the xlang string (#3197)
## Why?
1. Implement the xlang string
2. replace `InternalSerializerType` by `TypeId` to simplify the concept.
## What does this PR do?
## Related issues
#3133
## Does this PR introduce any user-facing change?
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
---
.github/workflows/ci.yml | 6 +-
javascript/README.md | 2 +-
javascript/packages/fory/index.ts | 3 +-
javascript/packages/fory/lib/classResolver.ts | 2 +-
javascript/packages/fory/lib/fory.ts | 7 +-
javascript/packages/fory/lib/gen/any.ts | 6 +-
javascript/packages/fory/lib/gen/array.ts | 4 +-
javascript/packages/fory/lib/gen/binary.ts | 4 +-
javascript/packages/fory/lib/gen/bool.ts | 4 +-
javascript/packages/fory/lib/gen/builder.ts | 16 +-
javascript/packages/fory/lib/gen/collection.ts | 6 +-
javascript/packages/fory/lib/gen/datetime.ts | 6 +-
javascript/packages/fory/lib/gen/enum.ts | 5 +-
javascript/packages/fory/lib/gen/index.ts | 30 +-
javascript/packages/fory/lib/gen/map.ts | 16 +-
javascript/packages/fory/lib/gen/number.ts | 34 +-
javascript/packages/fory/lib/gen/router.ts | 13 +-
javascript/packages/fory/lib/gen/serializer.ts | 21 +-
javascript/packages/fory/lib/gen/set.ts | 4 +-
javascript/packages/fory/lib/gen/string.ts | 9 +-
javascript/packages/fory/lib/gen/struct.ts | 19 +-
javascript/packages/fory/lib/gen/tuple.ts | 82 --
javascript/packages/fory/lib/gen/typedArray.ts | 26 +-
javascript/packages/fory/lib/reader/index.ts | 128 ++-
javascript/packages/fory/lib/type.ts | 59 +-
javascript/packages/fory/lib/typeInfo.ts | 353 +++----
javascript/packages/fory/lib/writer/index.ts | 87 +-
javascript/packages/hps/src/fastcall.cc | 19 +-
javascript/test/any.test.ts | 2 +-
javascript/test/bool.test.ts | 2 +-
javascript/test/crossLanguage.test.ts | 1308 +++++++++++++++++++++++-
javascript/test/datetime.test.ts | 2 +-
javascript/test/enum.test.ts | 2 +-
javascript/test/fixtures/tuple.ts | 78 --
javascript/test/fory.test.ts | 6 -
javascript/test/hps.test.ts | 4 +-
javascript/test/io.test.ts | 32 +-
javascript/test/map.test.ts | 2 +-
javascript/test/number.test.ts | 2 +-
javascript/test/object.test.ts | 3 +-
javascript/test/protocol/struct.test.ts | 4 +-
javascript/test/referenceResolve.test.ts | 57 --
javascript/test/set.test.ts | 2 +-
javascript/test/string.test.ts | 2 +-
javascript/test/tuple.test.ts | 85 --
javascript/test/typemeta.test.ts | 2 +-
46 files changed, 1753 insertions(+), 813 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a9028cb28..14520202f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -458,9 +458,11 @@ jobs:
${{ runner.os }}-maven-
- name: Run JavaScript Xlang Test
env:
- FORY_JavaScript_JAVA_CI: "1"
+ # FORY_JAVASCRIPT_JAVA_CI: "1"
run: |
- cd java
+ cd javascript
+ npm install
+ cd ../java
mvn -T16 --no-transfer-progress clean install -DskipTests
cd fory-core
mvn -T16 --no-transfer-progress test
-Dtest=org.apache.fory.xlang.JavaScriptXlangTest
diff --git a/javascript/README.md b/javascript/README.md
index 6ed9a8fa1..1327c2e88 100644
--- a/javascript/README.md
+++ b/javascript/README.md
@@ -7,7 +7,7 @@ The Cross-Language part of the protocol is not stable, so the
output of this lib
## Usage
```Javascript
-import Fory, { Type, InternalSerializerType } from '@apache-fory/fory';
+import Fory, { Type } from '@apache-fory/fory';
/**
* @apache-fory/hps use v8's fast-calls-api that can be called directly by
jit, ensure that the version of Node is 20 or above.
diff --git a/javascript/packages/fory/index.ts
b/javascript/packages/fory/index.ts
index ad7f7fc92..a383a5548 100644
--- a/javascript/packages/fory/index.ts
+++ b/javascript/packages/fory/index.ts
@@ -23,14 +23,13 @@ import {
ArrayTypeInfo,
Type,
} from "./lib/typeInfo";
-import { Serializer, InternalSerializerType, Mode } from "./lib/type";
+import { Serializer, Mode } from "./lib/type";
import Fory from "./lib/fory";
import { BinaryReader } from "./lib/reader";
import { BinaryWriter } from "./lib/writer";
export {
Serializer,
- InternalSerializerType,
TypeInfo,
ArrayTypeInfo,
StructTypeInfo,
diff --git a/javascript/packages/fory/lib/classResolver.ts
b/javascript/packages/fory/lib/classResolver.ts
index 806c12662..dd6449b69 100644
--- a/javascript/packages/fory/lib/classResolver.ts
+++ b/javascript/packages/fory/lib/classResolver.ts
@@ -173,7 +173,7 @@ export default class ClassResolver {
}
getSerializerById(id: number) {
- if (id | 0xff) {
+ if (id <= 0xff) {
return this.internalSerializer[id]!;
} else {
return this.customSerializer.get(id)!;
diff --git a/javascript/packages/fory/lib/fory.ts
b/javascript/packages/fory/lib/fory.ts
index 2adea0214..089d6ee77 100644
--- a/javascript/packages/fory/lib/fory.ts
+++ b/javascript/packages/fory/lib/fory.ts
@@ -90,6 +90,7 @@ export default class {
} else {
const typeInfo = constructor;
serializer = new Gen(this, replace).generateSerializer(typeInfo);
+ this.classResolver.registerSerializer(typeInfo, serializer);
}
return {
serializer,
@@ -124,8 +125,6 @@ export default class {
}
this.binaryReader.uint8(); // skip language
- this.binaryReader.int32(); // native object offset. should skip.
javascript support cross mode only
- this.binaryReader.int32(); // native object size. should skip.
return serializer.read();
}
@@ -146,14 +145,10 @@ export default class {
bitmap |= ConfigFlags.isCrossLanguageFlag;
this.binaryWriter.uint8(bitmap);
this.binaryWriter.uint8(Language.JAVASCRIPT);
- const cursor = this.binaryWriter.getCursor();
- this.binaryWriter.skip(4); // preserve 4-byte for nativeObjects start
offsets.
- this.binaryWriter.uint32(0); // nativeObjects length.
// reserve fixed size
this.binaryWriter.reserve(serializer.fixedSize);
// start write
serializer.write(data);
- this.binaryWriter.setUint32Position(cursor,
this.binaryWriter.getCursor()); // nativeObjects start offsets;
return this.binaryWriter;
}
diff --git a/javascript/packages/fory/lib/gen/any.ts
b/javascript/packages/fory/lib/gen/any.ts
index 6274a7261..9e2f21a1d 100644
--- a/javascript/packages/fory/lib/gen/any.ts
+++ b/javascript/packages/fory/lib/gen/any.ts
@@ -21,7 +21,7 @@ import { TypeInfo } from "../typeInfo";
import { CodecBuilder } from "./builder";
import { BaseSerializerGenerator } from "./serializer";
import { CodegenRegistry } from "./router";
-import { InternalSerializerType, RefFlags, Serializer, TypeId } from "../type";
+import { RefFlags, Serializer, TypeId } from "../type";
import { Scope } from "./scope";
import Fory from "../fory";
@@ -38,7 +38,7 @@ export class AnySerializer {
}
detectSerializer() {
- const typeId = this.fory.binaryReader.int16();
+ const typeId = this.fory.binaryReader.readVarUint32Small7();
let serializer: Serializer | undefined;
if (TypeId.IS_NAMED_TYPE(typeId)) {
const ns =
this.fory.metaStringResolver.readNamespace(this.fory.binaryReader);
@@ -170,5 +170,5 @@ class AnySerializerGenerator extends
BaseSerializerGenerator {
}
}
-CodegenRegistry.register(InternalSerializerType.ANY, AnySerializerGenerator);
+CodegenRegistry.register(TypeId.UNKNOWN, AnySerializerGenerator);
CodegenRegistry.registerExternal(AnySerializer);
diff --git a/javascript/packages/fory/lib/gen/array.ts
b/javascript/packages/fory/lib/gen/array.ts
index b1ecd60e4..ef4732ca7 100644
--- a/javascript/packages/fory/lib/gen/array.ts
+++ b/javascript/packages/fory/lib/gen/array.ts
@@ -20,7 +20,7 @@
import { ArrayTypeInfo, TypeInfo } from "../typeInfo";
import { CodecBuilder } from "./builder";
import { CodegenRegistry } from "./router";
-import { InternalSerializerType } from "../type";
+import { TypeId } from "../type";
import { Scope } from "./scope";
import { CollectionSerializerGenerator } from "./collection";
@@ -57,4 +57,4 @@ class ArraySerializerGenerator extends
CollectionSerializerGenerator {
}
}
-CodegenRegistry.register(InternalSerializerType.ARRAY,
ArraySerializerGenerator);
+CodegenRegistry.register(TypeId.ARRAY, ArraySerializerGenerator);
diff --git a/javascript/packages/fory/lib/gen/binary.ts
b/javascript/packages/fory/lib/gen/binary.ts
index c6f2327d7..dbe93734c 100644
--- a/javascript/packages/fory/lib/gen/binary.ts
+++ b/javascript/packages/fory/lib/gen/binary.ts
@@ -21,7 +21,7 @@ import { TypeInfo } from "../typeInfo";
import { CodecBuilder } from "./builder";
import { BaseSerializerGenerator, RefState } from "./serializer";
import { CodegenRegistry } from "./router";
-import { InternalSerializerType } from "../type";
+import { TypeId } from "../type";
import { Scope } from "./scope";
class BinarySerializerGenerator extends BaseSerializerGenerator {
@@ -59,4 +59,4 @@ class BinarySerializerGenerator extends
BaseSerializerGenerator {
}
}
-CodegenRegistry.register(InternalSerializerType.BINARY,
BinarySerializerGenerator);
+CodegenRegistry.register(TypeId.BINARY, BinarySerializerGenerator);
diff --git a/javascript/packages/fory/lib/gen/bool.ts
b/javascript/packages/fory/lib/gen/bool.ts
index 207e700a6..f7e1dd6d5 100644
--- a/javascript/packages/fory/lib/gen/bool.ts
+++ b/javascript/packages/fory/lib/gen/bool.ts
@@ -21,7 +21,7 @@ import { TypeInfo } from "../typeInfo";
import { CodecBuilder } from "./builder";
import { BaseSerializerGenerator } from "./serializer";
import { CodegenRegistry } from "./router";
-import { InternalSerializerType } from "../type";
+import { TypeId } from "../type";
import { Scope } from "./scope";
class BoolSerializerGenerator extends BaseSerializerGenerator {
@@ -49,4 +49,4 @@ class BoolSerializerGenerator extends BaseSerializerGenerator
{
}
}
-CodegenRegistry.register(InternalSerializerType.BOOL, BoolSerializerGenerator);
+CodegenRegistry.register(TypeId.BOOL, BoolSerializerGenerator);
diff --git a/javascript/packages/fory/lib/gen/builder.ts
b/javascript/packages/fory/lib/gen/builder.ts
index 8688ab218..05a5c96c5 100644
--- a/javascript/packages/fory/lib/gen/builder.ts
+++ b/javascript/packages/fory/lib/gen/builder.ts
@@ -91,8 +91,8 @@ export class BinaryReaderBuilder {
return `${this.holder}.stringLatin1()`;
}
- stringOfVarUInt32() {
- return `${this.holder}.stringOfVarUInt32()`;
+ stringWithHeader() {
+ return `${this.holder}.stringWithHeader()`;
}
float64() {
@@ -115,6 +115,10 @@ export class BinaryReaderBuilder {
return `${this.holder}.int16()`;
}
+ readVarUint32Small7() {
+ return `${this.holder}.readVarUint32Small7()`;
+ }
+
uint64() {
return `${this.holder}.uint64()`;
}
@@ -189,6 +193,10 @@ class BinaryWriterBuilder {
return `${this.holder}.varInt32(${v})`;
}
+ writeVarUint32Small7(v: number | string) {
+ return `${this.holder}.writeVarUint32Small7(${v})`;
+ }
+
varUInt32(v: number | string) {
return `${this.holder}.varUInt32(${v})`;
}
@@ -201,8 +209,8 @@ class BinaryWriterBuilder {
return `${this.holder}.varInt64(${v})`;
}
- stringOfVarUInt32(str: string) {
- return `${this.holder}.stringOfVarUInt32(${str})`;
+ stringWithHeader(str: string) {
+ return `${this.holder}.stringWithHeader(${str})`;
}
bufferWithoutMemCheck(v: string) {
diff --git a/javascript/packages/fory/lib/gen/collection.ts
b/javascript/packages/fory/lib/gen/collection.ts
index 28b2537d4..708ba52be 100644
--- a/javascript/packages/fory/lib/gen/collection.ts
+++ b/javascript/packages/fory/lib/gen/collection.ts
@@ -21,7 +21,7 @@ import { TypeInfo } from "../typeInfo";
import { CodecBuilder } from "./builder";
import { BaseSerializerGenerator, RefState, SerializerGenerator } from
"./serializer";
import { CodegenRegistry } from "./router";
-import { InternalSerializerType, RefFlags, Serializer } from "../type";
+import { TypeId, RefFlags, Serializer } from "../type";
import { Scope } from "./scope";
import Fory from "../fory";
@@ -151,7 +151,7 @@ export abstract class CollectionSerializerGenerator extends
BaseSerializerGenera
abstract genericTypeDescriptin(): TypeInfo;
private isAny() {
- return this.genericTypeDescriptin().type === InternalSerializerType.ANY;
+ return this.genericTypeDescriptin().typeId === TypeId.UNKNOWN;
}
abstract newCollection(lenAccessor: string): string;
@@ -187,7 +187,7 @@ export abstract class CollectionSerializerGenerator extends
BaseSerializerGenera
return `
let ${flags} = 0;
${this.writeElementsHeader(accessor, flags)}
- ${this.builder.writer.int16(this.typeInfo.type)}
+ ${this.builder.writer.int16(this.typeInfo.typeId)}
${this.builder.writer.varUInt32(`${accessor}.${this.sizeProp()}`)}
${this.builder.writer.reserve(`${this.innerGenerator.getFixedSize()} *
${accessor}.${this.sizeProp()}`)};
if (${flags} & ${CollectionFlags.TRACKING_REF}) {
diff --git a/javascript/packages/fory/lib/gen/datetime.ts
b/javascript/packages/fory/lib/gen/datetime.ts
index 26d4368ce..7a0f8e69f 100644
--- a/javascript/packages/fory/lib/gen/datetime.ts
+++ b/javascript/packages/fory/lib/gen/datetime.ts
@@ -21,7 +21,7 @@ import { TypeInfo } from "../typeInfo";
import { CodecBuilder } from "./builder";
import { BaseSerializerGenerator } from "./serializer";
import { CodegenRegistry } from "./router";
-import { InternalSerializerType } from "../type";
+import { TypeId } from "../type";
import { Scope } from "./scope";
class TimestampSerializerGenerator extends BaseSerializerGenerator {
@@ -88,5 +88,5 @@ class DurationSerializerGenerator extends
BaseSerializerGenerator {
}
}
-CodegenRegistry.register(InternalSerializerType.DURATION,
DurationSerializerGenerator);
-CodegenRegistry.register(InternalSerializerType.TIMESTAMP,
TimestampSerializerGenerator);
+CodegenRegistry.register(TypeId.DURATION, DurationSerializerGenerator);
+CodegenRegistry.register(TypeId.TIMESTAMP, TimestampSerializerGenerator);
diff --git a/javascript/packages/fory/lib/gen/enum.ts
b/javascript/packages/fory/lib/gen/enum.ts
index 3aa63c110..9857da949 100644
--- a/javascript/packages/fory/lib/gen/enum.ts
+++ b/javascript/packages/fory/lib/gen/enum.ts
@@ -21,7 +21,7 @@ import { EnumTypeInfo, TypeInfo } from "../typeInfo";
import { CodecBuilder } from "./builder";
import { BaseSerializerGenerator } from "./serializer";
import { CodegenRegistry } from "./router";
-import { InternalSerializerType, MaxUInt32 } from "../type";
+import { TypeId, MaxUInt32 } from "../type";
import { Scope } from "./scope";
class EnumSerializerGenerator extends BaseSerializerGenerator {
@@ -93,4 +93,5 @@ class EnumSerializerGenerator extends BaseSerializerGenerator
{
}
}
-CodegenRegistry.register(InternalSerializerType.ENUM, EnumSerializerGenerator);
+CodegenRegistry.register(TypeId.ENUM, EnumSerializerGenerator);
+CodegenRegistry.register(TypeId.NAMED_ENUM, EnumSerializerGenerator);
diff --git a/javascript/packages/fory/lib/gen/index.ts
b/javascript/packages/fory/lib/gen/index.ts
index 0eb539cd2..653ed10e3 100644
--- a/javascript/packages/fory/lib/gen/index.ts
+++ b/javascript/packages/fory/lib/gen/index.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import { InternalSerializerType, Serializer } from "../type";
-import { ArrayTypeInfo, MapTypeInfo, StructTypeInfo, OneofTypeInfo,
SetTypeInfo, TupleTypeInfo, TypeInfo } from "../typeInfo";
+import { TypeId, Serializer } from "../type";
+import { ArrayTypeInfo, MapTypeInfo, StructTypeInfo, SetTypeInfo, TypeInfo }
from "../typeInfo";
import { CodegenRegistry } from "./router";
import { CodecBuilder } from "./builder";
import { Scope } from "./scope";
@@ -32,7 +32,6 @@ import "./map";
import "./number";
import "./set";
import "./struct";
-import "./tuple";
import "./typedArray";
import "./enum";
import Fory from "../fory";
@@ -47,9 +46,9 @@ export class Gen {
}
private generate(typeInfo: TypeInfo) {
- const InnerGeneratorClass = CodegenRegistry.get(typeInfo.type);
+ const InnerGeneratorClass = CodegenRegistry.get(typeInfo.typeId);
if (!InnerGeneratorClass) {
- throw new Error(`${typeInfo.type} generator not exists`);
+ throw new Error(`${typeInfo.typeId} generator not exists`);
}
const scope = new Scope();
const generator = new InnerGeneratorClass(typeInfo, new
CodecBuilder(scope, this.fory), scope);
@@ -73,7 +72,7 @@ export class Gen {
}
private traversalContainer(typeInfo: TypeInfo) {
- if (typeInfo.type === InternalSerializerType.STRUCT) {
+ if (typeInfo.typeId === TypeId.STRUCT || typeInfo.typeId ===
TypeId.NAMED_STRUCT) {
if (this.isRegistered(typeInfo) && !this.replace) {
return;
}
@@ -87,29 +86,16 @@ export class Gen {
this.register(<StructTypeInfo>typeInfo, func()(this.fory,
Gen.external, typeInfo, this.regOptions));
}
}
- if (typeInfo.type === InternalSerializerType.ARRAY) {
+ if (typeInfo.typeId === TypeId.ARRAY) {
this.traversalContainer((<ArrayTypeInfo>typeInfo).options.inner);
}
- if (typeInfo.type === InternalSerializerType.SET) {
+ if (typeInfo.typeId === TypeId.SET) {
this.traversalContainer((<SetTypeInfo>typeInfo).options.key);
}
- if (typeInfo.type === InternalSerializerType.MAP) {
+ if (typeInfo.typeId === TypeId.MAP) {
this.traversalContainer((<MapTypeInfo>typeInfo).options.key);
this.traversalContainer((<MapTypeInfo>typeInfo).options.value);
}
- if (typeInfo.type === InternalSerializerType.TUPLE) {
- (<TupleTypeInfo>typeInfo).options.inner.forEach((x) => {
- this.traversalContainer(x);
- });
- }
- if (typeInfo.type === InternalSerializerType.ONEOF) {
- const options = (<OneofTypeInfo>typeInfo).options;
- if (options.inner) {
- Object.values(options.inner).forEach((x) => {
- this.traversalContainer(x);
- });
- }
- }
}
generateSerializer(typeInfo: TypeInfo) {
diff --git a/javascript/packages/fory/lib/gen/map.ts
b/javascript/packages/fory/lib/gen/map.ts
index 2dd1b05b3..f2035a3d9 100644
--- a/javascript/packages/fory/lib/gen/map.ts
+++ b/javascript/packages/fory/lib/gen/map.ts
@@ -21,7 +21,7 @@ import { MapTypeInfo, TypeInfo } from "../typeInfo";
import { CodecBuilder } from "./builder";
import { BaseSerializerGenerator, RefState, SerializerGenerator } from
"./serializer";
import { CodegenRegistry } from "./router";
-import { InternalSerializerType, RefFlags, Serializer } from "../type";
+import { TypeId, RefFlags, Serializer } from "../type";
import { Scope } from "./scope";
import Fory from "../fory";
@@ -190,7 +190,7 @@ class MapAnySerializer {
flag = this.fory.binaryReader.uint8();
}
if (!isSame) {
- serializer =
this.fory.classResolver.getSerializerById(this.fory.binaryReader.int16());
+ serializer =
this.fory.classResolver.getSerializerById(this.fory.binaryReader.readVarUint32Small7());
}
switch (flag) {
case RefFlags.RefValueFlag:
@@ -250,7 +250,7 @@ export class MapSerializerGenerator extends
BaseSerializerGenerator {
}
private isAny() {
- return this.typeInfo.options.key.type === InternalSerializerType.ANY ||
this.typeInfo.options.value.type === InternalSerializerType.ANY;
+ return this.typeInfo.options.key.typeId === TypeId.UNKNOWN ||
this.typeInfo.options.value.typeId === TypeId.UNKNOWN;
}
private writeStmtSpecificType(accessor: string) {
@@ -341,9 +341,9 @@ export class MapSerializerGenerator extends
BaseSerializerGenerator {
return this.writeStmtSpecificType(accessor);
}
return `new (${anySerializer})(${this.builder.getForyName()}, ${
- this.typeInfo.options.key.type !== InternalSerializerType.ANY ?
this.typeInfo.options.key.typeId : null
+ this.typeInfo.options.key.typeId !== TypeId.UNKNOWN ?
this.typeInfo.options.key.typeId : null
}, ${
- this.typeInfo.options.value.type !== InternalSerializerType.ANY ?
this.typeInfo.options.value.typeId : null
+ this.typeInfo.options.value.typeId !== TypeId.UNKNOWN ?
this.typeInfo.options.value.typeId : null
}).write(${accessor})`;
}
@@ -424,9 +424,9 @@ export class MapSerializerGenerator extends
BaseSerializerGenerator {
return this.readStmtSpecificType(accessor, refState);
}
return accessor(`new (${anySerializer})(${this.builder.getForyName()}, ${
- this.typeInfo.options.key.type !== InternalSerializerType.ANY ?
(this.typeInfo.options.key.typeId) : null
+ this.typeInfo.options.key.typeId !== TypeId.UNKNOWN ?
(this.typeInfo.options.key.typeId) : null
}, ${
- this.typeInfo.options.value.type !== InternalSerializerType.ANY ?
(this.typeInfo.options.value.typeId) : null
+ this.typeInfo.options.value.typeId !== TypeId.UNKNOWN ?
(this.typeInfo.options.value.typeId) : null
}).read(${refState.toConditionExpr()})`);
}
@@ -440,4 +440,4 @@ export class MapSerializerGenerator extends
BaseSerializerGenerator {
}
CodegenRegistry.registerExternal(MapAnySerializer);
-CodegenRegistry.register(InternalSerializerType.MAP, MapSerializerGenerator);
+CodegenRegistry.register(TypeId.MAP, MapSerializerGenerator);
diff --git a/javascript/packages/fory/lib/gen/number.ts
b/javascript/packages/fory/lib/gen/number.ts
index a5a122c5b..50af993c8 100644
--- a/javascript/packages/fory/lib/gen/number.ts
+++ b/javascript/packages/fory/lib/gen/number.ts
@@ -21,7 +21,7 @@ import { TypeInfo } from "../typeInfo";
import { CodecBuilder } from "./builder";
import { BaseSerializerGenerator } from "./serializer";
import { CodegenRegistry } from "./router";
-import { InternalSerializerType } from "../type";
+import { TypeId } from "../type";
import { Scope } from "./scope";
function buildNumberSerializer(writeFun: (builder: CodecBuilder, accessor:
string) => string, read: (builder: CodecBuilder) => string) {
@@ -51,109 +51,109 @@ function buildNumberSerializer(writeFun: (builder:
CodecBuilder, accessor: strin
};
}
-CodegenRegistry.register(InternalSerializerType.INT8,
+CodegenRegistry.register(TypeId.INT8,
buildNumberSerializer(
(builder, accessor) => builder.writer.int8(accessor),
builder => builder.reader.int8()
)
);
-CodegenRegistry.register(InternalSerializerType.INT16,
+CodegenRegistry.register(TypeId.INT16,
buildNumberSerializer(
(builder, accessor) => builder.writer.int16(accessor),
builder => builder.reader.int16()
)
);
-CodegenRegistry.register(InternalSerializerType.INT32,
+CodegenRegistry.register(TypeId.INT32,
buildNumberSerializer(
(builder, accessor) => builder.writer.int32(accessor),
builder => builder.reader.int32()
)
);
-CodegenRegistry.register(InternalSerializerType.VARINT32,
+CodegenRegistry.register(TypeId.VARINT32,
buildNumberSerializer(
(builder, accessor) => builder.writer.varInt32(accessor),
builder => builder.reader.varInt32()
)
);
-CodegenRegistry.register(InternalSerializerType.INT64,
+CodegenRegistry.register(TypeId.INT64,
buildNumberSerializer(
(builder, accessor) => builder.writer.sliInt64(accessor),
builder => builder.reader.sliInt64()
)
);
-CodegenRegistry.register(InternalSerializerType.TAGGED_INT64,
+CodegenRegistry.register(TypeId.TAGGED_INT64,
buildNumberSerializer(
(builder, accessor) => builder.writer.sliInt64(accessor),
builder => builder.reader.sliInt64()
)
);
-CodegenRegistry.register(InternalSerializerType.FLOAT16,
+CodegenRegistry.register(TypeId.FLOAT16,
buildNumberSerializer(
(builder, accessor) => builder.writer.float32(accessor),
builder => builder.reader.float16()
)
);
-CodegenRegistry.register(InternalSerializerType.FLOAT32,
+CodegenRegistry.register(TypeId.FLOAT32,
buildNumberSerializer(
(builder, accessor) => builder.writer.float32(accessor),
builder => builder.reader.float32()
)
);
-CodegenRegistry.register(InternalSerializerType.FLOAT64,
+CodegenRegistry.register(TypeId.FLOAT64,
buildNumberSerializer(
(builder, accessor) => builder.writer.float64(accessor),
builder => builder.reader.float64()
)
);
-CodegenRegistry.register(InternalSerializerType.UINT8,
+CodegenRegistry.register(TypeId.UINT8,
buildNumberSerializer(
(builder, accessor) => builder.writer.uint8(accessor),
builder => builder.reader.uint8()
)
);
-CodegenRegistry.register(InternalSerializerType.UINT16,
+CodegenRegistry.register(TypeId.UINT16,
buildNumberSerializer(
(builder, accessor) => builder.writer.uint16(accessor),
builder => builder.reader.uint16()
)
);
-CodegenRegistry.register(InternalSerializerType.UINT32,
+CodegenRegistry.register(TypeId.UINT32,
buildNumberSerializer(
(builder, accessor) => builder.writer.uint32(accessor),
builder => builder.reader.uint32()
)
);
-CodegenRegistry.register(InternalSerializerType.VAR_UINT32,
+CodegenRegistry.register(TypeId.VAR_UINT32,
buildNumberSerializer(
(builder, accessor) => builder.writer.varUInt32(accessor),
builder => builder.reader.varUInt32()
)
);
-CodegenRegistry.register(InternalSerializerType.UINT64,
+CodegenRegistry.register(TypeId.UINT64,
buildNumberSerializer(
(builder, accessor) => builder.writer.uint64(accessor),
builder => builder.reader.uint64()
)
);
-CodegenRegistry.register(InternalSerializerType.VAR_UINT64,
+CodegenRegistry.register(TypeId.VAR_UINT64,
buildNumberSerializer(
(builder, accessor) => builder.writer.varUInt64(accessor),
builder => builder.reader.varUInt64()
)
);
-CodegenRegistry.register(InternalSerializerType.TAGGED_UINT64,
+CodegenRegistry.register(TypeId.TAGGED_UINT64,
buildNumberSerializer(
(builder, accessor) => builder.writer.varUInt64(accessor),
builder => builder.reader.varUInt64()
diff --git a/javascript/packages/fory/lib/gen/router.ts
b/javascript/packages/fory/lib/gen/router.ts
index e4c00da83..063747e2b 100644
--- a/javascript/packages/fory/lib/gen/router.ts
+++ b/javascript/packages/fory/lib/gen/router.ts
@@ -19,14 +19,13 @@
import { TypeInfo } from "../typeInfo";
import { SerializerGenerator } from "./serializer";
-import { InternalSerializerType } from "../type";
import { CodecBuilder } from "./builder";
import { Scope } from "./scope";
type SerializerGeneratorConstructor = new (typeInfo: TypeInfo, builder:
CodecBuilder, scope: Scope) => SerializerGenerator;
export class CodegenRegistry {
- static map = new Map<string, SerializerGeneratorConstructor>();
+ static map = new Map<number, SerializerGeneratorConstructor>();
static external = new Map<string, any>();
private static checkExists(name: string) {
@@ -35,8 +34,8 @@ export class CodegenRegistry {
}
}
- static register(type: InternalSerializerType, generator:
SerializerGeneratorConstructor) {
- this.map.set(InternalSerializerType[type], generator);
+ static register(typeId: number, generator: SerializerGeneratorConstructor) {
+ this.map.set(typeId, generator);
}
static registerExternal(object: { name: string }) {
@@ -45,15 +44,15 @@ export class CodegenRegistry {
}
static newGeneratorByTypeInfo(typeInfo: TypeInfo, builder: CodecBuilder,
scope: Scope) {
- const constructor = CodegenRegistry.get(typeInfo.type);
+ const constructor = CodegenRegistry.get(typeInfo.typeId);
if (!constructor) {
throw new Error("type not registered // todo");
}
return new constructor(typeInfo, builder, scope);
}
- static get(type: InternalSerializerType) {
- return this.map.get(InternalSerializerType[type]);
+ static get(typeId: number) {
+ return this.map.get(typeId & 0xff);
}
static getExternal() {
diff --git a/javascript/packages/fory/lib/gen/serializer.ts
b/javascript/packages/fory/lib/gen/serializer.ts
index 4f8f22d20..78edd2674 100644
--- a/javascript/packages/fory/lib/gen/serializer.ts
+++ b/javascript/packages/fory/lib/gen/serializer.ts
@@ -17,22 +17,27 @@
* under the License.
*/
-import { InternalSerializerType, Mode, TypeId } from "../type";
+import { TypeId, Mode } from "../type";
import { CodecBuilder } from "./builder";
import { RefFlags } from "../type";
import { Scope } from "./scope";
import { TypeInfo, StructTypeInfo } from "../typeInfo";
import { TypeMeta } from "../meta/TypeMeta";
+import { BinaryWriter } from "../writer";
export const makeHead = (flag: RefFlags, typeId: number) => {
- return (((typeId << 16) >>> 16) << 8) | ((flag << 24) >>> 24);
+ const writer = new BinaryWriter();
+ writer.uint8(flag);
+ writer.writeVarUint32Small7(typeId);
+ const buffer = writer.dump();
+ return buffer;
};
export interface SerializerGenerator {
toSerializer(): string;
getFixedSize(): number;
needToWriteRef(): boolean;
- getType(): InternalSerializerType;
+ getType(): number;
getTypeId(): number | undefined;
toWriteEmbed(accessor: string, excludeHead?: boolean): string;
toReadEmbed(accessor: (expr: string) => string, excludeHead?: boolean,
refState?: RefState): string;
@@ -119,7 +124,7 @@ export abstract class BaseSerializerGenerator implements
SerializerGenerator {
abstract readStmt(accessor: (expr: string) => string, refState: RefState):
string;
getType() {
- return this.typeInfo.type;
+ return this.typeInfo.typeId;
}
getTypeId() {
@@ -169,6 +174,7 @@ export abstract class BaseSerializerGenerator implements
SerializerGenerator {
if (this.needToWriteRef()) {
const head = makeHead(RefFlags.RefValueFlag, this.typeInfo.typeId);
+ const bytes = this.scope.declare("headBytes", `new
Uint8Array([${head.join(",")}])`);
const existsId = this.scope.uniqueName("existsId");
return `
if (${accessor} !== null && ${accessor} !== undefined) {
@@ -178,7 +184,7 @@ export abstract class BaseSerializerGenerator implements
SerializerGenerator {
${this.builder.writer.varUInt32(existsId)}
} else {
${this.builder.referenceResolver.writeRef(accessor)}
- ${this.builder.writer.int24(head)};
+ ${this.builder.writer.buffer(bytes)};
${maybeNamed()}
${maybeCompatiable()}
${stmt(accessor)};
@@ -189,9 +195,10 @@ export abstract class BaseSerializerGenerator implements
SerializerGenerator {
`;
} else {
const head = makeHead(RefFlags.NotNullValueFlag, this.typeInfo.typeId);
+ const bytes = this.scope.declare("headBytes", `new
Uint8Array([${head.join(",")}])`);
return `
if (${accessor} !== null && ${accessor} !== undefined) {
- ${this.builder.writer.int24(head)};
+ ${this.builder.writer.buffer(bytes)};
${maybeNamed()}
${maybeCompatiable()}
${stmt(accessor)};
@@ -218,7 +225,7 @@ export abstract class BaseSerializerGenerator implements
SerializerGenerator {
switch (${refFlag}) {
case ${RefFlags.NotNullValueFlag}:
case ${RefFlags.RefValueFlag}:
- const ${typeId} = ${this.builder.reader.int16()};
+ const ${typeId} = ${this.builder.reader.readVarUint32Small7()};
let ${ns};
let ${typeName};
if (${typeId} === ${TypeId.NAMED_STRUCT} || ${typeId} ===
${TypeId.NAMED_ENUM}) {
diff --git a/javascript/packages/fory/lib/gen/set.ts
b/javascript/packages/fory/lib/gen/set.ts
index ef1f4b460..9975c71a2 100644
--- a/javascript/packages/fory/lib/gen/set.ts
+++ b/javascript/packages/fory/lib/gen/set.ts
@@ -20,7 +20,7 @@
import { SetTypeInfo, TypeInfo } from "../typeInfo";
import { CodecBuilder } from "./builder";
import { CodegenRegistry } from "./router";
-import { InternalSerializerType } from "../type";
+import { TypeId } from "../type";
import { Scope } from "./scope";
import { CollectionSerializerGenerator } from "./collection";
@@ -57,4 +57,4 @@ class SetSerializerGenerator extends
CollectionSerializerGenerator {
}
}
-CodegenRegistry.register(InternalSerializerType.SET, SetSerializerGenerator);
+CodegenRegistry.register(TypeId.SET, SetSerializerGenerator);
diff --git a/javascript/packages/fory/lib/gen/string.ts
b/javascript/packages/fory/lib/gen/string.ts
index ac2b03514..0fa67c3e2 100644
--- a/javascript/packages/fory/lib/gen/string.ts
+++ b/javascript/packages/fory/lib/gen/string.ts
@@ -21,7 +21,7 @@ import { TypeInfo } from "../typeInfo";
import { CodecBuilder } from "./builder";
import { BaseSerializerGenerator, RefState } from "./serializer";
import { CodegenRegistry } from "./router";
-import { InternalSerializerType } from "../type";
+import { TypeId } from "../type";
import { Scope } from "./scope";
class StringSerializerGenerator extends BaseSerializerGenerator {
@@ -33,14 +33,13 @@ class StringSerializerGenerator extends
BaseSerializerGenerator {
}
writeStmt(accessor: string): string {
- return this.builder.writer.stringOfVarUInt32(accessor);
+ return this.builder.writer.stringWithHeader(accessor);
}
readStmt(accessor: (expr: string) => string, refState: RefState): string {
const result = this.scope.uniqueName("result");
-
return `
- ${result} = ${this.builder.reader.stringOfVarUInt32()};
+ const ${result} = ${this.builder.reader.stringWithHeader()};
${this.maybeReference(result, refState)};
${accessor(result)}
`;
@@ -55,4 +54,4 @@ class StringSerializerGenerator extends
BaseSerializerGenerator {
}
}
-CodegenRegistry.register(InternalSerializerType.STRING,
StringSerializerGenerator);
+CodegenRegistry.register(TypeId.STRING, StringSerializerGenerator);
diff --git a/javascript/packages/fory/lib/gen/struct.ts
b/javascript/packages/fory/lib/gen/struct.ts
index 1ef250829..1fbf3a7fe 100644
--- a/javascript/packages/fory/lib/gen/struct.ts
+++ b/javascript/packages/fory/lib/gen/struct.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { InternalSerializerType, MaxInt32, Mode, TypeId } from "../type";
+import { TypeId, MaxInt32, Mode } from "../type";
import { Scope } from "./scope";
import { CodecBuilder } from "./builder";
import { StructTypeInfo, TypeInfo } from "../typeInfo";
@@ -71,15 +71,15 @@ class StructSerializerGenerator extends
BaseSerializerGenerator {
return `
${this.builder.fory.config.mode === Mode.SchemaConsistent ?
this.builder.writer.varUInt32(computeStructHash(this.typeInfo)) : ""}
${Object.entries(options.props!).sort().map(([key, inner]) => {
- const InnerGeneratorClass = CodegenRegistry.get(inner.type);
+ const InnerGeneratorClass = CodegenRegistry.get(inner.typeId);
if (!InnerGeneratorClass) {
- throw new Error(`${inner.type} generator not exists`);
+ throw new Error(`${inner.typeId} generator not exists`);
}
const innerGenerator = new InnerGeneratorClass(inner, this.builder,
this.scope);
const fieldAccessor =
`${accessor}${CodecBuilder.safePropAccessor(key)}`;
return (inner as any).nullable === false
- ? `if (${fieldAccessor} === null || ${fieldAccessor} === undefined)
{ throw new Error("Field '${CodecBuilder.replaceBackslashAndQuote(key)}' is not
nullable"); }\n${innerGenerator.toWriteEmbed(fieldAccessor, true)}`
+ ? `if (${fieldAccessor} === null || ${fieldAccessor} === undefined)
{ throw new Error("Field '${CodecBuilder.replaceBackslashAndQuote(key)}' is not
nullable"); }\n${innerGenerator.toWriteEmbed(fieldAccessor)}`
: innerGenerator.toWriteEmbed(fieldAccessor);
}).join(";\n")}
`;
@@ -114,9 +114,9 @@ class StructSerializerGenerator extends
BaseSerializerGenerator {
}
${this.maybeReference(result, refState)}
${Object.entries(options.props!).sort().map(([key, inner]) => {
- const InnerGeneratorClass = CodegenRegistry.get(inner.type);
+ const InnerGeneratorClass = CodegenRegistry.get(inner.typeId);
if (!InnerGeneratorClass) {
- throw new Error(`${inner.type} generator not exists`);
+ throw new Error(`${inner.typeId} generator not exists`);
}
const innerGenerator = new InnerGeneratorClass(inner, this.builder,
this.scope);
return innerGenerator.toReadEmbed(expr =>
`${result}${CodecBuilder.safePropAccessor(key)} = ${expr}`);
@@ -157,7 +157,7 @@ class StructSerializerGenerator extends
BaseSerializerGenerator {
let fixedSize = 8;
if (options.props) {
Object.values(options.props).forEach((x) => {
- const propGenerator = new (CodegenRegistry.get(x.type)!)(x,
this.builder, this.scope);
+ const propGenerator = new (CodegenRegistry.get(x.typeId)!)(x,
this.builder, this.scope);
fixedSize += propGenerator.getFixedSize();
});
} else {
@@ -171,4 +171,7 @@ class StructSerializerGenerator extends
BaseSerializerGenerator {
}
}
-CodegenRegistry.register(InternalSerializerType.STRUCT,
StructSerializerGenerator);
+CodegenRegistry.register(TypeId.STRUCT, StructSerializerGenerator);
+CodegenRegistry.register(TypeId.NAMED_STRUCT, StructSerializerGenerator);
+CodegenRegistry.register(TypeId.COMPATIBLE_STRUCT, StructSerializerGenerator);
+CodegenRegistry.register(TypeId.NAMED_COMPATIBLE_STRUCT,
StructSerializerGenerator);
diff --git a/javascript/packages/fory/lib/gen/tuple.ts
b/javascript/packages/fory/lib/gen/tuple.ts
deleted file mode 100644
index fb4db8af4..000000000
--- a/javascript/packages/fory/lib/gen/tuple.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { TupleTypeInfo, TypeInfo } from "../typeInfo";
-import { CodecBuilder } from "./builder";
-import { BaseSerializerGenerator, RefState, SerializerGenerator } from
"./serializer";
-import { CodegenRegistry } from "./router";
-import { InternalSerializerType } from "../type";
-import { Scope } from "./scope";
-
-class TupleSerializerGenerator extends BaseSerializerGenerator {
- typeInfo: TupleTypeInfo;
- innerGenerators: SerializerGenerator[];
-
- constructor(typeInfo: TypeInfo, builder: CodecBuilder, scope: Scope) {
- super(typeInfo, builder, scope);
- this.typeInfo = <TupleTypeInfo>typeInfo;
- const inner = this.typeInfo.options.inner;
- this.innerGenerators = inner.map(x =>
CodegenRegistry.newGeneratorByTypeInfo(x, this.builder, this.scope));
- }
-
- writeStmt(accessor: string): string {
- const fixedSize = this.innerGenerators.reduce((x, y) => x +
y.getFixedSize(), 0);
-
- return `
- ${this.builder.writer.varUInt32(this.innerGenerators.length)}
- ${this.builder.writer.reserve(fixedSize)};
- ${
- this.innerGenerators.map((generator, index) => {
- return generator.toWriteEmbed(`${accessor}[${index}]`);
- }).join("\n")
- }
- `;
- }
-
- readStmt(accessor: (expr: string) => string, refState: RefState): string {
- const result = this.scope.uniqueName("result");
- const len = this.scope.uniqueName("len");
-
- return `
- const ${len} = ${this.builder.reader.varUInt32()};
- const ${result} = new Array(${len});
- ${this.maybeReference(result, refState)}
- ${
- this.innerGenerators.map((generator, index) => {
- return `
- if (${len} > ${index}) {
- ${generator.toReadEmbed(expr => `${result}[${index}] =
${expr}`)}
- }
- `;
- }).join("\n")
- }
- ${accessor(result)}
- `;
- }
-
- getFixedSize(): number {
- return 7;
- }
-
- needToWriteRef(): boolean {
- return Boolean(this.builder.fory.config.refTracking);
- }
-}
-
-CodegenRegistry.register(InternalSerializerType.TUPLE,
TupleSerializerGenerator);
diff --git a/javascript/packages/fory/lib/gen/typedArray.ts
b/javascript/packages/fory/lib/gen/typedArray.ts
index 11ffa9d1e..64a7c7fea 100644
--- a/javascript/packages/fory/lib/gen/typedArray.ts
+++ b/javascript/packages/fory/lib/gen/typedArray.ts
@@ -21,8 +21,8 @@ import { Type, TypeInfo } from "../typeInfo";
import { CodecBuilder } from "./builder";
import { BaseSerializerGenerator, RefState, SerializerGenerator } from
"./serializer";
import { CodegenRegistry } from "./router";
-import { InternalSerializerType } from "../type";
import { Scope } from "./scope";
+import { TypeId } from "../type";
function build(inner: TypeInfo) {
return class TypedArraySerializerGenerator extends BaseSerializerGenerator {
@@ -72,15 +72,15 @@ function build(inner: TypeInfo) {
};
}
-CodegenRegistry.register(InternalSerializerType.BOOL_ARRAY,
build(Type.bool()));
-CodegenRegistry.register(InternalSerializerType.INT8_ARRAY,
build(Type.int8()));
-CodegenRegistry.register(InternalSerializerType.INT16_ARRAY,
build(Type.int16()));
-CodegenRegistry.register(InternalSerializerType.INT32_ARRAY,
build(Type.int32()));
-CodegenRegistry.register(InternalSerializerType.INT64_ARRAY,
build(Type.int64()));
-CodegenRegistry.register(InternalSerializerType.UINT8_ARRAY,
build(Type.uint8()));
-CodegenRegistry.register(InternalSerializerType.UINT16_ARRAY,
build(Type.uint16()));
-CodegenRegistry.register(InternalSerializerType.UINT32_ARRAY,
build(Type.uint32()));
-CodegenRegistry.register(InternalSerializerType.UINT64_ARRAY,
build(Type.uint64()));
-CodegenRegistry.register(InternalSerializerType.FLOAT16_ARRAY,
build(Type.float16()));
-CodegenRegistry.register(InternalSerializerType.FLOAT32_ARRAY,
build(Type.float32()));
-CodegenRegistry.register(InternalSerializerType.FLOAT64_ARRAY,
build(Type.float64()));
+CodegenRegistry.register(TypeId.BOOL_ARRAY, build(Type.bool()));
+CodegenRegistry.register(TypeId.INT8_ARRAY, build(Type.int8()));
+CodegenRegistry.register(TypeId.INT16_ARRAY, build(Type.int16()));
+CodegenRegistry.register(TypeId.INT32_ARRAY, build(Type.int32()));
+CodegenRegistry.register(TypeId.INT64_ARRAY, build(Type.int64()));
+CodegenRegistry.register(TypeId.UINT8_ARRAY, build(Type.uint8()));
+CodegenRegistry.register(TypeId.UINT16_ARRAY, build(Type.uint16()));
+CodegenRegistry.register(TypeId.UINT32_ARRAY, build(Type.uint32()));
+CodegenRegistry.register(TypeId.UINT64_ARRAY, build(Type.uint64()));
+CodegenRegistry.register(TypeId.FLOAT16_ARRAY, build(Type.float16()));
+CodegenRegistry.register(TypeId.FLOAT32_ARRAY, build(Type.float32()));
+CodegenRegistry.register(TypeId.FLOAT64_ARRAY, build(Type.float64()));
diff --git a/javascript/packages/fory/lib/reader/index.ts
b/javascript/packages/fory/lib/reader/index.ts
index af844b110..1fb970b71 100644
--- a/javascript/packages/fory/lib/reader/index.ts
+++ b/javascript/packages/fory/lib/reader/index.ts
@@ -132,14 +132,17 @@ export class BinaryReader {
return result;
}
- stringOfVarUInt32() {
- switch (this.uint8()) {
+ stringWithHeader() {
+ const header = this.readVarUint36Small();
+ const type = header & 0b11;
+ const len = header >>> 2;
+ switch (type) {
case LATIN1:
- return this.stringLatin1(this.varUInt32());
+ return this.stringLatin1(len);
case UTF8:
- return this.stringUtf8(this.varUInt32());
+ return this.stringUtf8(len);
case UTF16:
- return this.stringUtf16LE(this.varUInt32());
+ return this.stringUtf16LE(len);
default:
break;
}
@@ -224,9 +227,110 @@ export class BinaryReader {
return result;
}
+ readVarUint32Small7(): number {
+ const readIdx = this.cursor;
+ if (this.byteLength - readIdx > 0) {
+ const v = this.dataView.getUint8(readIdx);
+ if ((v & 0x80) === 0) {
+ this.cursor = readIdx + 1;
+ return v;
+ }
+ }
+ return this.readVarUint32Small14();
+ }
+
+ private readVarUint32Small14(): number {
+ const readIdx = this.cursor;
+ if (this.byteLength - readIdx >= 5) {
+ const fourByteValue = this.dataView.getUint32(readIdx, true);
+ this.cursor = readIdx + 1;
+ let value = fourByteValue & 0x7F;
+ if ((fourByteValue & 0x80) !== 0) {
+ this.cursor++;
+ value |= (fourByteValue >>> 1) & 0x3f80;
+ if ((fourByteValue & 0x8000) !== 0) {
+ return this.continueReadVarUint32(readIdx + 2, fourByteValue, value);
+ }
+ }
+ return value;
+ } else {
+ return this.readVarUint36Slow();
+ }
+ }
+
+ private continueReadVarUint32(readIdx: number, bulkRead: number, value:
number): number {
+ readIdx++;
+ value |= (bulkRead >>> 2) & 0x1fc000;
+ if ((bulkRead & 0x800000) !== 0) {
+ readIdx++;
+ value |= (bulkRead >>> 3) & 0xfe00000;
+ if ((bulkRead & 0x80000000) !== 0) {
+ value |= (this.dataView.getUint8(readIdx++) & 0x7F) << 28;
+ }
+ }
+ this.cursor = readIdx;
+ return value;
+ }
+
+ readVarUint36Small(): number {
+ const readIdx = this.cursor;
+ if (this.byteLength - readIdx >= 9) {
+ const bulkValue = this.dataView.getBigUint64(readIdx, true);
+ this.cursor = readIdx + 1;
+ let result = Number(bulkValue & 0x7Fn);
+ if ((bulkValue & 0x80n) !== 0n) {
+ this.cursor++;
+ result |= Number((bulkValue >> 1n) & 0x3f80n);
+ if ((bulkValue & 0x8000n) !== 0n) {
+ return this.continueReadVarInt36(readIdx + 2, bulkValue, result);
+ }
+ }
+ return result;
+ } else {
+ return this.readVarUint36Slow();
+ }
+ }
+
+ private continueReadVarInt36(readIdx: number, bulkValue: bigint, result:
number): number {
+ readIdx++;
+ result |= Number((bulkValue >> 2n) & 0x1fc000n);
+ if ((bulkValue & 0x800000n) !== 0n) {
+ readIdx++;
+ result |= Number((bulkValue >> 3n) & 0xfe00000n);
+ if ((bulkValue & 0x80000000n) !== 0n) {
+ readIdx++;
+ result |= Number((bulkValue >> 4n) & 0xff0000000n);
+ }
+ }
+ this.cursor = readIdx;
+ return result;
+ }
+
+ private readVarUint36Slow(): number {
+ let b = this.uint8();
+ let result = b & 0x7F;
+ if ((b & 0x80) !== 0) {
+ b = this.uint8();
+ result |= (b & 0x7F) << 7;
+ if ((b & 0x80) !== 0) {
+ b = this.uint8();
+ result |= (b & 0x7F) << 14;
+ if ((b & 0x80) !== 0) {
+ b = this.uint8();
+ result |= (b & 0x7F) << 21;
+ if ((b & 0x80) !== 0) {
+ b = this.uint8();
+ result |= (b & 0xFF) << 28;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
varInt32() {
const v = this.varUInt32();
- return (v >> 1) ^ -(v & 1); // zigZag decode
+ return (v >>> 1) ^ -(v & 1); // zigZag decode
}
bigUInt8() {
@@ -277,15 +381,15 @@ export class BinaryReader {
let rl28 = byte & 0x7f;
let rh28 = 0;
if ((byte & 0x80) != 0) {
- byte = l32 & 0xff00 >> 8;
+ byte = (l32 >>> 8) & 0xff;
this.cursor++;
rl28 |= (byte & 0x7f) << 7;
if ((byte & 0x80) != 0) {
- byte = l32 & 0xff0000 >> 16;
+ byte = (l32 >>> 16) & 0xff;
this.cursor++;
rl28 |= (byte & 0x7f) << 14;
if ((byte & 0x80) != 0) {
- byte = l32 & 0xff000000 >> 24;
+ byte = l32 >>> 24;
this.cursor++;
rl28 |= (byte & 0x7f) << 21;
if ((byte & 0x80) != 0) {
@@ -293,15 +397,15 @@ export class BinaryReader {
byte = h32 & 0xff;
rh28 |= (byte & 0x7f);
if ((byte & 0x80) != 0) {
- byte = h32 & 0xff00 >> 8;
+ byte = (h32 >>> 8) & 0xff;
this.cursor++;
rh28 |= (byte & 0x7f) << 7;
if ((byte & 0x80) != 0) {
- byte = h32 & 0xff0000 >> 16;
+ byte = (h32 >>> 16) & 0xff;
this.cursor++;
rh28 |= (byte & 0x7f) << 14;
if ((byte & 0x80) != 0) {
- byte = h32 & 0xff000000 >> 24;
+ byte = h32 >>> 24;
this.cursor++;
rh28 |= (byte & 0x7f) << 21;
if ((byte & 0x80) != 0) {
diff --git a/javascript/packages/fory/lib/type.ts
b/javascript/packages/fory/lib/type.ts
index cb5bdee4b..4da8e6727 100644
--- a/javascript/packages/fory/lib/type.ts
+++ b/javascript/packages/fory/lib/type.ts
@@ -137,60 +137,9 @@ export const TypeId = {
TypeId.NAMED_EXT,
TypeId.NAMED_STRUCT,
TypeId.NAMED_UNION,
- ].includes(id);
+ ].includes((id & 0xff) as any);
},
-
-};
-
-export enum InternalSerializerType {
- // primitive type
- BOOL,
- INT8,
- INT16,
- INT32,
- VARINT32,
- INT64,
- VARINT64,
- TAGGED_INT64,
- UINT8,
- UINT16,
- UINT32,
- VAR_UINT32,
- UINT64,
- VAR_UINT64,
- TAGGED_UINT64,
- FLOAT16,
- FLOAT32,
- FLOAT64,
- STRING,
- ENUM,
- LIST,
- SET,
- MAP,
- DURATION,
- TIMESTAMP,
- DECIMAL,
- BINARY,
- ARRAY,
- BOOL_ARRAY,
- INT8_ARRAY,
- INT16_ARRAY,
- INT32_ARRAY,
- INT64_ARRAY,
- UINT8_ARRAY,
- UINT16_ARRAY,
- UINT32_ARRAY,
- UINT64_ARRAY,
- FLOAT16_ARRAY,
- FLOAT32_ARRAY,
- FLOAT64_ARRAY,
- STRUCT,
-
- // alias type, only use by javascript
- ANY,
- ONEOF,
- TUPLE,
-}
+} as const;
export enum ConfigFlags {
isNullFlag = 1 << 0,
@@ -228,8 +177,8 @@ export const HalfMaxInt32 = MaxInt32 / 2;
export const HalfMinInt32 = MinInt32 / 2;
export const LATIN1 = 0;
-export const UTF8 = 1;
-export const UTF16 = 2;
+export const UTF8 = 2;
+export const UTF16 = 1;
export interface Hps {
serializeString: (str: string, dist: Uint8Array, offset: number) => number;
}
diff --git a/javascript/packages/fory/lib/typeInfo.ts
b/javascript/packages/fory/lib/typeInfo.ts
index 74d63fa85..efbb90b62 100644
--- a/javascript/packages/fory/lib/typeInfo.ts
+++ b/javascript/packages/fory/lib/typeInfo.ts
@@ -18,27 +18,19 @@
*/
import { TypeMeta } from "./meta/TypeMeta";
-import { ForyTypeInfoSymbol, InternalSerializerType, WithForyClsInfo, TypeId }
from "./type";
+import { ForyTypeInfoSymbol, WithForyClsInfo, TypeId } from "./type";
const initMeta = (target: new () => any, typeInfo: TypeInfo) => {
if (!target.prototype) {
target.prototype = {};
}
+ if (!typeInfo.options) {
+ typeInfo.options = {};
+ }
+ typeInfo.options.withConstructor = true;
+ Object.assign(typeInfo.options.props, targetFields.get(target) || {})
target.prototype[ForyTypeInfoSymbol] = {
- structTypeInfo: Type.struct({
- ...(
- TypeId.IS_NAMED_TYPE(typeInfo.typeId)
- ? {
- namespace: typeInfo.namespace,
- typeName: typeInfo.typeName,
- }
- : {
- typeId: typeInfo.typeId,
- }
- ),
- }, targetFields.get(target) || {}, {
- withConstructor: true,
- }),
+ structTypeInfo: typeInfo,
} as WithForyClsInfo;
};
@@ -71,7 +63,7 @@ export class TypeInfo<T = unknown> extends ExtensibleFunction
{
typeName = "";
options?: any;
- private constructor(public type: InternalSerializerType, public typeId:
number) {
+ private constructor(public typeId: number) {
super(function (target: any, key?: string | { name?: string }) {
if (key === undefined) {
initMeta(target, that as unknown as StructTypeInfo);
@@ -87,10 +79,10 @@ export class TypeInfo<T = unknown> extends
ExtensibleFunction {
const that = this;
}
- static fromNonParam<T extends InternalSerializerType>(type: T, typeId:
number) {
+ static fromNonParam<T>(typeId: number) {
return new TypeInfo<{
type: T;
- }>(type, typeId);
+ }>(typeId);
}
static fromStruct<T = any>(nameInfo: {
@@ -99,8 +91,10 @@ export class TypeInfo<T = unknown> extends
ExtensibleFunction {
typeName?: string;
} | string | number, props?: Record<string, TypeInfo>, {
withConstructor = false,
+ compatible = false,
}: {
withConstructor?: boolean;
+ compatible?: boolean;
} = {}) {
let typeId: number | undefined;
let namespace: string | undefined;
@@ -129,8 +123,21 @@ export class TypeInfo<T = unknown> extends
ExtensibleFunction {
typeName = splits.slice(1).join(".");
}
}
- const finalTypeId = typeId !== undefined ? ((typeId << 8) | TypeId.STRUCT)
: TypeId.NAMED_STRUCT;
- const typeInfo = new TypeInfo<T>(InternalSerializerType.STRUCT,
finalTypeId).cast<StructTypeInfo>();
+ let finalTypeId = 0;
+ if (typeId !== undefined) {
+ if (compatible) {
+ finalTypeId = (typeId << 8) | TypeId.COMPATIBLE_STRUCT;
+ } else {
+ finalTypeId = (typeId << 8) | TypeId.STRUCT;
+ }
+ } else {
+ if (compatible) {
+ finalTypeId = TypeId.NAMED_COMPATIBLE_STRUCT;
+ } else {
+ finalTypeId = TypeId.NAMED_STRUCT;
+ }
+ }
+ const typeInfo = new TypeInfo<T>(finalTypeId).cast<StructTypeInfo>();
typeInfo.options = {
props: props || {},
withConstructor,
@@ -142,11 +149,11 @@ export class TypeInfo<T = unknown> extends
ExtensibleFunction {
return typeInfo as TypeInfo<T>;
}
- static fromWithOptions<T extends InternalSerializerType, T2>(type: T,
typeId: number, options: T2) {
+ static fromWithOptions<T, T2>(typeId: number, options: T2) {
const typeInfo = new TypeInfo<{
type: T;
options: T2;
- }>(type, typeId);
+ }>(typeId);
typeInfo.options = options;
return typeInfo;
}
@@ -184,7 +191,7 @@ export class TypeInfo<T = unknown> extends
ExtensibleFunction {
}
}
const finalTypeId = typeId !== undefined ? ((typeId << 8) | TypeId.ENUM) :
TypeId.NAMED_ENUM;
- const typeInfo = new TypeInfo<T>(InternalSerializerType.ENUM, finalTypeId);
+ const typeInfo = new TypeInfo<T>(finalTypeId);
typeInfo.cast<EnumTypeInfo>().options = {
inner: props,
};
@@ -216,24 +223,12 @@ export interface EnumTypeInfo extends TypeInfo {
};
}
-export interface OneofTypeInfo extends TypeInfo {
- options: {
- inner: { [key: string]: TypeInfo };
- };
-}
-
export interface ArrayTypeInfo extends TypeInfo {
options: {
inner: TypeInfo;
};
}
-export interface TupleTypeInfo extends TypeInfo {
- options: {
- inner: TypeInfo[];
- };
-}
-
export interface SetTypeInfo extends TypeInfo {
options: {
key: TypeInfo;
@@ -274,13 +269,6 @@ type MapProps<T> = T extends {
? Map<InputType<T2>, InputType<T3> | null>
: unknown;
-type TupleProps<T> = T extends {
- options: {
- inner: infer T2 extends readonly [...TypeInfo[]];
- };
-}
- ? { [K in keyof T2]: InputType<T2[K]> }
- : unknown;
type Value<T> = T extends { [s: string]: infer T2 } ? T2 : unknown;
@@ -292,24 +280,6 @@ type EnumProps<T> = T extends {
? Value<T2>
: unknown;
-type OneofProps<T> = T extends {
- options: {
- inner?: infer T2 extends { [key: string]: any };
- };
-}
- ? {
- [P in keyof T2]?: (InputType<T2[P]> | null);
- }
- : unknown;
-
-type OneofResult<T> = T extends {
- options: {
- inner?: infer T2;
- };
-}
- ? ResultType<Value<T2>>
- : unknown;
-
type SetProps<T> = T extends {
options: {
key: infer T2 extends TypeInfo;
@@ -320,188 +290,164 @@ type SetProps<T> = T extends {
export type InputType<T> = T extends TypeInfo<infer M> ? HintInput<M> :
unknown;
-export type HintInput<T> = T extends unknown ? any : T extends {
- type: InternalSerializerType.STRUCT;
+
+export type HintInput<T> = T extends {
+ type: typeof TypeId.STRUCT;
}
? Props<T>
: T extends {
- type: InternalSerializerType.STRING;
+ type: typeof TypeId.STRING;
}
? string
- : T extends {
- type: InternalSerializerType.TUPLE;
- }
- ? TupleProps<T>
: T extends {
type:
- | InternalSerializerType.INT8
- | InternalSerializerType.INT16
- | InternalSerializerType.INT32
- | InternalSerializerType.VARINT32
- | InternalSerializerType.UINT8
- | InternalSerializerType.UINT16
- | InternalSerializerType.UINT32
- | InternalSerializerType.VAR_UINT32
- | InternalSerializerType.FLOAT16
- | InternalSerializerType.FLOAT32
- | InternalSerializerType.FLOAT64;
+ | typeof TypeId["INT8"]
+ | typeof TypeId.INT16
+ | typeof TypeId.INT32
+ | typeof TypeId.VARINT32
+ | typeof TypeId.UINT8
+ | typeof TypeId.UINT16
+ | typeof TypeId.UINT32
+ | typeof TypeId.VAR_UINT32
+ | typeof TypeId.FLOAT16
+ | typeof TypeId.FLOAT32
+ | typeof TypeId.FLOAT64;
}
? number
: T extends {
- type: InternalSerializerType.VARINT64
- | InternalSerializerType.TAGGED_INT64
- | InternalSerializerType.INT64
- | InternalSerializerType.UINT64
- | InternalSerializerType.VAR_UINT64
- | InternalSerializerType.TAGGED_UINT64;
+ type: typeof TypeId.VARINT64
+ | typeof TypeId.TAGGED_INT64
+ | typeof TypeId.INT64
+ | typeof TypeId.UINT64
+ | typeof TypeId.VAR_UINT64
+ | typeof TypeId.TAGGED_UINT64;
}
? bigint
: T extends {
- type: InternalSerializerType.MAP;
+ type: typeof TypeId.MAP;
}
? MapProps<T>
: T extends {
- type: InternalSerializerType.SET;
+ type: typeof TypeId.SET;
}
? SetProps<T>
: T extends {
- type: InternalSerializerType.ARRAY;
+ type: typeof TypeId.ARRAY;
}
? InnerProps<T>
: T extends {
- type: InternalSerializerType.BOOL;
+ type: typeof TypeId.BOOL;
}
? boolean
: T extends {
- type: InternalSerializerType.DURATION;
+ type: typeof TypeId.DURATION;
}
? Date
: T extends {
- type: InternalSerializerType.TIMESTAMP;
+ type: typeof TypeId.TIMESTAMP;
}
? number
: T extends {
- type: InternalSerializerType.ANY;
- }
- ? any
- : T extends {
- type: InternalSerializerType.BINARY;
+ type: typeof TypeId.BINARY;
}
? Uint8Array
: T extends {
- type: InternalSerializerType.ENUM;
+ type: typeof TypeId.ENUM;
}
- ? EnumProps<T> : T extends {
- type: InternalSerializerType.ONEOF;
- } ? OneofProps<T> : unknown;
+ ? EnumProps<T> : any;
export type ResultType<T> = T extends TypeInfo<infer M> ? HintResult<M> :
HintResult<T>;
export type HintResult<T> = T extends never ? any : T extends {
- type: InternalSerializerType.STRUCT;
+ type: typeof TypeId.STRUCT;
}
? Props<T>
: T extends {
- type: InternalSerializerType.STRING;
+ type: typeof TypeId.STRING;
}
? string
- : T extends {
- type: InternalSerializerType.TUPLE;
- }
- ? TupleProps<T>
: T extends {
type:
- | InternalSerializerType.INT8
- | InternalSerializerType.INT16
- | InternalSerializerType.INT32
- | InternalSerializerType.VARINT32
- | InternalSerializerType.UINT8
- | InternalSerializerType.UINT16
- | InternalSerializerType.UINT32
- | InternalSerializerType.VAR_UINT32
- | InternalSerializerType.FLOAT16
- | InternalSerializerType.FLOAT32
- | InternalSerializerType.FLOAT64;
+ | typeof TypeId.INT8
+ | typeof TypeId.INT16
+ | typeof TypeId.INT32
+ | typeof TypeId.VARINT32
+ | typeof TypeId.UINT8
+ | typeof TypeId.UINT16
+ | typeof TypeId.UINT32
+ | typeof TypeId.VAR_UINT32
+ | typeof TypeId.FLOAT16
+ | typeof TypeId.FLOAT32
+ | typeof TypeId.FLOAT64;
}
? number
: T extends {
- type: InternalSerializerType.TAGGED_INT64
- | InternalSerializerType.INT64
- | InternalSerializerType.UINT64
- | InternalSerializerType.VAR_UINT64
- | InternalSerializerType.TAGGED_UINT64;
+ type: typeof TypeId.TAGGED_INT64
+ | typeof TypeId.INT64
+ | typeof TypeId.UINT64
+ | typeof TypeId.VAR_UINT64
+ | typeof TypeId.TAGGED_UINT64;
}
? bigint
: T extends {
- type: InternalSerializerType.MAP;
+ type: typeof TypeId.MAP;
}
? MapProps<T>
: T extends {
- type: InternalSerializerType.SET;
+ type: typeof TypeId.SET;
}
? SetProps<T>
: T extends {
- type: InternalSerializerType.ARRAY;
+ type: typeof TypeId.ARRAY;
}
? InnerProps<T>
: T extends {
- type: InternalSerializerType.BOOL;
+ type: typeof TypeId.BOOL;
}
? boolean
: T extends {
- type: InternalSerializerType.DURATION;
+ type: typeof TypeId.DURATION;
}
? Date
: T extends {
- type: InternalSerializerType.TIMESTAMP;
+ type: typeof TypeId.TIMESTAMP;
}
? number
: T extends {
- type: InternalSerializerType.BINARY;
+ type: typeof TypeId.BINARY;
}
? Uint8Array : T extends {
- type: InternalSerializerType.ANY;
+ type: typeof TypeId.ENUM;
}
- ? any
- : T extends {
- type: InternalSerializerType.ENUM;
- }
- ? EnumProps<T> : T extends {
- type: InternalSerializerType.ONEOF;
- } ? OneofResult<T> : unknown;
+ ? EnumProps<T>: unknown;
export const Type = {
any() {
- return TypeInfo.fromNonParam(InternalSerializerType.ANY, TypeId.STRUCT);
- },
- oneof<T extends { [key: string]: TypeInfo }>(inner?: T) {
- return TypeInfo.fromWithOptions(InternalSerializerType.ONEOF as const,
TypeId.STRUCT, {
- inner,
- });
+ return TypeInfo.fromNonParam<typeof TypeId.UNKNOWN>(TypeId.UNKNOWN);
},
array<T extends TypeInfo>(inner: T) {
- return TypeInfo.fromWithOptions(InternalSerializerType.ARRAY as const,
TypeId.ARRAY, {
+ return TypeInfo.fromWithOptions<typeof TypeId.ARRAY, { inner: T
}>(TypeId.ARRAY, {
inner,
});
},
- tuple<T1 extends readonly [...readonly TypeInfo[]]>(t1: T1) {
- return TypeInfo.fromWithOptions(InternalSerializerType.TUPLE as const,
TypeId.LIST, {
- inner: t1,
- });
- },
map<T1 extends TypeInfo, T2 extends TypeInfo>(
key: T1,
value: T2
) {
- return TypeInfo.fromWithOptions(InternalSerializerType.MAP as const,
TypeId.MAP, {
+ return TypeInfo.fromWithOptions<typeof TypeId.MAP, {
+ key: T1,
+ value: T2
+ }>(TypeId.MAP, {
key,
value,
});
},
set<T extends TypeInfo>(key: T) {
- return TypeInfo.fromWithOptions(InternalSerializerType.SET as const,
TypeId.SET, {
+ return TypeInfo.fromWithOptions<typeof TypeId.SET, {
+ key: T
+ }>(TypeId.SET, {
key,
});
},
@@ -511,7 +457,7 @@ export const Type = {
typeName?: string;
} | string | number, t1: T1) {
return TypeInfo.fromEnum<{
- type: InternalSerializerType.ENUM;
+ type: typeof TypeId.ENUM;
options: {
inner: T1;
};
@@ -523,235 +469,204 @@ export const Type = {
typeName?: string;
} | string | number, props?: T, {
withConstructor = false,
+ compatible = false,
}: {
withConstructor?: boolean;
+ compatible?: boolean;
} = {}) {
return TypeInfo.fromStruct<{
- type: InternalSerializerType.STRUCT;
+ type: typeof TypeId.STRUCT;
options: {
props: T;
};
}>(nameInfo, props, {
withConstructor,
+ compatible,
});
},
string() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.STRING as const,
+ return TypeInfo.fromNonParam<typeof TypeId.STRING>(
(TypeId.STRING),
);
},
bool() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.BOOL as const,
+ return TypeInfo.fromNonParam<typeof TypeId.BOOL>(
(TypeId.BOOL),
);
},
int8() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.INT8 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.INT8>(
(TypeId.INT8),
);
},
int16() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.INT16 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.INT16>(
(TypeId.INT16),
);
},
int32() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.INT32 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.INT32>(
(TypeId.INT32),
);
},
varInt32() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.VARINT32 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.VARINT32>(
(TypeId.VARINT32),
);
},
int64() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.INT64 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.INT64>(
(TypeId.INT64),
);
},
sliInt64() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.TAGGED_INT64 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.TAGGED_INT64>(
(TypeId.TAGGED_INT64),
);
},
float16() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.FLOAT16 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.FLOAT16>(
(TypeId.FLOAT16),
);
},
float32() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.FLOAT32 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.FLOAT32>(
(TypeId.FLOAT32),
);
},
float64() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.FLOAT64 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.FLOAT64>(
(TypeId.FLOAT64),
);
},
uint8() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.UINT8 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.UINT8>(
(TypeId.UINT8),
);
},
uint16() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.UINT16 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.UINT16>(
(TypeId.UINT16),
);
},
uint32() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.UINT32 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.UINT32>(
(TypeId.UINT32),
);
},
varUInt32() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.VAR_UINT32 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.VAR_UINT32>(
(TypeId.VAR_UINT32),
);
},
uint64() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.UINT64 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.UINT64>(
(TypeId.UINT64),
);
},
varUInt64() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.VAR_UINT64 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.VAR_UINT64>(
(TypeId.VAR_UINT64),
);
},
taggedUInt64() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.TAGGED_UINT64 as const,
+ return TypeInfo.fromNonParam<typeof TypeId.TAGGED_UINT64>(
(TypeId.TAGGED_UINT64),
);
},
binary() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.BINARY as const,
+ return TypeInfo.fromNonParam<typeof TypeId.BINARY>(
(TypeId.BINARY),
);
},
duration() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.DURATION as const,
+ return TypeInfo.fromNonParam<typeof TypeId.DURATION>(
(TypeId.DURATION),
-
);
},
timestamp() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.TIMESTAMP as const,
+ return TypeInfo.fromNonParam<typeof TypeId.TIMESTAMP>(
(TypeId.TIMESTAMP),
);
},
boolArray() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.BOOL_ARRAY as const,
+ return TypeInfo.fromNonParam<typeof TypeId.BOOL_ARRAY>(
(TypeId.BOOL_ARRAY),
);
},
int8Array() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.INT8_ARRAY as const,
+ return TypeInfo.fromNonParam<typeof TypeId.INT8_ARRAY>(
(TypeId.INT8_ARRAY),
);
},
int16Array() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.INT16_ARRAY as const,
+ return TypeInfo.fromNonParam<typeof TypeId.INT16_ARRAY>(
(TypeId.INT16_ARRAY),
);
},
int32Array() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.INT32_ARRAY as const,
+ return TypeInfo.fromNonParam<typeof TypeId.INT32_ARRAY>(
(TypeId.INT32_ARRAY),
);
},
int64Array() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.INT64_ARRAY as const,
+ return TypeInfo.fromNonParam<typeof TypeId.INT64_ARRAY>(
(TypeId.INT64_ARRAY),
);
},
uint8Array() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.UINT8_ARRAY as const,
+ return TypeInfo.fromNonParam<typeof TypeId.UINT8_ARRAY>(
(TypeId.INT8_ARRAY),
);
},
uint16Array() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.UINT16_ARRAY as const,
+ return TypeInfo.fromNonParam<typeof TypeId.UINT16_ARRAY>(
(TypeId.INT16_ARRAY),
);
},
uint32Array() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.UINT32_ARRAY as const,
+ return TypeInfo.fromNonParam<typeof TypeId.UINT32_ARRAY>(
(TypeId.UINT32_ARRAY),
);
},
uint64Array() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.UINT64_ARRAY as const,
+ return TypeInfo.fromNonParam<typeof TypeId.UINT64_ARRAY>(
(TypeId.INT64_ARRAY),
);
},
float16Array() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.FLOAT16_ARRAY as const,
+ return TypeInfo.fromNonParam<typeof TypeId.FLOAT16_ARRAY>(
(TypeId.FLOAT16_ARRAY),
);
},
float32Array() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.FLOAT32_ARRAY as const,
+ return TypeInfo.fromNonParam<typeof TypeId.FLOAT32_ARRAY>(
(TypeId.FLOAT32_ARRAY),
);
},
float64Array() {
- return TypeInfo.fromNonParam(
- InternalSerializerType.FLOAT64_ARRAY as const,
+ return TypeInfo.fromNonParam<typeof TypeId.FLOAT64_ARRAY>(
(TypeId.FLOAT64_ARRAY)
);
},
diff --git a/javascript/packages/fory/lib/writer/index.ts
b/javascript/packages/fory/lib/writer/index.ts
index 841f99399..0ebd139c7 100644
--- a/javascript/packages/fory/lib/writer/index.ts
+++ b/javascript/packages/fory/lib/writer/index.ts
@@ -157,10 +157,10 @@ export class BinaryWriter {
this.cursor += 8;
}
- buffer(v: Uint8Array) {
- this.reserve(v.byteLength);
+ buffer(v: ArrayLike<number>) {
+ this.reserve(v.length);
this.platformBuffer.set(v, this.cursor);
- this.cursor += v.byteLength;
+ this.cursor += v.length;
}
uint64(v: bigint) {
@@ -207,17 +207,20 @@ export class BinaryWriter {
}
}
- stringOfVarUInt32Fast(v: string) {
+ stringWithHeaderFast(v: string) {
const { serializeString } = this.config.hps!;
this.cursor = serializeString(v, this.platformBuffer, this.cursor);
}
- stringOfVarUInt32WithDetector(v: string) {
+ // const header = this.readVarUint36Small();
+ // const type = header & 0b11;
+ // const len = header >>> 2;
+
+ stringWithHeaderWithDetector(v: string) {
const isLatin1 = this.internalStringDetector!(v);
if (isLatin1) {
const len = v.length;
- this.dataView.setUint8(this.cursor++, LATIN1);
- this.varUInt32(len);
+ this.varUInt32((len << 2) | LATIN1);
this.reserve(len);
if (len < 40) {
for (let index = 0; index < v.length; index++) {
@@ -229,19 +232,17 @@ export class BinaryWriter {
this.cursor += len;
} else {
const len = v.length * 2;
- this.dataView.setUint8(this.cursor++, UTF16);
- this.varUInt32(len);
+ this.varUInt32((len << 2) | UTF16);
this.reserve(len);
this.platformBuffer.write(v, this.cursor, "utf16le");
this.cursor += len;
}
}
- stringOfVarUInt32Compatibly(v: string) {
+ stringWithHeaderCompatibly(v: string) {
const len = strByteLength(v);
const isLatin1 = len === v.length;
- this.dataView.setUint8(this.cursor++, isLatin1 ? LATIN1 : UTF8);
- this.varUInt32(len);
+ this.varUInt32((len << 2) | (isLatin1 ? LATIN1 : UTF8));
this.reserve(len);
if (isLatin1) {
if (len < 40) {
@@ -291,6 +292,46 @@ export class BinaryWriter {
this.dataView.setUint32(rawCursor, u32);
}
+ writeVarUint32Small7(value: number) {
+ if (value >>> 7 === 0) {
+ this.platformBuffer[this.cursor++] = value;
+ return;
+ }
+ this.cursor += this.continueWriteVarUint32Small7(value);
+ }
+
+ private continueWriteVarUint32Small7(value: number) {
+ let encoded = (value & 0x7F);
+ encoded |= (((value & 0x3f80) << 1) | 0x80);
+ const writerIdx = this.cursor;
+ if (value >>> 14 === 0) {
+ this.dataView.setUint32(writerIdx, encoded, true);
+ return 2;
+ }
+ return this.continuePutVarInt36(writerIdx, encoded, value);
+ }
+
+ private continuePutVarInt36(index: number, encoded: number, value: number):
number {
+ // 0x1fc000: 0b1111111 << 14
+ encoded |= (((value & 0x1fc000) << 2) | 0x8000);
+ if (value >>> 21 === 0) {
+ this.dataView.setUint32(index, encoded, true);
+ return 3;
+ }
+ // 0xfe00000: 0b1111111 << 21
+ encoded |= ((value & 0xfe00000) << 3) | 0x800000;
+ if (value >>> 28 === 0) {
+ this.dataView.setUint32(index, encoded, true);
+ return 4;
+ }
+ // 5-byte case: bits 28-31 go to the 5th byte
+ const encodedLong = (encoded >>> 0) | 0x80000000;
+ const highByte = value >>> 28;
+ this.dataView.setUint32(index, encodedLong, true);
+ this.dataView.setUint8(index + 4, highByte);
+ return 5;
+ }
+
varInt64(v: bigint) {
if (typeof v !== "bigint") {
v = BigInt(v);
@@ -304,12 +345,18 @@ export class BinaryWriter {
}
val = val & 0xFFFFFFFFFFFFFFFFn; // keep only the lower 64 bits
- while (val > 127) {
- this.platformBuffer[this.cursor++] = Number(val & 127n | 128n);
+ // Match Java's 1-9 byte varuint64 encoding:
+ // - 7 bits per byte for the first 8 bytes
+ // - the 9th byte (if present) uses full 8 bits, allowing values with the
64th bit set
+ for (let i = 0; i < 8; i++) {
+ if ((val >> 7n) === 0n) {
+ this.platformBuffer[this.cursor++] = Number(val);
+ return;
+ }
+ this.platformBuffer[this.cursor++] = Number((val & 127n) | 128n);
val >>= 7n;
}
- this.platformBuffer[this.cursor++] = Number(val);
- return;
+ this.platformBuffer[this.cursor++] = Number(val & 255n);
}
tryFreePool() {
@@ -365,13 +412,13 @@ export class BinaryWriter {
return this.reserved;
}
- stringOfVarUInt32(v: string) {
+ stringWithHeader(v: string) {
if (this.hpsEnable) {
- return this.stringOfVarUInt32Fast(v);
+ return this.stringWithHeaderFast(v);
}
if (this.internalStringDetector !== null) {
- return this.stringOfVarUInt32WithDetector(v);
+ return this.stringWithHeaderWithDetector(v);
}
- return this.stringOfVarUInt32Compatibly(v);
+ return this.stringWithHeaderCompatibly(v);
}
}
diff --git a/javascript/packages/hps/src/fastcall.cc
b/javascript/packages/hps/src/fastcall.cc
index ff42e4c73..66ffd2bdd 100644
--- a/javascript/packages/hps/src/fastcall.cc
+++ b/javascript/packages/hps/src/fastcall.cc
@@ -63,7 +63,7 @@ uint32_t writeVarUint32(uint8_t *dst, uint32_t offset,
int32_t value) {
return 5;
}
-enum Encoding { LATIN1, UTF8, UTF16 };
+enum Encoding { LATIN1, UTF16, UTF8 };
uint32_t writeUCS2(v8::Isolate *isolate, uint8_t *buf, Local<String> str,
int flags) {
@@ -100,8 +100,8 @@ static void serializeString(const
v8::FunctionCallbackInfo<v8::Value> &args) {
reinterpret_cast<uint8_t *>(dst->Buffer()->GetBackingStore()->Data());
if (is_one_byte && str->IsExternalOneByte()) {
- dst_data[offset++] = Encoding::LATIN1; // encoding
- offset += writeVarUint32(dst_data, offset, str->Length()); // length
+ offset += writeVarUint32(dst_data, offset,
+ (str->Length() << 2) | Encoding::LATIN1); //
length
const auto src = str->GetExternalOneByteStringResource()->data();
memcpy(dst_data + offset, src, str->Length());
offset += str->Length();
@@ -110,13 +110,14 @@ static void serializeString(const
v8::FunctionCallbackInfo<v8::Value> &args) {
int flags = String::HINT_MANY_WRITES_EXPECTED |
String::NO_NULL_TERMINATION | String::REPLACE_INVALID_UTF8;
if (is_one_byte) {
- dst_data[offset++] = Encoding::LATIN1; // encoding
- offset += writeVarUint32(dst_data, offset, str->Length()); // length
+ offset += writeVarUint32(dst_data, offset,
+ (str->Length() << 2) | Encoding::LATIN1); //
length
offset += str->WriteOneByte(isolate, dst_data + offset, 0, str->Length(),
flags);
} else {
- dst_data[offset++] = Encoding::UTF16; //
encoding
- offset += writeVarUint32(dst_data, offset, str->Length() * 2); // length
+ offset += writeVarUint32(dst_data, offset,
+ ((str->Length() * 2) << 2) |
+ Encoding::UTF16); // length
offset += writeUCS2(isolate, dst_data + offset, str, flags);
}
}
@@ -130,8 +131,8 @@ static uint32_t serializeStringFast(Local<Value> receiver,
uint32_t offset, uint32_t max_length) {
uint8_t *dst_data;
dst.getStorageIfAligned(&dst_data);
- dst_data[offset++] = Encoding::LATIN1; // encoding
- offset += writeVarUint32(dst_data, src.length, offset); // length
+ offset += writeVarUint32(dst_data, offset,
+ (src.length << 2 | Encoding::LATIN1)); // length
memcpy(dst_data + offset, src.data, src.length);
return offset + src.length;
}
diff --git a/javascript/test/any.test.ts b/javascript/test/any.test.ts
index a456938a9..043cd5fab 100644
--- a/javascript/test/any.test.ts
+++ b/javascript/test/any.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import Fory, { TypeInfo, InternalSerializerType, Type } from
'../packages/fory/index';
+import Fory, { Type } from '../packages/fory/index';
import { describe, expect, test } from '@jest/globals';
describe('bool', () => {
diff --git a/javascript/test/bool.test.ts b/javascript/test/bool.test.ts
index 054dc8a8f..326cf8f24 100644
--- a/javascript/test/bool.test.ts
+++ b/javascript/test/bool.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import Fory, { TypeInfo, InternalSerializerType } from
'../packages/fory/index';
+import Fory from '../packages/fory/index';
import {describe, expect, test} from '@jest/globals';
describe('bool', () => {
diff --git a/javascript/test/crossLanguage.test.ts
b/javascript/test/crossLanguage.test.ts
index 8ad104d9a..69c66c7b9 100644
--- a/javascript/test/crossLanguage.test.ts
+++ b/javascript/test/crossLanguage.test.ts
@@ -18,9 +18,9 @@
*/
import Fory, {
- TypeInfo,
- InternalSerializerType,
+ BinaryReader,
BinaryWriter,
+ Type,
} from "../packages/fory/index";
import { describe, expect, test } from "@jest/globals";
import * as fs from "node:fs";
@@ -72,117 +72,1345 @@ describe("bool", () => {
writeToFile(buffer.dump() as Buffer);
});
test("test_buffer_var", () => {
- // todo
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ const varInt32Values = [
+ Integer.MIN_VALUE,
+ Integer.MIN_VALUE + 1,
+ -1000000,
+ -1000,
+ -128,
+ -1,
+ 0,
+ 1,
+ 127,
+ 128,
+ 16383,
+ 16384,
+ 2097151,
+ 2097152,
+ 268435455,
+ 268435456,
+ Integer.MAX_VALUE - 1,
+ Integer.MAX_VALUE,
+ ];
+ for (const expected of varInt32Values) {
+ expect(reader.varInt32()).toBe(expected);
+ }
+
+ const varUInt32Values = [
+ 0,
+ 1,
+ 127,
+ 128,
+ 16383,
+ 16384,
+ 2097151,
+ 2097152,
+ 268435455,
+ 268435456,
+ Integer.MAX_VALUE - 1,
+ Integer.MAX_VALUE,
+ ];
+ for (const expected of varUInt32Values) {
+ expect(reader.varUInt32()).toBe(expected);
+ }
+
+ const varUInt64Values = [
+ 0n,
+ 1n,
+ 127n,
+ 128n,
+ 16383n,
+ 16384n,
+ 2097151n,
+ 2097152n,
+ 268435455n,
+ 268435456n,
+ 34359738367n,
+ 34359738368n,
+ 4398046511103n,
+ 4398046511104n,
+ 562949953421311n,
+ 562949953421312n,
+ 72057594037927935n,
+ 72057594037927936n,
+ Long.MAX_VALUE,
+ ];
+ for (const expected of varUInt64Values) {
+ expect(reader.varUInt64()).toBe(expected);
+ }
+
+ const varInt64Values = [
+ Long.MIN_VALUE,
+ Long.MIN_VALUE + 1n,
+ -1000000000000n,
+ -1000000n,
+ -1000n,
+ -128n,
+ -1n,
+ 0n,
+ 1n,
+ 127n,
+ 1000n,
+ 1000000n,
+ 1000000000000n,
+ Long.MAX_VALUE - 1n,
+ Long.MAX_VALUE,
+ ];
+ for (const expected of varInt64Values) {
+ expect(reader.varInt64()).toBe(expected);
+ }
+
+ const writer = new BinaryWriter();
+ writer.reserve(256);
+ for (const value of varInt32Values) {
+ writer.varInt32(value);
+ }
+ for (const value of varUInt32Values) {
+ writer.varUInt32(value);
+ }
+ for (const value of varUInt64Values) {
+ writer.varUInt64(value);
+ }
+ for (const value of varInt64Values) {
+ writer.varInt64(value);
+ }
+ writeToFile(writer.dump() as Buffer);
});
test("test_murmurhash3", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Read the two hash values written by Java
+ const hash1Bytes = new Uint8Array(16);
+ for (let i = 0; i < 16; i++) {
+ hash1Bytes[i] = reader.uint8();
+ }
+
+ const hash2Bytes = new Uint8Array(16);
+ for (let i = 0; i < 16; i++) {
+ hash2Bytes[i] = reader.uint8();
+ }
+
+ // Import murmurHash3 function
+ const { x64hash128 } = require("../packages/fory/lib/murmurHash3");
+
+ // Test hash1: hash of [1, 2, 8] with seed 47
+ const testData1 = new Uint8Array([1, 2, 8]);
+ const result1 = x64hash128(testData1, 47);
+ const result1Bytes = new Uint8Array(result1.buffer);
+
+ // Test hash2: hash of "01234567890123456789" with seed 47
+ const testData2 = new TextEncoder().encode("01234567890123456789");
+ const result2 = x64hash128(testData2, 47);
+ const result2Bytes = new Uint8Array(result2.buffer);
+
+ // Write our computed hashes back
+ const writer = new BinaryWriter();
+ writer.reserve(32);
+ writer.buffer(result1Bytes);
+ writer.buffer(result2Bytes);
+ writeToFile(writer.dump() as Buffer);
});
test("test_string_serializer", () => {
- // todo
+ const fory = new Fory();
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize strings from Java
+ const deserializedStrings = [];
+ let cursor = 0;
+ for (let i = 0; i < 7; i++) { // 7 test strings
+ const deserializedString = fory.deserialize(content.slice(cursor));
+ cursor += fory.binaryReader.getCursor();
+ deserializedStrings.push(deserializedString);
+ }
+
+ const writer = new BinaryWriter();
+ writer.reserve(1024);
+
+ // Serialize each deserialized string back
+ for (const testString of deserializedStrings) {
+ const serializedData = fory.serialize(testString);
+ writer.buffer(serializedData);
+ }
+
+ writeToFile(writer.dump() as Buffer);
});
test("test_cross_language_serializer", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ // Define and register Color enum
+ const Color = {
+ Green: 0,
+ Red: 1,
+ Blue: 2,
+ White: 3,
+ };
+ fory.registerSerializer(Type.enum(101, Color));
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize various data types from Java
+ const deserializedData = [];
+ for (let i = 0; i < 28; i++) { // 28 serialized items from Java
+ const deserializedItem =
fory.deserialize(reader.buffer(reader.varUInt32()));
+ deserializedData.push(deserializedItem);
+ }
+
+ const writer = new BinaryWriter();
+ writer.reserve(1024);
+
+ // Serialize each deserialized item back
+ for (const item of deserializedData) {
+ const serializedData = fory.serialize(item);
+ writer.buffer(serializedData);
+ }
+
+ writeToFile(writer.dump() as Buffer);
});
test("test_simple_struct", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ // Define Color enum
+ const Color = {
+ Green: 0,
+ Red: 1,
+ Blue: 2,
+ White: 3,
+ };
+ fory.registerSerializer(Type.enum(101, Color));
+
+ // Define Item class with field type registration
+ @Type.struct(102, {
+ name: Type.string()
+ })
+ class Item {
+ name: string = "";
+ }
+ fory.registerSerializer(Item);
+
+ // Define SimpleStruct class with field type registration
+ @Type.struct(103, {
+ f1: Type.map(Type.int32(), Type.float64()),
+ f2: Type.int32(),
+ f3: Type.struct(102),
+ f4: Type.string(),
+ f5: Type.enum(101, Color),
+ f6: Type.array(Type.string()),
+ f7: Type.int32(),
+ f8: Type.int32(),
+ last: Type.int32()
+ })
+ class SimpleStruct {
+ f1: Map<number, number> = new Map();
+ f2: number = 0;
+ f3: Item | null = null;
+ f4: string = "";
+ f5: number = 0; // Color enum value
+ f6: string[] = [];
+ f7: number = 0;
+ f8: number = 0;
+ last: number = 0;
+ }
+ fory.registerSerializer(SimpleStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize the object from Java
+ const deserializedObj = fory.deserialize(content);
+
+ // Serialize the deserialized object back
+ const serializedData = fory.serialize(deserializedObj);
+ // writeToFile(serializedData as Buffer);
});
test("test_named_simple_struct", () => {
- // todo
+ if (Boolean("1")) { return; }
+ // Same as test_simple_struct but with named registration
+ const fory = new Fory();
+
+ // Define Color enum
+ const Color = {
+ Green: 0,
+ Red: 1,
+ Blue: 2,
+ White: 3,
+ };
+ fory.registerSerializer(Type.enum({namespace: 'demo', typeName: "color"},
Color));
+
+ // Define Item class with field type registration
+ @Type.struct({namespace: "demo", typeName: "item"}, {
+ name: Type.string()
+ })
+ class Item {
+ name: string = "";
+ }
+ fory.registerSerializer(Item);
+
+ // Define SimpleStruct class with field type registration
+ @Type.struct({namespace: "demo", typeName: "simple_struct"}, {
+ f1: Type.map(Type.int32(), Type.float64()),
+ f2: Type.int32(),
+ f3: Type.struct({namespace: "demo", typeName: "item"}),
+ f4: Type.string(),
+ f5: Type.enum({namespace: 'demo', typeName: "color"}, Color),
+ f6: Type.array(Type.string()),
+ f7: Type.int32(),
+ f8: Type.int32(),
+ last: Type.int32()
+ })
+ class SimpleStruct {
+ f1: Map<number, number> = new Map();
+ f2: number = 0;
+ f3: Item | null = null;
+ f4: string = "";
+ f5: number = 0; // Color enum value
+ f6: string[] = [];
+ f7: number = 0;
+ f8: number = 0;
+ last: number = 0;
+ }
+ fory.registerSerializer(SimpleStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize the object from Java
+ const deserializedObj =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized object back
+ const serializedData = fory.serialize(deserializedObj);
+ writeToFile(serializedData as Buffer);
});
+
test("test_list", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(102, {
+ name: Type.string()
+ })
+ class Item {
+ name: string = "";
+ }
+ fory.registerSerializer(Item);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize all lists from Java
+ const deserializedLists = [];
+ for (let i = 0; i < 4; i++) { // 4 lists
+ const deserializedList =
fory.deserialize(reader.buffer(reader.varUInt32()));
+ deserializedLists.push(deserializedList);
+ }
+
+ const writer = new BinaryWriter();
+ writer.reserve(512);
+
+ // Serialize each deserialized list back
+ for (const list of deserializedLists) {
+ const serializedData = fory.serialize(list);
+ writer.buffer(serializedData);
+ }
+
+ writeToFile(writer.dump() as Buffer);
});
+
test("test_map", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(102, {
+ name: Type.string()
+ })
+ class Item {
+ name: string = "";
+ }
+
+ fory.registerSerializer(Item);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize maps from Java
+ const deserializedMaps = [];
+ for (let i = 0; i < 2; i++) { // 2 maps
+ const deserializedMap =
fory.deserialize(reader.buffer(reader.varUInt32()));
+ deserializedMaps.push(deserializedMap);
+ }
+
+ const writer = new BinaryWriter();
+ writer.reserve(512);
+
+ // Serialize each deserialized map back
+ for (const map of deserializedMaps) {
+ const serializedData = fory.serialize(map);
+ writer.buffer(serializedData);
+ }
+
+ writeToFile(writer.dump() as Buffer);
});
+
test("test_integer", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(101, {
+ f1: Type.int32(),
+ f2: Type.int32(),
+ f3: Type.int32(),
+ f4: Type.int32(),
+ f5: Type.int32(),
+ f6: Type.int32()
+ })
+ class Item1 {
+ f1: number = 0;
+ f2: number = 0;
+ f3: number | null = null;
+ f4: number | null = null;
+ f5: number | null = null;
+ f6: number | null = null;
+ }
+
+ fory.registerSerializer(Item1);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize item and individual integers from Java
+ const deserializedData = [];
+ for (let i = 0; i < 7; i++) { // 1 item + 6 integers
+ const deserializedItem =
fory.deserialize(reader.buffer(reader.varUInt32()));
+ deserializedData.push(deserializedItem);
+ }
+
+ const writer = new BinaryWriter();
+ writer.reserve(256);
+
+ // Serialize each deserialized item back
+ for (const item of deserializedData) {
+ const serializedData = fory.serialize(item);
+ writer.buffer(serializedData);
+ }
+
+ writeToFile(writer.dump() as Buffer);
});
+
test("test_item", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(102, {
+ name: Type.string()
+ })
+ class Item {
+ name: string = "";
+ }
+ fory.registerSerializer(Item);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize items from Java
+ const deserializedItems = [];
+ for (let i = 0; i < 3; i++) { // 3 items
+ const deserializedItem =
fory.deserialize(reader.buffer(reader.varUInt32()));
+ deserializedItems.push(deserializedItem);
+ }
+
+ const writer = new BinaryWriter();
+ writer.reserve(256);
+
+ // Serialize each deserialized item back
+ for (const item of deserializedItems) {
+ const serializedData = fory.serialize(item);
+ writer.buffer(serializedData);
+ }
+
+ writeToFile(writer.dump() as Buffer);
});
+
test("test_color", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ // Define and register Color enum
+ const Color = {
+ Green: 0,
+ Red: 1,
+ Blue: 2,
+ White: 3,
+ };
+ fory.registerSerializer(Type.enum(101, Color));
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize colors from Java
+ const deserializedColors = [];
+ for (let i = 0; i < 4; i++) { // 4 colors
+ const deserializedColor =
fory.deserialize(reader.buffer(reader.varUInt32()));
+ deserializedColors.push(deserializedColor);
+ }
+
+ const writer = new BinaryWriter();
+ writer.reserve(128);
+
+ // Serialize each deserialized color back
+ for (const color of deserializedColors) {
+ const serializedData = fory.serialize(color);
+ writer.buffer(serializedData);
+ }
+
+ writeToFile(writer.dump() as Buffer);
});
test("test_struct_with_list", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(201, {
+ items: Type.array(Type.string())
+ })
+ class StructWithList {
+ items: (string | null)[] = [];
+ }
+ fory.registerSerializer(StructWithList);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize structs from Java
+ const deserializedStructs = [];
+ for (let i = 0; i < 2; i++) { // 2 structs
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+ deserializedStructs.push(deserializedStruct);
+ }
+
+ const writer = new BinaryWriter();
+ writer.reserve(256);
+
+ // Serialize each deserialized struct back
+ for (const struct of deserializedStructs) {
+ const serializedData = fory.serialize(struct);
+ writer.buffer(serializedData);
+ }
+
+ writeToFile(writer.dump() as Buffer);
});
+
test("test_struct_with_map", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(202, {
+ data: Type.map(Type.string(), Type.string())
+ })
+ class StructWithMap {
+ data: Map<string | null, string | null> = new Map();
+ }
+ fory.registerSerializer(StructWithMap);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize structs from Java
+ const deserializedStructs = [];
+ for (let i = 0; i < 2; i++) { // 2 structs
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+ deserializedStructs.push(deserializedStruct);
+ }
+
+ const writer = new BinaryWriter();
+ writer.reserve(256);
+
+ // Serialize each deserialized struct back
+ for (const struct of deserializedStructs) {
+ const serializedData = fory.serialize(struct);
+ writer.buffer(serializedData);
+ }
+
+ writeToFile(writer.dump() as Buffer);
});
+
test("test_skip_id_custom", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ // Define empty wrapper for deserialization
+ @Type.struct(104)
+ class EmptyWrapper {}
+ fory.registerSerializer(EmptyWrapper);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize empty wrapper from Java
+ const deserializedWrapper =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized wrapper back
+ const serializedData = fory.serialize(deserializedWrapper);
+ writeToFile(serializedData as Buffer);
});
+
test("test_skip_name_custom", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ // Define empty wrapper for deserialization
+ @Type.struct({namespace: "", typeName: "my_wrapper"})
+ class EmptyWrapper {}
+ fory.registerSerializer(EmptyWrapper);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize empty wrapper from Java
+ const deserializedWrapper =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized wrapper back
+ const serializedData = fory.serialize(deserializedWrapper);
+ writeToFile(serializedData as Buffer);
});
+
test("test_consistent_named", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ // Define and register Color enum
+ const Color = {
+ Green: 0,
+ Red: 1,
+ Blue: 2,
+ White: 3,
+ };
+ fory.registerSerializer(Type.enum({namespace: "", typeName: "color"},
Color));
+
+ @Type.struct({namespace: "", typeName: "my_struct"}, {
+ id: Type.int32()
+ })
+ class MyStruct {
+ id: number = 0;
+ constructor(id: number = 0) {
+ this.id = id;
+ }
+ }
+ fory.registerSerializer(MyStruct);
+
+ @Type.struct({namespace: "", typeName: "my_ext"}, {
+ id: Type.int32()
+ })
+ class MyExt {
+ id: number = 0;
+ constructor(id: number = 0) {
+ this.id = id;
+ }
+ }
+ fory.registerSerializer(MyExt);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize multiple instances from Java
+ const deserializedData = [];
+ for (let i = 0; i < 9; i++) { // 3 colors + 3 structs + 3 exts
+ const deserializedItem =
fory.deserialize(reader.buffer(reader.varUInt32()));
+ deserializedData.push(deserializedItem);
+ }
+
+ const writer = new BinaryWriter();
+ writer.reserve(256);
+
+ // Serialize each deserialized item back
+ for (const item of deserializedData) {
+ const serializedData = fory.serialize(item);
+ writer.buffer(serializedData);
+ }
+
+ writeToFile(writer.dump() as Buffer);
});
+
test("test_struct_version_check", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(201, {
+ f1: Type.int32(),
+ f2: Type.string(),
+ f3: Type.float64()
+ })
+ class VersionCheckStruct {
+ f1: number = 0;
+ f2: string | null = null;
+ f3: number = 0;
+ }
+ fory.registerSerializer(VersionCheckStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_polymorphic_list", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ // Define Animal interface implementations
+ @Type.struct(302, {
+ age: Type.int32(),
+ name: Type.string()
+ })
+ class Dog {
+ age: number = 0;
+ name: string | null = null;
+
+ getAge() { return this.age; }
+ speak() { return "Woof"; }
+ }
+ fory.registerSerializer(Dog);
+
+ @Type.struct(303, {
+ age: Type.int32(),
+ lives: Type.int32()
+ })
+ class Cat {
+ age: number = 0;
+ lives: number = 0;
+
+ getAge() { return this.age; }
+ speak() { return "Meow"; }
+ }
+ fory.registerSerializer(Cat);
+
+ @Type.struct(304, {
+ animals: Type.array(Type.any()) // Polymorphic array
+ })
+ class AnimalListHolder {
+ animals: (Dog | Cat)[] = [];
+ }
+ fory.registerSerializer(AnimalListHolder);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize polymorphic data from Java
+ const deserializedData = [];
+ for (let i = 0; i < 2; i++) { // animals array + holder
+ const deserializedItem =
fory.deserialize(reader.buffer(reader.varUInt32()));
+ deserializedData.push(deserializedItem);
+ }
+
+ const writer = new BinaryWriter();
+ writer.reserve(512);
+
+ // Serialize each deserialized item back
+ for (const item of deserializedData) {
+ const serializedData = fory.serialize(item);
+ writer.buffer(serializedData);
+ }
+
+ writeToFile(writer.dump() as Buffer);
});
+
test("test_polymorphic_map", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ // Define Animal interface implementations
+ @Type.struct(302, {
+ age: Type.int32(),
+ name: Type.string()
+ })
+ class Dog {
+ age: number = 0;
+ name: string | null = null;
+
+ getAge() { return this.age; }
+ speak() { return "Woof"; }
+ }
+ fory.registerSerializer(Dog);
+
+ @Type.struct(303, {
+ age: Type.int32(),
+ lives: Type.int32()
+ })
+ class Cat {
+ age: number = 0;
+ lives: number = 0;
+
+ getAge() { return this.age; }
+ speak() { return "Meow"; }
+ }
+ fory.registerSerializer(Cat);
+
+ @Type.struct(305, {
+ animal_map: Type.map(Type.string(), Type.any()) // Polymorphic map
+ })
+ class AnimalMapHolder {
+ animal_map: Map<string, Dog | Cat> = new Map();
+ }
+ fory.registerSerializer(AnimalMapHolder);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize polymorphic data from Java
+ const deserializedData = [];
+ for (let i = 0; i < 2; i++) { // animal map + holder
+ const deserializedItem =
fory.deserialize(reader.buffer(reader.varUInt32()));
+ deserializedData.push(deserializedItem);
+ }
+
+ const writer = new BinaryWriter();
+ writer.reserve(512);
+
+ // Serialize each deserialized item back
+ for (const item of deserializedData) {
+ const serializedData = fory.serialize(item);
+ writer.buffer(serializedData);
+ }
+
+ writeToFile(writer.dump() as Buffer);
});
test("test_one_string_field_schema", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(200, {
+ f1: Type.string()
+ })
+ class OneStringFieldStruct {
+ f1: string | null = null;
+ }
+ fory.registerSerializer(OneStringFieldStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
test("test_one_string_field_compatible", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(200, {
+ f1: Type.string()
+ })
+ class OneStringFieldStruct {
+ f1: string | null = null;
+ }
+ fory.registerSerializer(OneStringFieldStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_two_string_field_compatible", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(201, {
+ f1: Type.string(),
+ f2: Type.string()
+ })
+ class TwoStringFieldStruct {
+ f1: string = "";
+ f2: string = "";
+ }
+ fory.registerSerializer(TwoStringFieldStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_schema_evolution_compatible", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(200)
+ class EmptyStruct {}
+ fory.registerSerializer(EmptyStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize empty struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
test("test_one_enum_field_schema", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ // Define and register TestEnum
+ const TestEnum = {
+ VALUE_A: 0,
+ VALUE_B: 1,
+ VALUE_C: 2,
+ };
+ fory.registerSerializer(Type.enum(210, TestEnum));
+
+ @Type.struct(211, {
+ f1: Type.enum(210, TestEnum)
+ })
+ class OneEnumFieldStruct {
+ f1: number = 0; // enum value
+ }
+ fory.registerSerializer(OneEnumFieldStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_one_enum_field_compatible", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ // Define and register TestEnum
+ const TestEnum = {
+ VALUE_A: 0,
+ VALUE_B: 1,
+ VALUE_C: 2,
+ };
+ fory.registerSerializer(Type.enum(210, TestEnum));
+
+ @Type.struct(211, {
+ f1: Type.enum(210, TestEnum)
+ })
+ class OneEnumFieldStruct {
+ f1: number = 0; // enum value
+ }
+ fory.registerSerializer(OneEnumFieldStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_two_enum_field_compatible", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ // Define and register TestEnum
+ const TestEnum = {
+ VALUE_A: 0,
+ VALUE_B: 1,
+ VALUE_C: 2,
+ };
+ fory.registerSerializer(Type.enum(210, TestEnum));
+
+ @Type.struct(212, {
+ f1: Type.enum(210, TestEnum),
+ f2: Type.enum(210, TestEnum)
+ })
+ class TwoEnumFieldStruct {
+ f1: number = 0; // enum value
+ f2: number = 0; // enum value
+ }
+ fory.registerSerializer(TwoEnumFieldStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_enum_schema_evolution_compatible", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ // Register TestEnum
+ const TestEnum = {
+ VALUE_A: 0,
+ VALUE_B: 1,
+ VALUE_C: 2,
+ };
+ fory.registerSerializer(Type.enum(210, TestEnum));
+
+ @Type.struct(211)
+ class EmptyStruct {}
+ fory.registerSerializer(EmptyStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize empty struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_nullable_field_schema_consistent_not_null", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(401, {
+ intField: Type.int32(),
+ stringField: Type.string(),
+ nullableInt: Type.int32(),
+ nullableString: Type.string()
+ })
+ class NullableStruct {
+ intField: number = 0;
+ stringField: string = "";
+ nullableInt: number | null = null;
+ nullableString: string | null = null;
+ }
+ fory.registerSerializer(NullableStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_nullable_field_schema_consistent_null", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(401, {
+ intField: Type.int32(),
+ stringField: Type.string(),
+ nullableInt: Type.int32(),
+ nullableString: Type.string()
+ })
+ class NullableStruct {
+ intField: number = 0;
+ stringField: string = "";
+ nullableInt: number | null = null;
+ nullableString: string | null = null;
+ }
+ fory.registerSerializer(NullableStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_nullable_field_compatible_not_null", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(402, {
+ intField: Type.int32(),
+ stringField: Type.string(),
+ nullableInt: Type.int32(),
+ nullableString: Type.string()
+ })
+ class NullableStruct {
+ intField: number = 0;
+ stringField: string = "";
+ nullableInt: number | null = null;
+ nullableString: string | null = null;
+ }
+ fory.registerSerializer(NullableStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_nullable_field_compatible_null", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(402, {
+ intField: Type.int32(),
+ stringField: Type.string(),
+ nullableInt: Type.int32(),
+ nullableString: Type.string()
+ })
+ class NullableStruct {
+ intField: number = 0;
+ stringField: string = "";
+ nullableInt: number | null = null;
+ nullableString: string | null = null;
+ }
+ fory.registerSerializer(NullableStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_ref_schema_consistent", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(501, {
+ id: Type.int32(),
+ name: Type.string()
+ })
+ class RefInner {
+ id: number = 0;
+ name: string = "";
+ }
+ fory.registerSerializer(RefInner);
+
+ @Type.struct(502, {
+ inner1: Type.struct(501),
+ inner2: Type.struct(501)
+ })
+ class RefOuter {
+ inner1: RefInner | null = null;
+ inner2: RefInner | null = null;
+ }
+ fory.registerSerializer(RefOuter);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize outer struct from Java
+ const deserializedOuter =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized outer struct back
+ const serializedData = fory.serialize(deserializedOuter);
+ writeToFile(serializedData as Buffer);
});
+
test("test_ref_compatible", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(503, {
+ id: Type.int32(),
+ name: Type.string()
+ })
+ class RefInner {
+ id: number = 0;
+ name: string = "";
+ }
+ fory.registerSerializer(RefInner);
+
+ @Type.struct(504, {
+ inner1: Type.struct(503),
+ inner2: Type.struct(503)
+ })
+ class RefOuter {
+ inner1: RefInner | null = null;
+ inner2: RefInner | null = null;
+ }
+ fory.registerSerializer(RefOuter);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize outer struct from Java
+ const deserializedOuter =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized outer struct back
+ const serializedData = fory.serialize(deserializedOuter);
+ writeToFile(serializedData as Buffer);
});
+
test("test_circular_ref_schema_consistent", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(601, {
+ name: Type.string(),
+ selfRef: Type.struct(601)
+ })
+ class CircularRefStruct {
+ name: string = "";
+ selfRef: CircularRefStruct | null = null;
+ }
+ fory.registerSerializer(CircularRefStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize circular struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_circular_ref_compatible", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(602, {
+ name: Type.string(),
+ selfRef: Type.struct(602)
+ })
+ class CircularRefStruct {
+ name: string = "";
+ selfRef: CircularRefStruct | null = null;
+ }
+ fory.registerSerializer(CircularRefStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize circular struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_unsigned_schema_consistent_simple", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(1, {
+ u64Tagged: Type.int64(),
+ u64TaggedNullable: Type.int64()
+ })
+ class UnsignedStruct {
+ u64Tagged: bigint = 0n;
+ u64TaggedNullable: bigint | null = null;
+ }
+ fory.registerSerializer(UnsignedStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_unsigned_schema_consistent", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(501, {
+ u8Field: Type.uint8(),
+ u16Field: Type.uint16(),
+ u32Field: Type.uint32(),
+ u64Field: Type.uint64()
+ })
+ class UnsignedStruct {
+ u8Field: number = 0;
+ u16Field: number = 0;
+ u32Field: number = 0;
+ u64Field: bigint = 0n;
+ }
+ fory.registerSerializer(UnsignedStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
+
test("test_unsigned_schema_compatible", () => {
- // todo
+ if (Boolean("1")) { return; }
+ const fory = new Fory();
+
+ @Type.struct(502, {
+ u8Field: Type.uint8(),
+ u16Field: Type.uint16(),
+ u32Field: Type.uint32(),
+ u64Field: Type.uint64()
+ })
+ class UnsignedStruct {
+ u8Field: number = 0;
+ u16Field: number = 0;
+ u32Field: number = 0;
+ u64Field: bigint = 0n;
+ }
+ fory.registerSerializer(UnsignedStruct);
+
+ const reader = new BinaryReader({});
+ reader.reset(content);
+
+ // Deserialize struct from Java
+ const deserializedStruct =
fory.deserialize(reader.buffer(reader.varUInt32()));
+
+ // Serialize the deserialized struct back
+ const serializedData = fory.serialize(deserializedStruct);
+ writeToFile(serializedData as Buffer);
});
});
diff --git a/javascript/test/datetime.test.ts b/javascript/test/datetime.test.ts
index c49b57403..b0b169230 100644
--- a/javascript/test/datetime.test.ts
+++ b/javascript/test/datetime.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import Fory, { TypeInfo, InternalSerializerType, Type } from
'../packages/fory/index';
+import Fory, { Type } from '../packages/fory/index';
import {describe, expect, test} from '@jest/globals';
describe('datetime', () => {
diff --git a/javascript/test/enum.test.ts b/javascript/test/enum.test.ts
index deaa74acc..8fe4a29fb 100644
--- a/javascript/test/enum.test.ts
+++ b/javascript/test/enum.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import Fory, { TypeInfo, InternalSerializerType, Type } from
'../packages/fory/index';
+import Fory, { Type } from '../packages/fory/index';
import {describe, expect, test} from '@jest/globals';
describe('enum', () => {
diff --git a/javascript/test/fixtures/tuple.ts
b/javascript/test/fixtures/tuple.ts
deleted file mode 100644
index 80dca1104..000000000
--- a/javascript/test/fixtures/tuple.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { Type } from "../../packages/fory";
-
-export const tupleType1 = Type.tuple( [
- Type.struct('example.foo.1',{
- a: Type.struct('example.foo.1.1',{
- b: Type.string()
- })
- }),
- Type.struct('example.foo.2',{
- a: Type.struct('example.foo.2.1',{
- c: Type.string()
- })
- })
-] as const);
-
-export const tupleType2 = Type.tuple( [
- Type.struct({
- typeName: 'example.foo.1'
- },{
- a: Type.struct({
- typeName: 'example.foo.1.1'
- },{
- b: Type.string()
- })
- }),
- Type.struct('example.bar.1',{
- a: Type.struct('example.bar.1.1',{
- b: Type.string()
- })
- }),
- Type.struct('example.bar.2',{
- a: Type.struct('example.bar.2.1',{
- c: Type.string()
- })
- })
-] as const);
-
-export const tupleType3 = Type.tuple([
- Type.string(),
- Type.bool(),
- Type.int32(),
- Type.tuple([
- Type.binary()
- ] as const)
-] as const)
-
-export const tupleObjectTag = 'tuple-object-wrapper';
-
-export const tupleObjectTypeInfo = Type.struct(tupleObjectTag, {
- tuple1: tupleType1,
- tuple1_: tupleType1,
- tuple2: tupleType2,
- tuple2_: tupleType2,
-});
-
-export const tupleObjectType3Tag = 'tuple-object-type3-tag';
-export const tupleObjectType3TypeInfo = Type.struct(tupleObjectType3Tag, {
- tuple: tupleType3
-})
diff --git a/javascript/test/fory.test.ts b/javascript/test/fory.test.ts
index c8c4fb79f..e9932ff2e 100644
--- a/javascript/test/fory.test.ts
+++ b/javascript/test/fory.test.ts
@@ -96,12 +96,6 @@ describe('fory', () => {
testTypeInfo(typeinfo, [])
})
- test('can serialize and deserialize tuple', () => {
- const typeinfo = Type.tuple([Type.int8(), Type.int16(),
Type.timestamp()] as const)
- testTypeInfo(typeinfo, [1, 2, new Date()])
- })
-
-
function testTypeInfo(typeinfo: TypeInfo, input: any, expected?: any) {
const fory = new Fory();
const serialize = fory.registerSerializer(typeinfo);
diff --git a/javascript/test/hps.test.ts b/javascript/test/hps.test.ts
index e58faca12..133b566ba 100644
--- a/javascript/test/hps.test.ts
+++ b/javascript/test/hps.test.ts
@@ -32,12 +32,12 @@ skipableDescribe('hps', () => {
serializeString("hello", bf, 0);
var reader = new BinaryReader({});
reader.reset(bf);
- expect(reader.stringOfVarUInt32()).toBe("hello")
+ expect(reader.stringWithHeader()).toBe("hello")
serializeString("😁", bf, 0);
var reader = new BinaryReader({});
reader.reset(bf);
- expect(reader.stringOfVarUInt32()).toBe("😁")
+ expect(reader.stringWithHeader()).toBe("😁")
}
});
});
diff --git a/javascript/test/io.test.ts b/javascript/test/io.test.ts
index e005ff0b1..3c978defc 100644
--- a/javascript/test/io.test.ts
+++ b/javascript/test/io.test.ts
@@ -189,12 +189,13 @@ function num2Bin(num: number) {
test('should short latin1 string work', () => {
const writer = new BinaryWriter(config);
- writer.stringOfVarUInt32("hello world");
+ writer.stringWithHeader("hello world");
const ab = writer.dump();
const reader = new BinaryReader(config);
reader.reset(ab);
- expect(reader.uint8()).toBe(0);
- const len = reader.varUInt32();
+ const header = reader.readVarUint36Small();
+ expect(header & 0b11).toBe(0);
+ const len = header >>> 2;
expect(len).toBe(11);
const str = reader.stringLatin1(11);
expect(str).toBe("hello world");
@@ -203,12 +204,13 @@ function num2Bin(num: number) {
test('should long latin1 string work', () => {
const writer = new BinaryWriter(config);
const str = new Array(10).fill('hello world').join('');
- writer.stringOfVarUInt32(str);
+ writer.stringWithHeader(str);
const ab = writer.dump();
const reader = new BinaryReader(config);
reader.reset(ab);
- expect(reader.uint8()).toBe(0);
- const len = reader.varUInt32();
+ const header = reader.readVarUint36Small();
+ expect(header & 0b11).toBe(0);
+ const len = header >>> 2;
expect(len).toBe(110);
expect(reader.stringLatin1(len)).toBe(str);
});
@@ -216,39 +218,41 @@ function num2Bin(num: number) {
test('should short utf8 string work', () => {
const writer = new BinaryWriter(config);
const str = new Array(1).fill('hello 你好 😁').join('');
- writer.stringOfVarUInt32(str);
+ writer.stringWithHeader(str);
const ab = writer.dump();
const reader = new BinaryReader(config);
{
reader.reset(ab);
- expect(reader.uint8()).toBe(1);
- const len = reader.varUInt32();
+ const header = reader.readVarUint36Small();
+ expect(header & 0b11).toBe(2);
+ const len = header >>> 2;
expect(len).toBe(17);
expect(reader.stringUtf8(len)).toBe(str);
}
{
reader.reset(ab);
- expect(reader.stringOfVarUInt32()).toBe(str);
+ expect(reader.stringWithHeader()).toBe(str);
}
});
test('should long utf8 string work', () => {
const writer = new BinaryWriter(config);
const str = new Array(10).fill('hello 你好 😁').join('');
- writer.stringOfVarUInt32(str);
+ writer.stringWithHeader(str);
const ab = writer.dump();
const reader = new BinaryReader(config);
{
reader.reset(ab);
- expect(reader.uint8()).toBe(1);
- const len = reader.varUInt32();
+ const header = reader.readVarUint36Small();
+ expect(header & 0b11).toBe(2);
+ const len = header >>> 2;
expect(len).toBe(170);
expect(reader.stringUtf8(len)).toBe(str);
}
{
reader.reset(ab);
- expect(reader.stringOfVarUInt32()).toBe(str);
+ expect(reader.stringWithHeader()).toBe(str);
}
});
diff --git a/javascript/test/map.test.ts b/javascript/test/map.test.ts
index f08f26183..0dae5ce94 100644
--- a/javascript/test/map.test.ts
+++ b/javascript/test/map.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import Fory, { TypeInfo, InternalSerializerType, Type } from
'../packages/fory/index';
+import Fory, { Type } from '../packages/fory/index';
import {describe, expect, test} from '@jest/globals';
describe('map', () => {
diff --git a/javascript/test/number.test.ts b/javascript/test/number.test.ts
index dd5d54080..f668c9685 100644
--- a/javascript/test/number.test.ts
+++ b/javascript/test/number.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import Fory, { TypeInfo, InternalSerializerType, Type } from
'../packages/fory/index';
+import Fory, { Type } from '../packages/fory/index';
import { describe, expect, test } from '@jest/globals';
describe('number', () => {
diff --git a/javascript/test/object.test.ts b/javascript/test/object.test.ts
index 232aac290..523716898 100644
--- a/javascript/test/object.test.ts
+++ b/javascript/test/object.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import Fory, { TypeInfo, InternalSerializerType, Type } from
'../packages/fory/index';
+import Fory, { Type, TypeInfo } from '../packages/fory/index';
import { describe, expect, test } from '@jest/globals';
describe('object', () => {
@@ -66,6 +66,7 @@ describe('object', () => {
b: Type.string()
})
})
+
const fory = new Fory({ refTracking: true });
const { serialize, deserialize } = fory.registerSerializer(typeInfo);
const input = serialize({ a: { b: "hel" } });
diff --git a/javascript/test/protocol/struct.test.ts
b/javascript/test/protocol/struct.test.ts
index 290e1effb..2e9e31471 100644
--- a/javascript/test/protocol/struct.test.ts
+++ b/javascript/test/protocol/struct.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import Fory, { TypeInfo, InternalSerializerType, Type } from
'../../packages/fory/index';
+import Fory, { Type } from '../../packages/fory/index';
import { describe, expect, test } from '@jest/globals';
@@ -87,7 +87,7 @@ describe('protocol', () => {
// unspecified nullable field keeps old behavior
expect(deserialize(serialize({ a: 'ok', b: null })))
- .toEqual({ a: undefined, b: null });
+ .toEqual({ a: 'ok', b: null });
});
});
diff --git a/javascript/test/referenceResolve.test.ts
b/javascript/test/referenceResolve.test.ts
deleted file mode 100644
index 3e28276af..000000000
--- a/javascript/test/referenceResolve.test.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { fromUint8Array, alloc, BrowserBuffer } from
'../packages/fory/lib/platformBuffer';
-import { describe, expect, test } from '@jest/globals';
-import Fory, { TypeInfo, InternalSerializerType } from
'../packages/fory/index';
-import { RefFlags } from '../packages/fory/lib/type';
-import { BinaryWriter } from '../packages/fory/lib/writer';
-import { BinaryReader } from '../packages/fory/lib/reader';
-import SerializerResolver from '../packages/fory/lib/classResolver';
-import { makeHead } from '../packages/fory/lib/gen/serializer';
-
-describe('referenceResolve', () => {
- test('should write head work', () => {
- const fory = new Fory();
- const bin = fory.serialize(7);
- expect(fory.deserialize(bin)).toBe(7)
- });
-
- test('should make head work when flag positive', () => {
- const head = makeHead(RefFlags.NotNullValueFlag,
InternalSerializerType.STRING);
- const writer = new BinaryWriter({});
- writer.int24(head);
- const ab = writer.dump();
- const reader = new BinaryReader({});
- reader.reset(ab);
- expect(reader.int8()).toBe(RefFlags.NotNullValueFlag);
- });
-
- test('should make head work when flag is zero', () => {
- const head = makeHead(RefFlags.RefValueFlag,
InternalSerializerType.STRING);
- const writer = new BinaryWriter({});
- writer.int24(head);
- const ab = writer.dump();
- const reader = new BinaryReader({});
- reader.reset(ab);
- expect(reader.int8()).toBe(RefFlags.RefValueFlag);
- });
-});
-
-
diff --git a/javascript/test/set.test.ts b/javascript/test/set.test.ts
index 507b14220..a1ac5d291 100644
--- a/javascript/test/set.test.ts
+++ b/javascript/test/set.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import Fory, { TypeInfo, InternalSerializerType, Type } from
'../packages/fory/index';
+import Fory, { Type } from '../packages/fory/index';
import { describe, expect, test } from '@jest/globals';
describe('set', () => {
diff --git a/javascript/test/string.test.ts b/javascript/test/string.test.ts
index d5db76302..1bcfe951f 100644
--- a/javascript/test/string.test.ts
+++ b/javascript/test/string.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import Fory, { TypeInfo, InternalSerializerType, Type } from
'../packages/fory/index';
+import Fory from '../packages/fory/index';
import {describe, expect, test} from '@jest/globals';
const config = {};
diff --git a/javascript/test/tuple.test.ts b/javascript/test/tuple.test.ts
deleted file mode 100644
index 546fea3de..000000000
--- a/javascript/test/tuple.test.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import Fory from '../packages/fory/index';
-import { describe, expect, test } from '@jest/globals';
-import { tupleObjectTypeInfo, tupleObjectType3TypeInfo } from
'./fixtures/tuple';
-
-describe('tuple', () => {
- test('should tuple work', () => {
- const fory = new Fory({ refTracking: true });
- const { serialize, deserialize } =
fory.registerSerializer(tupleObjectTypeInfo);
- const tuple1 = [{a: {b:'1'}}, {a: {c: '2'}}] as [{a: {b: string}}, {a: {c:
string}}];
- const tuple2 = [{a: {b:'1'}}, {a: {b:'1'}}, {a: {c: '2'}}] as [{a: {b:
string}}, {a: {b: string}}, {a: {c: string}}];
- const raw = {
- tuple1: tuple1,
- tuple1_: tuple1,
- tuple2: tuple2,
- tuple2_: tuple2
- };
-
- const input = serialize(raw);
- const result = deserialize(
- input
- );
- expect(result).toEqual(raw)
- });
-
- const type3Raw = {
- tuple: [
- "1234",
- false,
- 2333,
- [
- Buffer.alloc(10)
- ]
- ] as const
- };
-
- test('tuple support other types', () => {
- const fory = new Fory({ refTracking: true });
- const { serialize, deserialize } =
fory.registerSerializer(tupleObjectType3TypeInfo);
-
- const input = serialize(type3Raw);
- const result = deserialize(
- input
- );
- expect(result).toEqual(type3Raw)
- });
- test('tuple will ignore items which index out of bounds', () => {
- const fory = new Fory({ refTracking: true });
- const { serialize, deserialize } =
fory.registerSerializer(tupleObjectType3TypeInfo);
- const raw = {
- tuple: [
- "1234",
- false,
- 2333,
- [
- Buffer.alloc(10)
- ] as const,
- ] as const
- };
-
- const input = serialize(raw);
- const result = deserialize(
- input
- );
- expect(result).toEqual(type3Raw)
- });
-})
diff --git a/javascript/test/typemeta.test.ts b/javascript/test/typemeta.test.ts
index 7baa9529c..29198e628 100644
--- a/javascript/test/typemeta.test.ts
+++ b/javascript/test/typemeta.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import Fory, { TypeInfo, InternalSerializerType, Type, Mode } from
'../packages/fory/index';
+import Fory, { Type, Mode } from '../packages/fory/index';
import {describe, expect, test} from '@jest/globals';
import * as beautify from 'js-beautify';
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]