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/incubator-fury.git


The following commit(s) were added to refs/heads/main by this push:
     new 53ee111c feat(javascript): Implement Xlang map (#1549)
53ee111c is described below

commit 53ee111c312debb362a61fc5045db709d876e9ce
Author: weipeng <[email protected]>
AuthorDate: Mon Apr 22 23:44:59 2024 +0800

    feat(javascript): Implement Xlang map (#1549)
    
    ## What does this PR do?
    1. Implement the map protocol.
    2. Cache the primitive type serializer, guess serializer by data type
    every time is unnecessary.
    
    In this PR , the code generator is simple call the AnySerializer which
    is much more slower then jit code, I will implement the code generator
    next PR.
    
    ## Does this PR introduce any user-facing change?
    No user-facing change.
    
    ## Benchmark
    Before:
    | (index)    | Values |
    |-------------|--------|
    | serialize  | 365    |
    | deserialize | 193    |
    
    After:
    
    | (index)    | Values |
    |-------------|--------|
    | serialize  | 519    |
    | deserialize | 238    |
    
    ---------
    
    Co-authored-by: wangweipeng <weipeng>
---
 javascript/benchmark/map.js                    |  60 ++++++
 javascript/packages/fury/lib/classResolver.ts  |  50 +++--
 javascript/packages/fury/lib/gen/collection.ts |  13 +-
 javascript/packages/fury/lib/gen/map.ts        | 276 ++++++++++++++++++++-----
 javascript/packages/fury/lib/meta.ts           |  17 ++
 javascript/packages/fury/lib/writer/index.ts   |   8 +
 6 files changed, 345 insertions(+), 79 deletions(-)

diff --git a/javascript/benchmark/map.js b/javascript/benchmark/map.js
new file mode 100644
index 00000000..8e4df29f
--- /dev/null
+++ b/javascript/benchmark/map.js
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+const Fury = require("@furyjs/fury");
+const hps = require('@furyjs/hps');
+const fury = new Fury.default({ hps, refTracking: false, useSliceString: true 
});
+const Benchmark = require("benchmark");
+const Type = Fury.Type;
+
+
+
+const { serialize, deserialize, serializeVolatile } = 
fury.registerSerializer(Type.map(Type.any(), Type.any()));
+const sample = new Map([["foo", "ba1"],["foo1", "ba1"],["foo2", 
"ba1"],["foo3", "ba1"],["foo4", "ba1"],["foo5", "ba1"]]);
+const furyAb = serialize(sample);
+
+
+async function start() {
+
+  let result = {
+    serialize: 0,
+    deserialize: 0
+  }
+
+  {
+    var suite = new Benchmark.Suite();
+    suite
+      .add("serialize", function () {
+        serializeVolatile(sample).dispose()
+      })
+      .add("deserialize", function () {
+        deserialize(furyAb)
+      })
+      .on("complete", function (e) {
+        e.currentTarget.forEach(({ name, hz }) => {
+          result[name] = Math.ceil(hz / 10000);
+        });
+      })
+      .run({ async: false });
+  }
+
+  console.table(result);
+
+}
+start();
diff --git a/javascript/packages/fury/lib/classResolver.ts 
b/javascript/packages/fury/lib/classResolver.ts
index c2d0f4c4..27dbbc64 100644
--- a/javascript/packages/fury/lib/classResolver.ts
+++ b/javascript/packages/fury/lib/classResolver.ts
@@ -72,6 +72,7 @@ const uninitSerialize = {
     fixedSize: 0,
     type: InternalSerializerType.ANY,
     needToWriteRef: false,
+    typeId: null,
   },
 };
 
@@ -114,8 +115,26 @@ export default class SerializerResolver {
     this.registerSerializer(fury, Type.float16Array());
     this.registerSerializer(fury, Type.float32Array());
     this.registerSerializer(fury, Type.float64Array());
+
+    this.numberSerializer = 
this.getSerializerById(SerializerResolver.getTypeIdByInternalSerializerType(InternalSerializerType.FLOAT64));
+    this.int64Serializer = 
this.getSerializerById(SerializerResolver.getTypeIdByInternalSerializerType(InternalSerializerType.INT64));
+    this.boolSerializer = 
this.getSerializerById(SerializerResolver.getTypeIdByInternalSerializerType(InternalSerializerType.BOOL));
+    this.dateSerializer = 
this.getSerializerById(SerializerResolver.getTypeIdByInternalSerializerType(InternalSerializerType.TIMESTAMP));
+    this.stringSerializer = 
this.getSerializerById(SerializerResolver.getTypeIdByInternalSerializerType(InternalSerializerType.STRING));
+    this.setSerializer = 
this.getSerializerById(SerializerResolver.getTypeIdByInternalSerializerType(InternalSerializerType.SET));
+    this.arraySerializer = 
this.getSerializerById(SerializerResolver.getTypeIdByInternalSerializerType(InternalSerializerType.ARRAY));
+    this.mapSerializer = 
this.getSerializerById(SerializerResolver.getTypeIdByInternalSerializerType(InternalSerializerType.MAP));
   }
 
+  private numberSerializer: null | Serializer = null;
+  private int64Serializer: null | Serializer = null;
+  private boolSerializer: null | Serializer = null;
+  private dateSerializer: null | Serializer = null;
+  private stringSerializer: null | Serializer = null;
+  private setSerializer: null | Serializer = null;
+  private arraySerializer: null | Serializer = null;
+  private mapSerializer: null | Serializer = null;
+
   init(fury: Fury) {
     this.initInternalSerializer(fury);
   }
@@ -213,42 +232,37 @@ export default class SerializerResolver {
   }
 
   getSerializerByData(v: any) {
-    if (v === null || v === undefined) {
-      return null;
+    if (typeof v === "number") {
+      return this.numberSerializer;
     }
 
-    if (typeof v === "number") {
-      return this.getSerializerByType(InternalSerializerType.FLOAT64);
+    if (typeof v === "string") {
+      return this.stringSerializer;
     }
 
-    if (typeof v === "bigint") {
-      return this.getSerializerByType(InternalSerializerType.INT64);
+    if (Array.isArray(v)) {
+      return this.arraySerializer;
     }
 
     if (typeof v === "boolean") {
-      return this.getSerializerByType(InternalSerializerType.BOOL);
+      return this.boolSerializer;
     }
 
-    if (v instanceof Date) {
-      return this.getSerializerByType(InternalSerializerType.TIMESTAMP);
+    if (typeof v === "bigint") {
+      return this.int64Serializer;
     }
 
-    if (typeof v === "string") {
-      return this.getSerializerByType(InternalSerializerType.STRING);
+    if (v instanceof Date) {
+      return this.dateSerializer;
     }
 
     if (v instanceof Map) {
-      return this.getSerializerByType(InternalSerializerType.MAP);
+      return this.mapSerializer;
     }
 
     if (v instanceof Set) {
-      return this.getSerializerByType(InternalSerializerType.SET);
+      return this.setSerializer;
     }
-
-    if (Array.isArray(v)) {
-      return this.getSerializerByType(InternalSerializerType.ARRAY);
-    }
-
     throw new Error(`Failed to detect the Fury type from JavaScript type: 
${typeof v}`);
   }
 
diff --git a/javascript/packages/fury/lib/gen/collection.ts 
b/javascript/packages/fury/lib/gen/collection.ts
index 0b53edb0..5620e499 100644
--- a/javascript/packages/fury/lib/gen/collection.ts
+++ b/javascript/packages/fury/lib/gen/collection.ts
@@ -56,10 +56,9 @@ class CollectionAnySerializer {
       }
       if (isSame) {
         const current = this.fury.classResolver.getSerializerByData(item);
-        if (serializer !== null && current !== null && current !== serializer) 
{
+        if (serializer !== null && current !== serializer) {
           isSame = false;
-        }
-        if (current !== null) {
+        } else {
           serializer = current;
         }
       }
@@ -71,16 +70,12 @@ class CollectionAnySerializer {
     if (includeNone) {
       flag |= CollectionFlags.HAS_NULL;
     }
-    if (serializer !== null && serializer.meta.needToWriteRef) {
+    if (serializer!.meta.needToWriteRef) {
       flag |= CollectionFlags.TRACKING_REF;
     }
     this.fury.binaryWriter.uint8(flag);
     if (isSame) {
-      if (serializer) {
-        this.fury.binaryWriter.int16(serializer.meta.type);
-      } else {
-        this.fury.binaryWriter.skip(2);
-      }
+      this.fury.binaryWriter.int16(serializer!.meta.type);
     }
     return {
       serializer,
diff --git a/javascript/packages/fury/lib/gen/map.ts 
b/javascript/packages/fury/lib/gen/map.ts
index 7976491d..dc6eda05 100644
--- a/javascript/packages/fury/lib/gen/map.ts
+++ b/javascript/packages/fury/lib/gen/map.ts
@@ -21,77 +21,249 @@ import { MapTypeDescription, TypeDescription } from 
"../description";
 import { CodecBuilder } from "./builder";
 import { BaseSerializerGenerator, RefState } from "./serializer";
 import { CodegenRegistry } from "./router";
-import { InternalSerializerType } from "../type";
+import { InternalSerializerType, RefFlags, Serializer } from "../type";
 import { Scope } from "./scope";
+import Fury from "../fury";
 
-class MapSerializerGenerator extends BaseSerializerGenerator {
-  description: MapTypeDescription;
+const MapFlags = {
+  /** Whether track elements ref. */
+  TRACKING_REF: 0b1,
 
-  constructor(description: TypeDescription, builder: CodecBuilder, scope: 
Scope) {
-    super(description, builder, scope);
-    this.description = <MapTypeDescription>description;
+  /** Whether collection has null. */
+  HAS_NULL: 0b10,
+
+  /** Whether collection elements type is not declare type. */
+  NOT_DECL_ELEMENT_TYPE: 0b100,
+
+  /** Whether collection elements type different. */
+  NOT_SAME_TYPE: 0b1000,
+};
+
+class TypeInfo {
+  private static IS_NULL = 0b10;
+  private static TRACKING_REF = 0b01;
+  static elementInfo(typeId: number, isNull: 0 | 1, trackRef: 0 | 1) {
+    return typeId << 16 | isNull << 1 | trackRef;
   }
 
-  private innerMeta() {
-    const key = this.description.options.key;
-    const value = this.description.options.value;
-    return [this.builder.meta(key), this.builder.meta(value)];
+  static isNull(info: number) {
+    return info & this.IS_NULL;
+  }
+
+  static trackingRef(info: number) {
+    return info & this.TRACKING_REF;
+  }
+}
+
+class MapChunkWriter {
+  private preKeyInfo = 0;
+  private preValueInfo = 0;
+
+  private chunkSize = 0;
+  private chunkOffset = 0;
+  private header = 0;
+
+  constructor(private fury: Fury) {
+
+  }
+
+  private getHead(keyInfo: number, valueInfo: number) {
+    let flag = 0;
+    if (TypeInfo.isNull(keyInfo)) {
+      flag |= MapFlags.HAS_NULL;
+    }
+    if (TypeInfo.trackingRef(keyInfo)) {
+      flag |= MapFlags.TRACKING_REF;
+    }
+    flag <<= 4;
+    if (TypeInfo.isNull(valueInfo)) {
+      flag |= MapFlags.HAS_NULL;
+    }
+    if (TypeInfo.trackingRef(valueInfo)) {
+      flag |= MapFlags.TRACKING_REF;
+    }
+    return flag;
   }
 
-  private innerGenerator() {
-    const key = this.description.options.key;
-    const value = this.description.options.value;
+  private writeHead(keyInfo: number, valueInfo: number) {
+    // KV header
+    const header = this.getHead(keyInfo, valueInfo);
+    this.fury.binaryWriter.uint8(header);
+    // chunkSize, max 255
+    this.chunkOffset = this.fury.binaryWriter.getCursor();
+    this.fury.binaryWriter.uint8(0);
+    this.fury.binaryWriter.uint32((keyInfo >> 16) | (valueInfo & 0xFFFF0000));
+    return header;
+  }
 
-    const KeyGeneratorClass = CodegenRegistry.get(key.type);
-    const ValueGeneratorClass = CodegenRegistry.get(value.type);
-    if (!KeyGeneratorClass) {
-      throw new Error(`${key.type} generator not exists`);
+  next(keyInfo: number, valueInfo: number) {
+    // max size of chunk is 255
+    if (this.chunkSize == 255
+      || this.chunkOffset == 0
+      || this.preKeyInfo !== keyInfo
+      || this.preValueInfo !== valueInfo
+    ) {
+      // new chunk
+      this.endChunk();
+      this.chunkSize++;
+      this.preKeyInfo = keyInfo;
+      this.preValueInfo = valueInfo;
+      return this.header = this.writeHead(keyInfo, valueInfo);
     }
-    if (!ValueGeneratorClass) {
-      throw new Error(`${value.type} generator not exists`);
+    this.chunkSize++;
+    return this.header;
+  }
+
+  endChunk() {
+    if (this.chunkOffset > 0) {
+      this.fury.binaryWriter.setUint8Position(this.chunkOffset, 
this.chunkSize);
+      this.chunkSize = 0;
     }
-    return [new KeyGeneratorClass(key, this.builder, this.scope), new 
ValueGeneratorClass(value, this.builder, this.scope)];
   }
+}
 
-  writeStmt(accessor: string): string {
-    const [keyMeta, valueMeta] = this.innerMeta();
-    const [keyGenerator, valueGenerator] = this.innerGenerator();
-    const key = this.scope.uniqueName("key");
-    const value = this.scope.uniqueName("value");
+class MapAnySerializer {
+  private keySerializer: Serializer | null = null;
+  private valueSerializer: Serializer | null = null;
 
-    return `
-            ${this.builder.writer.varUInt32(`${accessor}.size`)}
-            ${this.builder.writer.reserve(`${keyMeta.fixedSize + 
valueMeta.fixedSize} * ${accessor}.size`)};
-            for (const [${key}, ${value}] of ${accessor}.entries()) {
-                ${keyGenerator.toWriteEmbed(key)}
-                ${valueGenerator.toWriteEmbed(value)}
-            }
-        `;
+  constructor(private fury: Fury, keySerializerId: null | number, 
valueSerializerId: null | number) {
+    if (keySerializerId !== null) {
+      fury.classResolver.getSerializerById(keySerializerId);
+    }
+    if (valueSerializerId !== null) {
+      fury.classResolver.getSerializerById(valueSerializerId);
+    }
   }
 
-  readStmt(accessor: (expr: string) => string, refState: RefState): string {
-    const [keyGenerator, valueGenerator] = this.innerGenerator();
-    const key = this.scope.uniqueName("key");
-    const value = this.scope.uniqueName("value");
+  private writeHead(header: number, v: any) {
+    if (header !== 0) {
+      if (header & MapFlags.HAS_NULL) {
+        if (v === null || v === undefined) {
+          this.fury.binaryWriter.uint8(RefFlags.NullFlag);
+        }
+      }
+      if (header & MapFlags.TRACKING_REF) {
+        const keyRef = this.fury.referenceResolver.existsWriteObject(v);
+        if (keyRef !== undefined) {
+          this.fury.binaryWriter.uint8(RefFlags.RefFlag);
+          this.fury.binaryWriter.uint16(keyRef);
+        } else {
+          this.fury.binaryWriter.uint8(RefFlags.RefValueFlag);
+        }
+      } else {
+        this.fury.binaryWriter.uint8(RefFlags.NotNullValueFlag);
+      }
+    }
+  }
 
-    const result = this.scope.uniqueName("result");
-    const idx = this.scope.uniqueName("idx");
-    const len = this.scope.uniqueName("len");
+  write(value: Map<any, any>) {
+    const mapChunkWriter = new MapChunkWriter(this.fury);
+    this.fury.binaryWriter.varInt32(value.size);
+    for (const [k, v] of value.entries()) {
+      const keySerializer = this.keySerializer !== null ? this.keySerializer : 
this.fury.classResolver.getSerializerByData(k);
+      const valueSerializer = this.valueSerializer !== null ? 
this.valueSerializer : this.fury.classResolver.getSerializerByData(v);
 
+      const header = mapChunkWriter.next(
+        TypeInfo.elementInfo(keySerializer!.meta.typeId!, k == null ? 1 : 0, 
keySerializer!.meta.needToWriteRef ? 1 : 0),
+        TypeInfo.elementInfo(valueSerializer!.meta.typeId!, v == null ? 1 : 0, 
valueSerializer!.meta.needToWriteRef ? 1 : 0)
+      );
+
+      this.writeHead(header >> 4, k);
+      keySerializer!.writeInner(k);
+      this.writeHead(header & 0b00001111, v);
+      valueSerializer!.writeInner(v);
+    }
+    mapChunkWriter.endChunk();
+  }
+
+  private readElement(header: number, serializer: Serializer | null) {
+    if (header === 0) {
+      return serializer!.readInner(false);
+    }
+    const isSame = !(header & MapFlags.NOT_SAME_TYPE);
+    const includeNone = header & MapFlags.HAS_NULL;
+    const trackingRef = header & MapFlags.TRACKING_REF;
+
+    let flag = 0;
+    if (trackingRef || includeNone) {
+      flag = this.fury.binaryReader.uint8();
+    }
+    if (!isSame) {
+      serializer = 
this.fury.classResolver.getSerializerByType(this.fury.binaryReader.int16());
+    }
+    switch (flag) {
+      case RefFlags.RefValueFlag:
+        return serializer!.readInner(true);
+      case RefFlags.RefFlag:
+        return 
this.fury.referenceResolver.getReadObject(this.fury.binaryReader.varUInt32());
+      case RefFlags.NullFlag:
+        return null;
+      case RefFlags.NotNullValueFlag:
+        return serializer!.readInner(false);
+    }
+  }
+
+  read(fromRef: boolean): any {
+    let count = this.fury.binaryReader.varInt32();
+    const result = new Map();
+    if (fromRef) {
+      this.fury.referenceResolver.reference(result);
+    }
+    while (count > 0) {
+      const header = this.fury.binaryReader.uint16();
+      const chunkSize = header >> 8;
+      const keyHeader = header >> 12;
+      const valueHeader = header & 0b00001111;
+
+      let keySerializer = null;
+      let valueSerializer = null;
+
+      if (!(keyHeader & MapFlags.NOT_SAME_TYPE)) {
+        keySerializer = 
this.fury.classResolver.getSerializerById(this.fury.binaryReader.uint16());
+      }
+      if (!(valueHeader & MapFlags.NOT_SAME_TYPE)) {
+        valueSerializer = 
this.fury.classResolver.getSerializerById(this.fury.binaryReader.uint16());
+      }
+      for (let index = 0; index < chunkSize; index++) {
+        result.set(
+          this.readElement(keyHeader, keySerializer),
+          this.readElement(valueHeader, valueSerializer)
+        );
+        count--;
+      }
+    }
+    return result;
+  }
+}
+
+export class MapSerializerGenerator extends BaseSerializerGenerator {
+  description: MapTypeDescription;
+
+  constructor(description: TypeDescription, builder: CodecBuilder, scope: 
Scope) {
+    super(description, builder, scope);
+    this.description = <MapTypeDescription>description;
+  }
+
+  private innerMeta() {
+    const inner = this.description;
+    return [this.builder.meta(inner.options.key), 
this.builder.meta(inner.options.value)];
+  }
+
+  writeStmt(accessor: string): string {
+    const [keyMeta, valueMeta] = this.innerMeta();
+    const anySerializer = this.builder.getExternal(MapAnySerializer.name);
     return `
-            const ${result} = new Map();
-            ${this.maybeReference(result, refState)};
-            const ${len} = ${this.builder.reader.varUInt32()};
-            for (let ${idx} = 0; ${idx} < ${len}; ${idx}++) {
-                let ${key};
-                let ${value};
-                ${keyGenerator.toReadEmbed(x => `${key} = ${x};`)}
-                ${valueGenerator.toReadEmbed(x => `${value} = ${x};`)}
-                ${result}.set(${key}, ${value});
-            }
-            ${accessor(result)}
-         `;
+        new (${anySerializer})(${this.builder.furyName()}, ${keyMeta.typeId}, 
${valueMeta.typeId}).write(${accessor})
+    `;
+  }
+
+  readStmt(accessor: (expr: string) => string, refState: RefState): string {
+    const anySerializer = this.builder.getExternal(MapAnySerializer.name);
+    const [keyMeta, valueMeta] = this.innerMeta();
+    return accessor(`new (${anySerializer})(${this.builder.furyName()}, 
${keyMeta.typeId}, ${valueMeta.typeId}).read(${refState.toConditionExpr()})
+      `);
   }
 }
 
+CodegenRegistry.registerExternal(MapAnySerializer);
 CodegenRegistry.register(InternalSerializerType.MAP, MapSerializerGenerator);
diff --git a/javascript/packages/fury/lib/meta.ts 
b/javascript/packages/fury/lib/meta.ts
index 2e8978f9..2872b5c4 100644
--- a/javascript/packages/fury/lib/meta.ts
+++ b/javascript/packages/fury/lib/meta.ts
@@ -26,6 +26,7 @@ export type Meta = {
   fixedSize: number;
   needToWriteRef: boolean;
   type: InternalSerializerType;
+  typeId: number | null;
 };
 
 export const getMeta = (description: TypeDescription, fury: Fury): Meta => {
@@ -36,24 +37,28 @@ export const getMeta = (description: TypeDescription, fury: 
Fury): Meta => {
         fixedSize: 8,
         needToWriteRef: false,
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     case InternalSerializerType.ARRAY:
       return {
         fixedSize: 7,
         needToWriteRef: Boolean(fury.config.refTracking),
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     case InternalSerializerType.TUPLE:
       return {
         fixedSize: 7,
         needToWriteRef: Boolean(fury.config.refTracking),
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     case InternalSerializerType.MAP:
       return {
         fixedSize: 7,
         needToWriteRef: Boolean(fury.config.refTracking),
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     case InternalSerializerType.BOOL:
     case InternalSerializerType.INT8:
@@ -61,6 +66,7 @@ export const getMeta = (description: TypeDescription, fury: 
Fury): Meta => {
         fixedSize: 4,
         needToWriteRef: false,
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     case InternalSerializerType.INT16:
     case InternalSerializerType.FLOAT16:
@@ -68,6 +74,7 @@ export const getMeta = (description: TypeDescription, fury: 
Fury): Meta => {
         fixedSize: 5,
         needToWriteRef: false,
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     case InternalSerializerType.VAR_INT32:
     case InternalSerializerType.INT32:
@@ -76,6 +83,7 @@ export const getMeta = (description: TypeDescription, fury: 
Fury): Meta => {
         fixedSize: 7,
         needToWriteRef: false,
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     case InternalSerializerType.SLI_INT64:
     case InternalSerializerType.INT64:
@@ -84,24 +92,28 @@ export const getMeta = (description: TypeDescription, fury: 
Fury): Meta => {
         fixedSize: 11,
         needToWriteRef: false,
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     case InternalSerializerType.BINARY:
       return {
         fixedSize: 8,
         needToWriteRef: Boolean(fury.config.refTracking),
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     case InternalSerializerType.DURATION:
       return {
         fixedSize: 7,
         needToWriteRef: false,
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     case InternalSerializerType.TIMESTAMP:
       return {
         fixedSize: 11,
         needToWriteRef: false,
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     case InternalSerializerType.OBJECT:
     {
@@ -116,6 +128,7 @@ export const getMeta = (description: TypeDescription, fury: 
Fury): Meta => {
         fixedSize,
         needToWriteRef: Boolean(fury.config.refTracking),
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     }
 
@@ -124,6 +137,7 @@ export const getMeta = (description: TypeDescription, fury: 
Fury): Meta => {
         fixedSize: 7,
         needToWriteRef: Boolean(fury.config.refTracking),
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     case InternalSerializerType.BOOL_ARRAY:
     case InternalSerializerType.INT8_ARRAY:
@@ -137,6 +151,7 @@ export const getMeta = (description: TypeDescription, fury: 
Fury): Meta => {
         fixedSize: 7,
         needToWriteRef: Boolean(fury.config.refTracking),
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     case InternalSerializerType.ONEOF:
     case InternalSerializerType.ANY:
@@ -144,12 +159,14 @@ export const getMeta = (description: TypeDescription, 
fury: Fury): Meta => {
         fixedSize: 11,
         needToWriteRef: Boolean(fury.config.refTracking),
         type,
+        typeId: null,
       };
     case InternalSerializerType.ENUM:
       return {
         fixedSize: 7,
         needToWriteRef: false,
         type,
+        typeId: ClassResolver.getTypeIdByInternalSerializerType(type),
       };
     default:
       throw new Error(`Meta of ${description.type} not exists`);
diff --git a/javascript/packages/fury/lib/writer/index.ts 
b/javascript/packages/fury/lib/writer/index.ts
index 5f21afd9..69ef3090 100644
--- a/javascript/packages/fury/lib/writer/index.ts
+++ b/javascript/packages/fury/lib/writer/index.ts
@@ -318,6 +318,14 @@ export class BinaryWriter {
     this.dataView.setUint32(offset, v, true);
   }
 
+  setUint8Position(offset: number, v: number) {
+    this.dataView.setUint8(offset, v);
+  }
+
+  setUint16Position(offset: number, v: number) {
+    this.dataView.setUint16(offset, v, true);
+  }
+
   getByteLen() {
     return this.byteLength;
   }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to