1/*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16const MSG_HEAD_LENGTH = 20;
17const TYPT_LENGTH = 1;
18const CMD_LENGTH = 2;
19const SESSION_ID_LENGTH = 1;
20const SESSION_LENGTH = 4;
21export class Utils {
22    // 模块传进来的数据
23    static encode(message: MessageParam) {
24        let splitUint64 = message.session ? Utils.splitUint64ToUint32s(BigInt(message.session!)) : { high32: 0, low32: 0 };// 需处理64bit(session)
25        let totalByteLength = MSG_HEAD_LENGTH + (message.data_lenght ? message.data_lenght : 0);
26        let combinedBuffer = new ArrayBuffer(totalByteLength);// 一个更大的ArrayBuffer,合并前20个字节和data
27        let headBuffer = new ArrayBuffer(MSG_HEAD_LENGTH);
28        let dataView = new DataView(headBuffer);
29        let index = 0;
30        dataView.setUint8(index, message.type!);
31        index += TYPT_LENGTH;
32        dataView.setUint16(index, message.cmd ? message.cmd : 0);
33        index += CMD_LENGTH;
34        dataView.setUint8(index, message.session_id ? message.session_id : 0);
35        index += SESSION_ID_LENGTH;
36        dataView.setUint32(index, splitUint64?.high32!);
37        index += SESSION_LENGTH;
38        dataView.setUint32(index, splitUint64?.low32!);
39        index += SESSION_LENGTH;
40        dataView.setUint32(index, message.data_lenght ? message.data_lenght : 0);
41        // 处理合并message.data
42        let existingArray = new Uint8Array(headBuffer); // 将处理好的前20个字节 
43        let combinedArray = new Uint8Array(combinedBuffer);
44        // 分别将前20个字节和data对应的字节流set至combinedBuffer
45        combinedArray.set(existingArray, 0);
46        combinedArray.set(message.data ? message.data : new Uint8Array(0), headBuffer.byteLength);
47        return combinedBuffer
48    }
49
50    // onmessage接收到的数据解码
51    public static decode(message: ArrayBuffer) {
52        let decode: MessageParam | undefined;
53        let dataView = new DataView(message);
54        let sessionHigh = dataView.getUint32(4);
55        let sessionLow = dataView.getUint32(8);
56        // 将两个 32 位部分组合成一个 64 位的 BigInt  
57        let session = BigInt(sessionHigh) << BigInt(32) | BigInt(sessionLow);
58        // 先将data所需的字节截取出来
59        let dataBytes = new Uint8Array(message, MSG_HEAD_LENGTH, message.byteLength - MSG_HEAD_LENGTH);
60        // 解码 session 的两个 32 位部分  
61        decode = {
62            type: dataView.getUint8(0),
63            cmd: dataView.getUint16(1),
64            session_id: dataView.getUint8(3),
65            session: session,
66            data_lenght: dataView.getUint32(12),
67            data: dataBytes
68        }
69        return decode
70    }
71
72    // 处理64bit 需要拆分成两个32bit
73    public static splitUint64ToUint32s(bigInt: bigint): { high32: number, low32: number } {
74        // 使用位运算提取高32位和低32位  
75        // 右移32位得到高32位,并与0xFFFFFFFF进行按位与操作以确保结果是32位无符号整数  
76        const high32 = Number((bigInt >> BigInt(32)) & BigInt(0xFFFFFFFF));
77        // 低32位可以直接与0xFFFFFFFF进行按位与操作  
78        const low32 = Number(bigInt & BigInt(0xFFFFFFFF));
79        return { high32, low32 };
80    }
81}
82export class MessageParam {
83    type: number | undefined;
84    cmd: number | undefined;
85    session_id?: number | undefined;
86    session?: bigint | undefined;
87    data_lenght?: number | undefined;
88    data?: Uint8Array | undefined
89}