diff --git a/OpenHarmony/ohos_msgpack/.gitignore b/OpenHarmony/ohos_msgpack/.gitignore new file mode 100644 index 0000000..fbabf77 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/.gitignore @@ -0,0 +1,11 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/AppScope/app.json5 b/OpenHarmony/ohos_msgpack/AppScope/app.json5 new file mode 100644 index 0000000..796e4f3 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "cn.openharmony.msgpack", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.2-rc.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/OpenHarmony/ohos_msgpack/AppScope/resources/base/element/string.json b/OpenHarmony/ohos_msgpack/AppScope/resources/base/element/string.json new file mode 100644 index 0000000..40ba973 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "ohos_msgpack" + } + ] +} diff --git a/OpenHarmony/ohos_msgpack/AppScope/resources/base/media/app_icon.png b/OpenHarmony/ohos_msgpack/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000..ce307a8 Binary files /dev/null and b/OpenHarmony/ohos_msgpack/AppScope/resources/base/media/app_icon.png differ diff --git a/OpenHarmony/ohos_msgpack/CHANGELOG.md b/OpenHarmony/ohos_msgpack/CHANGELOG.md new file mode 100644 index 0000000..4a15092 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/CHANGELOG.md @@ -0,0 +1,12 @@ +## 1.0.2-rc.0 +- Fix Compilation Warnings + +## 1.0.1 +- 发布正式版本1.0.1 + +## 1.0.1-rc.0 +- 现以基于msgpack2.8 版本进行升级,升级成为msgpack3.0版本,可以实现更为复杂的编码。 + +## 1.0.0-rc.0 +- 基于msgpack 原库3.0.0-beta2 版本进行适配,使其可以运行在 OpenHarmony,并沿用其现有用法和特性。 +- 提供了一种紧凑高效的二进制序列化格式。 \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/LICENSE b/OpenHarmony/ohos_msgpack/LICENSE new file mode 100644 index 0000000..f0e7f3e --- /dev/null +++ b/OpenHarmony/ohos_msgpack/LICENSE @@ -0,0 +1,5 @@ +Copyright 2019 The MessagePack Community. + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/OpenHarmony/ohos_msgpack/NOTICE b/OpenHarmony/ohos_msgpack/NOTICE new file mode 100644 index 0000000..26a5915 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/NOTICE @@ -0,0 +1,21 @@ +OPEN SOURCE SOFTWARE NOTICE + +Please note we provide an open source software notice for the third party open source software along with this software and/or this software component (in the following just “this SOFTWARE”). The open source software licenses are granted by the respective right holders. + +Warranty Disclaimer +THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. + +Copyright Notice and License Texts + +---------------------------------------------------------------------- +Software: msgpack-javascript v3.0.0-beta2 +Copyright notice: +Copyright (c) 2019 The MessagePack Community. +License: ISC License + +Copyright 2019 The MessagePack Community. + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + diff --git a/OpenHarmony/ohos_msgpack/OAT.xml b/OpenHarmony/ohos_msgpack/OAT.xml new file mode 100644 index 0000000..a4790a8 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/OAT.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/README.OpenSource b/OpenHarmony/ohos_msgpack/README.OpenSource new file mode 100644 index 0000000..01d20e4 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/README.OpenSource @@ -0,0 +1,11 @@ +[ + { + "Name": "msgpack-javascript", + "License": "ISC License", + "License File": " LICENSE ", + "Version Number": "v3.0.0-beta2", + "Owner": "xiafeng@huawei.com", + "Upstream URL": "https://github.com/msgpack/msgpack-javascript", + "Description": "MessagePack is an extremely efficient object serialization library. It's like JSON, but very fast and small." + } +] \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/README.md b/OpenHarmony/ohos_msgpack/README.md new file mode 100644 index 0000000..0d0590a --- /dev/null +++ b/OpenHarmony/ohos_msgpack/README.md @@ -0,0 +1,118 @@ +# msgpack-javascript + +## Introduction +> MessagePack is a library that provides efficient object serialization. It is like JSON but offers higher efficiency and smaller data size. +> Currently, MessagePack 3.0 can be used to implement complex int64 encoding. + +## How to Install +```shell +ohpm install @ohos/msgpack +``` +For details, see [Installing an OpenHarmony HAR](https://gitcode.com/openharmony-tpc/docs/blob/master/OpenHarmony_har_usage.en.md). + +## How to Use + +### Encoding and Decoding +```javascript +import { encode,decode } from "@ohos/msgpack"; + +// Encode. +let encoded:Uint8Array = encode({ foo: "bar" }); +// Decode. +let decodedObject = decode(encoded); +``` + +### Using Encoder and Decoder +```javascript +import { Encoder,Decoder } from "@ohos/msgpack"; +// Reuse the encoder instance. +let encoder = new Encoder() +// Reuse the decoder instance. +let decoder = new Decoder() +// Encode. +let encoded:Uint8Array = encoder.encode({ foo: "bar" }); +// Decode. +let decodedObject = decoder.decode(encoded); +// Decode a complex int64 object. +let data: ESObject = + { + ints: [0, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER], + nums: [Number.NaN, Math.PI, Math.E, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY], + bigints: [BigInt(0), BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1), BigInt(Number.MIN_SAFE_INTEGER) - BigInt(1)], + }; +// Encode the minimum int64 value. +return BigInt(Number.MIN_SAFE_INTEGER) - BigInt(1); +// Encode and decode a common int64 value. +return BigInt(0); +// Encode the maximum int64 value. +return BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1); +``` + +### Encoding and Decoding an Array Object + +```javascript +import { encode,decodeMulti } from "@ohos/msgpack"; + +let items = [ + "foo", + 10, + { + name: "bar", + }, + [1, 2, 3], +]; +// Encode the item array. +let encodedItems = items.map((item) => encode(item)); +// Create a blank buffer for storing streams. +let encoded = new Uint8Array(encodedItems.reduce((p, c) => p + c.byteLength, 0)); +let offset = 0; +// Store the encoded items in the buffer. +for (let encodedItem of encodedItems) { + encoded.set(encodedItem, offset); + offset += encodedItem.byteLength; +} +let result: Array = []; +// Store the decoded items in the result array. +for (let item of decodeMulti(encoded)) { + result.push(item); +} +// The value of result is the same as that of items. +expect(result).assertDeepEquals(items); +``` + +## Directory Structure +```` +|---- msgpackJavaScript +| |---- entry # Sample code +| |---- Index.ets # External APIs + |---- EncodeDecodePage.ets # Common encoding and decoding + |---- Encoding64DemoFour.ets # Decoding complex int64 objects + |---- Encoding64DemoOne.ets # Encoding the minimum int64 value + |---- Encoding64DemoThree.ets # Encoding and decoding the common int64 value + |---- Encoding64DemoTwo.ets # Encoding the maximum int64 value + |---- EncodeDecodeConstructorPage.ets # Using encoder and decoder + |---- MultiDecodePage.ets # Decoding complex objects +| |---- library # Library code +| |---- README_EN.MD # Brief introduction of the MessagePack library +```` + +## About obfuscation +- Code obfuscation, please see[Code Obfuscation](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/arkts-utils/source-obfuscation.md) +- If you want the msgpack-javascript library not to be obfuscated during code obfuscation, you need to add corresponding exclusion rules in the obfuscation rule configuration file obfuscation-rules.txt: +``` +-keep +./oh_modules/@ohos/msgpack +``` + +## Constraints + +MessagePack has been verified only in the following version: + +- DevEco Studio: 5.0.3.132, SDK: API12 (5.0.0.19) + +## How to Contribute + +If you find any problem during the use, submit an [Issue](https://gitcode.com/openharmony-tpc/openharmony_tpc_samples/issues) or a [PR](https://gitcode.com/openharmony-tpc/openharmony_tpc_samples) to us. + +## License +This project is licensed under [ISC License](https://gitcode.com/openharmony-tpc/openharmony_tpc_samples/blob/master/ohos_msgpack/LICENSE). diff --git a/OpenHarmony/ohos_msgpack/README_zh.md b/OpenHarmony/ohos_msgpack/README_zh.md new file mode 100644 index 0000000..cbfc967 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/README_zh.md @@ -0,0 +1,119 @@ +# msgpack-javascript + +## 简介 +> MessagePack是一个非常高效的对象序列化库。它像JSON,但速度很快,而且很小。 +> 现在MessagePack已经适配了3.0版本,可用于实现int64的复杂性编码。 + +## 下载安装 +```shell +ohpm install @ohos/msgpack +``` +OpenHarmony ohpm 环境配置等更多内容,请参考[如何安装 OpenHarmony ohpm 包](https://gitcode.com/openharmony-tpc/docs/blob/master/OpenHarmony_har_usage.md) + +## 使用说明 + +### 编解码 +```javascript +import { encode,decode } from "@ohos/msgpack"; + +// 编码 +let encoded:Uint8Array = encode({ foo: "bar" }); +// 解码 +let decodedObject = decode(encoded); +``` + +### 构造器编解码 +```javascript +import { Encoder,Decoder } from "@ohos/msgpack"; +// 编码可复用构造器 +let encoder = new Encoder() +// 解码可复用构造器 +let decoder = new Decoder() +// 编码 +let encoded:Uint8Array = encoder.encode({ foo: "bar" }); +// 解码 +let decodedObject = decoder.decode(encoded); +// int64复杂对象解码 +let data: ESObject = + { + ints: [0, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER], + nums: [Number.NaN, Math.PI, Math.E, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY], + bigints: [BigInt(0), BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1), BigInt(Number.MIN_SAFE_INTEGER) - BigInt(1)], + }; +// int64编码最小值 +return BigInt(Number.MIN_SAFE_INTEGER) - BigInt(1); +// int64普通编解码 +return BigInt(0); +// int64编码最大值 +return BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1); +``` + +### 数组对象编解码 + +```javascript +import { encode,decodeMulti } from "@ohos/msgpack"; + +let items = [ + "foo", + 10, + { + name: "bar", + }, + [1, 2, 3], +]; +// 将数组编码 +let encodedItems = items.map((item) => encode(item)); +// 创建空白缓存区用来后续存数据流 +let encoded = new Uint8Array(encodedItems.reduce((p, c) => p + c.byteLength, 0)); +let offset = 0; +// 空白缓存区存入数据流 +for (let encodedItem of encodedItems) { + encoded.set(encodedItem, offset); + offset += encodedItem.byteLength; +} +let result: Array = []; +// 解码后将数据存入result数组中 +for (let item of decodeMulti(encoded)) { + result.push(item); +} +// result与items一致 +expect(result).assertDeepEquals(items); +``` + +## 目录结构 +```` +|---- msgpackJavaScript +| |---- entry # 示例代码文件夹 +| |---- Index.ets # 对外接口介绍 + |---- EncodeDecodePage.ets # 普通编解码 + |---- Encoding64DemoFour.ets # int64复杂对象解码 + |---- Encoding64DemoOne.ets # int64编码最小值 + |---- Encoding64DemoThree.ets # int64普通编解码 + |---- Encoding64DemoTwo.ets # int64编码最大值 + |---- EncodeDecodeConstructorPage.ets # 通过构造器编解码 + |---- MultiDecodePage.ets # 复杂对象解码 +| |---- library # 库代码文件夹 +| |---- README.MD # 安装使用方法 +```` + +## 关于混淆 +- 代码混淆,请查看[代码混淆简介](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/arkts-utils/source-obfuscation.md) +- 如果希望msgpack-javascript库在代码混淆过程中不会被混淆,需要在混淆规则配置文件obfuscation-rules.txt中添加相应的排除规则: +``` +-keep +./oh_modules/@ohos/msgpack +``` + +## 约束与限制 + +在下述版本验证通过: + +- DevEco Studio: 5.0.3.132, SDK: API12 (5.0.0.19) +- DevEco Studio: NEXT Beta1-5.0.3.806, SDK: API12 Release (5.0.0.66) + +## 贡献代码 + +使用过程中发现任何问题都可以提 [Issue](https://gitcode.com/openharmony-tpc/openharmony_tpc_samples/issues) 给组件,当然,也非常欢迎发 [PR](https://gitcode.com/openharmony-tpc/openharmony_tpc_samples) 共建。 + +## 开源协议 +本项目基于 [ISC License](https://gitcode.com/openharmony-tpc/openharmony_tpc_samples/blob/master/ohos_msgpack/LICENSE) ,请自由地享受和参与开源。 \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/build-profile.json5 b/OpenHarmony/ohos_msgpack/build-profile.json5 new file mode 100644 index 0000000..f8315ec --- /dev/null +++ b/OpenHarmony/ohos_msgpack/build-profile.json5 @@ -0,0 +1,32 @@ +{ + "app": { + "signingConfigs": [], + "products": [ + { + "compileSdkVersion": 12, + "compatibleSdkVersion": 12, + "name": "default", + "signingConfig": "default", + "runtimeOS": "OpenHarmony" + } + ], + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + }, + { + "name": "library", + "srcPath": "./library" + } + ] +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/.gitignore b/OpenHarmony/ohos_msgpack/entry/.gitignore new file mode 100644 index 0000000..e2713a2 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/build-profile.json5 b/OpenHarmony/ohos_msgpack/entry/build-profile.json5 new file mode 100644 index 0000000..dd1e4e9 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/build-profile.json5 @@ -0,0 +1,29 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": true, + "files": [ + "./obfuscation-rules.txt" + // 混淆规则文件 + ] + } + } + } + } + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/hvigorfile.ts b/OpenHarmony/ohos_msgpack/entry/hvigorfile.ts new file mode 100644 index 0000000..c6edcd9 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/OpenHarmony/ohos_msgpack/entry/obfuscation-rules.txt b/OpenHarmony/ohos_msgpack/entry/obfuscation-rules.txt new file mode 100644 index 0000000..e900c96 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/obfuscation-rules.txt @@ -0,0 +1,26 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation + +-keep +./oh_modules/@ohos/msgpack \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/oh-package.json5 b/OpenHarmony/ohos_msgpack/entry/oh-package.json5 new file mode 100644 index 0000000..8ee8c30 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "license": "", + "devDependencies": {}, + "author": "", + "name": "entry", + "description": "Please describe the basic information.", + "main": "", + "version": "1.0.2-rc.0", + "dependencies": { + "@ohos/msgpack": "file:../library" + } +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/ets/entryability/EntryAbility.ts b/OpenHarmony/ohos_msgpack/entry/src/main/ets/entryability/EntryAbility.ts new file mode 100644 index 0000000..272a4f7 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/ets/entryability/EntryAbility.ts @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import UIAbility from '@ohos.app.ability.UIAbility'; +import hilog from '@ohos.hilog'; +import window from '@ohos.window'; + +export default class EntryAbility extends UIAbility { + onCreate(want, launchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage) { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground() { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground() { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/EncodeDecodeConstructorPage.ets b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/EncodeDecodeConstructorPage.ets new file mode 100644 index 0000000..bf69fc3 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/EncodeDecodeConstructorPage.ets @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import { encode,Encoder } from "@ohos/msgpack"; +import { decode,Decoder } from "@ohos/msgpack"; +@Entry +@Component +struct EncodeDecodeConstructorPage { + + @State message: string = ''; + @State message2:string = ''; + @State message3:string = ''; + + encodedUint8?: Uint8Array = undefined; + + build() { + Row() { + Column() { + Button($r('app.string.Constructor_encoding')).onClick(()=>{ + console.log("dodo click on!") + let encodeletructor: Encoder = new Encoder(); + this.encodedUint8 = encodeletructor.encode(data) + this.message = this.getResourceString($r('app.string.Encoded_data'))+this.encodedUint8; + }) + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button($r('app.string.constructor_to_decode')).onClick(()=>{ + if(this.encodedUint8) { + let decodeletructor: Decoder = new Decoder(); + //let decodeObj = decodeletructor.decode(this.encodedUint8) + this.message2 = this.getResourceString($r('app.string.Decoded_data')) + JSON.stringify(decodeletructor.decode(this.encodedUint8)); + }else{ + this.message3 = this.getResourceString($r('app.string.undefined')); + } + }) + Text(this.message2) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } + + aboutToAppear() { + this.message = this.getResourceString($r('app.string.Display_encoded_data')); + this.message2 = this.getResourceString($r('app.string.Display_decoded_data')); + this.message3 = this.getResourceString($r('app.string.Error_message')); + } + + getResourceString(res: Resource) { + return getContext().resourceManager.getStringSync(res.id); + } +} + +class Data{ + foo: string = "" +} + +let data: Data = { foo: "bar" } \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/EncodeDecodePage.ets b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/EncodeDecodePage.ets new file mode 100644 index 0000000..421d2b3 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/EncodeDecodePage.ets @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import { encode,decode } from "@ohos/msgpack"; +@Entry +@Component +struct EncodeDecodePage { + + @State message: string = ''; + @State message2:string = ''; + @State message3:string = ''; + + encodedUint8?: Uint8Array = undefined; + + build() { + Row() { + Column() { + Button($r('app.string.Object_encoding')).onClick(()=>{ + console.log("dodo click on!") + this.encodedUint8 = encode(data); + this.message = this.getResourceString($r('app.string.Encoded_data'))+this.encodedUint8; + }) + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button($r('app.string.decode')).onClick(()=>{ + if(this.encodedUint8) { + this.message2 = this.getResourceString($r('app.string.Decoded_data')) + JSON.stringify(decode(this.encodedUint8)); + }else{ + this.message3 = this.getResourceString($r('app.string.undefined')); + } + }) + Text(this.message2) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } + aboutToAppear() { + this.message = this.getResourceString($r('app.string.Display_encoded_data')); + this.message2 = this.getResourceString($r('app.string.Display_decoded_data')); + this.message3 = this.getResourceString($r('app.string.Display_decoded_data')); + } + + getResourceString(res: Resource) { + return getContext().resourceManager.getStringSync(res.id); + } +} + +class Data{ + foo: string = "" +} + +let data: Data = { foo: "bar" } \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Encoding64DemoFour.ets b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Encoding64DemoFour.ets new file mode 100644 index 0000000..80d3574 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Encoding64DemoFour.ets @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import { encode, decode, ExtensionCodec } from '@ohos/msgpack'; + +@Entry +@Component +struct Encoding64DemoFour { + @State message: string = ''; + @State encodedMessage: string = ''; + @State decodeMessage: string = ''; + encodedUint8?: Uint8Array = undefined; + + aboutToAppear(): void { + this.message = this.getResourceString($r('app.string.Display_encoded_data')); + this.encodedMessage = this.getResourceString($r('app.string.Display_decoded_data')); + this.decodeMessage = this.getResourceString($r('app.string.Display_decoded_data')); + } + + getResourceString(res: Resource) { + return getContext().resourceManager.getStringSync(res.id); + } + + build() { + Row() { + Column() { + Button($r('app.string.Object_encoding')).onClick(() => { + const extensionCodec = new ExtensionCodec(); + extensionCodec.register({ + type: 0, + encode: (input: Object) => { + if (typeof input === 'bigint') { + if (input <= Number.MAX_SAFE_INTEGER && input >= Number.MIN_SAFE_INTEGER) { + return encode(Number.parseInt(input.toString(), 10)); + } else { + return encode(input.toString()); + } + } else { + return null; + } + }, + decode: (data: Uint8Array) => { + const value = decode(data) as string; + if (!(typeof value === 'string' || typeof value === 'number')) { + } + return BigInt(value); + }, + }); + + this.encodedUint8 = encode(data(), { useBigInt64: true, + extensionCodec + }); + this.message = this.getResourceString($r('app.string.Encoded_data')) + this.encodedUint8; + }) + Text(this.message) + .fontSize(25) + .fontWeight(FontWeight.Bold) + Button($r('app.string.decode')).onClick(() => { + if (this.encodedUint8) { + this.encodedMessage = this.getResourceString($r('app.string.Decoded_data')) + JSON.stringify(decode(this.encodedUint8)); + } else { + this.decodeMessage = this.getResourceString($r('app.string.undefined')); + } + }) + Text(this.encodedMessage) + .fontSize(25) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} + +interface CustomData { + ints: number[]; + nums: number[]; + bigints: bigint[]; +} + +function data() { + let data: CustomData = + { + ints: [0, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER], + nums: [Number.NaN, Math.PI, Math.E, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY], + bigints: [BigInt(0), BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1), BigInt(Number.MIN_SAFE_INTEGER) - BigInt(1)], + }; + return data; +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Encoding64DemoOne.ets b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Encoding64DemoOne.ets new file mode 100644 index 0000000..483f187 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Encoding64DemoOne.ets @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import { encode, decode, ExtensionCodec } from '@ohos/msgpack'; + +@Entry +@Component +struct Encoding64DemoOne { + @State message: string = ''; + @State encodedMessage: string = ''; + @State decodeMessage: string = ''; + encodedUint8?: Uint8Array = undefined; + + aboutToAppear(): void { + this.message = this.getResourceString($r('app.string.Display_encoded_data')); + this.encodedMessage = this.getResourceString($r('app.string.Display_decoded_data')); + this.decodeMessage = this.getResourceString($r('app.string.Display_decoded_data')); + } + + getResourceString(res: Resource) { + return getContext().resourceManager.getStringSync(res.id); + } + + build() { + Row() { + Column() { + Button($r('app.string.Object_encoding')).onClick(() => { + const extensionCodec = new ExtensionCodec(); + extensionCodec.register({ + type: 0, + encode: (input: Object) => { + if (typeof input === 'bigint') { + if (input <= Number.MAX_SAFE_INTEGER && input >= Number.MIN_SAFE_INTEGER) { + return encode(Number.parseInt(input.toString(), 10)); + } else { + return encode(input.toString()); + } + } else { + return null; + } + }, + decode: (data: Uint8Array) => { + const value = decode(data) as string; + if (!(typeof value === 'string' || typeof value === 'number')) { + } + return BigInt(value); + }, + }); + + this.encodedUint8 = encode(data(), { useBigInt64: true, + extensionCodec + }); + this.message = this.getResourceString($r('app.string.Encoded_data')) + this.encodedUint8; + }) + Text(this.message) + .fontSize(25) + .fontWeight(FontWeight.Bold) + Button($r('app.string.decode')).onClick(() => { + if (this.encodedUint8) { + this.encodedMessage = this.getResourceString($r('app.string.Decoded_data')) + JSON.stringify(decode(this.encodedUint8)); + } else { + this.decodeMessage = this.getResourceString($r('app.string.undefined')); + } + }) + Text(this.encodedMessage) + .fontSize(25) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} + +function data() { + return BigInt(Number.MIN_SAFE_INTEGER) - BigInt(1); +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Encoding64DemoThree.ets b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Encoding64DemoThree.ets new file mode 100644 index 0000000..4bc39fe --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Encoding64DemoThree.ets @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import { encode, decode, ExtensionCodec } from '@ohos/msgpack'; + +@Entry +@Component +struct Encoding64DemoThree { + @State message: string = ''; + @State encodedMessage: string = ''; + @State decodeMessage: string = ''; + encodedUint8?: Uint8Array = undefined; + + aboutToAppear(): void { + this.message = this.getResourceString($r('app.string.Display_encoded_data')); + this.encodedMessage = this.getResourceString($r('app.string.Display_decoded_data')); + this.decodeMessage = this.getResourceString($r('app.string.Display_decoded_data')); + } + + getResourceString(res: Resource) { + return getContext().resourceManager.getStringSync(res.id); + } + + build() { + Row() { + Column() { + Button($r('app.string.Object_encoding')).onClick(() => { + const extensionCodec = new ExtensionCodec(); + extensionCodec.register({ + type: 0, + encode: (input: Object) => { + if (typeof input === 'bigint') { + if (input <= Number.MAX_SAFE_INTEGER && input >= Number.MIN_SAFE_INTEGER) { + return encode(Number.parseInt(input.toString(), 10)); + } else { + return encode(input.toString()); + } + } else { + return null; + } + }, + decode: (data: Uint8Array) => { + const value = decode(data) as string; + if (!(typeof value === 'string' || typeof value === 'number')) { + } + return BigInt(value); + }, + }); + + this.encodedUint8 = encode(data(), { useBigInt64: true, + extensionCodec + }); + this.message = this.getResourceString($r('app.string.Encoded_data')) + this.encodedUint8; + }) + Text(this.message) + .fontSize(25) + .fontWeight(FontWeight.Bold) + Button($r('app.string.decode')).onClick(() => { + if (this.encodedUint8) { + this.encodedMessage = this.getResourceString($r('app.string.Decoded_data')) + JSON.stringify(decode(this.encodedUint8)); + } else { + this.decodeMessage = this.getResourceString($r('app.string.undefined')); + } + }) + Text(this.encodedMessage) + .fontSize(25) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} + +function data() { + return BigInt(0); +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Encoding64DemoTwo.ets b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Encoding64DemoTwo.ets new file mode 100644 index 0000000..47ce088 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Encoding64DemoTwo.ets @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import { encode, decode, ExtensionCodec } from '@ohos/msgpack'; + +@Entry +@Component +struct Encoding64DemoTwo { + @State message: string = ''; + @State encodedMessage: string = ''; + @State decodeMessage: string = ''; + encodedUint8?: Uint8Array = undefined; + + aboutToAppear(): void { + this.message = this.getResourceString($r('app.string.Display_encoded_data')); + this.encodedMessage = this.getResourceString($r('app.string.Display_decoded_data')); + this.decodeMessage = this.getResourceString($r('app.string.Display_decoded_data')); + } + + getResourceString(res: Resource) { + return getContext().resourceManager.getStringSync(res.id); + } + + build() { + Row() { + Column() { + Button($r('app.string.Object_encoding')).onClick(() => { + const extensionCodec = new ExtensionCodec(); + extensionCodec.register({ + type: 0, + encode: (input: Object) => { + if (typeof input === 'bigint') { + if (input <= Number.MAX_SAFE_INTEGER && input >= Number.MIN_SAFE_INTEGER) { + return encode(Number.parseInt(input.toString(), 10)); + } else { + return encode(input.toString()); + } + } else { + return null; + } + }, + decode: (data: Uint8Array) => { + const value = decode(data) as string; + if (!(typeof value === 'string' || typeof value === 'number')) { + } + return BigInt(value); + }, + }); + + this.encodedUint8 = encode(data(), { useBigInt64: true, + extensionCodec + }); + this.message = this.getResourceString($r('app.string.Encoded_data')) + this.encodedUint8; + }) + Text(this.message) + .fontSize(25) + .fontWeight(FontWeight.Bold) + Button($r('app.string.decode')).onClick(() => { + if (this.encodedUint8) { + this.encodedMessage = this.getResourceString($r('app.string.Decoded_data')) + JSON.stringify(decode(this.encodedUint8)); + } else { + this.decodeMessage = this.getResourceString($r('app.string.undefined')); + } + }) + Text(this.encodedMessage) + .fontSize(25) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} + +function data() { + return BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1); +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/ExamPage.ets b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/ExamPage.ets new file mode 100644 index 0000000..93fc88b --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/ExamPage.ets @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +import { MsgTimestamp } from "../../../ohosTest/ets/test/test/msg/msg-timestamp"; +import { encode, decode, ExtensionCodec } from "@ohos/msgpack"; +import ohBuffer from '@ohos.buffer'; +import Util from './Util'; + +@Entry +@Component +struct Index { + @State message: Resource = $r('app.string.log') + m1: Massage = { + string: "Кириллица", + msgpack: [ + [0xb2, 0xd0, 0x9a, 0xd0, 0xb8, 0xd1, 0x80, 0xd0, 0xb8, 0xd0, 0xbb, 0xd0, 0xbb, 0xd0, 0xb8, 0xd1, 0x86, 0xd0, 0xb0], + [0xd9, 0x12, 0xd0, 0x9a, 0xd0, 0xb8, 0xd1, 0x80, 0xd0, 0xb8, 0xd0, 0xbb, 0xd0, 0xbb, 0xd0, 0xb8, 0xd1, 0x86, 0xd0, 0xb0] + ] + }; + m2: Massage = { + string: "ひらがな", + msgpack: [ + [0xac, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x8c, 0xe3, 0x81, 0xaa], + [0xd9, 0x0c, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x8c, 0xe3, 0x81, 0xaa] + ] + }; + m3: Massage = { + string: "한글", + msgpack: [ + [0xa6, 0xed, 0x95, 0x9c, 0xea, 0xb8, 0x80], + [0xd9, 0x06, 0xed, 0x95, 0x9c, 0xea, 0xb8, 0x80] + ] + }; + m4: Massage = { + string: "汉字", + msgpack: [ + [0xa6, 0xe6, 0xb1, 0x89, 0xe5, 0xad, 0x97], + [0xd9, 0x06, 0xe6, 0xb1, 0x89, 0xe5, 0xad, 0x97] + ] + }; + m5: Massage = { + string: "漢字", + msgpack: [ + [0xa6, 0xe6, 0xbc, 0xa2, 0xe5, 0xad, 0x97], + [0xd9, 0x06, 0xe6, 0xbc, 0xa2, 0xe5, 0xad, 0x97] + ] + }; + m6: Massage = { + string: "❤", + msgpack: [ + [0xa3, 0xe2, 0x9d, 0xa4], + [0xd9, 0x03, 0xe2, 0x9d, 0xa4] + ] + }; + m7: Massage = { + string: "🍺", + msgpack: [ + [0xa4, 0xf0, 0x9f, 0x8d, 0xba], + [0xd9, 0x04, 0xf0, 0x9f, 0x8d, 0xba] + ] + }; + + build() { + Row() { + Column() { + Button(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .onClick(() => { + this.testSpecString(); + }) + } + .width('100%') + } + .height('100%') + } + + testSpecString() { + // 补齐XTS中未通过用例 + let inputs = [ + this.m1, + this.m2, + this.m3, + this.m4, + this.m5, + this.m6, + this.m7 + ] + + for (let i = 0; i < inputs.length; i++) { + let input = inputs[i]; + this.checkEncodeAndDecode(input.string, input.msgpack[0], input.msgpack[1]) + } + + } + + checkEncodeAndDecode(value: string, array1: number[], array2: number[]) { + console.log("dodo 输入value=" + value); + let extensionCodec: ExtensionCodec = new ExtensionCodec(); + extensionCodec.register(Util.register); + let b1: Uint8Array = encode(value, { extensionCodec }); + let u8 = b1; + for (let i = 0; i < u8.length; i++) { + console.log(`dodo 编码后buffer[${i}]=${u8[i]}`) + } + let encode1 = ohBuffer.from(array1); + let encode2 = ohBuffer.from(array2); + + console.log("dodo 解码后 array1 对应 decode1=" + decode(encode1.buffer, { + extensionCodec + }) + " array2 对应 decode2=" + decode(encode2.buffer, { extensionCodec })); + } +} + +class Massage { + string: string = ""; + msgpack: number[][] = [[0]]; +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Index.ets b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000..5b69dd1 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import router from '@ohos.router'; + +@Entry +@Component +struct Index { + build() { + Row() { + Column() { + Button($r('app.string.Simple_encoding_and_decoding')) + .onClick(() => { + router.pushUrl({ url: 'pages/EncodeDecodePage' }) + }) + Button('Encoding64DemoOne') + .margin({ top: 10 }) + .onClick(() => { + router.pushUrl({ url: 'pages/Encoding64DemoOne' }) + }) + Button('Encoding64DemoTwo') + .margin({ top: 10 }) + .onClick(() => { + router.pushUrl({ url: 'pages/Encoding64DemoTwo' }) + }) + Button('Encoding64DemoThree') + .margin({ top: 10 }) + .onClick(() => { + router.pushUrl({ url: 'pages/Encoding64DemoThree' }) + }) + Button('Encoding64DemoFour') + .margin({ top: 10 }) + .onClick(() => { + router.pushUrl({ url: 'pages/Encoding64DemoFour' }) + }) + Button($r('app.string.Constructor_encoding_and_decoding')) + .margin({ top: 10 }) + .onClick(() => { + router.pushUrl({ url: 'pages/EncodeDecodeConstructorPage' }) + }) + Button($r('app.string.Complex_encoding_decoding')) + .margin({ top: 10 }) + .onClick(() => { + router.pushUrl({ url: 'pages/MultiDecodePage' }) + }) + Button($r('app.string.Special_Character')) + .margin({ top: 10 }) + .onClick(() => { + router.pushUrl({ url: 'pages/ExamPage' }) + }) + } + .width('100%') + } + .height('100%') + } +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/MultiDecodePage.ets b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/MultiDecodePage.ets new file mode 100644 index 0000000..1722b56 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/MultiDecodePage.ets @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import { encode } from "@ohos/msgpack"; +import Util from './Util'; + +@Entry +@Component +struct MultiDecodePage { + @State message: string = ''; + @State message2: string = ''; + encodedUint8: Uint8Array | undefined = undefined; + + aboutToAppear(): void { + this.message = this.getResourceString($r('app.string.Display_original_data')); + this.message2 = this.getResourceString($r('app.string.Data_display_after_decodeMulti_decoding')); + } + + getResourceString(res: Resource) { + return getContext().resourceManager.getStringSync(res.id); + } + + build() { + Row() { + Column() { + Button($r('app.string.Object_Display')).onClick(() => { + console.log('dodo click on!') + let bar: Bar = { + name: "bar", + } + this.message = JSON.stringify([ + "foo", + 10, + bar, + [1, 2, 3], + ]) + }) + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button($r("app.string.MultiDecoder")).onClick(() => { + let bar: Bar = { + name: "bar", + } + let items = [ + "foo", + 10, + bar, + [1, 2, 3], + ] + let encodedItems: Uint8Array[] = items.map((item): Uint8Array => encode(item)); + let encoded = new Uint8Array(encodedItems.reduce((p: number, c: Uint8Array) => p + c.byteLength, 0)); + let offset = 0; + for (let encodedItem of encodedItems) { + encoded.set(encodedItem, offset); + offset += encodedItem.byteLength; + } + let result: Array = []; + Util.decodeMultiSetResult(encoded, result) + let retStr1 = JSON.stringify(result); + this.message2 = retStr1; + }) + Text(this.message2) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} + +interface Bar { + name: string; +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Util.ts b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Util.ts new file mode 100644 index 0000000..0190876 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/ets/pages/Util.ts @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import { MsgTimestamp } from "../../../ohosTest/ets/test/test/msg/msg-timestamp"; +import { EXT_TIMESTAMP, encodeTimeSpecToTimestamp, decodeMulti } from "@ohos/msgpack"; +import ohBuffer from '@ohos.buffer'; + +namespace Util { + export let register = { + type: EXT_TIMESTAMP, + encode: (input) => { + if (input instanceof MsgTimestamp) { + return encodeTimeSpecToTimestamp({ + sec: input.getTime(), + nsec: input.getNano(), + }); + } else { + return null; + } + }, + decode: (data: Uint8Array) => { + return MsgTimestamp.parse(ohBuffer.from(data)); + }, + } + + export function decodeMultiSetResult(encoded: Uint8Array, result: Array): void { + for (let item of decodeMulti(encoded)) { + result.push(item); + } + } + + export function objReplacer(key, value) { + if (typeof value === 'bigint') { + return value.toString(); + } else if (typeof value === 'object') { + for (const k in value) { + if (typeof value[k] === 'bigint') { + value[k] = value[k].toString(); + } else if (typeof value[k] === 'object') { + value[k] = objReplacer(k, value[k]); + } + } + } + return value; + } +} + +export default Util; \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/module.json5 b/OpenHarmony/ohos_msgpack/entry/src/main/module.json5 new file mode 100644 index 0000000..e1e2749 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/module.json5 @@ -0,0 +1,43 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:entry_MainAbility", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "metadata": [ + { + "name": "ArkTSPartialUpdate", + "value": "true" + } + ], + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ts", + "description": "$string:entry_MainAbility", + "icon": "$media:icon", + "label": "$string:entry_MainAbility", + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:white", + "visible": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/resources/base/element/color.json b/OpenHarmony/ohos_msgpack/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000..390d279 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/resources/base/element/color.json @@ -0,0 +1,12 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + }, + { + "name": "red", + "value": "#FFFC0404" + } + ] +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/resources/base/element/string.json b/OpenHarmony/ohos_msgpack/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000..76a7f01 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/resources/base/element/string.json @@ -0,0 +1,88 @@ +{ + "string": [ + { + "name": "entry_MainAbility", + "value": "msgpack" + }, + { + "name": "description_mainability", + "value": "Empty Ability" + }, + { + "name": "Display_encoded_data", + "value": "Display of encoded data" + }, + { + "name": "Display_decoded_data", + "value": "Display of decoded data" + }, + { + "name": "Error_message", + "value": "Error message" + }, + { + "name": "Constructor_encoding", + "value": "Constructor encoding" + }, + { + "name": "Encoded_data", + "value": "Encoded data=" + }, + { + "name": "constructor_to_decode", + "value": "Constructor decoding" + }, + { + "name": "Decoded_data", + "value": "Decoded data=" + }, + { + "name": "undefined", + "value": "The decoded data is undefined. Please click on the encoding button first" + }, + { + "name": "Object_encoding", + "value": "Object encoding" + }, + { + "name": "decode", + "value": "Decode" + }, + { + "name": "log", + "value": "Click to view log encoding input and decoding output" + }, + { + "name": "Simple_encoding_and_decoding", + "value": "Simple encoding and decoding" + }, + { + "name": "Constructor_encoding_and_decoding", + "value": "Constructor encoding and decoding" + }, + { + "name": "Complex_encoding_decoding", + "value": "Complex encoding and decoding" + }, + { + "name": "Special_Character", + "value": "Special Character Extended Encoding and Decoding" + }, + { + "name": "Display_original_data", + "value": "Display original data" + }, + { + "name": "Data_display_after_decodeMulti_decoding", + "value": "Data display after decodeMulti decoding" + }, + { + "name": "Object_Display", + "value": "Object Display" + }, + { + "name": "MultiDecoder", + "value": "MultiDecoder" + } + ] +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/resources/base/media/icon.png b/OpenHarmony/ohos_msgpack/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000..ce307a8 Binary files /dev/null and b/OpenHarmony/ohos_msgpack/entry/src/main/resources/base/media/icon.png differ diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/resources/base/profile/main_pages.json b/OpenHarmony/ohos_msgpack/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000..bf7fa22 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,13 @@ +{ + "src": [ + "pages/Index", + "pages/EncodeDecodePage", + "pages/EncodeDecodeConstructorPage", + "pages/MultiDecodePage", + "pages/ExamPage", + "pages/Encoding64DemoFour", + "pages/Encoding64DemoOne", + "pages/Encoding64DemoTwo", + "pages/Encoding64DemoThree" + ] +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/main/resources/zh_CN/element/string.json b/OpenHarmony/ohos_msgpack/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000..c434d6a --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,88 @@ +{ + "string": [ + { + "name": "entry_MainAbility", + "value": "msgpack" + }, + { + "name": "description_mainability", + "value": "Empty Ability" + }, + { + "name": "Display_encoded_data", + "value": "编码后的数据展示" + }, + { + "name": "Display_decoded_data", + "value": "解码后的数据展示" + }, + { + "name": "Error_message", + "value": "错误提示" + }, + { + "name": "Constructor_encoding", + "value": "点击构造器编码" + }, + { + "name": "Encoded_data", + "value": "编码后的数据=" + }, + { + "name": "constructor_to_decode", + "value": "点击构造器解码" + }, + { + "name": "Decoded_data", + "value": "解码后的数据=" + }, + { + "name": "undefined", + "value": "解码数据为undefined, 请先点击编码" + }, + { + "name": "Object_encoding", + "value": "点击对象编码" + }, + { + "name": "decode", + "value": "点击解码" + }, + { + "name": "log", + "value": "点击查看log编码输入和解码输出" + }, + { + "name": "Simple_encoding_and_decoding", + "value": "简单编码解码" + }, + { + "name": "Constructor_encoding_and_decoding", + "value": "构造器编码解码" + }, + { + "name": "Complex_encoding_decoding", + "value": "复杂Multi编码解码" + }, + { + "name": "Special_Character", + "value": "特殊字符扩展编解码" + }, + { + "name": "Display_original_data", + "value": "展示原数据" + }, + { + "name": "Data_display_after_decodeMulti_decoding", + "value": "decodeMulti解码后的数据展示" + }, + { + "name": "Object_Display", + "value": "对象展示" + }, + { + "name": "MultiDecoder", + "value": "点击MultiDecode" + } + ] +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/List.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000..2f7ee14 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import CachedKeyDecoderTest from './test/CachedKeyDecoder.test' +import CodecBigintTest from './test/codec-bigint.test' +import CodecFloatTest from './test/codec-float.test' +import CodecIntTest from './test/codec-int.test' +import CodecTimestampTest from './test/codec-timestamp.test' +import decodeJsfuzzTest from './test/decode.jsfuzz' +import DecodeBlobTest from './test/decode-blob.test' +import DecodeMaxLengthTest from './test/decode-max-length.test' +import DecodeArrayStreamTest from './test/decodeArrayStream.test' +import DecodeAsyncTest from './test/decodeAsync.test' +import decodeMultiTest from './test/decodeMulti.test' +import decodeMultiStreamTest from './test/decodeMultiStream.test' +import denoTest from './test/deno_test' +import edgeCasesTest from './test/edge-cases.test' +import encodeTest from './test/encode.test' +import ExtensionCodecTest from './test/ExtensionCodec.test' +import readmeTest from './test/readme.test' +import msgpackTestSuiteTest from './test/msgpack-test-suite.test' +import msgpackTestSuiteTest2 from './test/msgpack-test-suite2.test' +import msgpackExtTest from './test/msgpack-ext.test' +import prototypePollutionTest from './test/prototype-pollution.test' +import reuseInstancesTest from './test/reuse-instances.test' +import Bigint64Test from './test/Bigint64.test' + +export default function testsuite() { + CachedKeyDecoderTest() + CodecBigintTest() + CodecFloatTest() + CodecIntTest() + CodecTimestampTest() + decodeJsfuzzTest() + DecodeBlobTest() + DecodeMaxLengthTest() + DecodeArrayStreamTest() + DecodeAsyncTest() + decodeMultiTest() + decodeMultiStreamTest() + denoTest() + edgeCasesTest() + encodeTest() + ExtensionCodecTest() + readmeTest() + msgpackTestSuiteTest() + msgpackTestSuiteTest2() + msgpackExtTest() + prototypePollutionTest() + reuseInstancesTest() + Bigint64Test() +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/Bigint64.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/Bigint64.test.ets new file mode 100644 index 0000000..8558d45 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/Bigint64.test.ets @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from './assert2hypium'; +import { encode, decode } from '@ohos/msgpack'; +import { describe, it, TestType } from '@ohos/hypium'; +import Util from 'ets/pages/Util'; + +export default function Bigint64Test() { + const BASE_COUNT: number = 2000; + + describe('Bigint64Test', () => { + + it('encodes_and_decodes_0n', TestType.PERFORMANCE, () => { + let startTime1 = new Date().getTime(); + for (let index = 0; index < BASE_COUNT; index++) { + const value = JSON.stringify(Number(BigInt(1))); + const encoded = encode(value, { + useBigInt64: true + }); + assert.deepStrictEqual(decode(encoded, { + useBigInt64: true + }), value) + } + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / BASE_COUNT; + console.log('encodes_and_decodes_0n' + averageTime1) + }); + + it('encodes_and_decodes_MAX_SAFE_INTEGER_add_1', TestType.PERFORMANCE, () => { + let startTime1 = new Date().getTime(); + for (let index = 0; index < BASE_COUNT; index++) { + const value = JSON.stringify(Number(BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1))); + const encoded = encode(value, { + useBigInt64: true + }); + assert.deepStrictEqual(decode(encoded, { + useBigInt64: true + }), value) + } + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / BASE_COUNT; + console.log('encodes_and_decodes_MAX_SAFE_INTEGER_add_1' + averageTime1) + }); + + it('encodes_and_decodes_MAX_SAFE_INTEGER_del_1', TestType.PERFORMANCE, () => { + let startTime1 = new Date().getTime(); + for (let index = 0; index < BASE_COUNT; index++) { + const value = JSON.stringify(Number(BigInt(Number.MAX_SAFE_INTEGER) - BigInt(1))); + const encoded = encode(value, { + useBigInt64: true + }); + assert.deepStrictEqual(decode(encoded, { + useBigInt64: true + }), value) + } + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / BASE_COUNT; + console.log('encodes_and_decodes_MAX_SAFE_INTEGER_del_1' + averageTime1) + }); + + it('encodes_and_decodes_values_with_numbers_and_bigint', TestType.PERFORMANCE, () => { + let startTime1 = new Date().getTime(); + const value: ESObject = { + ints: [0, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER], + nums: [Number.NaN, Math.PI, Math.E, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY], + bigints: [BigInt(0), BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1), BigInt(Number.MIN_SAFE_INTEGER) - BigInt(1)], + }; + let json = JSON.stringify(value, Util.objReplacer) + for (let index = 0; index < BASE_COUNT; index++) { + const encoded = encode(JSON.parse(json), { + useBigInt64: true + }); + assert.notDeepStrictEqual(decode(encoded, { + useBigInt64: true + }), value); + } + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / BASE_COUNT; + console.log('encodes_and_decodes_values_with_numbers_and_bigint' + averageTime1) + }); + }) +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/CachedKeyDecoder.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/CachedKeyDecoder.test.ets new file mode 100644 index 0000000..ac406cb --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/CachedKeyDecoder.test.ets @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import { CachedKeyDecoder, KeyDecoder } from "@ohos/msgpack" +import { utf8Count, utf8EncodeJs } from '@ohos/msgpack' + +export default function CachedKeyDecoderTest() { + describe('CachedKeyDecoderTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + it("decodes_a_string", 0, () => { + let startTime1 = new Date().getTime(); + const decoder = new CachedKeyDecoder(); + expect(tryDecode(decoder, "foo")).assertDeepEquals("foo") + expect(tryDecode(decoder, "foo")).assertDeepEquals("foo") + expect(tryDecode(decoder, "foo")).assertDeepEquals("foo") + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 3; + console.log('msgpack-javascript:decodes_a_string averageTime =' + averageTime1) + // console.dir(decoder, { depth: 100 }); + }); + + it("decodes_strings", 0, () => { + let startTime1 = new Date().getTime(); + const decoder = new CachedKeyDecoder(); + expect(tryDecode(decoder, "foo")).assertDeepEquals("foo") + expect(tryDecode(decoder, "bar")).assertDeepEquals("bar") + expect(tryDecode(decoder, "foo")).assertDeepEquals("foo") + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 3; + console.log('msgpack-javascript:decodes_strings averageTime =' + averageTime1) + // console.dir(decoder, { depth: 100 }); + }); + + it("decodes_strings_with_purging_records", 0, () => { + let startTime1 = new Date().getTime(); + const decoder = new CachedKeyDecoder(16, 4); + for (let i = 0; i < 100; i++) { + expect(tryDecode(decoder, "foo1")).assertDeepEquals("foo1") + expect(tryDecode(decoder, "foo2")).assertDeepEquals("foo2") + expect(tryDecode(decoder, "foo3")).assertDeepEquals("foo3") + expect(tryDecode(decoder, "foo4")).assertDeepEquals("foo4") + expect(tryDecode(decoder, "foo5")).assertDeepEquals("foo5") + } + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 500; + console.log('msgpack-javascript:decodes_strings_with_purging_records averageTime =' + averageTime1) + // console.dir(decoder, { depth: 100 }); + }); + + + it("decodes_str_with_len_1", 0, () => { + let startTime1 = new Date().getTime(); + const decoder = new CachedKeyDecoder(); + expect(tryDecode(decoder, "f")).assertDeepEquals("f") + expect(tryDecode(decoder, "a")).assertDeepEquals("a") + expect(tryDecode(decoder, "f")).assertDeepEquals("f") + expect(tryDecode(decoder, "a")).assertDeepEquals("a") + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 4; + console.log('msgpack-javascript:decodes_str_with_len_1 averageTime =' + averageTime1) + // console.dir(decoder, { depth: 100 }); + }); + + it("decodes_str_with_len_maxKeyLength", 0, () => { + let startTime1 = new Date().getTime(); + const decoder = new CachedKeyDecoder(1); + expect(tryDecode(decoder, "f")).assertDeepEquals("f") + expect(tryDecode(decoder, "a")).assertDeepEquals("a") + expect(tryDecode(decoder, "f")).assertDeepEquals("f") + expect(tryDecode(decoder, "a")).assertDeepEquals("a") + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 4; + console.log('msgpack-javascript:decodes_str_with_len_maxKeyLength averageTime =' + averageTime1) + + //console.dir(decoder, { depth: 100 }); + }); + }) +} + +function tryDecode(keyDecoder: KeyDecoder, str: string): string { + const byteLength = utf8Count(str); + const bytes = new Uint8Array(byteLength); + utf8EncodeJs(str, bytes, 0); + if (!keyDecoder.canBeCached(byteLength)) { + throw new Error("Unexpected precondition"); + } + return keyDecoder.decode(bytes, 0, byteLength); +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/ExtensionCodec.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/ExtensionCodec.test.ets new file mode 100644 index 0000000..c60d7f7 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/ExtensionCodec.test.ets @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import ExtensionCodec from "../test/stdlib/ExtensionCodecTest"; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + + +export default function ExtensionCodecTest() { + describe('ExtensionCodecTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + ExtensionCodec.extensionCodecTest(it, expect) + + }) +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/assert2hypium.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/assert2hypium.ets new file mode 100644 index 0000000..4c47d35 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/assert2hypium.ets @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import { expect } from '@ohos/hypium' + + +namespace assert { + export let strictEqual: Function = (src: Object, dst: Object, info?: string) => { + expect(src).assertEqual(dst) + if (info) { + console.log(info) + } + } + + export let deepStrictEqual: Function = (src: Object, dst: Object, info?: string) => { + expect(src).assertDeepEquals(dst) + if (info) { + console.log(info) + } + } + + export let notDeepStrictEqual: Function = (src: Object, dst: Object, info?: string) => { + expect(src).not().assertDeepEquals(dst) + if (info) { + console.log(info) + } + } + + export let context: Function = (str: string, callback: Function) => { + callback(); + } + + export let throws: Function = (srcCallback: Function, dstInfo: Object) => { + try { + srcCallback(); + // 如果不报错就是用例失败 + expect(false).assertTrue() + } catch (err) { + // 报错 + expect(true).assertTrue() + console.log("err.msg=" + err.message) + console.log("dstInfo=" + dstInfo) + } + } +} + +export default assert; \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/codec-bigint.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/codec-bigint.test.ets new file mode 100644 index 0000000..e96240d --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/codec-bigint.test.ets @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import assert from "./assert2hypium"; +import CodecBigint from "../test/stdlib/CodecBigint"; + +// 测试用例通过 测试框架不支持 expect cannot serialize a BigInt +export default function CodecBigintTest() { + describe('CodecBigintTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + + beforeEach(() => { + // if (typeof BigInt === "undefined") { + // this.skip(); + // } + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it("encodes_and_decodes_0n", 0, () => { + let value = BigInt(0); + let decoded: Object = CodecBigint.encodes_and_decodes_0n() + // 测试框架无法覆盖BitInt(0)的情况 + // assert.deepStrictEqual(decoded, value); + assert.strictEqual(decoded, value); + }); + + it("encodes_and_decodes_MAX_SAFE_INTEGER_1", 0, () => { + const value = BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1); + let decoded: Object = CodecBigint.encodes_and_decodes_MAX_SAFE_INTEGER_1() + // assert.deepStrictEqual(decoded, value); + assert.strictEqual(decoded, value); + }); + + it("encodes_and_decodes_MIN_SAFE_INTEGER_minus1", 0, () => { + const value = BigInt(Number.MIN_SAFE_INTEGER) - BigInt(1); + let decoded: Object = CodecBigint.encodes_and_decodes_MIN_SAFE_INTEGER_minus1() + // assert.deepStrictEqual(decoded, value); + assert.strictEqual(decoded, value); + }); + + }) +} + + + + + + + + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/codec-float.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/codec-float.test.ets new file mode 100644 index 0000000..d8187b1 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/codec-float.test.ets @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import { decode } from "@ohos/msgpack"; +import ieee754 from "./ieee754/ieee754"; +import hilog from '@ohos.hilog'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import { floatSPECS } from './stdlib/StdlibData'; + +const FLOAT32_TYPE = 0xca; +const FLOAT64_TYPE = 0xcb; + +export default function CodecFloatTest() { + describe('CodecFloatTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + let float32 = (str: string,callback: Function) => { + callback(); + } + float32('float_32',() => { + for (const pair of Object.entries(floatSPECS)) { + let name = pair[0] + let value = pair[1] + it(`decodes_${name}_${value}_`,0, () => { + + const buf = new Uint8Array(4); + ieee754.write(buf, value, 0, false, 23, 4); + const expected: number = ieee754.read(buf, 0, false, 23, 4); + + let startTime1 = new Date().getTime(); + assert.strictEqual(decode([FLOAT32_TYPE, ...buf]), expected, "matched sign"); + assert.notDeepStrictEqual(decode([FLOAT32_TYPE, ...buf]), -(expected), "unmatched sign"); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:decodes_${name}_${value}_ averageTime = ${averageTime1}`) + + }); + } + + it(`decodes_NaN`,0, () => { + const buf = new Uint8Array(4); + ieee754.write(buf, Number.NaN, 0, false, 23, 4); + const expected: number = ieee754.read(buf, 0, false, 23, 4); + + let startTime1 = new Date().getTime(); + assert.deepStrictEqual(decode([FLOAT32_TYPE, ...buf]), expected, "matched sign"); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_NaN averageTime = ${averageTime1}`) + }); + }) + + + let float64 = (str: string,callback: Function) => { + callback(); + } + float64('float_64', () => { + for (const pair of Object.entries(floatSPECS)) { + let name = pair[0] + let value = pair[1] + it(`decodes_${name}_${value}_`,0, () => { + const buf = new Uint8Array(8); + ieee754.write(buf, value, 0, false, 52, 8); + const expected: number = ieee754.read(buf, 0, false, 52, 8); + let startTime1 = new Date().getTime(); + assert.strictEqual(decode([FLOAT64_TYPE, ...buf]), expected, "matched sign"); + assert.notDeepStrictEqual(decode([FLOAT64_TYPE, ...buf]), -(expected), "unmatched sign"); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:decodes_${name}_${value}_ averageTime = ${averageTime1}`) + }); + } + + it(`decodes_NaN`,0, () => { + const buf = new Uint8Array(8); + ieee754.write(buf, Number.NaN, 0, false, 52, 8); + const expected: number = ieee754.read(buf, 0, false, 52, 8); + let startTime1 = new Date().getTime(); + assert.deepStrictEqual(decode([FLOAT64_TYPE, ...buf]), expected, "matched sign"); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_NaN averageTime = ${averageTime1}`) + }); + }) + + + }) +} + + + + + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/codec-int.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/codec-int.test.ets new file mode 100644 index 0000000..e92acd8 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/codec-int.test.ets @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import { setInt64, getInt64, getUint64, setUint64 } from "@ohos/msgpack"; +import hilog from '@ohos.hilog'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import { INT64SPECS } from './stdlib/StdlibData'; + + +export default function CodecIntTest() { + describe('CodecIntTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + + assert.context("int_64", () => { + for (const name of Object.keys(INT64SPECS)) { + const value = INT64SPECS[name]!; + + it(`sets_and_gets_${value}_${value < 0 ? "-" : ""}0x${Math.abs(value).toString(16)}_`,0, () => { + let startTime1 = new Date().getTime(); + const b = new Uint8Array(8); + const view = new DataView(b.buffer); + setInt64(view, 0, value); + assert.deepStrictEqual(getInt64(view, 0), value); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:sets_and_gets_${value}_${value < 0 ? "-" : ""}0x${Math.abs(value).toString(16)}_ averageTime = ${averageTime1}`) + }); + } + }); + + assert.context("uint_64", () => { + it(`sets_and_gets_0`,0, () => { + let startTime1 = new Date().getTime(); + const b = new Uint8Array(8); + const view = new DataView(b.buffer); + setUint64(view, 0, 0); + assert.deepStrictEqual(getUint64(view, 0), 0); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:sets_and_gets_0 averageTime = ${averageTime1}`) + }); + + it(`sets_and_gets_MAX_SAFE_INTEGER`,0, () => { + let startTime1 = new Date().getTime(); + const b = new Uint8Array(8); + const view = new DataView(b.buffer); + setUint64(view, 0, Number.MAX_SAFE_INTEGER); + assert.deepStrictEqual(getUint64(view, 0), Number.MAX_SAFE_INTEGER); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:sets_and_gets_MAX_SAFE_INTEGER averageTime = ${averageTime1}`) + }); + }); + + }) +} + + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/codec-timestamp.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/codec-timestamp.test.ets new file mode 100644 index 0000000..84a52f7 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/codec-timestamp.test.ets @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import buffer from '@ohos.buffer'; +import { + encode, + decode, + encodeDateToTimeSpec, + decodeTimestampExtension, + decodeTimestampToTimeSpec, + encodeTimestampExtension, +} from "@ohos/msgpack"; + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import { timestampSPECS } from './stdlib/StdlibData'; +import { TimeSpec } from '@ohos/msgpack'; + + +export default function CodecTimestampTest() { + describe('CodecTimestampTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + assert.context("encode_decode", () => { + for (const name of Object.keys(timestampSPECS)) { + const value = timestampSPECS[name]!; + + it(`encodes_and_decodes_${name}_${value.toISOString()}_`, 0, () => { + let startTime1 = new Date().getTime(); + const encoded = encode(value); + assert.deepStrictEqual(decode(encoded), value); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:encodes_and_decodes_${name}_${value.toISOString()}_ averageTime = ${averageTime1}`) + }); + } + }); + + assert.context("encodeDateToTimeSpec", () => { + it("normalizes_new_Date_fu1_to_sec_fu1_nsec_999000000", 0 , () => { + let startTime1 = new Date().getTime(); + let x:TimeSpec = { sec: -1, nsec: 999000000 } + assert.deepStrictEqual(encodeDateToTimeSpec(new Date(-1)), x); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:normalizes_new_Date_fu1_to_sec_fu1_nsec_999000000 averageTime = ${averageTime1}`) + }); + }); + + assert.context("encodeDateToTimeSpec", () => { + it("decodes_timestamp_ext_binary_to_TimeSpec", 0 , () => { + let startTime1 = new Date().getTime(); + const encoded = encodeTimestampExtension(new Date(42000))!; + let x:TimeSpec = { sec: 42, nsec: 0 } + assert.deepStrictEqual(decodeTimestampToTimeSpec(encoded), x); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:decodes_timestamp_ext_binary_to_TimeSpec averageTime = ${averageTime1}`) + }); + }); + + + assert.context("decodeTimestampExtension_for_broken_data", () => { + it("throws_errors", 0,() => { + assert.throws(() => { + let startTime1 = new Date().getTime(); + decodeTimestampExtension(Uint8Array.from([0])); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodeTimestampExtension_for_broken_data averageTime = ${averageTime1}`) + }, new RegExp("/unrecognized data size for timestamp/i")); + }); + }); + + + + }) +} + + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decode-blob.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decode-blob.test.ets new file mode 100644 index 0000000..6bbb627 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decode-blob.test.ets @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import buffer from '@ohos.buffer'; +import assert from "./assert2hypium"; +import { encode, decode, decodeAsync } from "@ohos/msgpack"; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import Util from "../test/stdlib/Util"; +// const MyBlob = buffer.Blob; + +export default function DecodeBlobTest() { + describe('DecodeBlobTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + it("decodes_it_with_decode_", 0, async () => { + const encoded = encode("Hello!") + + const blob = new buffer.Blob([encoded]); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + + blob.arrayBuffer().then((buffer) => { + let startTime1 = new Date().getTime(); + let decoded = Util.decodeObject(buffer); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_it_with_decode_ averageTime = ${averageTime1}`) + assert.deepStrictEqual(decoded, "Hello!"); + }); + + }); + + it("decodes_it_with_decodeAsync_1", 0, async () => { + let startTime1 = new Date().getTime(); + + const blob = new buffer.Blob([encode("Hello!")]); + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_it_with_decodeAsync_1 averageTime = ${averageTime1}`) + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + // use any because the type of Blob#stream() in @types/node does not make sense here. + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + blob.text().then(text => { + assert.deepStrictEqual(text, "Hello!"); + }) + + }); + + it("decodes_it_with_decodeAsync_2", 0, async () => { + let startTime1 = new Date().getTime(); + + const blob = new buffer.Blob([encode("Hello!")]); + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_it_with_decodeAsync_2 averageTime = ${averageTime1}`) + + blob.arrayBuffer().then(buffer => { + decodeAsync(buffer as ESObject).then((result: Object) => { + assert.deepStrictEqual(result, "Hello!"); + }) + }) + + + }); + // OH的Blob暂时没有stream能力 + // it("decodes it with `decodeAsync()`", async () => { + // const blob = new MyBlob([encode("Hello!")]); + // // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + // if (!blob.stream) { + // this.skip(); + // } + // + // // use any because the type of Blob#stream() in @types/node does not make sense here. + // // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + // assert.deepStrictEqual(await decodeAsync(blob.stream() as any), "Hello!"); + // }); + }) +} + + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decode-max-length.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decode-max-length.test.ets new file mode 100644 index 0000000..1b7d7fa --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decode-max-length.test.ets @@ -0,0 +1,175 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import { encode, decode, DecoderOptions } from "@ohos/msgpack"; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it } from '@ohos/hypium' +import { decodeOption } from './stdlib/StdlibData'; + + +export default function DecodeMaxLengthTest() { + describe('DecodeMaxLengthTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + assert.context("maxStrLength", () => { + + let startTime1 = new Date().getTime(); + + const input = encode("foo"); + const options: DecoderOptions = decodeOption; + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:maxStrLength averageTime = ${averageTime1}`) + + it("throws_errors_synchronous_", 0, () => { + assert.throws(() => { + decode(input, options); + }, new RegExp("/max length exceeded/i")); + }); + + + }); + + assert.context("maxBinLength", () => { + let startTime1 = new Date().getTime(); + + const input = encode(Uint8Array.from([1, 2, 3])); + const options: MaxBinLength = { + maxBinLength: 1 + }; + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:maxBinLength averageTime = ${averageTime1}`) + + it("throws_errors_synchronous", 0, () => { + assert.throws(() => { + decode(input, options); + }, new RegExp('/max length exceeded/i')); + }); + + + }); + + assert.context("maxArrayLength", () => { + let startTime1 = new Date().getTime(); + + const input = encode([1, 2, 3]); + const options: MaxArrayLength = { + maxArrayLength: 1 + }; + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:maxArrayLength averageTime = ${averageTime1}`) + + it("throws_errors_synchronous_", 0, () => { + assert.throws(() => { + decode(input, options); + }, new RegExp('/max length exceeded/i')); + }); + + + }); + + assert.context("maxMapLength", () => { + let startTime1 = new Date().getTime(); + let inputValue: InputValue = { + foo: 1, bar: 1, baz: 3 + } + const input = encode(inputValue); + const options: MaxMapLength = { + maxMapLength: 1 + }; + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:maxMapLength averageTime = ${averageTime1}`) + + it("throws_errors_synchronous", 0, () => { + assert.throws(() => { + decode(input, options); + }, new RegExp('/max length exceeded/i')); + }); + + + }); + + assert.context("maxExtType", () => { + let startTime1 = new Date().getTime(); + + const input = encode(new Date()); + // timextamp ext requires at least 4 bytes. + const options: MaxExtLength = { + maxExtLength: 1 + }; + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:maxExtType averageTime = ${averageTime1}`) + + it("throws_errors_synchronous", 0, () => { + assert.throws(() => { + decode(input, options); + }, new RegExp(' /max length exceeded/i')); + }); + + + }); + + }) +} + +interface MaxBinLength { + maxBinLength: number; +} + +interface MaxArrayLength { + maxArrayLength: number; +} + +interface MaxMapLength { + maxMapLength: number; +} + +interface MaxExtLength { + maxExtLength: number; +} + +interface InputValue { + foo: number, + bar: number, + baz: number +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decode.jsfuzz.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decode.jsfuzz.ets new file mode 100644 index 0000000..2a253a4 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decode.jsfuzz.ets @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import hilog from '@ohos.hilog'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + +import assert from "./assert2hypium" +import { Decoder, encode, DecodeError } from "@ohos/msgpack"; +import { decodeobject } from './stdlib/StdlibData'; + +export default function decodeJsfuzzTest() { + describe('decodeJsfuzzTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + /** + * @param {Buffer} bytes + * @returns {void} + */ + // let fuzz = (bytes) => { + // const decoder = new Decoder(); + // try { + // decoder.decode(bytes); + // } catch (e) { + // if (e instanceof DecodeError) { + // // ok + // } else if (e instanceof RangeError) { + // // ok + // } else { + // throw e; + // } + // } + // } + it("make_sure_the_decoder_instance_is_not_broken", 0, () => { + // make sure the decoder instance is not broken + let startTime1 = new Date().getTime(); + + const decoder = new Decoder(); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:make_sure_the_decoder_instance_is_not_broken averageTime = ${averageTime1}`) + assert.deepStrictEqual(decoder.decode(encode(decodeobject)), decodeobject); + }) + + + + }) +} + + + + + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decodeArrayStream.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decodeArrayStream.test.ets new file mode 100644 index 0000000..2f864b4 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decodeArrayStream.test.ets @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import Util from "../test/stdlib/Util"; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + + +export default function DecodeArrayStreamTest() { + describe('DecodeArrayStreamTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + const generateSampleObject = () => { + let value: SampleObject = { + id: Math.random(), + name: "test", + }; + return value; + }; + + it("decodes_numbers_array_array8", 0, async () => { + const object = [1, 2, 3, 4, 5]; + const result: Array = []; + let startTime1 = new Date().getTime(); + await Util.decodeArrayStreamsSetResult(await Util.createStreams(object), result) + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_numbers_array_array8 averageTime = ${averageTime1}`) + assert.deepStrictEqual(object, result); + }); + + it("decodes_numbers_of_array_array16", 0, async () => { + const result: Array = []; + let startTime1 = new Date().getTime(); + await Util.decodeArrayStreamsSetResult(await Util.array16CreateStream(), result) + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_numbers_of_array_array16 averageTime = ${averageTime1}`) + + assert.deepStrictEqual(result, [1, 2, 3]); + }); + + it("decodes_numbers_of_array_array32", 0, async () => { + const result: Array = []; + let startTime1 = new Date().getTime(); + await Util.decodeArrayStreamsSetResult(await Util.array32CreateStream(), result) + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_numbers_of_array_array32 averageTime = ${averageTime1}`) + assert.deepStrictEqual(result, [1, 2, 3]); + }); + + it("decodes_objects_array", 0, async () => { + const objectsArrays: Array = []; + for (let i = 0; i < 10; i++) { + objectsArrays.push(generateSampleObject()); + } + const result: Array = []; + let startTime1 = new Date().getTime(); + await Util.decodeArrayStreamsSetResult(await Util.createStreams(objectsArrays), result); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_objects_array averageTime = ${averageTime1}`) + + assert.deepStrictEqual(objectsArrays, result); + }); + + it("fails_for_non_array_input", 0, async () => { + const object = "demo"; + + const result: Array = []; + let startTime1 = new Date().getTime(); + try { + await Util.decodeArrayStreamsSetResult(await Util.createStreams(object), result); + } catch (err) { + expect(err.message).assertContain('Unrecognized array type byte') + } finally { + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:fails_for_non_array_input averageTime = ${averageTime1}`) + } + }); + + + }) +} + + +interface SampleObject { + id: number, + name: string, +} + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decodeAsync.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decodeAsync.test.ets new file mode 100644 index 0000000..7638132 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decodeAsync.test.ets @@ -0,0 +1,142 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import { encode, decodeAsync } from "@ohos/msgpack"; +import Util from "../test/stdlib/Util"; +import { decodeAsyncObject } from "../test/stdlib/StdlibData"; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + +export default function DecodeAsyncTest() { + describe('DecodeAsyncTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + it("decodes_nil", 0, async () => { + let startTime1 = new Date().getTime(); + const object = await Util.decodeAsyncObject(await Util.nil1CreateStream()); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_nil averageTime = ${averageTime1}`) + + assert.deepStrictEqual(object, null); + }); + + it("decodes_fixarray_nil", 0, async () => { + let startTime1 = new Date().getTime(); + const object = await Util.decodeAsyncObject(await Util.nil2CreateStream()); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_fixarray_nil averageTime = ${averageTime1}`) + + assert.deepStrictEqual(object, [null]); + }); + + it("decodes_fixmap_foo_bar_", 0, async () => { + let startTime1 = new Date().getTime(); + const object = await Util.decodeAsyncObject(await Util.fooBarCreateStream()); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_fixmap_foo_bar_ averageTime = ${averageTime1}`) + let bar: Bar = { + foo: "bar", + } + assert.deepStrictEqual(object, bar); + }); + + it("decodes_multi_byte_integer_byte_by_byte", 0, async () => { + let startTime1 = new Date().getTime(); + const object = await Util.decodeAsyncObject(await Util.byteByByte3CreateStream()); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_multi_byte_integer_byte_by_byte averageTime = ${averageTime1}`) + assert.deepStrictEqual(object, 0x1234); + }); + + it("decodes_fixstr_byte_by_byte", 0, async () => { + let startTime1 = new Date().getTime(); + const object = await Util.decodeAsyncObject(await Util.byteByByte2CreateStream()); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_fixstr_byte_by_byte averageTime = ${averageTime1}`) + assert.deepStrictEqual(object, "foo"); + }); + + it("decodes_binary_byte_by_byte", 0, async () => { + let startTime1 = new Date().getTime(); + const object = await Util.decodeAsyncObject(await Util.byteByByteCreateStream()); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_binary_byte_by_byte averageTime = ${averageTime1}`) + assert.deepStrictEqual(object, Uint8Array.from([0x66, 0x6f, 0x6f])); + }); + + it("decodes_binary_with_noisy_buffer", 0, async () => { + let startTime1 = new Date().getTime(); + const object = await Util.decodeAsyncObject(await Util.noisyBufferCreateStream()); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_binary_with_noisy_buffer averageTime = ${averageTime1}`) + assert.deepStrictEqual(object, new Uint8Array(0)); + }); + + it("decodes_mixed_object_byte_by_byte", 0, async () => { + let stream: Object =await Util.createStreams(decodeAsyncObject); + let startTime1 = new Date().getTime(); + let result = await Util.decodeAsyncObject(stream); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_mixed_object_byte_by_byte averageTime = ${averageTime1}`) + assert.deepStrictEqual(result, decodeAsyncObject); + }); + it("decodes_BufferSource", 0, async () => { + // https://developer.mozilla.org/en-US/docs/Web/API/BufferSource + let startTime1 = new Date().getTime(); + // createStream() returns AsyncGenerator | BufferSource, ...> + const object: Object = await Util.decodeAsyncObject(await Util.bufferSourceCreateStream()); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_BufferSource averageTime = ${averageTime1}`) + let bar: Bar = { + foo: "bar", + } + assert.deepStrictEqual(object, bar); + }); + + }) +} + +interface Bar { + foo: string +} + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decodeMulti.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decodeMulti.test.ets new file mode 100644 index 0000000..cc17bfa --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decodeMulti.test.ets @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import { encode, decodeMulti } from "@ohos/msgpack"; +import Util from "../test/stdlib/Util"; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + +export default function decodeMultiTest() { + describe('decodeMultiTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it("decodes_multiple_objects_in_a_single_binary", 0, () => { + let bar: Bar = { + name: "bar", + } + const items = [ + "foo", + 10, + bar, + [1, 2, 3], + ]; + + const encodedItems = items.map((item) => encode(item)); + const encoded = new Uint8Array(encodedItems.reduce((p, c) => p + c.byteLength, 0)); + let offset = 0; + for (const encodedItem of encodedItems) { + encoded.set(encodedItem, offset); + offset += encodedItem.byteLength; + } + + const result: Array = []; + + let startTime1 = new Date().getTime(); + Util.decodeMultiSetResult(encoded, result) + + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_multiple_objects_in_a_single_binary averageTime = ${averageTime1}`) + + assert.deepStrictEqual(result, items); + }); + + }) +} + +interface Bar { + name: string, +} + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decodeMultiStream.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decodeMultiStream.test.ets new file mode 100644 index 0000000..95c3868 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/decodeMultiStream.test.ets @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import { encode } from "@ohos/msgpack"; +import Util from "../test/stdlib/Util"; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + +export default function decodeMultiStreamTest() { + describe('decodeMultiStreamTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it("decodes_stream", 0, async () => { + let bar: Bar = { + name: "bar", + } + const items = [ + "foo", + 10, + bar, + [1, 2, 3], + ]; + const result: Array = []; + let startTime1 = new Date().getTime(); + await Util.decodeMultiStreamsSetResult(await Util.decodesCreateStream(items), result) + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_stream averageTime = ${averageTime1}`) + assert.deepStrictEqual(result, items); + }); + + it("decodes_multiple_objects_in_a_single_binary_stream", 0, async () => { + let bar: Bar = { + name: "bar", + } + const items = [ + "foo", + 10, + bar, + [1, 2, 3], + ]; + const encodedItems = items.map((item) => encode(item)); + const encoded = new Uint8Array(encodedItems.reduce((p, c) => p + c.byteLength, 0)); + let offset = 0; + for (const encodedItem of encodedItems) { + encoded.set(encodedItem, offset); + offset += encodedItem.byteLength; + } + const result: Array = []; + let startTime1 = new Date().getTime(); + await Util.decodeMultiStreamsSetResult(await Util.Uint8ArrayCreateStreams(encoded), result) + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_multiple_objects_in_a_single_binary_stream averageTime = ${averageTime1}`) + assert.deepStrictEqual(result, items); + }); + + }) +} + +interface Bar { + name: string, +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/deno_test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/deno_test.ets new file mode 100644 index 0000000..fb40206 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/deno_test.ets @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import { encode, decode } from "@ohos/msgpack"; +import Util from "../test/stdlib/Util"; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + +export default function denoTest() { + describe('denoTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it("encode_decode", 0, () => { + let startTime1 = new Date().getTime(); + + const encoded = encode("Hello, world!"); + const decoded = Util.decodeObject(encoded); + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:encode_decode averageTime = ${averageTime1}`) + + assert.deepStrictEqual(decoded, "Hello, world!"); + }) + + }) +} + + + + + + + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/edge-cases.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/edge-cases.test.ets new file mode 100644 index 0000000..c5e7034 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/edge-cases.test.ets @@ -0,0 +1,236 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +// kind of hand-written fuzzing data +// any errors should not break Encoder/Decoder instance states + +import { encode, decodeAsync, decode, Encoder, Decoder, decodeMulti, decodeMultiStream } from "@ohos/msgpack"; +import { DataViewIndexOutOfBoundsError } from "@ohos/msgpack"; +import Util from "../test/stdlib/Util"; + +import assert from "./assert2hypium"; + +import hilog from '@ohos.hilog'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + +export default function edgeCasesTest() { + describe('edgeCasesTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + assert.context("try to encode cyclic refs", () => { + it("throws_errors_on_arrays", 0, () => { + const encoder = new Encoder(); + const cyclicRefs: Array = []; + cyclicRefs.push(cyclicRefs); + let regex: RegExp = new RegExp('too deep', 'i') + assert.throws(() => { + encoder.encode(cyclicRefs); + }, regex); + testEncoder(encoder); + }); + + it("throws_errors_on_objects", 0, () => { + const encoder = new Encoder(); + const cyclicRefs: Record = {}; + cyclicRefs["foo"] = cyclicRefs; + let regex: RegExp = new RegExp('too deep', 'i') + assert.throws(() => { + encoder.encode(cyclicRefs); + }, regex); + testEncoder(encoder); + }); + }); + + assert.context("try_to_encode_unrecognized_objects", () => { + it("throws_errors", 0, () => { + const encoder = new Encoder(); + let regex: RegExp = new RegExp('unrecognized object', 'i') + assert.throws(() => { + encode(() => { + }); + }, regex); + testEncoder(encoder); + }); + }); + + assert.context("try_to_decode_a_map_with_non_string_keys_asynchronous", () => { + it("throws_errors", 0, async () => { + const decoder = new Decoder(); + try { + await decoder.decodeAsync(await Util.throwsErrorsCreateStream()); + } catch (err) { + } + // await assert.rejects(async () => { + // await decoder.decodeAsync(createStream()); + // }, /The type of key must be string/i); + testDecoder(decoder); + }); + }); + + assert.context("try to decode invalid MessagePack binary", () => { + it("throws_errors", 0, () => { + const decoder = new Decoder(); + const TYPE_NEVER_USED = 0xc1; + let regex: RegExp = new RegExp('unrecognized type byte', 'i') + assert.throws(() => { + decoder.decode([TYPE_NEVER_USED]); + }, regex); + testDecoder(decoder); + }); + }); + + assert.context("try to decode insufficient data", () => { + it("throws_errors_synchronous1", 0, () => { + const decoder = new Decoder(); + assert.throws(() => { + decoder.decode([ + 0x92, // fixarray size=2 + 0xc0,// nil + ]); + // [IE11] A raw error thrown by DataView + }, DataViewIndexOutOfBoundsError); + testDecoder(decoder); + }); + + it("throws_errors_asynchronous1", 0, async () => { + const decoder = new Decoder(); + try { + await decoder.decodeAsync(await Util.asynchronous1CreateStream()); + } catch (err) { + + } + + // await assert.rejects(async () => { + // await decoder.decodeAsync(createStream()); + // }, RangeError); + testDecoder(decoder); + }); + }); + + assert.context("try to decode data with extra bytes", () => { + it("throws_errors_synchronous2", 0, () => { + const decoder = new Decoder(); + assert.throws(() => { + decoder.decode([ + 0x90, // fixarray size=0 + ...encode(null), + ]); + }, RangeError); + testDecoder(decoder); + }); + + it("throws_errors_asynchronous2", 0, async () => { + const decoder = new Decoder(); + try { + await decoder.decodeAsync(await Util.asynchronous2CreateStream()); + } catch (err) { + + } + // await assert.rejects(async () => { + // await decoder.decodeAsync(createStream()); + // }, RangeError); + testDecoder(decoder); + }); + + it("throws_errors_asynchronous3", 0, async () => { + const decoder = new Decoder(); + try { + await decoder.decodeAsync(await Util.asynchronous3CreateStream()); + } catch (err) { + } + // await assert.rejects(async () => { + // await decoder.decodeAsync(createStream()); + // }, RangeError); + testDecoder(decoder); + }); + }); + + assert.context("try to decode an empty input", () => { + it("throws_RangeError_synchronous", 0, () => { + assert.throws(() => { + decode([]); + }, RangeError); + }); + + it("decodes_an_empty_array_with_decodeMulti", 0, () => { + assert.deepStrictEqual(Util.expandDecodeMulti(), []); + }); + + it("throws_RangeError_asynchronous", 0, async () => { + try { + await decodeAsync(await Util.decodeMultiCreateStream()); + } catch (err) { + expect(err.message).assertContain("Insufficient") + } + // assert.rejects(async () => { + // await decodeAsync(createStream()); + // }, RangeError); + }); + + it("decodes_an_empty_array_with_decodeMultiStream", 0, async () => { + const results: Array = []; + let startTime1 = new Date().getTime(); + await Util.decodeMultiStreamsSetResult(await Util.decodeMultiCreateStream(), results) + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:decodes_an_empty_array_with_decodeMultiStream averageTime = ${averageTime1}`) + assert.deepStrictEqual(results, []); + }); + }); + }) +} + +interface FooBarBaz { + foo: number, + bar: number, + baz: string[], +} + +let testEncoder: Function = (encoder: Encoder): void => { + const object: FooBarBaz = { + foo: 1, + bar: 2, + baz: ["one", "two", "three"], + }; + assert.deepStrictEqual(decode(encoder.encode(object)), object); +} + +let testDecoder: Function = (decoder: Decoder): void => { + const object: FooBarBaz = { + foo: 1, + bar: 2, + baz: ["one", "two", "three"], + }; + assert.deepStrictEqual(decoder.decode(encode(object)), object); +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/encode.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/encode.test.ets new file mode 100644 index 0000000..4781632 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/encode.test.ets @@ -0,0 +1,229 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import { encode, decode } from "@ohos/msgpack"; +import hilog from '@ohos.hilog'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + +export default function encodeTest() { + describe('encodeTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + assert.context("encode_sortKeys", () => { + it("canonicalizes_encoded_binaries", 0, () => { + + let startTime1 = new Date().getTime(); + let ba1: BA = { + a: 1, b: 2 + } + let ba2: BA = { + b: 2, a: 1 + } + assert.deepStrictEqual(encode(ba1, { + sortKeys: true + }), encode(ba2, { + sortKeys: true + })); + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:canonicalizes_encoded_binaries averageTime = ${averageTime1}`) + }); + }); + + + assert.context("encode_forceFloat32", () => { + it("encodes_numbers_in_float64_wihout_forceFloat32", 0, () => { + let startTime1 = new Date().getTime(); + assert.deepStrictEqual(encode(3.14), Uint8Array.from([0xcb, 0x40, 0x9, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f])); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:encodes_numbers_in_float64_wihout_forceFloat32 averageTime = ${averageTime1}`) + }); + + it("encodes_numbers_in_float32_when_forceFloat32_true", 0, () => { + let startTime1 = new Date().getTime(); + assert.deepStrictEqual(encode(3.14, { + forceFloat32: true + }), Uint8Array.from([0xca, 0x40, 0x48, 0xf5, 0xc3])); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:encodes_numbers_in_float32_when_forceFloat32_true averageTime = ${averageTime1}`) + }); + + it("encodes_numbers_in_float64_with_forceFloat32_false", 0, () => { + let startTime1 = new Date().getTime(); + assert.deepStrictEqual( + encode(3.14, { + forceFloat32: false + }), + Uint8Array.from([0xcb, 0x40, 0x9, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f]), + ); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:encodes_numbers_in_float64_with_forceFloat32_false averageTime = ${averageTime1}`) + }); + }); + + assert.context("encode_forceFloat", () => { + it("encodes_integers_as_integers_without_forceIntegerToFloat", 0, () => { + let startTime1 = new Date().getTime(); + assert.deepStrictEqual(encode(3), Uint8Array.from([0x3])); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:encodes_integers_as_integers_without_forceIntegerToFloat averageTime = ${averageTime1}`) + }); + + it("encodes_integers_as_floating_point_when_forceIntegerToFloat_true", 0, () => { + let startTime1 = new Date().getTime(); + assert.deepStrictEqual( + encode(3, { + forceIntegerToFloat: true + }), + Uint8Array.from([0xcb, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), + ); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:encodes_integers_as_floating_point_when_forceIntegerToFloat_true averageTime = ${averageTime1}`) + }); + + it("encodes_integers_as_float32_when_forceIntegerToFloat_true_and_forceFloat32_true", 0, () => { + let startTime1 = new Date().getTime(); + assert.deepStrictEqual( + encode(3, { + forceIntegerToFloat: true, forceFloat32: true + }), + Uint8Array.from([0xca, 0x40, 0x40, 0x00, 0x00]), + ); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:encodes_integers_as_float32_when_forceIntegerToFloat_true_and_forceFloat32_true averageTime = ${averageTime1}`) + }); + + it("encodes_integers_as_integers_when_forceIntegerToFloat_false", 0, () => { + let startTime1 = new Date().getTime(); + assert.deepStrictEqual(encode(3, { + forceIntegerToFloat: false + }), Uint8Array.from([0x3])); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:encodes_integers_as_integers_when_forceIntegerToFloat_false averageTime = ${averageTime1}`) + }); + }); + + assert.context("encode_ignoreUndefined", () => { + it("encodes_foo_undefined_as_is_by_default", 0, () => { + let startTime1 = new Date().getTime(); + let fooBar1: FooBar = { + foo: undefined, bar: 42 + } + let fooBar2: FooBar = { + foo: null, + bar: 42, + } + assert.deepStrictEqual(decode(encode(fooBar1)), fooBar2); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:encodes_foo_undefined_as_is_by_default averageTime = ${averageTime1}`) + }); + + it("encodes_foo_undefined_as_is_with_ignoreUndefined_false", 0, () => { + let startTime1 = new Date().getTime(); + let fooBar1: FooBar = { + foo: undefined, bar: 42 + } + let ignoreUndefined: IgnoreUndefined = { + ignoreUndefined: false + } + let fooBar2: FooBar = { + foo: null, + bar: 42, + } + assert.deepStrictEqual(decode(encode(fooBar1, ignoreUndefined)), fooBar2); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:encodes_foo_undefined_as_is_with_ignoreUndefined_false averageTime = ${averageTime1}`) + }); + + it("encodes_foo_undefined_to_with_ignoreUndefined_true", 0, () => { + let startTime1 = new Date().getTime(); + let bar: Bar = { + bar: 42 + } + let ignoreUndefined: IgnoreUndefined = { + ignoreUndefined: true + } + let fooBar: FooBar = { + foo: undefined, bar: 42 + } + assert.deepStrictEqual(decode(encode(fooBar, ignoreUndefined)), bar); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:encodes_foo_undefined_as_is_with_ignoreUndefined_false averageTime = ${averageTime1}`) + }); + }); + + assert.context("encode_rrayBuffer as buffer", () => { + it("encode_rrayBuffer_as_buffer", 0, () => { + let startTime1 = new Date().getTime(); + const buffer = encode([1, 2, 3]); + const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteLength); + assert.deepStrictEqual(decode(arrayBuffer), decode(buffer)); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 3; + console.log(`msgpack-javascript:encode_rrayBuffer_as_buffer averageTime = ${averageTime1}`) + }) + }); + + }) +} + +interface BA { + b: number, + a: number +} + +interface Bar { + bar: number +} + +interface IgnoreUndefined { + ignoreUndefined: boolean +} + +interface FooBar { + foo: undefined | null, + bar: number +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/ieee754/ieee754.js b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/ieee754/ieee754.js new file mode 100644 index 0000000..f740f07 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/ieee754/ieee754.js @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ +var read = function (buffer, offset, isLE, mLen, nBytes) { + let e, m + const eLen = (nBytes * 8) - mLen - 1 + const eMax = (1 << eLen) - 1 + const eBias = eMax >> 1 + let nBits = -7 + let i = isLE ? (nBytes - 1) : 0 + const d = isLE ? -1 : 1 + let s = buffer[offset + i] + + i += d + + e = s & ((1 << (-nBits)) - 1) + s >>= (-nBits) + nBits += eLen + while (nBits > 0) { + e = (e * 256) + buffer[offset + i] + i += d + nBits -= 8 + } + + m = e & ((1 << (-nBits)) - 1) + e >>= (-nBits) + nBits += mLen + while (nBits > 0) { + m = (m * 256) + buffer[offset + i] + i += d + nBits -= 8 + } + + if (e === 0) { + e = 1 - eBias + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen) + e = e - eBias + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) +} + +var write = function (buffer, value, offset, isLE, mLen, nBytes) { + let e, m, c + let eLen = (nBytes * 8) - mLen - 1 + const eMax = (1 << eLen) - 1 + const eBias = eMax >> 1 + const rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) + let i = isLE ? 0 : (nBytes - 1) + const d = isLE ? 1 : -1 + const s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 + + value = Math.abs(value) + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0 + e = eMax + } else { + e = Math.floor(Math.log(value) / Math.LN2) + if (value * (c = Math.pow(2, -e)) < 1) { + e-- + c *= 2 + } + if (e + eBias >= 1) { + value += rt / c + } else { + value += rt * Math.pow(2, 1 - eBias) + } + if (value * c >= 2) { + e++ + c /= 2 + } + + if (e + eBias >= eMax) { + m = 0 + e = eMax + } else if (e + eBias >= 1) { + m = ((value * c) - 1) * Math.pow(2, mLen) + e = e + eBias + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + e = 0 + } + } + + while (mLen >= 8) { + buffer[offset + i] = m & 0xff + i += d + m /= 256 + mLen -= 8 + } + + e = (e << mLen) | m + eLen += mLen + while (eLen > 0) { + buffer[offset + i] = e & 0xff + i += d + e /= 256 + eLen -= 8 + } + + buffer[offset + i - d] |= s * 128 +} + +var ieee754={read,write} + +export default ieee754 \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/int64-buffer.js b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/int64-buffer.js new file mode 100644 index 0000000..31a7c35 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/int64-buffer.js @@ -0,0 +1,323 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +// int64-buffer.js + +/*jshint -W018 */ // Confusing use of '!'. +/*jshint -W030 */ // Expected an assignment or function call and instead saw an expression. +/*jshint -W093 */ // Did you mean to return a conditional instead of an assignment? + +var Uint64BE, Int64BE, Uint64LE, Int64LE; +import Buffer from '@ohos.buffer'; + + // constants + + var UNDEFINED = "undefined"; + var BUFFER = (UNDEFINED !== typeof Buffer) && Buffer; + var UINT8ARRAY = (UNDEFINED !== typeof Uint8Array) && Uint8Array; + var ARRAYBUFFER = (UNDEFINED !== typeof ArrayBuffer) && ArrayBuffer; + var ZERO = [0, 0, 0, 0, 0, 0, 0, 0]; + var isArray = Array.isArray || _isArray; + var BIT32 = 4294967296; + var BIT24 = 16777216; + + // storage class + + var storage; // Array; + + // generate classes + + Uint64BE = factory("Uint64BE", true, true); + Int64BE = factory("Int64BE", true, false); + Uint64LE = factory("Uint64LE", false, true); + Int64LE = factory("Int64LE", false, false); + + export {Uint64BE,Int64BE} + // class factory + + function factory(name, bigendian, unsigned) { + var posH = bigendian ? 0 : 4; + var posL = bigendian ? 4 : 0; + var pos0 = bigendian ? 0 : 3; + var pos1 = bigendian ? 1 : 2; + var pos2 = bigendian ? 2 : 1; + var pos3 = bigendian ? 3 : 0; + var fromPositive = bigendian ? fromPositiveBE : fromPositiveLE; + var fromNegative = bigendian ? fromNegativeBE : fromNegativeLE; + var proto = Int64.prototype; + var isName = "is" + name; + var _isInt64 = "_" + isName; + + // properties + proto.buffer = void 0; + proto.offset = 0; + proto[_isInt64] = true; + + // methods + proto.toNumber = toNumber; + proto.toString = toString; + proto.toJSON = toNumber; + proto.toArray = toArray; + + // add .toBuffer() method only when Buffer available + if (BUFFER) proto.toBuffer = toBuffer; + + // add .toArrayBuffer() method only when Uint8Array available + if (UINT8ARRAY) proto.toArrayBuffer = toArrayBuffer; + + // isUint64BE, isInt64BE + Int64[isName] = isInt64; + + // CommonJS + // exports[name] = Int64; + + return Int64; + + // constructor + function Int64(buffer, offset, value, raddix) { + if (!(this instanceof Int64)) return new Int64(buffer, offset, value, raddix); + return init(this, buffer, offset, value, raddix); + } + + // isUint64BE, isInt64BE + function isInt64(b) { + return !!(b && b[_isInt64]); + } + + // initializer + function init(that, buffer, offset, value, raddix) { + if (UINT8ARRAY && ARRAYBUFFER) { + if (buffer instanceof ARRAYBUFFER) buffer = new UINT8ARRAY(buffer); + if (value instanceof ARRAYBUFFER) value = new UINT8ARRAY(value); + } + + // Int64BE() style + if (!buffer && !offset && !value && !storage) { + // shortcut to initialize with zero + that.buffer = newArray(ZERO, 0); + return; + } + + // Int64BE(value, raddix) style + if (!isValidBuffer(buffer, offset)) { + var _storage = storage || Array; + raddix = offset; + value = buffer; + offset = 0; + buffer = new _storage(8); + } + + that.buffer = buffer; + that.offset = offset |= 0; + + // Int64BE(buffer, offset) style + if (UNDEFINED === typeof value) return; + + // Int64BE(buffer, offset, value, raddix) style + if ("string" === typeof value) { + fromString(buffer, offset, value, raddix || 10); + } else if (isValidBuffer(value, raddix)) { + fromArray(buffer, offset, value, raddix); + } else if ("number" === typeof raddix) { + writeInt32(buffer, offset + posH, value); // high + writeInt32(buffer, offset + posL, raddix); // low + } else if (value > 0) { + fromPositive(buffer, offset, value); // positive + } else if (value < 0) { + fromNegative(buffer, offset, value); // negative + } else { + fromArray(buffer, offset, ZERO, 0); // zero, NaN and others + } + } + + function fromString(buffer, offset, str, raddix) { + var pos = 0; + var len = str.length; + var high = 0; + var low = 0; + if (str[0] === "-") pos++; + var sign = pos; + while (pos < len) { + var chr = parseInt(str[pos++], raddix); + if (!(chr >= 0)) break; // NaN + low = low * raddix + chr; + high = high * raddix + Math.floor(low / BIT32); + low %= BIT32; + } + if (sign) { + high = ~high; + if (low) { + low = BIT32 - low; + } else { + high++; + } + } + writeInt32(buffer, offset + posH, high); + writeInt32(buffer, offset + posL, low); + } + + function toNumber() { + var buffer = this.buffer; + var offset = this.offset; + var high = readInt32(buffer, offset + posH); + var low = readInt32(buffer, offset + posL); + if (!unsigned) high |= 0; // a trick to get signed + return high ? (high * BIT32 + low) : low; + } + + function toString(radix) { + var buffer = this.buffer; + var offset = this.offset; + var high = readInt32(buffer, offset + posH); + var low = readInt32(buffer, offset + posL); + var str = ""; + var sign = !unsigned && (high & 0x80000000); + if (sign) { + high = ~high; + low = BIT32 - low; + } + radix = radix || 10; + while (1) { + var mod = (high % radix) * BIT32 + low; + high = Math.floor(high / radix); + low = Math.floor(mod / radix); + str = (mod % radix).toString(radix) + str; + if (!high && !low) break; + } + if (sign) { + str = "-" + str; + } + return str; + } + + function writeInt32(buffer, offset, value) { + buffer[offset + pos3] = value & 255; + value = value >> 8; + buffer[offset + pos2] = value & 255; + value = value >> 8; + buffer[offset + pos1] = value & 255; + value = value >> 8; + buffer[offset + pos0] = value & 255; + } + + function readInt32(buffer, offset) { + return (buffer[offset + pos0] * BIT24) + + (buffer[offset + pos1] << 16) + + (buffer[offset + pos2] << 8) + + buffer[offset + pos3]; + } + } + + function toArray(raw) { + var buffer = this.buffer; + var offset = this.offset; + storage = null; // Array + + if (raw !== false && isArray(buffer)) { + return (buffer.length === 8) ? buffer : buffer.slice(offset, offset + 8); + } + + return newArray(buffer, offset); + } + + function toBuffer(raw) { + var buffer = this.buffer; + var offset = this.offset; + storage = BUFFER; + + if (raw !== false && BUFFER.isBuffer(buffer)) { + return (buffer.length === 8) ? buffer : buffer.slice(offset, offset + 8); + } + + // Buffer.from(arraybuffer) available since Node v4.5.0 + // https://nodejs.org/en/blog/release/v4.5.0/ + return BUFFER.from(toArrayBuffer.call(this, raw)); + } + + function toArrayBuffer(raw) { + var buffer = this.buffer; + var offset = this.offset; + var arrbuf = buffer.buffer; + storage = UINT8ARRAY; + + // arrbuf.slice() ignores buffer.offset until Node v8.0.0 + if (raw !== false && !buffer.offset && (arrbuf instanceof ARRAYBUFFER)) { + return (arrbuf.byteLength === 8) ? arrbuf : arrbuf.slice(offset, offset + 8); + } + + var dest = new UINT8ARRAY(8); + fromArray(dest, 0, buffer, offset); + return dest.buffer; + } + + function isValidBuffer(buffer, offset) { + var len = buffer && buffer.length; + offset |= 0; + return len && (offset + 8 <= len) && ("string" !== typeof buffer[offset]); + } + + function fromArray(destbuf, destoff, srcbuf, srcoff) { + destoff |= 0; + srcoff |= 0; + for (var i = 0; i < 8; i++) { + destbuf[destoff++] = srcbuf[srcoff++] & 255; + } + } + + function newArray(buffer, offset) { + return Array.prototype.slice.call(buffer, offset, offset + 8); + } + + function fromPositiveBE(buffer, offset, value) { + var pos = offset + 8; + while (pos > offset) { + buffer[--pos] = value & 255; + value /= 256; + } + } + + function fromNegativeBE(buffer, offset, value) { + var pos = offset + 8; + value++; + while (pos > offset) { + buffer[--pos] = ((-value) & 255) ^ 255; + value /= 256; + } + } + + function fromPositiveLE(buffer, offset, value) { + var end = offset + 8; + while (offset < end) { + buffer[offset++] = value & 255; + value /= 256; + } + } + + function fromNegativeLE(buffer, offset, value) { + var end = offset + 8; + value++; + while (offset < end) { + buffer[offset++] = ((-value) & 255) ^ 255; + value /= 256; + } + } + + // https://github.com/retrofox/is-array + function _isArray(val) { + return !!val && "[object Array]" == Object.prototype.toString.call(val); + } + + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/msg-ext.js b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/msg-ext.js new file mode 100644 index 0000000..082d72e --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/msg-ext.js @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import Buffer from '@ohos.buffer'; +"use strict"; + +export default MsgExt; + +/** + * msgpack ext type container + */ + +export function MsgExt(payload, type) { + if (!(this instanceof MsgExt)) { + return new MsgExt(payload, type); + } + + if (!isNaN(payload) && Buffer.isBuffer(type)) { + return MsgExt.call(this, type, +payload); + } + + // ext type: -128 - +127 + if (type < -128 || 255 < type) { + throw new RangeError("Invalid ext type: " + type); + } + + if (-129 < type && type < 256) { + this.type = type; + } + + // payload + if (payload && !Buffer.isBuffer(payload)) { + payload = Buffer.from(payload); + } + + if (!payload) { + throw new TypeError("Invalid ext payload"); + } + + this.buffer = payload; + this.msgpackLength = getByteLength(payload); +} + +(function(P) { + P.type = void 0; + + P.buffer = void 0; + + P.writeMsgpackTo = writeMsgpackTo; + +})(MsgExt.prototype); + +var fixedToken = []; +fixedToken[1] = 0xd4; +fixedToken[2] = 0xd5; +fixedToken[4] = 0xd6; +fixedToken[8] = 0xd7; +fixedToken[16] = 0xd8; + +var flexToken = []; +flexToken[1] = 0xc7; +flexToken[2] = 0xc8; +flexToken[4] = 0xc9; + +function writeMsgpackTo(buffer, offset) { + var payload = this.buffer; + var length = payload.length; + + offset |= 0; + + // token + buffer[offset++] = getToken(length); + + // length for body length + var addr = getAddressLength(length); + if (addr === 1) { + buffer.writeUInt8(length, offset); + } else if (addr === 2) { + buffer.writeUInt16BE(length, offset); + } else if (addr === 4) { + buffer.writeUInt32BE(length, offset); + } + offset += addr; + + // ext type + buffer[offset++] = this.type & 255; + + // body + payload.copy(buffer, offset, 0, length); + + return offset + length; +} + +/** + * @private + */ + +function getToken(length) { + return fixedToken[length] || flexToken[getAddressLength(length)]; +} + +function getByteLength(payload) { + var length = payload && payload.length || 0; + return 2 + getAddressLength(length) + length; +} + +function getAddressLength(length) { + return fixedToken[length] ? 0 : length > 65535 ? 4 : length > 255 ? 2 : 1; +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/msg-interface.ts b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/msg-interface.ts new file mode 100644 index 0000000..9000656 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/msg-interface.ts @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import Buffer from '@ohos.buffer'; +// msg-interface + +/** + * @see https://github.com/kawanet/msg-interface + */ + +export interface MsgInterface { + /** + * expected maximum length of msgpack representation in bytes + */ + msgpackLength: number; + + /** + * write the msgpack representation to the buffer with an optional offset address + * @return {number} actual length of written in bytes + */ + writeMsgpackTo(buffer: Buffer, offset: number): number; +} + +/** + * @return {boolean} true when the argument has the MsgInterface implemented + */ + +export function isMsg(msg: any): boolean { + return !!(msg && msg.msgpackLength >= 0 && msg.writeMsgpackTo); +} + +/** + * @return {Buffer} msgpack representation + */ + +export function msgToBuffer(msg: MsgInterface): Buffer { + const expected = +msg.msgpackLength; + + if (isNaN(expected)) { + throw new Error("Invalid msgpackLength"); + } + + let buffer = Buffer.alloc(expected); + const actual = +msg.writeMsgpackTo(buffer, 0); + + // trim + if (expected > actual) { + buffer = buffer.slice(0, actual); + } + + return buffer; +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/msg-timestamp.ts b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/msg-timestamp.ts new file mode 100644 index 0000000..0956a09 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/msg-timestamp.ts @@ -0,0 +1,207 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +"use strict"; +import Buffer from '@ohos.buffer'; +import {MsgExt} from "./msg-ext"; +import {Int64BE} from "./int64-buffer"; +import Timestamp from "./timestamp"; + +const BIT34 = 0x400000000; +const BIT32 = 0x100000000; +const EXTTYPE = -1; + +/** + * Timestamp extension type is assigned to extension type -1. + */ + +export abstract class MsgTimestamp extends MsgExt { + constructor(buffer) { + super(buffer); + } + abstract getTime(): number; + + abstract getNano(): number; + + abstract toTimestamp(): Timestamp; + + toJSON(): string { + return this.toTimestamp().toJSON(); + } + + toString(fmt?: string): string { + return this.toTimestamp().toString(fmt); + } + + toDate(): Date { + return this.toTimestamp().toDate(); + } + + static from(timeT: number | Int64BE, nano?: number): MsgTimestamp { + nano = 0 | nano as number; + + const time = +timeT; + if (0 <= time && time < BIT32 && !nano) { + return MsgTimestamp32.from(time); + } else if (0 <= time && time < BIT34) { + return MsgTimestamp64.from(time, nano); + } else { + return MsgTimestamp96.from(timeT, nano); + } + } + + static parse(buffer): MsgTimestamp { + const length = buffer.length; + + switch (length) { + case 4: + return new MsgTimestamp32(buffer); + case 8: + return new MsgTimestamp64(buffer); + case 12: + return new MsgTimestamp96(buffer); + default: + throw new TypeError("Invalid payload length: " + length); + } + } +} + +// ext type -1 + +MsgTimestamp.prototype['type'] = EXTTYPE; + +/** + * Timestamp 32 format can represent a timestamp in [1970-01-01 00:00:00 UTC, 2106-02-07 06:28:16 UTC) range. Nanoseconds part is 0. + */ + +export class MsgTimestamp32 extends MsgTimestamp { + constructor(buffer) { + super(buffer); + } + + static from(time: number) { + const payload = Buffer.alloc(4); + + // seconds in 32-bit unsigned int + payload.writeUInt32BE(+time, 0); + + return new MsgTimestamp32(payload); + } + + getTime() { + // seconds in 32-bit unsigned int + return this['buffer'].readUInt32BE(0); + } + + getNano() { + return 0; + } + + toTimestamp() { + const time = this.getTime(); + return Timestamp.fromTimeT(time); + } +} + +/** + * Timestamp 64 format can represent a timestamp in [1970-01-01 00:00:00.000000000 UTC, 2514-05-30 01:53:04.000000000 UTC) range. + */ + +export class MsgTimestamp64 extends MsgTimestamp { + constructor(buffer) { + super(buffer); + } + static from(time: number, nano?: number) { + time = +time; + nano = 0 | nano as number; + + const payload = Buffer.alloc(8); + + // nanoseconds in 30-bit unsigned int + const high = (nano * 4) + ((time / BIT32) & 3); + payload.writeUInt32BE(high, 0); + + // seconds in 34-bit unsigned int + const low = time % BIT32; + payload.writeUInt32BE(low, 4); + + return new MsgTimestamp64(payload); + } + + getTime() { + const high = this['buffer'][3] & 3; + const low = this['buffer'].readUInt32BE(4); + + // seconds in 34-bit unsigned int + return high * BIT32 + low; + } + + getNano() { + const high = this['buffer'].readUInt32BE(0); + + // nanoseconds in 30-bit unsigned int + return Math.floor(high / 4); + } + + toTimestamp() { + const time = this.getTime(); + const nano = this.getNano(); + return Timestamp.fromTimeT(time).addNano(nano); + } +} + +/** + * Timestamp 96 format can represent a timestamp in [-584554047284-02-23 16:59:44 UTC, 584554051223-11-09 07:00:16.000000000 UTC) range. + */ + +export class MsgTimestamp96 extends MsgTimestamp { + constructor(buffer) { + super(buffer); + } + static from(time, nano?: number) { + const payload = Buffer.alloc(12); + nano = 0 | nano as number; + + // nanoseconds in 32-bit unsigned int + payload.writeUInt32BE(nano, 0); + + // seconds in 64-bit signed int + if (Int64BE.isInt64BE(time)) { + time.toBuffer().copy(payload, 4); + } else { + new Int64BE(payload, 4, +time); + } + + return new MsgTimestamp96(payload); + } + + getTime() { + // seconds in 64-bit signed int + return new Int64BE(this['buffer'], 4).toNumber(); + } + + getNano() { + // nanoseconds in 32-bit unsigned int + return this['buffer'].readUInt32BE(0); + } + + toTimestamp() { + const nano = this.getNano(); + + // seconds in 64-bit signed int + return Timestamp.fromInt64BE(this['buffer'], 4).addNano(nano); + } +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/timestamp.js b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/timestamp.js new file mode 100644 index 0000000..8ad1a84 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msg/timestamp.js @@ -0,0 +1,420 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +var Timestamp = (function() { + + + var SEC_DAY = 24 * 3600; // seconds per day + var YEAR_SLOT = 3200; // years per slot + var DAY_SLOT = (365 * 400 + 97) * YEAR_SLOT / 400; // days per slot + var SEC_SLOT = SEC_DAY * DAY_SLOT; // seconds per slot + var MSEC_SLOT = SEC_SLOT * 1000; // mseconds per slot + + // 15.9.1.1 Time Values and Time Range + // The actual range of times supported by ECMAScript Date objects is + // exactly –100,000,000 days to 100,000,000 days measured relative to + // midnight at the beginning of 01 January, 1970 UTC. + var MAX_MSEC = 1000 * 10000 * 10000 * SEC_DAY; + + var BIT24 = 0x1000000; + var BIT32 = 0x10000 * 0x10000; + var DEC6 = 1000 * 1000; + var DEC9 = 1000 * 1000 * 1000; + var ZERO9 = "000000000"; + + var trunc = Math.trunc || Math_trunc; + var P = Timestamp.prototype; + + // static methods + Timestamp.fromDate = fromDate; + Timestamp.fromInt64BE = buildFromInt64(0, 1, 2, 3, 0, 4); + Timestamp.fromInt64LE = buildFromInt64(3, 2, 1, 0, 4, 0); + Timestamp.fromString = fromString; + Timestamp.fromTimeT = fromTimeT; + + // private properties + P.year = 0; // Offset number for year precision + P.time = 0; // Milliseconds from epoch + P.nano = 0; // Offset number for nanosecond precision + + // instance methods + P.addNano = addNano; + P.getNano = getNano; + P.getTimeT = getTimeT; + P.getYear = getYear; + P.toDate = toDate; + P.toJSON = toJSON; + P.toString = toString; + P.writeInt64BE = buildWriteInt64(0, 1, 2, 3, 0, 4); + P.writeInt64LE = buildWriteInt64(3, 2, 1, 0, 4, 0); + + var FMT_JSON = "%Y-%m-%dT%H:%M:%S.%NZ"; + + var FMT_MONTH = [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + ]; + + var FMT_DAY = [ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + ]; + + var FMT_STRING = { + "%": "%", + F: "%Y-%m-%d", + n: "\n", + R: "%H:%M", + T: "%H:%M:%S", + t: "\t", + X: "%T", + Z: "GMT", + z: "+0000" + }; + + return Timestamp; + + function Timestamp(time, nano, year) { + var ts = this; + if (!(ts instanceof Timestamp)) return new Timestamp(time, nano, year); + ts.time = +time || 0; + ts.nano = +nano || 0; + ts.year = +year || 0; + normalize(ts); + } + + function getYear() { + var year = this.toDate().getUTCFullYear(); + return year + this.year; + } + + function normalize(ts) { + var year = ts.year; + var time = ts.time; + var nano = ts.nano; + var changed; + var slot; + + // normalize nano + if (nano < 0 || DEC6 <= nano) { + var n = Math.floor(nano / DEC6); + nano -= n * DEC6; + time += n; + changed = 1; + } + + var y = year % YEAR_SLOT; + if (time < -MAX_MSEC || MAX_MSEC < time || y) { + // shrink time into the minimal slot + slot = trunc(time / MSEC_SLOT); + if (slot) { + year += slot * YEAR_SLOT; + time -= slot * MSEC_SLOT; + } + + // add year offset smaller than a slot + var dt = newDate(time); + dt.setUTCFullYear(y + dt.getUTCFullYear()); + year -= y; + time = +dt; + + // use full range of 100 million days. + slot = trunc(year / YEAR_SLOT); + var total = time + slot * MSEC_SLOT; + if (slot && -MAX_MSEC <= total && total <= MAX_MSEC) { + year -= slot * YEAR_SLOT; + time = total; + } + + changed = 1; + } + + if (changed) { + ts.year = year; + ts.time = time; + ts.nano = nano; + } + + return ts; + } + + function toDate() { + var ts = normalize(this); + return newDate(ts.time); + } + + function newDate(time) { + var dt = new Date(0); + dt.setTime(time); + return dt; + } + + function addNano(nano) { + this.nano += +nano || 0; + return this; + } + + function getNano() { + var ts = normalize(this); + return ((ts.time % 1000) * DEC6 + (+ts.nano) + DEC9) % DEC9; + } + + function fromString(string) { + var time; + var ts = new Timestamp(); + string += ""; + + var array = string.replace(/^\s*[+\-]?\d+/, function(match) { + var year = +match; + // Use only years around 1970 to avoid Date's terrible behavior: + // 15.9.4.3 Date.UTC + // If y is not NaN and 0 <= y <= 99, then let yr be 1900+y + var y = 1970 + ((year - 1970) % 400); + ts.year = year - y; + return y; + }).replace(/(?:Z|([+\-]\d{2}):?(\d{2}))$/, function(match, hour, min) { + // time zone + if (hour < 0) min *= -1; + time = ((+hour) * 60 + (+min)) * 60000; + return ""; + }).replace(/\.\d+$/, function(match) { + // nanoseconds + ts.nano = +((match + ZERO9).substr(1, 9)); + return ""; + }).split(/\D+/); + + if (array.length > 1) { + array[1]--; // month starts from 0 + } else { + array[1] = 0; + } + + ts.time = time = Date.UTC.apply(Date, array) - (time || 0); + + if (isNaN(time)) { + throw new TypeError("Invalid Date"); + } + + return normalize(ts); + } + + function fromDate(date) { + return new Timestamp(+date); + } + + function fromTimeT(time) { + return fromTime(time, 0); + } + + function fromTime(low, high) { + high |= 0; + high *= BIT32; + low = +low || 0; + + // slot count + var slot = trunc(high / SEC_SLOT) + trunc(low / SEC_SLOT); + + // seconds within slot + var second = (high % SEC_SLOT) + (low % SEC_SLOT); + + // slot offset + var offset = trunc(second / SEC_SLOT); + if (offset) { + slot += offset; + second -= offset * SEC_SLOT; + } + + return new Timestamp(second * 1000, 0, slot * YEAR_SLOT); + } + + function getTimeT() { + var ts = normalize(this); + var time = Math.floor(ts.time / 1000); + + var year = ts.year; + if (year) time += year * DAY_SLOT * SEC_DAY / YEAR_SLOT; + + // this may loose some bits over than 53 bit precision + return time; + } + + function toJSON() { + return this.toString().replace(/0{1,6}Z$/, "Z"); + } + + function toString(format) { + var ts = this; + var dt = ts.toDate(); + var map = { + H: H, + L: L, + M: M, + N: N, + S: S, + Y: Y, + a: a, + b: b, + d: d, + e: e, + m: m, + s: s + }; + + return strftime(format || FMT_JSON); + + function strftime(format) { + return format.replace(/%./g, function(match) { + var m = match[1]; + var c = FMT_STRING[m]; + var f = map[m]; + return c ? strftime(c) : f ? f() : match; + }); + } + + function Y() { + var year = ts.getYear(); + if (year > 999999) { + return "+" + year; + } else if (year > 9999) { + return "+" + pad(year, 6); + } else if (year >= 0) { + return pad(year, 4); + } else if (year >= -999999) { + return "-" + pad(-year, 6); + } else { + return year; + } + } + + function m() { + return pad2(dt.getUTCMonth() + 1); + } + + function d() { + return pad2(dt.getUTCDate()); + } + + function e() { + return padS(dt.getUTCDate()); + } + + function H() { + return pad2(dt.getUTCHours()); + } + + function M() { + return pad2(dt.getUTCMinutes()); + } + + function S() { + return pad2(dt.getUTCSeconds()); + } + + function L() { + return pad(dt.getUTCMilliseconds(), 3); + } + + function N() { + return pad(ts.getNano(), 9); + } + + function a() { + return FMT_DAY[dt.getUTCDay()]; + } + + function b() { + return FMT_MONTH[dt.getUTCMonth()]; + } + + function s() { + return ts.getTimeT(); + } + } + + function buildWriteInt64(pos0, pos1, pos2, pos3, posH, posL) { + return writeInt64; + + function writeInt64(buffer, offset) { + var ts = normalize(this); + if (!buffer) buffer = new Array(8); + checkRange(buffer, offset |= 0); + + var second = Math.floor(ts.time / 1000); + var day = ts.year * (DAY_SLOT * SEC_DAY / YEAR_SLOT); + var high = trunc(day / BIT32) + trunc(second / BIT32); + var low = (day % BIT32) + (second % BIT32); + + // slot offset + var slot = Math.floor(low / BIT32); + if (slot) { + high += slot; + low -= slot * BIT32; + } + + writeUint32(buffer, offset + posH, high); + writeUint32(buffer, offset + posL, low); + return buffer; + } + + function writeUint32(buffer, offset, value) { + buffer[offset + pos0] = (value >> 24) & 255; + buffer[offset + pos1] = (value >> 16) & 255; + buffer[offset + pos2] = (value >> 8) & 255; + buffer[offset + pos3] = value & 255; + } + } + + function buildFromInt64(pos0, pos1, pos2, pos3, posH, posL) { + return fromInt64; + + function fromInt64(buffer, offset) { + checkRange(buffer, offset |= 0); + var high = readUint32(buffer, offset + posH); + var low = readUint32(buffer, offset + posL); + return fromTime(low, high); + } + + function readUint32(buffer, offset) { + return (buffer[offset + pos0] * BIT24) + + ((buffer[offset + pos1] << 16) | + (buffer[offset + pos2] << 8) | + buffer[offset + pos3]); + } + } + + function checkRange(buffer, offset) { + var last = buffer && buffer.length; + if (last == null) throw new TypeError("Invalid Buffer"); + if (last < offset + 8) throw new RangeError("Out of range"); + } + + function Math_trunc(x) { + var n = x - x % 1; + return n === 0 && (x < 0 || (x === 0 && (1 / x !== 1 / 0))) ? -0 : n; + } + + function padS(v) { + return (v > 9 ? "" : " ") + (v | 0); + } + + function pad2(v) { + return (v > 9 ? "" : "0") + (v | 0); + } + + function pad(v, len) { + return (ZERO9 + (v | 0)).substr(-len); + } +})(); +export default Timestamp; \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpack-ext.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpack-ext.test.ets new file mode 100644 index 0000000..b8df3b2 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpack-ext.test.ets @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import { encode, decode, ExtData } from "@ohos/msgpack"; +import hilog from '@ohos.hilog'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import { SPECS } from './stdlib/StdlibData'; +import Util from './stdlib/Util'; + +export default function msgpackExtTest() { + describe('msgpackExtTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + for (const name of Object.keys(SPECS)) { + const pair = SPECS[name]!; + let msgpackType = pair[0] + let extData = pair[1] + it(`preserves_ExtData_by_decode_encode_${name}__`, 0, () => { + let startTime1 = new Date().getTime(); + const encoded = encode(extData); + let decoded = Util.decodeObject(encoded) + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:preserves_ExtData_by_decode_encode_${name}__ averageTime = ${averageTime1}`) + + assert.strictEqual(encoded[0], msgpackType); + assert.deepStrictEqual(decoded, extData); + + }); + } + }) +} + + + + + + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpack-test-suite.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpack-test-suite.test.ets new file mode 100644 index 0000000..40347c2 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpack-test-suite.test.ets @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import MsgpackTestSuite from "../test/stdlib/MsgpackTestSuite"; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + + +export default function nmsgpackTestSuiteTest() { + describe('msgpackTestSuiteTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + MsgpackTestSuite.msgpackTestSuiteTest(it, expect) + }) +} + + + + + + + + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpack-test-suite2.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpack-test-suite2.test.ets new file mode 100644 index 0000000..ea1f25c --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpack-test-suite2.test.ets @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import MsgpackTestSuite2 from "../test/stdlib/MsgpackTestSuite2"; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + + +export default function nmsgpackTestSuiteTest2() { + describe('msgpackTestSuiteTest2', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + MsgpackTestSuite2.msgpackTestSuiteTest2(it, expect) + }) +} + + + + + + + + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/exam.js b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/exam.js new file mode 100644 index 0000000..c92bf95 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/exam.js @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * exam.js + */ + + + +import {Group} from "./group"; +import Type from "./type"; + +var binary = Type.getType("binary"); + +export function Exam(src) { + if (!(this instanceof Exam)) return new Exam(src); + this.src = src || {}; +} + +Exam.getExams = getExams; + +Exam.prototype.getMsgpacks = getMsgpacks; +Exam.prototype.getTypes = getTypes; +Exam.prototype.getValue = getValue; +Exam.prototype.matchMsgpack = matchMsgpack; +Exam.prototype.matchValue = matchValue; +Exam.prototype.stringify = stringify; + +function getExams(filter) { + var array = Group.getGroups().map(function(group) { + return group.getExams(filter); + }); + + return [].concat.apply([], array); +} + +function getTypes(filter) { + var src = this.src; + + return Object.keys(src).filter(function(type) { + return !filter || filter[type]; + }).map(function(type) { + return Type.getType(type); + }).filter(isTrue); +} + +function stringify(idx) { + // idx is a number + if (idx >= 0) { + return this.src.msgpack[idx]; + } + + // idx is a type + var type = (idx instanceof Type) ? idx : Type.getType(type); + if (type) { + return JSON.stringify(this.src[type]); + } +} + +function getValue(type) { + if (!(type instanceof Type)) type = Type.getType(type); + return type.parse(this.src[type]); +} + +function getMsgpacks() { + return this.msgpack || (this.msgpack = parseAllMsgpack(this.src)); +} + +function matchMsgpack(encoded) { + return this.getMsgpacks().some(function(check) { + return binary.compare(encoded, check); + }); +} + +function matchValue(value) { + var that = this; + + return this.getTypes().some(function(type) { + return type.compare(value, that.getValue(type)); + }); +} + +function parseAllMsgpack(src) { + var rows = src && src.msgpack || []; + return rows.map(binary.parse); +} + +function isTrue(v) { + return v; +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/group.js b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/group.js new file mode 100644 index 0000000..ba993f7 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/group.js @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/** + * group.js + */ + + + +import suite from "./msgpack-test-suite.json"; +import {Exam} from "./exam"; + +export function Group(name) { + if (!(this instanceof Group)) return new Group(name); + this.name = name; +} + +Group.getGroups = getGroups; + +Group.prototype.getExams = getExams; +Group.prototype.toString = toString; + +function getGroups() { + return Object.keys(suite).sort().map(Group); +} + +function getExams(filter) { + var name = this.name; + var array = suite[name]; + + if (!array) throw new Error("Group not found: " + name); + + return array.map(Exam).filter(function(exam) { + return !filter || exam.getTypes(filter).length; + }); +} + +function toString() { + return this.name; +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/msg-int64.js b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/msg-int64.js new file mode 100644 index 0000000..562d3f1 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/msg-int64.js @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +// msg-int64.js + +import {Uint64BE,Int64BE} from "../msg/int64-buffer"; + +export {MsgUInt64,MsgInt64} + + +inherits(MsgUInt64, Uint64BE, 0xcf); +inherits(MsgInt64, Int64BE, 0xd3); + +MsgUInt64.isUint64BE = Uint64BE.isUint64BE; +MsgInt64.isInt64BE = Int64BE.isInt64BE; + +function MsgUInt64() { + var that = (this instanceof MsgUInt64) ? this : new MsgUInt64(); + Uint64BE.apply(that, arguments); + return that; +} + +function MsgInt64() { + var that = (this instanceof MsgInt64) ? this : new MsgInt64(); + Int64BE.apply(that, arguments); + return that; +} + +function inherits(child, _super, token) { + var P = child.prototype = Object.create(_super.prototype); + + P.msgpackLength = 9; + + P.writeMsgpackTo = function(buffer, offset) { + offset |= 0; + buffer[offset] = token; + this.toBuffer().copy(buffer, offset + 1); + return 9; + }; +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/msgpack-test-suite.json b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/msgpack-test-suite.json new file mode 100644 index 0000000..b688e30 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/msgpack-test-suite.json @@ -0,0 +1,722 @@ +{ + "10.nil.yaml": [ + { + "nil": null, + "msgpack": [ + "c0" + ] + } + ], + "11.bool.yaml": [ + { + "bool": false, + "msgpack": [ + "c2" + ] + }, + { + "bool": true, + "msgpack": [ + "c3" + ] + } + ], + "12.binary.yaml": [ + { + "binary": "", + "msgpack": [ + "c4-00", + "c5-00-00", + "c6-00-00-00-00" + ] + }, + { + "binary": "01", + "msgpack": [ + "c4-01-01", + "c5-00-01-01", + "c6-00-00-00-01-01" + ] + }, + { + "binary": "00-ff", + "msgpack": [ + "c4-02-00-ff", + "c5-00-02-00-ff", + "c6-00-00-00-02-00-ff" + ] + } + ], + "20.number-positive.yaml": [ + { + "number": 0, + "msgpack": [ + "00", + "cc-00", + "cd-00-00", + "ce-00-00-00-00", + "cf-00-00-00-00-00-00-00-00", + "d0-00", + "d1-00-00", + "d2-00-00-00-00", + "d3-00-00-00-00-00-00-00-00", + "ca-00-00-00-00", + "cb-00-00-00-00-00-00-00-00" + ] + }, + { + "number": 1, + "msgpack": [ + "01", + "cc-01", + "cd-00-01", + "ce-00-00-00-01", + "cf-00-00-00-00-00-00-00-01", + "d0-01", + "d1-00-01", + "d2-00-00-00-01", + "d3-00-00-00-00-00-00-00-01", + "ca-3f-80-00-00", + "cb-3f-f0-00-00-00-00-00-00" + ] + }, + { + "number": 127, + "msgpack": [ + "7f", + "cc-7f", + "cd-00-7f", + "ce-00-00-00-7f", + "cf-00-00-00-00-00-00-00-7f", + "d0-7f", + "d1-00-7f", + "d2-00-00-00-7f", + "d3-00-00-00-00-00-00-00-7f" + ] + }, + { + "number": 128, + "msgpack": [ + "cc-80", + "cd-00-80", + "ce-00-00-00-80", + "cf-00-00-00-00-00-00-00-80", + "d1-00-80", + "d2-00-00-00-80", + "d3-00-00-00-00-00-00-00-80" + ] + }, + { + "number": 255, + "msgpack": [ + "cc-ff", + "cd-00-ff", + "ce-00-00-00-ff", + "cf-00-00-00-00-00-00-00-ff", + "d1-00-ff", + "d2-00-00-00-ff", + "d3-00-00-00-00-00-00-00-ff" + ] + }, + { + "number": 256, + "msgpack": [ + "cd-01-00", + "ce-00-00-01-00", + "cf-00-00-00-00-00-00-01-00", + "d1-01-00", + "d2-00-00-01-00", + "d3-00-00-00-00-00-00-01-00" + ] + }, + { + "number": 65535, + "msgpack": [ + "cd-ff-ff", + "ce-00-00-ff-ff", + "cf-00-00-00-00-00-00-ff-ff", + "d2-00-00-ff-ff", + "d3-00-00-00-00-00-00-ff-ff" + ] + }, + { + "number": 65536, + "msgpack": [ + "ce-00-01-00-00", + "cf-00-00-00-00-00-01-00-00", + "d2-00-01-00-00", + "d3-00-00-00-00-00-01-00-00" + ] + }, + { + "number": 2147483647, + "msgpack": [ + "ce-7f-ff-ff-ff", + "cf-00-00-00-00-7f-ff-ff-ff", + "d2-7f-ff-ff-ff", + "d3-00-00-00-00-7f-ff-ff-ff" + ] + }, + { + "number": 2147483648, + "msgpack": [ + "ce-80-00-00-00", + "cf-00-00-00-00-80-00-00-00", + "d3-00-00-00-00-80-00-00-00", + "ca-4f-00-00-00", + "cb-41-e0-00-00-00-00-00-00" + ] + }, + { + "number": 4294967295, + "msgpack": [ + "ce-ff-ff-ff-ff", + "cf-00-00-00-00-ff-ff-ff-ff", + "d3-00-00-00-00-ff-ff-ff-ff", + "cb-41-ef-ff-ff-ff-e0-00-00" + ] + } + ], + "21.number-negative.yaml": [ + { + "number": -1, + "msgpack": [ + "ff", + "d0-ff", + "d1-ff-ff", + "d2-ff-ff-ff-ff", + "d3-ff-ff-ff-ff-ff-ff-ff-ff", + "ca-bf-80-00-00", + "cb-bf-f0-00-00-00-00-00-00" + ] + }, + { + "number": -32, + "msgpack": [ + "e0", + "d0-e0", + "d1-ff-e0", + "d2-ff-ff-ff-e0", + "d3-ff-ff-ff-ff-ff-ff-ff-e0", + "ca-c2-00-00-00", + "cb-c0-40-00-00-00-00-00-00" + ] + }, + { + "number": -33, + "msgpack": [ + "d0-df", + "d1-ff-df", + "d2-ff-ff-ff-df", + "d3-ff-ff-ff-ff-ff-ff-ff-df" + ] + }, + { + "number": -128, + "msgpack": [ + "d0-80", + "d1-ff-80", + "d2-ff-ff-ff-80", + "d3-ff-ff-ff-ff-ff-ff-ff-80" + ] + }, + { + "number": -256, + "msgpack": [ + "d1-ff-00", + "d2-ff-ff-ff-00", + "d3-ff-ff-ff-ff-ff-ff-ff-00" + ] + }, + { + "number": -32768, + "msgpack": [ + "d1-80-00", + "d2-ff-ff-80-00", + "d3-ff-ff-ff-ff-ff-ff-80-00" + ] + }, + { + "number": -65536, + "msgpack": [ + "d2-ff-ff-00-00", + "d3-ff-ff-ff-ff-ff-ff-00-00" + ] + }, + { + "number": -2147483648, + "msgpack": [ + "d2-80-00-00-00", + "d3-ff-ff-ff-ff-80-00-00-00", + "cb-c1-e0-00-00-00-00-00-00" + ] + } + ], + "22.number-float.yaml": [ + { + "number": 0.5, + "msgpack": [ + "ca-3f-00-00-00", + "cb-3f-e0-00-00-00-00-00-00" + ] + }, + { + "number": -0.5, + "msgpack": [ + "ca-bf-00-00-00", + "cb-bf-e0-00-00-00-00-00-00" + ] + } + ], + "23.number-bignum.yaml": [ + { + "number": 4294967296, + "bignum": "4294967296", + "msgpack": [ + "cf-00-00-00-01-00-00-00-00", + "d3-00-00-00-01-00-00-00-00", + "ca-4f-80-00-00", + "cb-41-f0-00-00-00-00-00-00" + ] + }, + { + "number": -4294967296, + "bignum": "-4294967296", + "msgpack": [ + "d3-ff-ff-ff-ff-00-00-00-00", + "cb-c1-f0-00-00-00-00-00-00" + ] + }, + { + "number": 281474976710656, + "bignum": "281474976710656", + "msgpack": [ + "cf-00-01-00-00-00-00-00-00", + "d3-00-01-00-00-00-00-00-00", + "ca-57-80-00-00", + "cb-42-f0-00-00-00-00-00-00" + ] + }, + { + "number": -281474976710656, + "bignum": "-281474976710656", + "msgpack": [ + "d3-ff-ff-00-00-00-00-00-00", + "ca-d7-80-00-00", + "cb-c2-f0-00-00-00-00-00-00" + ] + }, + { + "bignum": "9223372036854775807", + "msgpack": [ + "d3-7f-ff-ff-ff-ff-ff-ff-ff", + "cf-7f-ff-ff-ff-ff-ff-ff-ff" + ] + }, + { + "bignum": "-9223372036854775807", + "msgpack": [ + "d3-80-00-00-00-00-00-00-01" + ] + }, + { + "bignum": "9223372036854775808", + "msgpack": [ + "cf-80-00-00-00-00-00-00-00" + ] + }, + { + "bignum": "-9223372036854775808", + "msgpack": [ + "d3-80-00-00-00-00-00-00-00" + ] + }, + { + "bignum": "18446744073709551615", + "msgpack": [ + "cf-ff-ff-ff-ff-ff-ff-ff-ff" + ] + } + ], + "30.string-ascii.yaml": [ + { + "string": "", + "msgpack": [ + "a0", + "d9-00", + "da-00-00", + "db-00-00-00-00" + ] + }, + { + "string": "a", + "msgpack": [ + "a1-61", + "d9-01-61", + "da-00-01-61", + "db-00-00-00-01-61" + ] + }, + { + "string": "1234567890123456789012345678901", + "msgpack": [ + "bf-31-32-33-34-35-36-37-38-39-30-31-32-33-34-35-36-37-38-39-30-31-32-33-34-35-36-37-38-39-30-31", + "d9-1f-31-32-33-34-35-36-37-38-39-30-31-32-33-34-35-36-37-38-39-30-31-32-33-34-35-36-37-38-39-30-31", + "da-00-1f-31-32-33-34-35-36-37-38-39-30-31-32-33-34-35-36-37-38-39-30-31-32-33-34-35-36-37-38-39-30-31" + ] + }, + { + "string": "12345678901234567890123456789012", + "msgpack": [ + "d9-20-31-32-33-34-35-36-37-38-39-30-31-32-33-34-35-36-37-38-39-30-31-32-33-34-35-36-37-38-39-30-31-32", + "da-00-20-31-32-33-34-35-36-37-38-39-30-31-32-33-34-35-36-37-38-39-30-31-32-33-34-35-36-37-38-39-30-31-32" + ] + } + ], + "31.string-utf8.yaml": [ + { + "string": "Кириллица", + "msgpack": [ + "b2-d0-9a-d0-b8-d1-80-d0-b8-d0-bb-d0-bb-d0-b8-d1-86-d0-b0", + "d9-12-d0-9a-d0-b8-d1-80-d0-b8-d0-bb-d0-bb-d0-b8-d1-86-d0-b0" + ] + }, + { + "string": "ひらがな", + "msgpack": [ + "ac-e3-81-b2-e3-82-89-e3-81-8c-e3-81-aa", + "d9-0c-e3-81-b2-e3-82-89-e3-81-8c-e3-81-aa" + ] + }, + { + "string": "한글", + "msgpack": [ + "a6-ed-95-9c-ea-b8-80", + "d9-06-ed-95-9c-ea-b8-80" + ] + }, + { + "string": "汉字", + "msgpack": [ + "a6-e6-b1-89-e5-ad-97", + "d9-06-e6-b1-89-e5-ad-97" + ] + }, + { + "string": "漢字", + "msgpack": [ + "a6-e6-bc-a2-e5-ad-97", + "d9-06-e6-bc-a2-e5-ad-97" + ] + } + ], + "32.string-emoji.yaml": [ + { + "string": "❤", + "msgpack": [ + "a3-e2-9d-a4", + "d9-03-e2-9d-a4" + ] + }, + { + "string": "🍺", + "msgpack": [ + "a4-f0-9f-8d-ba", + "d9-04-f0-9f-8d-ba" + ] + } + ], + "40.array.yaml": [ + { + "array": [], + "msgpack": [ + "90", + "dc-00-00", + "dd-00-00-00-00" + ] + }, + { + "array": [ 1 ], + "msgpack": [ + "91-01", + "dc-00-01-01", + "dd-00-00-00-01-01" + ] + }, + { + "array": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], + "msgpack": [ + "9f-01-02-03-04-05-06-07-08-09-0a-0b-0c-0d-0e-0f", + "dc-00-0f-01-02-03-04-05-06-07-08-09-0a-0b-0c-0d-0e-0f", + "dd-00-00-00-0f-01-02-03-04-05-06-07-08-09-0a-0b-0c-0d-0e-0f" + ] + }, + { + "array": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ], + "msgpack": [ + "dc-00-10-01-02-03-04-05-06-07-08-09-0a-0b-0c-0d-0e-0f-10", + "dd-00-00-00-10-01-02-03-04-05-06-07-08-09-0a-0b-0c-0d-0e-0f-10" + ] + }, + { + "array": [ + "a" + ], + "msgpack": [ + "91-a1-61", + "dc-00-01-a1-61", + "dd-00-00-00-01-a1-61" + ] + } + ], + "41.map.yaml": [ + { + "map": {}, + "msgpack": [ + "80", + "de-00-00", + "df-00-00-00-00" + ] + }, + { + "map": { + "a": 1 + }, + "msgpack": [ + "81-a1-61-01", + "de-00-01-a1-61-01", + "df-00-00-00-01-a1-61-01" + ] + }, + { + "map": { + "a": "A" + }, + "msgpack": [ + "81-a1-61-a1-41", + "de-00-01-a1-61-a1-41", + "df-00-00-00-01-a1-61-a1-41" + ] + } + ], + "42.nested.yaml": [ + { + "array": [ + [] + ], + "msgpack": [ + "91-90", + "dc-00-01-dc-00-00", + "dd-00-00-00-01-dd-00-00-00-00" + ] + }, + { + "array": [ + {} + ], + "msgpack": [ + "91-80", + "dc-00-01-80", + "dd-00-00-00-01-80" + ] + }, + { + "map": { + "a": {} + }, + "msgpack": [ + "81-a1-61-80", + "de-00-01-a1-61-de-00-00", + "df-00-00-00-01-a1-61-df-00-00-00-00" + ] + }, + { + "map": { + "a": [] + }, + "msgpack": [ + "81-a1-61-90", + "de-00-01-a1-61-90", + "df-00-00-00-01-a1-61-90" + ] + } + ], + "50.timestamp.yaml": [ + { + "timestamp": [ 1514862245, 0 ], + "msgpack": [ + "d6-ff-5a-4a-f6-a5" + ] + }, + { + "timestamp": [ 1514862245, 678901234 ], + "msgpack": [ + "d7-ff-a1-dc-d7-c8-5a-4a-f6-a5" + ] + }, + { + "timestamp": [ 2147483647, 999999999 ], + "msgpack": [ + "d7-ff-ee-6b-27-fc-7f-ff-ff-ff" + ] + }, + { + "timestamp": [ 2147483648, 0 ], + "msgpack": [ + "d6-ff-80-00-00-00" + ] + }, + { + "timestamp": [ 2147483648, 1 ], + "msgpack": [ + "d7-ff-00-00-00-04-80-00-00-00" + ] + }, + { + "timestamp": [ 4294967295, 0 ], + "msgpack": [ + "d6-ff-ff-ff-ff-ff" + ] + }, + { + "timestamp": [ 4294967295, 999999999 ], + "msgpack": [ + "d7-ff-ee-6b-27-fc-ff-ff-ff-ff" + ] + }, + { + "timestamp": [ 4294967296, 0 ], + "msgpack": [ + "d7-ff-00-00-00-01-00-00-00-00" + ] + }, + { + "timestamp": [ 17179869183, 999999999 ], + "msgpack": [ + "d7-ff-ee-6b-27-ff-ff-ff-ff-ff" + ] + }, + { + "timestamp": [ 17179869184, 0 ], + "msgpack": [ + "c7-0c-ff-00-00-00-00-00-00-00-04-00-00-00-00" + ] + }, + { + "timestamp": [ -1, 0 ], + "msgpack": [ + "c7-0c-ff-00-00-00-00-ff-ff-ff-ff-ff-ff-ff-ff" + ] + }, + { + "timestamp": [ -1, 999999999 ], + "msgpack": [ + "c7-0c-ff-3b-9a-c9-ff-ff-ff-ff-ff-ff-ff-ff-ff" + ] + }, + { + "timestamp": [ 0, 0 ], + "msgpack": [ + "d6-ff-00-00-00-00" + ] + }, + { + "timestamp": [ 0, 1 ], + "msgpack": [ + "d7-ff-00-00-00-04-00-00-00-00" + ] + }, + { + "timestamp": [ 1, 0 ], + "msgpack": [ + "d6-ff-00-00-00-01" + ] + }, + { + "timestamp": [ -2208988801, 999999999 ], + "msgpack": [ + "c7-0c-ff-3b-9a-c9-ff-ff-ff-ff-ff-7c-55-81-7f" + ] + }, + { + "timestamp": [ -2208988800, 0 ], + "msgpack": [ + "c7-0c-ff-00-00-00-00-ff-ff-ff-ff-7c-55-81-80" + ] + }, + { + "timestamp": [ -62167219200, 0 ], + "msgpack": [ + "c7-0c-ff-00-00-00-00-ff-ff-ff-f1-86-8b-84-00" + ] + }, + { + "timestamp": [ 253402300799, 999999999 ], + "msgpack": [ + "c7-0c-ff-3b-9a-c9-ff-00-00-00-3a-ff-f4-41-7f" + ] + } + ], + "60.ext.yaml": [ + { + "ext": [ 1, + "10" + ], + "msgpack": [ + "d4-01-10" + ] + }, + { + "ext": [ 2, + "20-21" + ], + "msgpack": [ + "d5-02-20-21" + ] + }, + { + "ext": [ 3, + "30-31-32-33" + ], + "msgpack": [ + "d6-03-30-31-32-33" + ] + }, + { + "ext": [ 4, + "40-41-42-43-44-45-46-47" + ], + "msgpack": [ + "d7-04-40-41-42-43-44-45-46-47" + ] + }, + { + "ext": [ 5, + "50-51-52-53-54-55-56-57-58-59-5a-5b-5c-5d-5e-5f" + ], + "msgpack": [ + "d8-05-50-51-52-53-54-55-56-57-58-59-5a-5b-5c-5d-5e-5f" + ] + }, + { + "ext": [ 6, + "" + ], + "msgpack": [ + "c7-00-06", + "c8-00-00-06", + "c9-00-00-00-00-06" + ] + }, + { + "ext": [ 7, + "70-71-72" + ], + "msgpack": [ + "c7-03-07-70-71-72", + "c8-00-03-07-70-71-72", + "c9-00-00-00-03-07-70-71-72" + ] + } + ] +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/type.js b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/type.js new file mode 100644 index 0000000..3cf4d45 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/msgpacksuit/type.js @@ -0,0 +1,151 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import Buffer from '@ohos.buffer'; +/** + * type.js + */ + +import {MsgUInt64,MsgInt64} from "./msg-int64"; +import { MsgTimestamp } from "../msg/msg-timestamp"; +import MsgExt from "../msg/msg-ext"; + +export default Type; + +Type.getType = getType; + +Type.prototype.compare = compareStrict; +Type.prototype.parse = through; +Type.prototype.toString = toString; + +var types = {}; +types.array = new Type("array"); +types.bignum = new Type("bignum"); +types.binary = new Type("binary"); +types.bool = new Type("bool"); +types.ext = new Type("ext"); +types.map = new Type("map"); +types.nil = new Type("nil"); +types.number = new Type("number"); +types.string = new Type("string"); +types.timestamp = new Type("timestamp"); + +types.array.compare = compareDeep; +types.bignum.compare = compareString; +types.binary.compare = compareBinary; +types.ext.compare = compareExt; +types.map.compare = compareMap; +types.number.compare = compareNumber; +types.string.compare = compareString; +types.timestamp.compare = compareString; + +types.bignum.parse = parseBignum; +types.binary.parse = parseBinary; +types.ext.parse = parseExt; +types.timestamp.parse = parseTimestamp; + +function Type(name) { + if (!(this instanceof Type)) return new Type(name); + this.name = name; +} + +function toString() { + return this.name; +} + +function getType(type) { + return types[type]; +} + +function through(value) { + return value; +} + +function parseBignum(str) { + var orig = str += ""; + var parser = (str[0] === "-") ? MsgInt64 : MsgUInt64; + str = str.replace(/0x/, ""); + var radix = (str !== orig) ? 16 : 10; + return parser(str, radix); +} + +function parseBinary(str) { + var array = str && str.split(/[^0-9a-fA-F]+/g).map(parseHex) || []; + return Buffer.from ? Buffer.from(array) : new Buffer(array); +} + +function parseExt(array) { + var type = array[0]; + var buffer = parseBinary(array[1]); + return new MsgExt(buffer, type); +} + +function parseHex(str) { + return parseInt(str, 16) || 0; +} + +function parseTimestamp(array) { + return MsgTimestamp.from(array[0], array[1]); +} + +function compareExt(a, b) { + if (!a) return false; + if (!b) return false; + + return (a.type === b.type) && compareBinary(a.buffer, b.buffer); +} + +function compareString(a, b) { + return "" + a === "" + b; +} + +function compareNumber(a, b) { + return +a === +b; +} + +function compareStrict(a, b) { + return a === b; +} + +function compareBinary(a, b) { + if (!a) return false; + if (!b) return false; + + var aLen = a.length; + var bLen = b.length; + if (aLen !== bLen) return false; + + return [].every.call(a, function(value, idx) { + return value === b[idx]; + }); +} + +function compareMap(a, b) { + if (!a) return false; + if (!b) return false; + + var aKeys = Object.keys(a); + var bKeys = Object.keys(b); + if (aKeys.length !== bKeys.length) return false; + + return [].every.call(aKeys, function(key) { + return (key in b) && compareDeep(a[key], b[key]); + }); +} + +function compareDeep(a, b) { + return JSON.stringify(a) === JSON.stringify(b); +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/prototype-pollution.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/prototype-pollution.test.ets new file mode 100644 index 0000000..0e6b3c4 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/prototype-pollution.test.ets @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import { encode, decode, DecodeError } from "@ohos/msgpack"; +import hilog from '@ohos.hilog'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import { o } from './stdlib/StdlibData'; +import { defineProperty } from './stdlib/Stdlib'; + +export default function prototypePollutionTest() { + describe('prototypePollutionTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + assert.context("__proto__ exists as a map key", () => { + it("raises_DecodeError_in_decoding", 0, () => { + // override __proto__ as an enumerable property + defineProperty(); + let startTime1 = new Date().getTime(); + const encoded = encode(o); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:raises_DecodeError_in_decoding averageTime = ${averageTime1}`) + let decodeError: DecodeError | null = null + assert.throws(() => { + decode(encoded); + }, decodeError); + }); + }); + + }) +} + + + + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/readme.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/readme.test.ets new file mode 100644 index 0000000..4a3763d --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/readme.test.ets @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import { encode, decode } from "@ohos/msgpack"; +import Util from "../test/stdlib/Util"; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + +export default function readmeTest() { + describe('readmeTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + assert.context("## Synopsis", () => { + it("runs", 0, () => { + let foo: Foo = { + foo: "bar" + } + let object: ValueObject = { + nil: null, + integer: 1, + float: Math.PI, + string: "Hello, world!", + binary: Uint8Array.from([1, 2, 3]), + array: [10, 20, 30], + map: foo, + timestampExt: new Date(), + }; + + let startTime1 = new Date().getTime(); + const encoded = encode(object); + let decoded = Util.decodeObject(encoded); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:runs averageTime = ${averageTime1}`) + // encoded is an Uint8Array instance + + assert.deepStrictEqual(decoded, object); + + }); + }); + }) +} + + +interface Foo { + foo: string +} + +interface ValueObject { + nil: null, + integer: number, + float: number, + string: string, + binary: Uint8Array, + array: number[], + map: Foo, + timestampExt: Date, +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/reuse-instances.test.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/reuse-instances.test.ets new file mode 100644 index 0000000..e0d0d52 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/reuse-instances.test.ets @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import assert from "./assert2hypium"; +import { Encoder, Decoder, decode } from "@ohos/msgpack"; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import { data1, data2, reuseobject } from "./stdlib/StdlibData" +import ReuseInstances from "../test/stdlib/ReuseInstances"; + +export default function reuseInstancesTest() { + describe('reuseInstancesTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + const N = 10; + assert.context("encode() and decodeSync()", () => { + it("runs_multiple_times1", 0, () => { + for (let i = 0; i < N; i++) { + let startTime1 = new Date().getTime(); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:runs_multiple_times#${i} averageTime = ${averageTime1}`) + assert.deepStrictEqual(ReuseInstances.runsMultipleTimes1(), reuseobject, `#${i}`); + } + }); + }); + + assert.context("encode() and decodeAsync()", () => { + it("runs_multiple_times2", 0, async () => { + for (let i = 0; i < N; i++) { + let startTime1 = new Date().getTime(); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:runs_multiple_times#${i} averageTime = ${averageTime1}`) + assert.deepStrictEqual(await ReuseInstances.runsMultipleTimes2(), reuseobject, `#${i}`); + } + }); + }); + + assert.context("encode() and decodeStream()", () => { + it("runs_multiple_times3", 0, async () => { + for (let i = 0; i < N; i++) { + const a: Array = []; + await ReuseInstances.runsMultipleTimes3Or4(a,3) + let startTime1 = new Date().getTime(); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:runs_multiple_times#${i} averageTime = ${averageTime1}`) + assert.deepStrictEqual(a, [reuseobject], `#${i}`); + + } + }); + }); + + assert.context("encode() and decodeArrayStream()", () => { + it("runs_multiple_times4", 0, async () => { + for (let i = 0; i < N; i++) { + const a: Array = []; + await ReuseInstances.runsMultipleTimes3Or4(a, 4) + let startTime1 = new Date().getTime(); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:runs_multiple_times#${i} averageTime = ${averageTime1}`) + assert.deepStrictEqual(a, [[reuseobject]], `#${i}`); + } + }); + + assert.context("regression #212", () => { + it("runs_multiple_times5", 0, () => { + const encoder = new Encoder(); + const decoder = new Decoder(); + + const arr = [data1, data2]; + const enc = arr.map>((x) => [x, encoder.encode(x)]); + + enc.forEach((pair) => { + let orig = pair[0] + let acc = pair[1] + let startTime1 = new Date().getTime(); + + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:regression #212 runs_multiple_times#${orig} #${acc} averageTime = ${averageTime1}`) + + assert.deepStrictEqual(decoder.decode(acc as ESObject), orig); + + }); + }); + }); + + assert.context("Encoder#encodeSharedRef()", () => { + it("returns_the_shared_reference", 0, () => { + const encoder = new Encoder(); + let startTime1 = new Date().getTime(); + const a = encoder.encodeSharedRef(true); + const b = encoder.encodeSharedRef(false); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:returns_the_shared_reference averageTime = ${averageTime1}`) + + assert.deepStrictEqual(decode(a), decode(b)); // yes, this is the expected behavior + assert.deepStrictEqual(a.buffer, b.buffer); + }); + }); + }); + }) + + +} + + + + + + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/CodecBigint.ts b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/CodecBigint.ts new file mode 100644 index 0000000..9f0848c --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/CodecBigint.ts @@ -0,0 +1,136 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import { encode, decode, ExtensionCodec, DecodeError } from "@ohos/msgpack"; + +namespace CodecBigint { + export function encodes_and_decodes_0n(): Object { + let startTime1 = new Date().getTime(); + const extensionCodec = new ExtensionCodec(); + extensionCodec.register({ + type: 0, + encode: (input: Object) => { + if (typeof input === "bigint") { + if (input <= Number.MAX_SAFE_INTEGER && input >= Number.MIN_SAFE_INTEGER) { + return encode(Number.parseInt(input.toString(), 10)); + } else { + return encode(input.toString()); + } + } else { + return null; + } + }, + decode: (data: Uint8Array) => { + const val: Object = decode(data); + if (!(typeof val === "string" || typeof val === "number")) { + throw new DecodeError(`unexpected BigInt source: ${val} (${typeof val})`); + } + return BigInt(val); + }, + }); + const value = BigInt(0); + const encoded = encode(value, { extensionCodec }); + const decoded = decode(encoded, { extensionCodec }); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 4; + console.log('msgpack-javascript:encodes_and_decodes_0n averageTime =' + averageTime1) + return decoded; + } + + + export function encodes_and_decodes_MAX_SAFE_INTEGER_1(): Object { + const extensionCodec = new ExtensionCodec(); + extensionCodec.register({ + type: 0, + encode: (input: Object) => { + if (typeof input === "bigint") { + if (input <= Number.MAX_SAFE_INTEGER && input >= Number.MIN_SAFE_INTEGER) { + return encode(Number.parseInt(input.toString(), 10)); + } else { + return encode(input.toString()); + } + } else { + return null; + } + }, + decode: (data: Uint8Array) => { + const val = decode(data); + if (!(typeof val === "string" || typeof val === "number")) { + throw new DecodeError(`unexpected BigInt source: ${val} (${typeof val})`); + } + return BigInt(val); + }, + }); + const value = BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1); + + let startTime1 = new Date().getTime(); + + const encoded = encode(value, {useBigInt64: true, + extensionCodec + }); + const decoded = decode(encoded, {useBigInt64: true, + extensionCodec + }); + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log('msgpack-javascript:encodes_and_decodes_MAX_SAFE_INTEGER_1 averageTime =' + averageTime1) + return decoded; + } + + export function encodes_and_decodes_MIN_SAFE_INTEGER_minus1(): Object { + const extensionCodec = new ExtensionCodec(); + extensionCodec.register({ + type: 0, + encode: (input: Object) => { + if (typeof input === "bigint") { + if (input <= Number.MAX_SAFE_INTEGER && input >= Number.MIN_SAFE_INTEGER) { + return encode(Number.parseInt(input.toString(), 10)); + } else { + return encode(input.toString()); + } + } else { + return null; + } + }, + decode: (data: Uint8Array) => { + const val = decode(data); + if (!(typeof val === "string" || typeof val === "number")) { + throw new DecodeError(`unexpected BigInt source: ${val} (${typeof val})`); + } + return BigInt(val); + }, + }); + const value = BigInt(Number.MIN_SAFE_INTEGER) - BigInt(1); + + let startTime1 = new Date().getTime(); + + const encoded = encode(value, { + extensionCodec + }); + const decoded = decode(encoded, { + extensionCodec + }); + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log('msgpack-javascript:encodes_and_decodes_MIN_SAFE_INTEGER_minus1 averageTime =' + averageTime1) + return decoded; + } +} + +export default CodecBigint; \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/ExtensionCodecTest.ts b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/ExtensionCodecTest.ts new file mode 100644 index 0000000..c35b394 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/ExtensionCodecTest.ts @@ -0,0 +1,313 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import { encode, decode, ExtensionCodec, decodeAsync } from "@ohos/msgpack"; + +namespace ExtensionCodecTest { + export function extensionCodecTest(it: Function, expect: Function): void { + let context: Function = (str: string, callback: Function) => { + callback(); + } + let deepStrictEqual: Function = (src: Object, dst: Object, info?: string) => { + expect(src).assertDeepEquals(dst) + if (info) { + console.log(info) + } + } + context("timestamp", () => { + const extensionCodec = ExtensionCodec.defaultCodec; + + it("encodes_and_decodes_a_date_without_milliseconds_timestamp_32", 0, () => { + let startTime1 = new Date().getTime(); + const date = new Date(1556633024000); + const encoded = encode(date, { + extensionCodec + }); + deepStrictEqual( + decode(encoded, { + extensionCodec + }), + date, + `date: ${date.toISOString()}, encoded: ${encoded}`, + ); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:encodes_and_decodes_a_date_without_milliseconds_timestamp_32 averageTime = ${averageTime1}`) + }); + + it("encodes_and_decodes_a_date_with_milliseconds_timestamp_64", 0, () => { + let startTime1 = new Date().getTime(); + const date = new Date(1556633024123); + const encoded = encode(date, { + extensionCodec + }); + deepStrictEqual( + decode(encoded, { + extensionCodec + }), + date, + `date: ${date.toISOString()}, encoded: ${encoded}`, + ); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:encodes_and_decodes_a_date_with_milliseconds_timestamp_64 averageTime = ${averageTime1}`) + }); + + it("encodes_and_decodes_a_future_date_timestamp_96_", 0, () => { + let startTime1 = new Date().getTime(); + const date = new Date(0x400000000 * 1000); + const encoded = encode(date, { + extensionCodec + }); + deepStrictEqual( + decode(encoded, { + extensionCodec + }), + date, + `date: ${date.toISOString()}, encoded: ${encoded}`, + ); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:encodes_and_decodes_a_future_date_timestamp_96_ averageTime = ${averageTime1}`) + }); + }); + + context("custom extensions", () => { + const extensionCodec = new ExtensionCodec(); + + // Set + extensionCodec.register({ + type: 0, + encode: (object: unknown): Uint8Array | null => { + if (object instanceof Set) { + return encode([...object]); + } else { + return null; + } + }, + decode: (data: Uint8Array) => { + const array = decode(data) as Array; + return new Set(array); + }, + }); + + // Map + extensionCodec.register({ + type: 1, + encode: (object: unknown): Uint8Array | null => { + if (object instanceof Map) { + return encode([...object]); + } else { + return null; + } + }, + decode: (data: Uint8Array) => { + const array = decode(data) as Array<[unknown, unknown]>; + return new Map(array); + }, + }); + + it("encodes_and_decodes_custom_data_types_synchronously", 0, () => { + let startTime1 = new Date().getTime(); + const set = new Set([1, 2, 3]); + const map = new Map([ + ["foo", "bar"], + ["bar", "baz"], + ]); + const encoded = encode([set, map], { + extensionCodec + }); + deepStrictEqual(decode(encoded, { + extensionCodec + }), [set, map]); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:encodes_and_decodes_custom_data_types_synchronously averageTime = ${averageTime1}`) + }); + + it("encodes_and_decodes_custom_data_types_asynchronously_", 0, async () => { + let startTime1 = new Date().getTime(); + const set = new Set([1, 2, 3]); + const map = new Map([ + ["foo", "bar"], + ["bar", "baz"], + ]); + const encoded = encode([set, map], { + extensionCodec + }); + const createStream = async function* () { + yield encoded; + }; + deepStrictEqual(await decodeAsync(createStream(), { + extensionCodec + }), [set, map]); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:encodes_and_decodes_custom_data_types_asynchronously_ averageTime = ${averageTime1}`) + }); + }); + + context("custom_extensions_with_custom_context", () => { + class Context { + public expectations: Array = []; + + constructor(public ctxVal: number) { + } + + public hasVisited(val: any) { + this.expectations.push(val); + } + } + + const extensionCodec = new ExtensionCodec(); + + class Magic { + constructor(public val: T) { + } + } + + // Magic + extensionCodec.register({ + type: 0, + encode: (object: unknown, context): Uint8Array | null => { + if (object instanceof Magic) { + context.hasVisited({ + encoding: object.val + }); + return encode({ + magic: object.val, ctx: context.ctxVal + }, { + extensionCodec, context + }); + } else { + return null; + } + }, + decode: (data: Uint8Array, extType, context) => { + extType; + const decoded = decode(data, { + extensionCodec, context + }) as { magic: number }; + context.hasVisited({ + decoding: decoded.magic, ctx: context.ctxVal + }); + return new Magic(decoded.magic); + }, + }); + + it("encodes_and_decodes_custom_data_types_synchronously", 0, () => { + const context = new Context(42); + const magic1 = new Magic(17); + const magic2 = new Magic({ + foo: new Magic("inner") + }); + const test = [magic1, magic2]; + + let startTime1 = new Date().getTime(); + const encoded = encode(test, { + extensionCodec, context + }); + let decoded = decode(encoded, { + extensionCodec, context + }); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:encodes_and_decodes_custom_data_types_synchronously averageTime = ${averageTime1}`) + + deepStrictEqual(decoded, test); + deepStrictEqual(context.expectations, [ + { + encoding: magic1.val, + }, + { + encoding: magic2.val, + }, + { + encoding: magic2.val.foo.val, + }, + { + ctx: 42, + decoding: magic1.val, + }, + { + ctx: 42, + decoding: magic2.val.foo.val, + }, + { + ctx: 42, + decoding: magic2.val, + }, + ]); + + }); + + it("encodes_and_decodes_custom_data_types_asynchronously_", 0, async () => { + + const context = new Context(42); + const magic1 = new Magic(17); + const magic2 = new Magic({ + foo: new Magic("inner") + }); + const test = [magic1, magic2]; + + let startTime1 = new Date().getTime(); + const encoded = encode(test, { + extensionCodec, context + }); + const createStream = async function* () { + yield encoded; + }; + let decoded = await decodeAsync(createStream(), { + extensionCodec, context + }); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:encodes_and_decodes_custom_data_types_asynchronously_ averageTime = ${averageTime1}`) + + + deepStrictEqual(decoded, test); + deepStrictEqual(context.expectations, [ + { + encoding: magic1.val, + }, + { + encoding: magic2.val, + }, + { + encoding: magic2.val.foo.val, + }, + { + ctx: 42, + decoding: magic1.val, + }, + { + ctx: 42, + decoding: magic2.val.foo.val, + }, + { + ctx: 42, + decoding: magic2.val, + }, + ]); + + }); + }); + } + +} + +export default ExtensionCodecTest; \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/MsgpackTestSuite.ts b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/MsgpackTestSuite.ts new file mode 100644 index 0000000..51a0fe0 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/MsgpackTestSuite.ts @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import { encode, decode } from "@ohos/msgpack"; + +namespace MsgpackTestSuite { + export function msgpackTestSuiteTest(it: Function, expect: Function): void { + // by detecting test coverage + const SPECS = { + FLOAT64_POSITIVE_INF: Number.POSITIVE_INFINITY, + FLOAT64_NEGATIVE_INF: Number.NEGATIVE_INFINITY, + FLOAT64_NAN: Number.NaN, + STR16: "a".repeat(0x100), + STR16_MBS: "🌏".repeat(0x100), + STR32: "b".repeat(0x10_000), + STR32_MBS: "🍣".repeat(0x10_000), + STR32LARGE: "c".repeat(0x50_000), // may cause "RangeError: Maximum call stack size exceeded" in simple implelementions + STR_INCLUDING_NUL: "foo\0bar\0", + STR_BROKEN_FF: "\xff", + BIN16: new Uint8Array(0x100).fill(0xff), + BIN32: new Uint8Array(0x10_000).fill(0xff), + BIN32LARGE: new Uint8Array(0x50_000).fill(0xff), // regression: caused "RangeError: Maximum call stack size exceeded" + ARRAY16: new Array(0x100).fill(true), + ARRAY32: new Array(0x10000).fill(true), + MAP16: new Array(0x100).fill(null).reduce>((acc, _val, i) => { + acc[`k${i}`] = i; + return acc; + }, {}), + MAP32: new Array(0x10000).fill(null).reduce>((acc, _val, i) => { + acc[`k${i}`] = i; + return acc; + }, {}), + MIXED: new Array(0x10).fill(Number.MAX_SAFE_INTEGER), + } as Record; + + for (const name of Object.keys(SPECS)) { + const value = SPECS[name]; + + it(`encodes_and_decodes_${name}`, 0, () => { + let startTime1 = new Date().getTime(); + let encoded; + let decoded; + try { + encoded = encode(value); + decoded = decode(new Uint8Array(encoded)) + } catch (err) { + + } finally { + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 2; + console.log(`msgpack-javascript:encodes_and_decodes_${name} averageTime = ${averageTime1}`) + } + expect(decoded).assertDeepEquals(value) + }); + } + + it("int_8", 0, () => { + let startTime1 = new Date().getTime(); + expect(encode(-128)).assertDeepEquals(Uint8Array.from([0xd0, 0x80])) + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:int_8 averageTime = ${averageTime1}`) + }); + } + +} + +export default MsgpackTestSuite; \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/MsgpackTestSuite2.ts b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/MsgpackTestSuite2.ts new file mode 100644 index 0000000..c1891a2 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/MsgpackTestSuite2.ts @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import { Exam } from "../msgpacksuit/exam"; +import { MsgTimestamp } from "../msg/msg-timestamp"; +import ohBuffer from '@ohos.buffer'; +import { encode, decode, ExtensionCodec, EXT_TIMESTAMP, encodeTimeSpecToTimestamp } from "@ohos/msgpack"; + + +namespace MsgpackTestSuite2 { + export function msgpackTestSuiteTest2(it: Function, expect: Function): void { + const extensionCodec = new ExtensionCodec(); + extensionCodec.register({ + type: EXT_TIMESTAMP, + encode: (input) => { + if (input instanceof MsgTimestamp) { + return encodeTimeSpecToTimestamp({ + sec: input.getTime(), + nsec: input.getNano(), + }); + } else { + return null; + } + }, + decode: (data: Uint8Array) => { + return MsgTimestamp.parse(ohBuffer.from(data)); + }, + }); + + const TEST_TYPES = { + array: 1, + bignum: 0, // TODO + binary: 1, + bool: 1, + map: 1, + nil: 1, + number: 1, + string: 1, + timestamp: 1, + }; + + Exam.getExams(TEST_TYPES).forEach((exam) => { + const types = exam.getTypes(TEST_TYPES); + const first = types[0]!; + const title = `${first}: ${exam.stringify(first)}`; + let result = `${exam.stringify(first)}` + it(`encodes_${title}`, 0, () => { + types.forEach((type) => { + const value = exam.getValue(type); + let startTime1 = new Date().getTime(); + const u8 = encode(value, { + extensionCodec + }); + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:encodes_${title} averageTime = ${averageTime1}`) + if (exam.matchMsgpack(u8)) { + expect(exam.stringify(type) + "").assertContain(result) + } else { + } + }); + }); + it(`decodes_${title}`, 0, () => { + const msgpacks = exam.getMsgpacks(); + + msgpacks.forEach((encoded, idx) => { + + let startTime1 = new Date().getTime(); + + const value = decode(encoded.buffer, { + extensionCodec + }); + + let endTime1 = new Date().getTime(); + let averageTime1 = ((endTime1 - startTime1) * 1000) / 1; + console.log(`msgpack-javascript:encodes_${title} averageTime = ${averageTime1}`) + + let bufferStr = exam.stringify(idx); + + if (exam.matchValue(value)) { + // 源库判断当前idx的数据内容是否存在,此处我们替换为 + // assert(true, exam.stringify(idx)); + let bufStrs = bufferStr.split('-') + let hexs = [] + let buf = []; + for (let i = 0; i < bufStrs.length; i++) { + let uin8Str = '0x' + bufStrs[i]; + hexs.push(uin8Str) + let radix10 = Number.parseInt(uin8Str) + buf.push(radix10) + } + for (let i = 0; i < buf.length; i++) { + expect(buf[i]).assertEqual(encoded[i]) + } + } + }); + }); + }); + } + +} + +export default MsgpackTestSuite2; \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/ReuseInstances.ts b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/ReuseInstances.ts new file mode 100644 index 0000000..ae72aac --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/ReuseInstances.ts @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import { Encoder, Decoder } from "@ohos/msgpack"; +import { reuseobject } from "./StdlibData" + +namespace ReuseInstances { + const createStream = async function* (...args: any) { + for (const item of args) { + yield item; + } + }; + + export function runsMultipleTimes1(): Object { + let encoder = new Encoder(); + let decoder = new Decoder(); + let encoded: Uint8Array = encoder.encode(reuseobject); + return decoder.decode(encoded); + } + + export async function runsMultipleTimes2(): Promise { + let encoder = new Encoder(); + let decoder = new Decoder(); + let encoded: Uint8Array = encoder.encode(reuseobject); + return await decoder.decodeAsync(createStream(encoded)); + } + + export async function runsMultipleTimes3Or4(result: Array, index: number): Promise { + let encoder = new Encoder(); + let decoder = new Decoder(); + let encoded: Uint8Array; + if (index === 4) { + encoded = encoder.encode([reuseobject]); + } else if (index === 3) { + encoded = encoder.encode(reuseobject); + } + for await (const item of decoder.decodeStream(createStream(encoded))) { + result.push(item); + } + } + +} + +export default ReuseInstances; \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/Stdlib.ts b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/Stdlib.ts new file mode 100644 index 0000000..057d11f --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/Stdlib.ts @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import { o } from './StdlibData'; + +export function seq(n: number) { + const a: Array = []; + for (let i = 0; i < n; i++) { + a.push((i + 1) % 0xff); + } + return Uint8Array.from(a); +} + +export function defineProperty() { + Object.defineProperty(o, "__proto__", { + value: new Date(0), + enumerable: true, + }); +} + diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/StdlibData.ts b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/StdlibData.ts new file mode 100644 index 0000000..2d3d90c --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/StdlibData.ts @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import { ExtData } from '@ohos/msgpack'; +import { seq } from './Stdlib'; + +export const data1 = { + isCommunication: false, + isWarning: false, + alarmId: "619f65a2774abf00568b7210", + intervalStart: "2022-05-20T12:00:00.000Z", + intervalStop: "2022-05-20T13:00:00.000Z", + triggeredAt: "2022-05-20T13:00:00.000Z", + component: "someComponent", + _id: "6287920245a582301475627d", +}; + +export const data2 = { + foo: "bar", +}; + +export const o = { + foo: "bar", +}; + +export const reuseobject = { + nil: null, + integer: 1, + float: Math.PI, + string: "Hello, world!", + binary: Uint8Array.from([1, 2, 3]), + array: [10, 20, 30], + map: { foo: "bar" }, + timestampExt: new Date(), +}; + +export const SPECS = { + FIXEXT1: [0xd4, new ExtData(0, seq(1))], + FIXEXT2: [0xd5, new ExtData(0, seq(2))], + FIXEXT4: [0xd6, new ExtData(0, seq(4))], + FIXEXT8: [0xd7, new ExtData(0, seq(8))], + FIXEXT16: [0xd8, new ExtData(0, seq(16))], + EXT8: [0xc7, new ExtData(0, seq(17))], + EXT16: [0xc8, new ExtData(0, seq(0x100))], + EXT32: [0xc9, new ExtData(0, seq(0x10000))], +} as Record; + +export const TEST_TYPES = { + array: 1, + bignum: 0, // TODO + binary: 1, + bool: 1, + map: 1, + nil: 1, + number: 1, + string: 1, + timestamp: 1, +}; + +export const floatSPECS = { + POSITIVE_ZERO: +0.0, + NEGATIVE_ZERO: -0.0, + POSITIVE_INFINITY: Number.POSITIVE_INFINITY, + NEGATIVE_INFINITY: Number.NEGATIVE_INFINITY, + + POSITIVE_VALUE_1: +0.1, + POSITIVE_VALUE_2: +42, + POSITIVE_VALUE_3: +Math.PI, + POSITIVE_VALUE_4: +Math.E, + NEGATIVE_VALUE_1: -0.1, + NEGATIVE_VALUE_2: -42, + NEGATIVE_VALUE_3: -Math.PI, + NEGATIVE_VALUE_4: -Math.E, + + MAX_SAFE_INTEGER: Number.MAX_SAFE_INTEGER, + MIN_SAFE_INTEGER: Number.MIN_SAFE_INTEGER, + + MAX_VALUE: Number.MAX_VALUE, + MIN_VALUE: Number.MIN_VALUE, +} as Record; + +export const INT64SPECS = { + ZERO: 0, + ONE: 1, + MINUS_ONE: -1, + X_FF: 0xff, + MINUS_X_FF: -0xff, + INT32_MAX: 0x7fffffff, + INT32_MIN: -0x7fffffff - 1, + MAX_SAFE_INTEGER: Number.MAX_SAFE_INTEGER, + MIN_SAFE_INTEGER: Number.MIN_SAFE_INTEGER, +} as Record; + +const TIME = 1556636810389; +export const timestampSPECS = { + ZERO: new Date(0), + TIME_BEFORE_EPOCH_NS: new Date(-1), + TIME_BEFORE_EPOCH_SEC: new Date(-1000), + TIME_BEFORE_EPOCH_SEC_AND_NS: new Date(-1002), + TIMESTAMP32: new Date(Math.floor(TIME / 1000) * 1000), + TIMESTAMP64: new Date(TIME), + TIMESTAMP64_OVER_INT32: new Date(Date.UTC(2200, 0)), // cf. https://github.com/msgpack/msgpack-ruby/pull/172 + TIMESTAMP96_SEC_OVER_UINT32: new Date(0x400000000 * 1000), + TIMESTAMP96_SEC_OVER_UINT32_WITH_NS: new Date(0x400000000 * 1000 + 2), + + REGRESSION_1: new Date(1556799054803), +} as Record; + +export const decodeobject = { + foo: 1, + bar: 2, + baz: ["one", "two", "three"], +}; + +export const decodeOption = { + maxStrLength: 1 +}; + +export const decodeAsyncObject = { + nil: null, + true: true, + false: false, + int: -42, + uint64: Number.MAX_SAFE_INTEGER, + int64: Number.MIN_SAFE_INTEGER, + float: Math.PI, + string: "Hello, world!", + longString: "Hello, world!\n".repeat(100), + binary: Uint8Array.from([0xf1, 0xf2, 0xf3]), + array: [1000, 2000, 3000], + map: { + foo: 1, bar: 2, baz: 3 + }, + timestampExt: new Date(), + map0: {}, + array0: [], + str0: "", + bin0: Uint8Array.from([]), +}; \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/Util.ts b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/Util.ts new file mode 100644 index 0000000..c203f32 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/test/test/stdlib/Util.ts @@ -0,0 +1,162 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +import { encode, decode, decodeAsync, decodeArrayStream, decodeMultiStream, decodeMulti } from "@ohos/msgpack"; + +type BufferSource = ArrayBufferView | ArrayBuffer; + +namespace Util { + + export function decodeObject(object: Object): Object { + return decode(object as any); + } + + export async function decodeAsyncObject(object: Object): Promise { + return await decodeAsync(object as any) + } + + export async function decodeArrayStreamsSetResult(stream: Object, result: Array): Promise { + for await (const item of decodeArrayStream(stream as any)) { + result.push(item); + } + } + + export async function decodeMultiStreamsSetResult(stream: Object, result: Array): Promise { + for await (const item of decodeMultiStream(stream as any)) { + result.push(item); + } + } + + export function decodeMultiSetResult(stream: Object, result: Array): void { + for (const item of decodeMulti(stream as any)) { + result.push(item); + } + } + + export async function* createStreams(object: Object): Object { + for (const byte of encode(object)) { + yield [byte]; + } + } + + export async function* decodesCreateStream(items: Array): AsyncGenerator { + for (const item of items) { + yield encode(item); + } + } + + export async function* Uint8ArrayCreateStreams(array: Uint8Array): AsyncGenerator { + yield array; + } + + export async function* decodeMultiCreateStream() { + yield []; + } + + export async function* throwsErrorsCreateStream() { + yield [0x81]; // fixmap size=1 + yield encode(null); + yield encode(null); + } + + export async function* asynchronous1CreateStream() { + yield [0x92]; // fixarray size=2 + yield encode(null); + } + + export async function* asynchronous2CreateStream() { + yield [0x90]; // fixarray size=0 + yield encode(null); + } + ; + + export async function* asynchronous3CreateStream() { + yield [0x90, ...encode(null)]; // fixarray size=0 + nil + } + + export async function* bufferSourceCreateStream() { + yield [0x81] as ArrayLike; // fixmap size=1 + yield encode("foo") as BufferSource; + yield encode("bar") as BufferSource; + } + + function wrapWithNoisyBuffer(byte: number) { + return Uint8Array.from([0x01, byte, 0x02]).subarray(1, 2); + } + + export async function* noisyBufferCreateStream(): Object { + yield wrapWithNoisyBuffer(0xc5); // bin 16 + yield [0x00]; + yield [0x00]; // bin size=0 + } + + export async function* byteByByteCreateStream(): Object { + yield [0xc4]; // bin 8 + yield [0x03]; // bin size=3 + yield [0x66]; // "f" + yield [0x6f]; // "o" + yield [0x6f]; // "o" + } + + export async function* byteByByte2CreateStream(): Object { + yield [0xa3]; // fixstr size=3 + yield [0x66]; // "f" + yield [0x6f]; // "o" + yield [0x6f]; // "o" + } + + export async function* byteByByte3CreateStream(): Object { + yield [0xcd]; // uint 16 + yield [0x12]; + yield [0x34]; + } + + export async function* fooBarCreateStream(): Object { + yield [0x81]; // fixmap size=1 + yield encode("foo"); + yield encode("bar"); + } + + export async function* nil1CreateStream(): Object { + yield wrapWithNoisyBuffer(0xc0); // nil + } + + export async function* nil2CreateStream(): Object { + yield wrapWithNoisyBuffer(0x91); // fixarray size=1 + yield [0xc0]; // nil + } + + export async function* array16CreateStream(): Object { + yield [0xdc, 0, 3]; + yield encode(1); + yield encode(2); + yield encode(3); + } + + export async function* array32CreateStream(): Object { + yield [0xdd, 0, 0, 0, 3]; + yield encode(1); + yield encode(2); + yield encode(3); + } + + export function expandDecodeMulti(): Object { + return [...decodeMulti([])]; + } +} + +export default Util; \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/testability/TestAbility.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/testability/TestAbility.ets new file mode 100644 index 0000000..826237e --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/testability/TestAbility.ets @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import UIAbility from '@ohos.app.ability.UIAbility'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import hilog from '@ohos.hilog'; +import { Hypium } from '@ohos/hypium'; +import testsuite from '../test/List.test'; +import window from '@ohos.window'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import Want from '@ohos.app.ability.Want'; + +export default class TestAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); + hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); + hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:'+ JSON.stringify(launchParam) ?? ''); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + let abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); + windowStage.loadContent('testability/pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/testability/pages/Index.ets b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 0000000..d3f3374 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import hilog from '@ohos.hilog'; + +@Entry +@Component +struct Index { + aboutToAppear() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear'); + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts new file mode 100644 index 0000000..9e91383 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +import hilog from '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +async function onAbilityCreateCallback() { + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName + var debug = abilityDelegatorArguments.parameters['-D'] + if (debug == 'true') + { + cmd += ' -D' + } + hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd); + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/module.json5 b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000..c386019 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/module.json5 @@ -0,0 +1,36 @@ +{ + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "exported": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/resources/base/element/color.json b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 0000000..3c71296 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/resources/base/element/string.json b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 0000000..65d8fa5 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/resources/base/media/icon.png b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000..e69de29 diff --git a/OpenHarmony/ohos_msgpack/entry/src/ohosTest/resources/base/profile/test_pages.json b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/resources/base/profile/test_pages.json new file mode 100644 index 0000000..b7e7343 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/entry/src/ohosTest/resources/base/profile/test_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "testability/pages/Index" + ] +} diff --git a/OpenHarmony/ohos_msgpack/hvigor/hvigor-config.json5 b/OpenHarmony/ohos_msgpack/hvigor/hvigor-config.json5 new file mode 100644 index 0000000..122677b --- /dev/null +++ b/OpenHarmony/ohos_msgpack/hvigor/hvigor-config.json5 @@ -0,0 +1,6 @@ +{ + "hvigorVersion": "3.0.9", + "dependencies": { + "@ohos/hvigor-ohos-plugin": "3.0.9" + } +} \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/hvigor/hvigor-wrapper.js b/OpenHarmony/ohos_msgpack/hvigor/hvigor-wrapper.js new file mode 100644 index 0000000..2be61f6 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/hvigor/hvigor-wrapper.js @@ -0,0 +1 @@ +"use strict";var u=require("path"),D=require("os"),e=require("fs"),t=require("child_process"),r=require("crypto"),n="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},i={},C={},F=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(C,"__esModule",{value:!0}),C.maxPathLength=C.isMac=C.isLinux=C.isWindows=void 0;const E=F(D),A="Windows_NT",o="Darwin";function a(){return E.default.type()===A}function c(){return E.default.type()===o}C.isWindows=a,C.isLinux=function(){return"Linux"===E.default.type()},C.isMac=c,C.maxPathLength=function(){return c()?1016:a()?259:4095},function(e){var t=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),r=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),i=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&t(D,u,e);return r(D,u),D};Object.defineProperty(e,"__esModule",{value:!0}),e.WORK_SPACE=e.HVIGOR_PROJECT_WRAPPER_HOME=e.HVIGOR_PROJECT_ROOT_DIR=e.HVIGOR_PROJECT_CACHES_HOME=e.HVIGOR_PNPM_STORE_PATH=e.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH=e.PROJECT_CACHES=e.HVIGOR_WRAPPER_TOOLS_HOME=e.HVIGOR_USER_HOME=e.DEFAULT_PACKAGE_JSON=e.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME=e.PNPM=e.HVIGOR=e.NPM_TOOL=e.PNPM_TOOL=e.HVIGOR_ENGINE_PACKAGE_NAME=void 0;const F=i(D),E=i(u),A=C;e.HVIGOR_ENGINE_PACKAGE_NAME="@ohos/hvigor",e.PNPM_TOOL=(0,A.isWindows)()?"pnpm.cmd":"pnpm",e.NPM_TOOL=(0,A.isWindows)()?"npm.cmd":"npm",e.HVIGOR="hvigor",e.PNPM="pnpm",e.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME="hvigor-config.json5",e.DEFAULT_PACKAGE_JSON="package.json",e.HVIGOR_USER_HOME=E.resolve(F.homedir(),".hvigor"),e.HVIGOR_WRAPPER_TOOLS_HOME=E.resolve(e.HVIGOR_USER_HOME,"wrapper","tools"),e.PROJECT_CACHES="project_caches",e.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH=E.resolve(e.HVIGOR_WRAPPER_TOOLS_HOME,"node_modules",".bin",e.PNPM_TOOL),e.HVIGOR_PNPM_STORE_PATH=E.resolve(e.HVIGOR_USER_HOME,"caches"),e.HVIGOR_PROJECT_CACHES_HOME=E.resolve(e.HVIGOR_USER_HOME,e.PROJECT_CACHES),e.HVIGOR_PROJECT_ROOT_DIR=process.cwd(),e.HVIGOR_PROJECT_WRAPPER_HOME=E.resolve(e.HVIGOR_PROJECT_ROOT_DIR,e.HVIGOR),e.WORK_SPACE="workspace"}(i);var s={},l={};Object.defineProperty(l,"__esModule",{value:!0}),l.logInfoPrintConsole=l.logErrorAndExit=void 0,l.logErrorAndExit=function(u){u instanceof Error?console.error(u.message):console.error(u),process.exit(-1)},l.logInfoPrintConsole=function(u){console.log(u)};var B=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),d=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),f=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&B(D,u,e);return d(D,u),D};Object.defineProperty(s,"__esModule",{value:!0});var _=s.executeBuild=void 0;const p=f(e),O=f(u),h=l;_=s.executeBuild=function(u){const D=O.resolve(u,"node_modules","@ohos","hvigor","bin","hvigor.js");try{const u=p.realpathSync(D);require(u)}catch(e){(0,h.logErrorAndExit)(`Error: ENOENT: no such file ${D},delete ${u} and retry.`)}};var P={},v={},g={},m={};Object.defineProperty(m,"__esModule",{value:!0}),m.Unicode=void 0;class R{}m.Unicode=R,R.SPACE_SEPARATOR=/[\u1680\u2000-\u200A\u202F\u205F\u3000]/,R.ID_START=/[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/,R.ID_CONTINUE=/[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/,Object.defineProperty(g,"__esModule",{value:!0}),g.JudgeUtil=void 0;const y=m;g.JudgeUtil=class{static isIgnoreChar(u){return"string"==typeof u&&("\t"===u||"\v"===u||"\f"===u||" "===u||" "===u||"\ufeff"===u||"\n"===u||"\r"===u||"\u2028"===u||"\u2029"===u)}static isSpaceSeparator(u){return"string"==typeof u&&y.Unicode.SPACE_SEPARATOR.test(u)}static isIdStartChar(u){return"string"==typeof u&&(u>="a"&&u<="z"||u>="A"&&u<="Z"||"$"===u||"_"===u||y.Unicode.ID_START.test(u))}static isIdContinueChar(u){return"string"==typeof u&&(u>="a"&&u<="z"||u>="A"&&u<="Z"||u>="0"&&u<="9"||"$"===u||"_"===u||"‌"===u||"‍"===u||y.Unicode.ID_CONTINUE.test(u))}static isDigitWithoutZero(u){return/[1-9]/.test(u)}static isDigit(u){return"string"==typeof u&&/[0-9]/.test(u)}static isHexDigit(u){return"string"==typeof u&&/[0-9A-Fa-f]/.test(u)}};var I=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(v,"__esModule",{value:!0}),v.parseJsonText=v.parseJsonFile=void 0;const N=I(e),b=I(D),S=I(u),w=g;var H;!function(u){u[u.Char=0]="Char",u[u.EOF=1]="EOF",u[u.Identifier=2]="Identifier"}(H||(H={}));let x,M,T,V,G,j,J="start",U=[],W=0,L=1,$=0,k=!1,K="default",z="'",q=1;function Z(u,D=!1){M=String(u),J="start",U=[],W=0,L=1,$=0,V=void 0,k=D;do{x=X(),ru[J]()}while("eof"!==x.type);return V}function X(){for(K="default",G="",z="'",q=1;;){j=Q();const u=uu[K]();if(u)return u}}function Q(){if(M[W])return String.fromCodePoint(M.codePointAt(W))}function Y(){const u=Q();return"\n"===u?(L++,$=0):u?$+=u.length:$++,u&&(W+=u.length),u}v.parseJsonFile=function(u,D=!1,e="utf-8"){const t=N.default.readFileSync(S.default.resolve(u),{encoding:e});try{return Z(t,D)}catch(D){if(D instanceof SyntaxError){const e=D.message.split("at");if(2===e.length)throw new Error(`${e[0].trim()}${b.default.EOL}\t at ${u}:${e[1].trim()}`)}throw new Error(`${u} is not in valid JSON/JSON5 format.`)}},v.parseJsonText=Z;const uu={default(){switch(j){case"/":return Y(),void(K="comment");case void 0:return Y(),Du("eof")}if(!w.JudgeUtil.isIgnoreChar(j)&&!w.JudgeUtil.isSpaceSeparator(j))return uu[J]();Y()},start(){K="value"},beforePropertyName(){switch(j){case"$":case"_":return G=Y(),void(K="identifierName");case"\\":return Y(),void(K="identifierNameStartEscape");case"}":return Du("punctuator",Y());case'"':case"'":return z=j,Y(),void(K="string")}if(w.JudgeUtil.isIdStartChar(j))return G+=Y(),void(K="identifierName");throw Fu(H.Char,Y())},afterPropertyName(){if(":"===j)return Du("punctuator",Y());throw Fu(H.Char,Y())},beforePropertyValue(){K="value"},afterPropertyValue(){switch(j){case",":case"}":return Du("punctuator",Y())}throw Fu(H.Char,Y())},beforeArrayValue(){if("]"===j)return Du("punctuator",Y());K="value"},afterArrayValue(){switch(j){case",":case"]":return Du("punctuator",Y())}throw Fu(H.Char,Y())},end(){throw Fu(H.Char,Y())},comment(){switch(j){case"*":return Y(),void(K="multiLineComment");case"/":return Y(),void(K="singleLineComment")}throw Fu(H.Char,Y())},multiLineComment(){switch(j){case"*":return Y(),void(K="multiLineCommentAsterisk");case void 0:throw Fu(H.Char,Y())}Y()},multiLineCommentAsterisk(){switch(j){case"*":return void Y();case"/":return Y(),void(K="default");case void 0:throw Fu(H.Char,Y())}Y(),K="multiLineComment"},singleLineComment(){switch(j){case"\n":case"\r":case"\u2028":case"\u2029":return Y(),void(K="default");case void 0:return Y(),Du("eof")}Y()},value(){switch(j){case"{":case"[":return Du("punctuator",Y());case"n":return Y(),eu("ull"),Du("null",null);case"t":return Y(),eu("rue"),Du("boolean",!0);case"f":return Y(),eu("alse"),Du("boolean",!1);case"-":case"+":return"-"===Y()&&(q=-1),void(K="numerical");case".":case"0":case"I":case"N":return void(K="numerical");case'"':case"'":return z=j,Y(),G="",void(K="string")}if(void 0===j||!w.JudgeUtil.isDigitWithoutZero(j))throw Fu(H.Char,Y());K="numerical"},numerical(){switch(j){case".":return G=Y(),void(K="decimalPointLeading");case"0":return G=Y(),void(K="zero");case"I":return Y(),eu("nfinity"),Du("numeric",q*(1/0));case"N":return Y(),eu("aN"),Du("numeric",NaN)}if(void 0!==j&&w.JudgeUtil.isDigitWithoutZero(j))return G=Y(),void(K="decimalInteger");throw Fu(H.Char,Y())},zero(){switch(j){case".":case"e":case"E":return void(K="decimal");case"x":case"X":return G+=Y(),void(K="hexadecimal")}return Du("numeric",0)},decimalInteger(){switch(j){case".":case"e":case"E":return void(K="decimal")}if(!w.JudgeUtil.isDigit(j))return Du("numeric",q*Number(G));G+=Y()},decimal(){switch(j){case".":G+=Y(),K="decimalFraction";break;case"e":case"E":G+=Y(),K="decimalExponent"}},decimalPointLeading(){if(w.JudgeUtil.isDigit(j))return G+=Y(),void(K="decimalFraction");throw Fu(H.Char,Y())},decimalFraction(){switch(j){case"e":case"E":return G+=Y(),void(K="decimalExponent")}if(!w.JudgeUtil.isDigit(j))return Du("numeric",q*Number(G));G+=Y()},decimalExponent(){switch(j){case"+":case"-":return G+=Y(),void(K="decimalExponentSign")}if(w.JudgeUtil.isDigit(j))return G+=Y(),void(K="decimalExponentInteger");throw Fu(H.Char,Y())},decimalExponentSign(){if(w.JudgeUtil.isDigit(j))return G+=Y(),void(K="decimalExponentInteger");throw Fu(H.Char,Y())},decimalExponentInteger(){if(!w.JudgeUtil.isDigit(j))return Du("numeric",q*Number(G));G+=Y()},hexadecimal(){if(w.JudgeUtil.isHexDigit(j))return G+=Y(),void(K="hexadecimalInteger");throw Fu(H.Char,Y())},hexadecimalInteger(){if(!w.JudgeUtil.isHexDigit(j))return Du("numeric",q*Number(G));G+=Y()},identifierNameStartEscape(){if("u"!==j)throw Fu(H.Char,Y());Y();const u=tu();switch(u){case"$":case"_":break;default:if(!w.JudgeUtil.isIdStartChar(u))throw Fu(H.Identifier)}G+=u,K="identifierName"},identifierName(){switch(j){case"$":case"_":case"‌":case"‍":return void(G+=Y());case"\\":return Y(),void(K="identifierNameEscape")}if(!w.JudgeUtil.isIdContinueChar(j))return Du("identifier",G);G+=Y()},identifierNameEscape(){if("u"!==j)throw Fu(H.Char,Y());Y();const u=tu();switch(u){case"$":case"_":case"‌":case"‍":break;default:if(!w.JudgeUtil.isIdContinueChar(u))throw Fu(H.Identifier)}G+=u,K="identifierName"},string(){switch(j){case"\\":return Y(),void(G+=function(){const u=Q(),D=function(){switch(Q()){case"b":return Y(),"\b";case"f":return Y(),"\f";case"n":return Y(),"\n";case"r":return Y(),"\r";case"t":return Y(),"\t";case"v":return Y(),"\v"}return}();if(D)return D;switch(u){case"0":if(Y(),w.JudgeUtil.isDigit(Q()))throw Fu(H.Char,Y());return"\0";case"x":return Y(),function(){let u="",D=Q();if(!w.JudgeUtil.isHexDigit(D))throw Fu(H.Char,Y());if(u+=Y(),D=Q(),!w.JudgeUtil.isHexDigit(D))throw Fu(H.Char,Y());return u+=Y(),String.fromCodePoint(parseInt(u,16))}();case"u":return Y(),tu();case"\n":case"\u2028":case"\u2029":return Y(),"";case"\r":return Y(),"\n"===Q()&&Y(),""}if(void 0===u||w.JudgeUtil.isDigitWithoutZero(u))throw Fu(H.Char,Y());return Y()}());case'"':case"'":if(j===z){const u=Du("string",G);return Y(),u}return void(G+=Y());case"\n":case"\r":case void 0:throw Fu(H.Char,Y());case"\u2028":case"\u2029":!function(u){console.warn(`JSON5: '${Cu(u)}' in strings is not valid ECMAScript; consider escaping.`)}(j)}G+=Y()}};function Du(u,D){return{type:u,value:D,line:L,column:$}}function eu(u){for(const D of u){if(Q()!==D)throw Fu(H.Char,Y());Y()}}function tu(){let u="",D=4;for(;D-- >0;){const D=Q();if(!w.JudgeUtil.isHexDigit(D))throw Fu(H.Char,Y());u+=Y()}return String.fromCodePoint(parseInt(u,16))}const ru={start(){if("eof"===x.type)throw Fu(H.EOF);nu()},beforePropertyName(){switch(x.type){case"identifier":case"string":return T=x.value,void(J="afterPropertyName");case"punctuator":return void iu();case"eof":throw Fu(H.EOF)}},afterPropertyName(){if("eof"===x.type)throw Fu(H.EOF);J="beforePropertyValue"},beforePropertyValue(){if("eof"===x.type)throw Fu(H.EOF);nu()},afterPropertyValue(){if("eof"===x.type)throw Fu(H.EOF);switch(x.value){case",":return void(J="beforePropertyName");case"}":iu()}},beforeArrayValue(){if("eof"===x.type)throw Fu(H.EOF);"punctuator"!==x.type||"]"!==x.value?nu():iu()},afterArrayValue(){if("eof"===x.type)throw Fu(H.EOF);switch(x.value){case",":return void(J="beforeArrayValue");case"]":iu()}},end(){}};function nu(){const u=function(){let u;switch(x.type){case"punctuator":switch(x.value){case"{":u={};break;case"[":u=[]}break;case"null":case"boolean":case"numeric":case"string":u=x.value}return u}();if(k&&"object"==typeof u&&(u._line=L,u._column=$),void 0===V)V=u;else{const D=U[U.length-1];Array.isArray(D)?k&&"object"!=typeof u?D.push({value:u,_line:L,_column:$}):D.push(u):D[T]=k&&"object"!=typeof u?{value:u,_line:L,_column:$}:u}!function(u){if(u&&"object"==typeof u)U.push(u),J=Array.isArray(u)?"beforeArrayValue":"beforePropertyName";else{const u=U[U.length-1];J=u?Array.isArray(u)?"afterArrayValue":"afterPropertyValue":"end"}}(u)}function iu(){U.pop();const u=U[U.length-1];J=u?Array.isArray(u)?"afterArrayValue":"afterPropertyValue":"end"}function Cu(u){const D={"'":"\\'",'"':'\\"',"\\":"\\\\","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t","\v":"\\v","\0":"\\0","\u2028":"\\u2028","\u2029":"\\u2029"};if(D[u])return D[u];if(u<" "){const D=u.charCodeAt(0).toString(16);return`\\x${`00${D}`.substring(D.length)}`}return u}function Fu(u,D){let e="";switch(u){case H.Char:e=void 0===D?`JSON5: invalid end of input at ${L}:${$}`:`JSON5: invalid character '${Cu(D)}' at ${L}:${$}`;break;case H.EOF:e=`JSON5: invalid end of input at ${L}:${$}`;break;case H.Identifier:$-=5,e=`JSON5: invalid identifier character at ${L}:${$}`}const t=new Eu(e);return t.lineNumber=L,t.columnNumber=$,t}class Eu extends SyntaxError{}var Au={},ou=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),au=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),cu=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&ou(D,u,e);return au(D,u),D},su=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(Au,"__esModule",{value:!0}),Au.isFileExists=Au.offlinePluginConversion=Au.executeCommand=Au.getNpmPath=Au.hasNpmPackInPaths=void 0;const lu=t,Bu=su(e),du=cu(u),fu=i,_u=l;Au.hasNpmPackInPaths=function(u,D){try{return require.resolve(u,{paths:[...D]}),!0}catch(u){return!1}},Au.getNpmPath=function(){const u=process.execPath;return du.join(du.dirname(u),fu.NPM_TOOL)},Au.executeCommand=function(u,D,e){0!==(0,lu.spawnSync)(u,D,e).status&&(0,_u.logErrorAndExit)(`Error: ${u} ${D} execute failed.See above for details.`)},Au.offlinePluginConversion=function(u,D){return D.startsWith("file:")||D.endsWith(".tgz")?du.resolve(u,fu.HVIGOR,D.replace("file:","")):D},Au.isFileExists=function(u){return Bu.default.existsSync(u)&&Bu.default.statSync(u).isFile()};var pu={};!function(u){var D=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(u,"__esModule",{value:!0}),u.hashFile=u.hash=u.createHash=void 0;const t=D(r),i=D(e);u.createHash=(u="MD5")=>t.default.createHash(u);u.hash=(D,e)=>(0,u.createHash)(e).update(D).digest("hex");u.hashFile=(D,e)=>{if(i.default.existsSync(D))return(0,u.hash)(i.default.readFileSync(D,"utf-8"),e)}}(pu);var Ou=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),hu=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),Pu=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&Ou(D,u,e);return hu(D,u),D},vu=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(P,"__esModule",{value:!0});var gu=P.initProjectWorkSpace=void 0;const mu=Pu(e),Ru=Pu(u),yu=i,Iu=v,Nu=l,bu=Au,Su=vu(D),wu=pu;let Hu,xu,Mu;function Tu(u,D,e){return void 0!==e.dependencies&&(0,bu.offlinePluginConversion)(yu.HVIGOR_PROJECT_ROOT_DIR,D.dependencies[u])===Ru.normalize(e.dependencies[u])}function Vu(){const u=Ru.join(Mu,yu.WORK_SPACE);if((0,Nu.logInfoPrintConsole)("Hvigor cleaning..."),!mu.existsSync(u))return;const D=mu.readdirSync(u);if(!D||0===D.length)return;const e=Ru.resolve(Mu,"node_modules","@ohos","hvigor","bin","hvigor.js");mu.existsSync(e)&&(0,bu.executeCommand)(process.argv[0],[e,"--stop-daemon"],{});try{D.forEach((D=>{mu.rmSync(Ru.resolve(u,D),{recursive:!0})}))}catch(D){(0,Nu.logErrorAndExit)(`The hvigor build tool cannot be installed. Please manually clear the workspace directory and synchronize the project again.\n\n Workspace Path: ${u}.`)}}gu=P.initProjectWorkSpace=function(){if(Hu=function(){const u=Ru.resolve(yu.HVIGOR_PROJECT_WRAPPER_HOME,yu.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME);mu.existsSync(u)||(0,Nu.logErrorAndExit)(`Error: Hvigor config file ${u} does not exist.`);return(0,Iu.parseJsonFile)(u)}(),Mu=function(u){let D,e=u.hvigorVersion;e.endsWith(".tgz")&&(e=function(u){let D=Ru.normalize(u);const e=D.lastIndexOf(Ru.sep);-1!==e&&(D=D.substring(e+1));D=D.replace(".tgz","");let t=0;for(let u=0;u="0"&&D.charAt(u)<="9"){t=u;break}return D=D.substring(t),D}(e));D=e>"2.5.0"?function(u){let D=`${yu.HVIGOR_ENGINE_PACKAGE_NAME}@${u.hvigorVersion}`;const e=u.dependencies;if(e){Object.getOwnPropertyNames(e).sort().forEach((u=>{D+=`,${u}@${e[u]}`}))}return(0,wu.hash)(D)}(u):(0,wu.hash)(process.cwd());return Ru.resolve(Su.default.homedir(),".hvigor","project_caches",D)}(Hu),xu=function(){const u=Ru.resolve(Mu,yu.WORK_SPACE,yu.DEFAULT_PACKAGE_JSON);return mu.existsSync(u)?(0,Iu.parseJsonFile)(u):{dependencies:{}}}(),!(0,bu.hasNpmPackInPaths)(yu.HVIGOR_ENGINE_PACKAGE_NAME,[Ru.join(Mu,yu.WORK_SPACE)])||(0,bu.offlinePluginConversion)(yu.HVIGOR_PROJECT_ROOT_DIR,Hu.hvigorVersion)!==xu.dependencies[yu.HVIGOR_ENGINE_PACKAGE_NAME]||!function(){function u(u){const D=null==u?void 0:u.dependencies;return void 0===D?0:Object.getOwnPropertyNames(D).length}const D=u(Hu),e=u(xu);if(D+1!==e)return!1;for(const u in null==Hu?void 0:Hu.dependencies)if(!(0,bu.hasNpmPackInPaths)(u,[Ru.join(Mu,yu.WORK_SPACE)])||!Tu(u,Hu,xu))return!1;return!0}()){Vu();try{!function(){(0,Nu.logInfoPrintConsole)("Hvigor installing...");for(const u in Hu.dependencies)Hu.dependencies[u]&&(Hu.dependencies[u]=(0,bu.offlinePluginConversion)(yu.HVIGOR_PROJECT_ROOT_DIR,Hu.dependencies[u]));const u={dependencies:{...Hu.dependencies}};u.dependencies[yu.HVIGOR_ENGINE_PACKAGE_NAME]=(0,bu.offlinePluginConversion)(yu.HVIGOR_PROJECT_ROOT_DIR,Hu.hvigorVersion);const D=Ru.join(Mu,yu.WORK_SPACE);try{mu.mkdirSync(D,{recursive:!0});const e=Ru.resolve(D,yu.DEFAULT_PACKAGE_JSON);mu.writeFileSync(e,JSON.stringify(u))}catch(u){(0,Nu.logErrorAndExit)(u)}(function(){const u=["config","set","store-dir",yu.HVIGOR_PNPM_STORE_PATH],D={cwd:Ru.join(Mu,yu.WORK_SPACE),stdio:["inherit","inherit","inherit"]};(0,bu.executeCommand)(yu.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,u,D)})(),function(){const u=["install"],D={cwd:Ru.join(Mu,yu.WORK_SPACE),stdio:["inherit","inherit","inherit"]};(0,bu.executeCommand)(yu.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,u,D)}(),(0,Nu.logInfoPrintConsole)("Hvigor install success.")}()}catch(u){Vu()}}return Mu};var Gu={};!function(r){var C=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),F=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),E=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&C(D,u,e);return F(D,u),D},A=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(r,"__esModule",{value:!0}),r.executeInstallPnpm=r.isPnpmInstalled=r.environmentHandler=r.checkNpmConifg=r.PNPM_VERSION=void 0;const o=t,a=E(e),c=A(D),s=E(u),B=i,d=l,f=Au;r.PNPM_VERSION="7.30.0",r.checkNpmConifg=function(){const u=s.resolve(B.HVIGOR_PROJECT_ROOT_DIR,".npmrc"),D=s.resolve(c.default.homedir(),".npmrc");if((0,f.isFileExists)(u)||(0,f.isFileExists)(D))return;const e=(0,f.getNpmPath)(),t=(0,o.spawnSync)(e,["config","get","prefix"],{cwd:B.HVIGOR_PROJECT_ROOT_DIR});if(0!==t.status||!t.stdout)return void(0,d.logErrorAndExit)("Error: The hvigor depends on the npmrc file. Configure the npmrc file first.");const r=s.resolve(`${t.stdout}`.replace(/[\r\n]/gi,""),".npmrc");(0,f.isFileExists)(r)||(0,d.logErrorAndExit)("Error: The hvigor depends on the npmrc file. Configure the npmrc file first.")},r.environmentHandler=function(){process.env["npm_config_update-notifier"]="false"},r.isPnpmInstalled=function(){return!!a.existsSync(B.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH)&&(0,f.hasNpmPackInPaths)("pnpm",[B.HVIGOR_WRAPPER_TOOLS_HOME])},r.executeInstallPnpm=function(){(0,d.logInfoPrintConsole)(`Installing pnpm@${r.PNPM_VERSION}...`);const u=(0,f.getNpmPath)();!function(){const u=s.resolve(B.HVIGOR_WRAPPER_TOOLS_HOME,B.DEFAULT_PACKAGE_JSON);try{a.existsSync(B.HVIGOR_WRAPPER_TOOLS_HOME)||a.mkdirSync(B.HVIGOR_WRAPPER_TOOLS_HOME,{recursive:!0});const D={dependencies:{}};D.dependencies[B.PNPM]=r.PNPM_VERSION,a.writeFileSync(u,JSON.stringify(D))}catch(D){(0,d.logErrorAndExit)(`Error: EPERM: operation not permitted,create ${u} failed.`)}}(),(0,f.executeCommand)(u,["install","pnpm"],{cwd:B.HVIGOR_WRAPPER_TOOLS_HOME,stdio:["inherit","inherit","inherit"],env:process.env}),(0,d.logInfoPrintConsole)("Pnpm install success.")}}(Gu),function(){Gu.checkNpmConifg(),Gu.environmentHandler(),Gu.isPnpmInstalled()||Gu.executeInstallPnpm();const D=gu();_(u.join(D,i.WORK_SPACE))}(); \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/hvigorfile.ts b/OpenHarmony/ohos_msgpack/hvigorfile.ts new file mode 100644 index 0000000..f3cb9f1 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/OpenHarmony/ohos_msgpack/hvigorw b/OpenHarmony/ohos_msgpack/hvigorw new file mode 100644 index 0000000..ff6a29a --- /dev/null +++ b/OpenHarmony/ohos_msgpack/hvigorw @@ -0,0 +1,48 @@ +#!/bin/bash + +# ---------------------------------------------------------------------------- +# Hvigor startup script, version 1.0.0 +# +# Required ENV vars: +# ------------------ +# NODE_HOME - location of a Node home dir +# or +# Add /usr/local/nodejs/bin to the PATH environment variable +# ---------------------------------------------------------------------------- + +HVIGOR_APP_HOME="`pwd -P`" +HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js +warn() { + echo "" + echo -e "\033[1;33m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m" +} + +error() { + echo "" + echo -e "\033[1;31m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m" +} + +fail() { + error "$@" + exit 1 +} + +# Determine node to start hvigor wrapper script +if [ -n "${NODE_HOME}" ];then + EXECUTABLE_NODE="${NODE_HOME}/bin/node" + if [ ! -x "$EXECUTABLE_NODE" ];then + fail "ERROR: NODE_HOME is set to an invalid directory,check $NODE_HOME\n\nPlease set NODE_HOME in your environment to the location where your nodejs installed" + fi +else + EXECUTABLE_NODE="node" + which ${EXECUTABLE_NODE} > /dev/null 2>&1 || fail "ERROR: NODE_HOME is not set and not 'node' command found in your path" +fi + +# Check hvigor wrapper script +if [ ! -r "$HVIGOR_WRAPPER_SCRIPT" ];then + fail "ERROR: Couldn't find hvigor/hvigor-wrapper.js in ${HVIGOR_APP_HOME}" +fi + +# start hvigor-wrapper script +exec "${EXECUTABLE_NODE}" \ + "${HVIGOR_WRAPPER_SCRIPT}" "$@" diff --git a/OpenHarmony/ohos_msgpack/hvigorw.bat b/OpenHarmony/ohos_msgpack/hvigorw.bat new file mode 100644 index 0000000..d570007 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/hvigorw.bat @@ -0,0 +1,64 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Hvigor startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js +set NODE_EXE=node.exe + +goto start + +:start +@rem Find node.exe +if defined NODE_HOME goto findNodeFromNodeHome + +%NODE_EXE% --version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH. +echo. +echo Please set the NODE_HOME variable in your environment to match the +echo location of your NodeJs installation. + +goto fail + +:findNodeFromNodeHome +set NODE_HOME=%NODE_HOME:"=% +set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE% + +if exist "%NODE_EXE_PATH%" goto execute +echo. +echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH. +echo. +echo Please set the NODE_HOME variable in your environment to match the +echo location of your NodeJs installation. + +goto fail + +:execute +@rem Execute hvigor +"%NODE_EXE%" "%WRAPPER_MODULE_PATH%" %* + +if "%ERRORLEVEL%" == "0" goto hvigorwEnd + +:fail +exit /b 1 + +:hvigorwEnd +if "%OS%" == "Windows_NT" endlocal + +:end diff --git a/OpenHarmony/ohos_msgpack/library/.gitignore b/OpenHarmony/ohos_msgpack/library/.gitignore new file mode 100644 index 0000000..e2713a2 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/OpenHarmony/ohos_msgpack/library/Index.ts b/OpenHarmony/ohos_msgpack/library/Index.ts new file mode 100644 index 0000000..2aa9396 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/Index.ts @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Copyright + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +export { encode, + EncodeOptions, + decode, + decodeMulti, + DecodeOptions, + decodeAsync, + decodeArrayStream, + decodeMultiStream, + decodeStream, + Decoder, + DataViewIndexOutOfBoundsError, + DecoderOptions, + DecodeError, + Encoder, + EncoderOptions, + ExtensionCodec, + ExtensionCodecType, ExtensionDecoderType, ExtensionEncoderType, + + ExtData, + EXT_TIMESTAMP, + encodeDateToTimeSpec, + encodeTimeSpecToTimestamp, + decodeTimestampToTimeSpec, + encodeTimestampExtension, + decodeTimestampExtension, + setInt64, getInt64, getUint64, setUint64, + utf8Count, utf8EncodeJs, CachedKeyDecoder, KeyDecoder, + TimeSpec, + +} from './src/main/ets/index' diff --git a/OpenHarmony/ohos_msgpack/library/build-profile.json5 b/OpenHarmony/ohos_msgpack/library/build-profile.json5 new file mode 100644 index 0000000..79961f9 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/build-profile.json5 @@ -0,0 +1,10 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "targets": [ + { + "name": "default" + } + ] +} diff --git a/OpenHarmony/ohos_msgpack/library/hvigorfile.ts b/OpenHarmony/ohos_msgpack/library/hvigorfile.ts new file mode 100644 index 0000000..4218707 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/hvigorfile.ts @@ -0,0 +1,6 @@ +import { harTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/OpenHarmony/ohos_msgpack/library/oh-package.json5 b/OpenHarmony/ohos_msgpack/library/oh-package.json5 new file mode 100644 index 0000000..2271c12 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/oh-package.json5 @@ -0,0 +1,21 @@ +{ + "types": "", + "keywords": [ + "msgpack", + "HarmonyOS", + "OpenHarmony" + ], + "author": "ohos_tpc", + "description": "This library is an implementation of MessagePack for TypeScript and JavaScript, providing a compact and efficient binary serialization format.", + "main": "Index.ts", + "type": "module", + "repository": "https://gitcode.com/openharmony-tpc/openharmony_tpc_samples/tree/master/ohos_msgpack", + "version": "1.0.2-rc.0", + "tags": [ + "Tool" + ], + "dependencies": {}, + "license": "ISC License", + "devDependencies": {}, + "name": "@ohos/msgpack" +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/CachedKeyDecoder.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/CachedKeyDecoder.ts new file mode 100644 index 0000000..b57c222 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/CachedKeyDecoder.ts @@ -0,0 +1,79 @@ +import { utf8DecodeJs } from "./utils/utf8"; + +const DEFAULT_MAX_KEY_LENGTH = 16; +const DEFAULT_MAX_LENGTH_PER_KEY = 16; + +export interface KeyDecoder { + canBeCached(byteLength: number): boolean; + decode(bytes: Uint8Array, inputOffset: number, byteLength: number): string; +} +interface KeyCacheRecord { + readonly bytes: Uint8Array; + readonly str: string; +} + +export class CachedKeyDecoder implements KeyDecoder { + hit = 0; + miss = 0; + private readonly caches: Array>; + + constructor( + readonly maxKeyLength = DEFAULT_MAX_KEY_LENGTH, + readonly maxLengthPerKey = DEFAULT_MAX_LENGTH_PER_KEY, + ) { + // avoid `new Array(N)`, which makes a sparse array, + // because a sparse array is typically slower than a non-sparse array. + this.caches = []; + for (let i = 0; i < this.maxKeyLength; i++) { + this.caches.push([]); + } + } + + public canBeCached(byteLength: number): boolean { + return byteLength > 0 && byteLength <= this.maxKeyLength; + } + + private find(bytes: Uint8Array, inputOffset: number, byteLength: number): string | null { + const records = this.caches[byteLength - 1]!; + + FIND_CHUNK: for (const record of records) { + const recordBytes = record.bytes; + + for (let j = 0; j < byteLength; j++) { + if (recordBytes[j] !== bytes[inputOffset + j]) { + continue FIND_CHUNK; + } + } + return record.str; + } + return null; + } + + private store(bytes: Uint8Array, value: string) { + const records = this.caches[bytes.length - 1]!; + const record: KeyCacheRecord = { bytes, str: value }; + + if (records.length >= this.maxLengthPerKey) { + // `records` are full! + // Set `record` to an arbitrary position. + records[(Math.random() * records.length) | 0] = record; + } else { + records.push(record); + } + } + + public decode(bytes: Uint8Array, inputOffset: number, byteLength: number): string { + const cachedValue = this.find(bytes, inputOffset, byteLength); + if (cachedValue != null) { + this.hit++; + return cachedValue; + } + this.miss++; + + const str = utf8DecodeJs(bytes, inputOffset, byteLength); + // Ensure to copy a slice of bytes because the byte may be NodeJS Buffer and Buffer#slice() returns a reference to its internal ArrayBuffer. + const slicedCopyOfBytes = Uint8Array.prototype.slice.call(bytes, inputOffset, inputOffset + byteLength); + this.store(slicedCopyOfBytes, str); + return str; + } +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/DecodeError.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/DecodeError.ts new file mode 100644 index 0000000..203fe1b --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/DecodeError.ts @@ -0,0 +1,15 @@ +export class DecodeError extends Error { + constructor(message: string) { + super(message); + + // fix the prototype chain in a cross-platform way + const proto: typeof DecodeError.prototype = Object.create(DecodeError.prototype); + Object.setPrototypeOf(this, proto); + + Object.defineProperty(this, "name", { + configurable: true, + enumerable: false, + value: DecodeError.name, + }); + } +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/Decoder.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/Decoder.ts new file mode 100644 index 0000000..74771d3 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/Decoder.ts @@ -0,0 +1,778 @@ +import { prettyByte } from "./utils/prettyByte"; +import { ExtensionCodec, ExtensionCodecType } from "./ExtensionCodec"; +import { getInt64, getUint64, UINT32_MAX } from "./utils/int"; +import { utf8Decode } from "./utils/utf8"; +import { createDataView, ensureUint8Array } from "./utils/typedArrays"; +import { CachedKeyDecoder, KeyDecoder } from "./CachedKeyDecoder"; +import { DecodeError } from "./DecodeError"; +import type { ContextOf } from "./context"; + +export type DecoderOptions = Readonly< + Partial<{ + extensionCodec: ExtensionCodecType; + + /** + * Decodes Int64 and Uint64 as bigint if it's set to true. + * Depends on ES2020's {@link DataView#getBigInt64} and + * {@link DataView#getBigUint64}. + * + * Defaults to false. + */ + useBigInt64: boolean; + + /** + * Maximum string length. + * + * Defaults to 4_294_967_295 (UINT32_MAX). + */ + maxStrLength: number; + /** + * Maximum binary length. + * + * Defaults to 4_294_967_295 (UINT32_MAX). + */ + maxBinLength: number; + /** + * Maximum array length. + * + * Defaults to 4_294_967_295 (UINT32_MAX). + */ + maxArrayLength: number; + /** + * Maximum map length. + * + * Defaults to 4_294_967_295 (UINT32_MAX). + */ + maxMapLength: number; + /** + * Maximum extension length. + * + * Defaults to 4_294_967_295 (UINT32_MAX). + */ + maxExtLength: number; + + /** + * An object key decoder. Defaults to the shared instance of {@link CachedKeyDecoder}. + * `null` is a special value to disable the use of the key decoder at all. + */ + keyDecoder: KeyDecoder | null; + }> +> & + ContextOf; + +const STATE_ARRAY = "array"; +const STATE_MAP_KEY = "map_key"; +const STATE_MAP_VALUE = "map_value"; + +type MapKeyType = string | number; + +const isValidMapKeyType = (key: unknown): key is MapKeyType => { + return typeof key === "string" || typeof key === "number"; +}; + +type StackMapState = { + type: typeof STATE_MAP_KEY | typeof STATE_MAP_VALUE; + size: number; + key: MapKeyType | null; + readCount: number; + map: Record; +}; + +type StackArrayState = { + type: typeof STATE_ARRAY; + size: number; + array: Array; + position: number; +}; + +class StackPool { + private readonly stack: Array = []; + private stackHeadPosition = -1; + + public get length(): number { + return this.stackHeadPosition + 1; + } + + public top(): StackState | undefined { + return this.stack[this.stackHeadPosition]; + } + + public pushArrayState(size: number) { + const state = this.getUninitializedStateFromPool() as StackArrayState; + + state.type = STATE_ARRAY; + state.position = 0; + state.size = size; + state.array = new Array(size); + } + + public pushMapState(size: number) { + const state = this.getUninitializedStateFromPool() as StackMapState; + + state.type = STATE_MAP_KEY; + state.readCount = 0; + state.size = size; + state.map = {}; + } + + private getUninitializedStateFromPool() { + this.stackHeadPosition++; + + if (this.stackHeadPosition === this.stack.length) { + const partialState: Partial = { + type: undefined, + size: 0, + array: undefined, + position: 0, + readCount: 0, + map: undefined, + key: null, + }; + + this.stack.push(partialState as StackState); + } + + return this.stack[this.stackHeadPosition]; + } + + public release(state: StackState): void { + const topStackState = this.stack[this.stackHeadPosition]; + + if (topStackState !== state) { + throw new Error("Invalid stack state. Released state is not on top of the stack."); + } + + if (state.type === STATE_ARRAY) { + const partialState = state as Partial; + partialState.size = 0; + partialState.array = undefined; + partialState.position = 0; + partialState.type = undefined; + } + + if (state.type === STATE_MAP_KEY || state.type === STATE_MAP_VALUE) { + const partialState = state as Partial; + partialState.size = 0; + partialState.map = undefined; + partialState.readCount = 0; + partialState.type = undefined; + } + + this.stackHeadPosition--; + } + + public reset(): void { + this.stack.length = 0; + this.stackHeadPosition = -1; + } +} + +type StackState = StackArrayState | StackMapState; + +const HEAD_BYTE_REQUIRED = -1; + +const EMPTY_VIEW = new DataView(new ArrayBuffer(0)); +const EMPTY_BYTES = new Uint8Array(EMPTY_VIEW.buffer); + +try { + // IE11: The spec says it should throw RangeError, + // IE11: but in IE11 it throws TypeError. + EMPTY_VIEW.getInt8(0); +} catch (e) { + if (!(e instanceof RangeError)) { + throw new Error( + "This module is not supported in the current JavaScript engine because DataView does not throw RangeError on out-of-bounds access", + ); + } +} +export const DataViewIndexOutOfBoundsError = RangeError; + +const MORE_DATA = new DataViewIndexOutOfBoundsError("Insufficient data"); + +const sharedCachedKeyDecoder = new CachedKeyDecoder(); + +export class Decoder { + private readonly extensionCodec: ExtensionCodecType; + private readonly context: ContextType; + private readonly useBigInt64: boolean; + private readonly maxStrLength: number; + private readonly maxBinLength: number; + private readonly maxArrayLength: number; + private readonly maxMapLength: number; + private readonly maxExtLength: number; + private readonly keyDecoder: KeyDecoder | null; + + private totalPos = 0; + private pos = 0; + + private view = EMPTY_VIEW; + private bytes = EMPTY_BYTES; + private headByte = HEAD_BYTE_REQUIRED; + private readonly stack = new StackPool(); + + public constructor(options?: DecoderOptions) { + this.extensionCodec = options?.extensionCodec ?? (ExtensionCodec.defaultCodec as ExtensionCodecType); + this.context = (options as unknown as { context: ContextType } | undefined)?.context as ContextType; // needs a type assertion because EncoderOptions has no context property when ContextType is undefined + + this.useBigInt64 = options?.useBigInt64 ?? false; + this.maxStrLength = options?.maxStrLength ?? UINT32_MAX; + this.maxBinLength = options?.maxBinLength ?? UINT32_MAX; + this.maxArrayLength = options?.maxArrayLength ?? UINT32_MAX; + this.maxMapLength = options?.maxMapLength ?? UINT32_MAX; + this.maxExtLength = options?.maxExtLength ?? UINT32_MAX; + this.keyDecoder = options?.keyDecoder !== undefined ? options.keyDecoder : sharedCachedKeyDecoder; + } + + private reinitializeState() { + this.totalPos = 0; + this.headByte = HEAD_BYTE_REQUIRED; + this.stack.reset(); + + // view, bytes, and pos will be re-initialized in setBuffer() + } + + private setBuffer(buffer: ArrayLike | Uint8Array | ArrayBufferView | ArrayBuffer): void { + this.bytes = ensureUint8Array(buffer); + this.view = createDataView(this.bytes); + this.pos = 0; + } + + private appendBuffer(buffer: ArrayLike | Uint8Array | ArrayBufferView | ArrayBuffer) { + if (this.headByte === HEAD_BYTE_REQUIRED && !this.hasRemaining(1)) { + this.setBuffer(buffer); + } else { + const remainingData = this.bytes.subarray(this.pos); + const newData = ensureUint8Array(buffer); + + // concat remainingData + newData + const newBuffer = new Uint8Array(remainingData.length + newData.length); + newBuffer.set(remainingData); + newBuffer.set(newData, remainingData.length); + this.setBuffer(newBuffer); + } + } + + private hasRemaining(size: number) { + return this.view.byteLength - this.pos >= size; + } + + private createExtraByteError(posToShow: number): Error { + const { view, pos } = this; + return new RangeError(`Extra ${view.byteLength - pos} of ${view.byteLength} byte(s) found at buffer[${posToShow}]`); + } + + /** + * @throws {@link DecodeError} + * @throws {@link RangeError} + */ + public decode(buffer: ArrayLike | Uint8Array | ArrayBufferView | ArrayBuffer): unknown { + this.reinitializeState(); + this.setBuffer(buffer); + + const object = this.doDecodeSync(); + if (this.hasRemaining(1)) { + throw this.createExtraByteError(this.pos); + } + return object; + } + + public *decodeMulti(buffer: ArrayLike | Uint8Array | ArrayBufferView | ArrayBuffer): Generator { + this.reinitializeState(); + this.setBuffer(buffer); + + while (this.hasRemaining(1)) { + yield this.doDecodeSync(); + } + } + + public async decodeAsync(stream: AsyncIterable | Uint8Array | ArrayBufferView | ArrayBuffer>): Promise { + let decoded = false; + let object: unknown; + for await (const buffer of stream) { + if (decoded) { + throw this.createExtraByteError(this.totalPos); + } + + this.appendBuffer(buffer); + + try { + object = this.doDecodeSync(); + decoded = true; + } catch (e) { + if (!(e instanceof DataViewIndexOutOfBoundsError)) { + throw e; // rethrow + } + // fallthrough + } + this.totalPos += this.pos; + } + + if (decoded) { + if (this.hasRemaining(1)) { + throw this.createExtraByteError(this.totalPos); + } + return object; + } + + const { headByte, pos, totalPos } = this; + throw new RangeError( + `Insufficient data in parsing ${prettyByte(headByte)} at ${totalPos} (${pos} in the current buffer)`, + ); + } + + public decodeArrayStream( + stream: AsyncIterable | Uint8Array | ArrayBufferView | ArrayBuffer>, + ): AsyncGenerator { + return this.decodeMultiAsync(stream, true); + } + + public decodeStream(stream: AsyncIterable | Uint8Array | ArrayBufferView | ArrayBuffer>): AsyncGenerator { + return this.decodeMultiAsync(stream, false); + } + + private async *decodeMultiAsync(stream: AsyncIterable | Uint8Array | ArrayBufferView | ArrayBuffer>, isArray: boolean) { + let isArrayHeaderRequired = isArray; + let arrayItemsLeft = -1; + + for await (const buffer of stream) { + if (isArray && arrayItemsLeft === 0) { + throw this.createExtraByteError(this.totalPos); + } + + this.appendBuffer(buffer); + + if (isArrayHeaderRequired) { + arrayItemsLeft = this.readArraySize(); + isArrayHeaderRequired = false; + this.complete(); + } + + try { + while (true) { + yield this.doDecodeSync(); + if (--arrayItemsLeft === 0) { + break; + } + } + } catch (e) { + if (!(e instanceof DataViewIndexOutOfBoundsError)) { + throw e; // rethrow + } + // fallthrough + } + this.totalPos += this.pos; + } + } + + private doDecodeSync(): unknown { + DECODE: while (true) { + const headByte = this.readHeadByte(); + let object: unknown; + + if (headByte >= 0xe0) { + // negative fixint (111x xxxx) 0xe0 - 0xff + object = headByte - 0x100; + } else if (headByte < 0xc0) { + if (headByte < 0x80) { + // positive fixint (0xxx xxxx) 0x00 - 0x7f + object = headByte; + } else if (headByte < 0x90) { + // fixmap (1000 xxxx) 0x80 - 0x8f + const size = headByte - 0x80; + if (size !== 0) { + this.pushMapState(size); + this.complete(); + continue DECODE; + } else { + object = {}; + } + } else if (headByte < 0xa0) { + // fixarray (1001 xxxx) 0x90 - 0x9f + const size = headByte - 0x90; + if (size !== 0) { + this.pushArrayState(size); + this.complete(); + continue DECODE; + } else { + object = []; + } + } else { + // fixstr (101x xxxx) 0xa0 - 0xbf + const byteLength = headByte - 0xa0; + object = this.decodeUtf8String(byteLength, 0); + } + } else if (headByte === 0xc0) { + // nil + object = null; + } else if (headByte === 0xc2) { + // false + object = false; + } else if (headByte === 0xc3) { + // true + object = true; + } else if (headByte === 0xca) { + // float 32 + object = this.readF32(); + } else if (headByte === 0xcb) { + // float 64 + object = this.readF64(); + } else if (headByte === 0xcc) { + // uint 8 + object = this.readU8(); + } else if (headByte === 0xcd) { + // uint 16 + object = this.readU16(); + } else if (headByte === 0xce) { + // uint 32 + object = this.readU32(); + } else if (headByte === 0xcf) { + // uint 64 + if (this.useBigInt64) { + object = this.readU64AsBigInt(); + } else { + object = this.readU64(); + } + } else if (headByte === 0xd0) { + // int 8 + object = this.readI8(); + } else if (headByte === 0xd1) { + // int 16 + object = this.readI16(); + } else if (headByte === 0xd2) { + // int 32 + object = this.readI32(); + } else if (headByte === 0xd3) { + // int 64 + if (this.useBigInt64) { + object = this.readI64AsBigInt(); + } else { + object = this.readI64(); + } + } else if (headByte === 0xd9) { + // str 8 + const byteLength = this.lookU8(); + object = this.decodeUtf8String(byteLength, 1); + } else if (headByte === 0xda) { + // str 16 + const byteLength = this.lookU16(); + object = this.decodeUtf8String(byteLength, 2); + } else if (headByte === 0xdb) { + // str 32 + const byteLength = this.lookU32(); + object = this.decodeUtf8String(byteLength, 4); + } else if (headByte === 0xdc) { + // array 16 + const size = this.readU16(); + if (size !== 0) { + this.pushArrayState(size); + this.complete(); + continue DECODE; + } else { + object = []; + } + } else if (headByte === 0xdd) { + // array 32 + const size = this.readU32(); + if (size !== 0) { + this.pushArrayState(size); + this.complete(); + continue DECODE; + } else { + object = []; + } + } else if (headByte === 0xde) { + // map 16 + const size = this.readU16(); + if (size !== 0) { + this.pushMapState(size); + this.complete(); + continue DECODE; + } else { + object = {}; + } + } else if (headByte === 0xdf) { + // map 32 + const size = this.readU32(); + if (size !== 0) { + this.pushMapState(size); + this.complete(); + continue DECODE; + } else { + object = {}; + } + } else if (headByte === 0xc4) { + // bin 8 + const size = this.lookU8(); + object = this.decodeBinary(size, 1); + } else if (headByte === 0xc5) { + // bin 16 + const size = this.lookU16(); + object = this.decodeBinary(size, 2); + } else if (headByte === 0xc6) { + // bin 32 + const size = this.lookU32(); + object = this.decodeBinary(size, 4); + } else if (headByte === 0xd4) { + // fixext 1 + object = this.decodeExtension(1, 0); + } else if (headByte === 0xd5) { + // fixext 2 + object = this.decodeExtension(2, 0); + } else if (headByte === 0xd6) { + // fixext 4 + object = this.decodeExtension(4, 0); + } else if (headByte === 0xd7) { + // fixext 8 + object = this.decodeExtension(8, 0); + } else if (headByte === 0xd8) { + // fixext 16 + object = this.decodeExtension(16, 0); + } else if (headByte === 0xc7) { + // ext 8 + const size = this.lookU8(); + object = this.decodeExtension(size, 1); + } else if (headByte === 0xc8) { + // ext 16 + const size = this.lookU16(); + object = this.decodeExtension(size, 2); + } else if (headByte === 0xc9) { + // ext 32 + const size = this.lookU32(); + object = this.decodeExtension(size, 4); + } else { + throw new DecodeError(`Unrecognized type byte: ${prettyByte(headByte)}`); + } + + this.complete(); + + const stack = this.stack; + while (stack.length > 0) { + // arrays and maps + const state = stack.top()!; + if (state.type === STATE_ARRAY) { + state.array[state.position] = object; + state.position++; + if (state.position === state.size) { + object = state.array; + stack.release(state); + } else { + continue DECODE; + } + } else if (state.type === STATE_MAP_KEY) { + if (!isValidMapKeyType(object)) { + throw new DecodeError("The type of key must be string or number but " + typeof object); + } + if (object === "__proto__") { + throw new DecodeError("The key __proto__ is not allowed"); + } + + state.key = object; + state.type = STATE_MAP_VALUE; + continue DECODE; + } else { + // it must be `state.type === State.MAP_VALUE` here + + state.map[state.key!] = object; + state.readCount++; + + if (state.readCount === state.size) { + object = state.map; + stack.release(state); + } else { + state.key = null; + state.type = STATE_MAP_KEY; + continue DECODE; + } + } + } + + return object; + } + } + + private readHeadByte(): number { + if (this.headByte === HEAD_BYTE_REQUIRED) { + this.headByte = this.readU8(); + // console.log("headByte", prettyByte(this.headByte)); + } + + return this.headByte; + } + + private complete(): void { + this.headByte = HEAD_BYTE_REQUIRED; + } + + private readArraySize(): number { + const headByte = this.readHeadByte(); + + switch (headByte) { + case 0xdc: + return this.readU16(); + case 0xdd: + return this.readU32(); + default: { + if (headByte < 0xa0) { + return headByte - 0x90; + } else { + throw new DecodeError(`Unrecognized array type byte: ${prettyByte(headByte)}`); + } + } + } + } + + private pushMapState(size: number) { + if (size > this.maxMapLength) { + throw new DecodeError(`Max length exceeded: map length (${size}) > maxMapLengthLength (${this.maxMapLength})`); + } + + this.stack.pushMapState(size); + } + + private pushArrayState(size: number) { + if (size > this.maxArrayLength) { + throw new DecodeError(`Max length exceeded: array length (${size}) > maxArrayLength (${this.maxArrayLength})`); + } + + this.stack.pushArrayState(size); + } + + private decodeUtf8String(byteLength: number, headerOffset: number): string { + if (byteLength > this.maxStrLength) { + throw new DecodeError( + `Max length exceeded: UTF-8 byte length (${byteLength}) > maxStrLength (${this.maxStrLength})`, + ); + } + + if (this.bytes.byteLength < this.pos + headerOffset + byteLength) { + throw MORE_DATA; + } + + const offset = this.pos + headerOffset; + let object: string; + if (this.stateIsMapKey() && this.keyDecoder?.canBeCached(byteLength)) { + object = this.keyDecoder.decode(this.bytes, offset, byteLength); + } else { + object = utf8Decode(this.bytes, offset, byteLength); + } + this.pos += headerOffset + byteLength; + return object; + } + + private stateIsMapKey(): boolean { + if (this.stack.length > 0) { + const state = this.stack.top()!; + return state.type === STATE_MAP_KEY; + } + return false; + } + + private decodeBinary(byteLength: number, headOffset: number): Uint8Array { + if (byteLength > this.maxBinLength) { + throw new DecodeError(`Max length exceeded: bin length (${byteLength}) > maxBinLength (${this.maxBinLength})`); + } + + if (!this.hasRemaining(byteLength + headOffset)) { + throw MORE_DATA; + } + + const offset = this.pos + headOffset; + const object = this.bytes.subarray(offset, offset + byteLength); + this.pos += headOffset + byteLength; + return object; + } + + private decodeExtension(size: number, headOffset: number): unknown { + if (size > this.maxExtLength) { + throw new DecodeError(`Max length exceeded: ext length (${size}) > maxExtLength (${this.maxExtLength})`); + } + + const extType = this.view.getInt8(this.pos + headOffset); + const data = this.decodeBinary(size, headOffset + 1 /* extType */); + return this.extensionCodec.decode(data, extType, this.context); + } + + private lookU8() { + return this.view.getUint8(this.pos); + } + + private lookU16() { + return this.view.getUint16(this.pos); + } + + private lookU32() { + return this.view.getUint32(this.pos); + } + + private readU8(): number { + const value = this.view.getUint8(this.pos); + this.pos++; + return value; + } + + private readI8(): number { + const value = this.view.getInt8(this.pos); + this.pos++; + return value; + } + + private readU16(): number { + const value = this.view.getUint16(this.pos); + this.pos += 2; + return value; + } + + private readI16(): number { + const value = this.view.getInt16(this.pos); + this.pos += 2; + return value; + } + + private readU32(): number { + const value = this.view.getUint32(this.pos); + this.pos += 4; + return value; + } + + private readI32(): number { + const value = this.view.getInt32(this.pos); + this.pos += 4; + return value; + } + + private readU64(): number { + const value = getUint64(this.view, this.pos); + this.pos += 8; + return value; + } + + private readI64(): number { + const value = getInt64(this.view, this.pos); + this.pos += 8; + return value; + } + + private readU64AsBigInt(): bigint { + const value = this.view.getBigUint64(this.pos); + this.pos += 8; + return value; + } + + private readI64AsBigInt(): bigint { + const value = this.view.getBigInt64(this.pos); + this.pos += 8; + return value; + } + + private readF32() { + const value = this.view.getFloat32(this.pos); + this.pos += 4; + return value; + } + + private readF64() { + const value = this.view.getFloat64(this.pos); + this.pos += 8; + return value; + } +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/Encoder.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/Encoder.ts new file mode 100644 index 0000000..6e0c281 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/Encoder.ts @@ -0,0 +1,525 @@ +import { utf8Count, utf8Encode } from "./utils/utf8"; +import { ExtensionCodec, ExtensionCodecType } from "./ExtensionCodec"; +import { setInt64, setUint64 } from "./utils/int"; +import { ensureUint8Array } from "./utils/typedArrays"; +import type { ExtData } from "./ExtData"; +import type { ContextOf } from "./context"; + +export const DEFAULT_MAX_DEPTH = 100; +export const DEFAULT_INITIAL_BUFFER_SIZE = 2048; + +export type EncoderOptions = Partial< + Readonly<{ + extensionCodec: ExtensionCodecType; + + /** + * Encodes bigint as Int64 or Uint64 if it's set to true. + * {@link forceIntegerToFloat} does not affect bigint. + * Depends on ES2020's {@link DataView#setBigInt64} and + * {@link DataView#setBigUint64}. + * + * Defaults to false. + */ + useBigInt64: boolean; + + /** + * The maximum depth in nested objects and arrays. + * + * Defaults to 100. + */ + maxDepth: number; + + /** + * The initial size of the internal buffer. + * + * Defaults to 2048. + */ + initialBufferSize: number; + + /** + * If `true`, the keys of an object is sorted. In other words, the encoded + * binary is canonical and thus comparable to another encoded binary. + * + * Defaults to `false`. If enabled, it spends more time in encoding objects. + */ + sortKeys: boolean; + /** + * If `true`, non-integer numbers are encoded in float32, not in float64 (the default). + * + * Only use it if precisions don't matter. + * + * Defaults to `false`. + */ + forceFloat32: boolean; + + /** + * If `true`, an object property with `undefined` value are ignored. + * e.g. `{ foo: undefined }` will be encoded as `{}`, as `JSON.stringify()` does. + * + * Defaults to `false`. If enabled, it spends more time in encoding objects. + */ + ignoreUndefined: boolean; + + /** + * If `true`, integer numbers are encoded as floating point numbers, + * with the `forceFloat32` option taken into account. + * + * Defaults to `false`. + */ + forceIntegerToFloat: boolean; + }> +> & + ContextOf; + +export class Encoder { + private readonly extensionCodec: ExtensionCodecType; + private readonly context: ContextType; + private readonly useBigInt64: boolean; + private readonly maxDepth: number; + private readonly initialBufferSize: number; + private readonly sortKeys: boolean; + private readonly forceFloat32: boolean; + private readonly ignoreUndefined: boolean; + private readonly forceIntegerToFloat: boolean; + + private pos: number; + private view: DataView; + private bytes: Uint8Array; + + public constructor(options?: EncoderOptions) { + this.extensionCodec = options?.extensionCodec ?? (ExtensionCodec.defaultCodec as ExtensionCodecType); + this.context = (options as unknown as { context: ContextType } | undefined)?.context as ContextType; // needs a type assertion because EncoderOptions has no context property when ContextType is undefined + + this.useBigInt64 = options?.useBigInt64 ?? false; + this.maxDepth = options?.maxDepth ?? DEFAULT_MAX_DEPTH; + this.initialBufferSize = options?.initialBufferSize ?? DEFAULT_INITIAL_BUFFER_SIZE; + this.sortKeys = options?.sortKeys ?? false; + this.forceFloat32 = options?.forceFloat32 ?? false; + this.ignoreUndefined = options?.ignoreUndefined ?? false; + this.forceIntegerToFloat = options?.forceIntegerToFloat ?? false; + + this.pos = 0; + this.view = new DataView(new ArrayBuffer(this.initialBufferSize)); + this.bytes = new Uint8Array(this.view.buffer); + } + + private reinitializeState() { + this.pos = 0; + } + + /** + * This is almost equivalent to {@link Encoder#encode}, but it returns an reference of the encoder's internal buffer and thus much faster than {@link Encoder#encode}. + * + * @returns Encodes the object and returns a shared reference the encoder's internal buffer. + */ + public encodeSharedRef(object: unknown): Uint8Array { + this.reinitializeState(); + this.doEncode(object, 1); + return this.bytes.subarray(0, this.pos); + } + + /** + * @returns Encodes the object and returns a copy of the encoder's internal buffer. + */ + public encode(object: unknown): Uint8Array { + this.reinitializeState(); + this.doEncode(object, 1); + return this.bytes.slice(0, this.pos); + } + + private doEncode(object: unknown, depth: number): void { + if (depth > this.maxDepth) { + throw new Error(`Too deep objects in depth ${depth}`); + } + + if (object == null) { + this.encodeNil(); + } else if (typeof object === "boolean") { + this.encodeBoolean(object); + } else if (typeof object === "number") { + if (!this.forceIntegerToFloat) { + this.encodeNumber(object); + } else { + this.encodeNumberAsFloat(object); + } + } else if (typeof object === "string") { + this.encodeString(object); + } else if (this.useBigInt64 && typeof object === "bigint") { + this.encodeBigInt64(object); + } else { + this.encodeObject(object, depth); + } + } + + private ensureBufferSizeToWrite(sizeToWrite: number) { + const requiredSize = this.pos + sizeToWrite; + + if (this.view.byteLength < requiredSize) { + this.resizeBuffer(requiredSize * 2); + } + } + + private resizeBuffer(newSize: number) { + const newBuffer = new ArrayBuffer(newSize); + const newBytes = new Uint8Array(newBuffer); + const newView = new DataView(newBuffer); + + newBytes.set(this.bytes); + + this.view = newView; + this.bytes = newBytes; + } + + private encodeNil() { + this.writeU8(0xc0); + } + + private encodeBoolean(object: boolean) { + if (object === false) { + this.writeU8(0xc2); + } else { + this.writeU8(0xc3); + } + } + + private encodeNumber(object: number): void { + if (!this.forceIntegerToFloat && Number.isSafeInteger(object)) { + if (object >= 0) { + if (object < 0x80) { + // positive fixint + this.writeU8(object); + } else if (object < 0x100) { + // uint 8 + this.writeU8(0xcc); + this.writeU8(object); + } else if (object < 0x10000) { + // uint 16 + this.writeU8(0xcd); + this.writeU16(object); + } else if (object < 0x100000000) { + // uint 32 + this.writeU8(0xce); + this.writeU32(object); + } else if (!this.useBigInt64) { + // uint 64 + this.writeU8(0xcf); + this.writeU64(object); + } else { + this.encodeNumberAsFloat(object); + } + } else { + if (object >= -0x20) { + // negative fixint + this.writeU8(0xe0 | (object + 0x20)); + } else if (object >= -0x80) { + // int 8 + this.writeU8(0xd0); + this.writeI8(object); + } else if (object >= -0x8000) { + // int 16 + this.writeU8(0xd1); + this.writeI16(object); + } else if (object >= -0x80000000) { + // int 32 + this.writeU8(0xd2); + this.writeI32(object); + } else if (!this.useBigInt64) { + // int 64 + this.writeU8(0xd3); + this.writeI64(object); + } else { + this.encodeNumberAsFloat(object); + } + } + } else { + this.encodeNumberAsFloat(object); + } + } + + private encodeNumberAsFloat(object: number): void { + if (this.forceFloat32) { + // float 32 + this.writeU8(0xca); + this.writeF32(object); + } else { + // float 64 + this.writeU8(0xcb); + this.writeF64(object); + } + } + + private encodeBigInt64(object: bigint): void { + if (object >= BigInt(0)) { + // uint 64 + this.writeU8(0xcf); + this.writeBigUint64(object); + } else { + // int 64 + this.writeU8(0xd3); + this.writeBigInt64(object); + } + } + + private writeStringHeader(byteLength: number) { + if (byteLength < 32) { + // fixstr + this.writeU8(0xa0 + byteLength); + } else if (byteLength < 0x100) { + // str 8 + this.writeU8(0xd9); + this.writeU8(byteLength); + } else if (byteLength < 0x10000) { + // str 16 + this.writeU8(0xda); + this.writeU16(byteLength); + } else if (byteLength < 0x100000000) { + // str 32 + this.writeU8(0xdb); + this.writeU32(byteLength); + } else { + throw new Error(`Too long string: ${byteLength} bytes in UTF-8`); + } + } + + private encodeString(object: string) { + const maxHeaderSize = 1 + 4; + + const byteLength = utf8Count(object); + this.ensureBufferSizeToWrite(maxHeaderSize + byteLength); + this.writeStringHeader(byteLength); + utf8Encode(object, this.bytes, this.pos); + this.pos += byteLength; + } + + private encodeObject(object: unknown, depth: number) { + // try to encode objects with custom codec first of non-primitives + const ext = this.extensionCodec.tryToEncode(object, this.context); + if (ext != null) { + this.encodeExtension(ext); + } else if (Array.isArray(object)) { + this.encodeArray(object, depth); + } else if (ArrayBuffer.isView(object)) { + this.encodeBinary(object); + } else if (typeof object === "object") { + this.encodeMap(object as Record, depth); + } else { + // symbol, function and other special object come here unless extensionCodec handles them. + throw new Error(`Unrecognized object: ${Object.prototype.toString.apply(object)}`); + } + } + + private encodeBinary(object: ArrayBufferView) { + const size = object.byteLength; + if (size < 0x100) { + // bin 8 + this.writeU8(0xc4); + this.writeU8(size); + } else if (size < 0x10000) { + // bin 16 + this.writeU8(0xc5); + this.writeU16(size); + } else if (size < 0x100000000) { + // bin 32 + this.writeU8(0xc6); + this.writeU32(size); + } else { + throw new Error(`Too large binary: ${size}`); + } + const bytes = ensureUint8Array(object); + this.writeU8a(bytes); + } + + private encodeArray(object: Array, depth: number) { + const size = object.length; + if (size < 16) { + // fixarray + this.writeU8(0x90 + size); + } else if (size < 0x10000) { + // array 16 + this.writeU8(0xdc); + this.writeU16(size); + } else if (size < 0x100000000) { + // array 32 + this.writeU8(0xdd); + this.writeU32(size); + } else { + throw new Error(`Too large array: ${size}`); + } + for (const item of object) { + this.doEncode(item, depth + 1); + } + } + + private countWithoutUndefined(object: Record, keys: ReadonlyArray): number { + let count = 0; + + for (const key of keys) { + if (object[key] !== undefined) { + count++; + } + } + + return count; + } + + private encodeMap(object: Record, depth: number) { + const keys = Object.keys(object); + if (this.sortKeys) { + keys.sort(); + } + + const size = this.ignoreUndefined ? this.countWithoutUndefined(object, keys) : keys.length; + + if (size < 16) { + // fixmap + this.writeU8(0x80 + size); + } else if (size < 0x10000) { + // map 16 + this.writeU8(0xde); + this.writeU16(size); + } else if (size < 0x100000000) { + // map 32 + this.writeU8(0xdf); + this.writeU32(size); + } else { + throw new Error(`Too large map object: ${size}`); + } + + for (const key of keys) { + const value = object[key]; + + if (!(this.ignoreUndefined && value === undefined)) { + this.encodeString(key); + this.doEncode(value, depth + 1); + } + } + } + + private encodeExtension(ext: ExtData) { + const size = ext.data.length; + if (size === 1) { + // fixext 1 + this.writeU8(0xd4); + } else if (size === 2) { + // fixext 2 + this.writeU8(0xd5); + } else if (size === 4) { + // fixext 4 + this.writeU8(0xd6); + } else if (size === 8) { + // fixext 8 + this.writeU8(0xd7); + } else if (size === 16) { + // fixext 16 + this.writeU8(0xd8); + } else if (size < 0x100) { + // ext 8 + this.writeU8(0xc7); + this.writeU8(size); + } else if (size < 0x10000) { + // ext 16 + this.writeU8(0xc8); + this.writeU16(size); + } else if (size < 0x100000000) { + // ext 32 + this.writeU8(0xc9); + this.writeU32(size); + } else { + throw new Error(`Too large extension object: ${size}`); + } + this.writeI8(ext.type); + this.writeU8a(ext.data); + } + + private writeU8(value: number) { + this.ensureBufferSizeToWrite(1); + + this.view.setUint8(this.pos, value); + this.pos++; + } + + private writeU8a(values: ArrayLike) { + const size = values.length; + this.ensureBufferSizeToWrite(size); + + this.bytes.set(values, this.pos); + this.pos += size; + } + + private writeI8(value: number) { + this.ensureBufferSizeToWrite(1); + + this.view.setInt8(this.pos, value); + this.pos++; + } + + private writeU16(value: number) { + this.ensureBufferSizeToWrite(2); + + this.view.setUint16(this.pos, value); + this.pos += 2; + } + + private writeI16(value: number) { + this.ensureBufferSizeToWrite(2); + + this.view.setInt16(this.pos, value); + this.pos += 2; + } + + private writeU32(value: number) { + this.ensureBufferSizeToWrite(4); + + this.view.setUint32(this.pos, value); + this.pos += 4; + } + + private writeI32(value: number) { + this.ensureBufferSizeToWrite(4); + + this.view.setInt32(this.pos, value); + this.pos += 4; + } + + private writeF32(value: number) { + this.ensureBufferSizeToWrite(4); + + this.view.setFloat32(this.pos, value); + this.pos += 4; + } + + private writeF64(value: number) { + this.ensureBufferSizeToWrite(8); + + this.view.setFloat64(this.pos, value); + this.pos += 8; + } + + private writeU64(value: number) { + this.ensureBufferSizeToWrite(8); + + setUint64(this.view, this.pos, value); + this.pos += 8; + } + + private writeI64(value: number) { + this.ensureBufferSizeToWrite(8); + + setInt64(this.view, this.pos, value); + this.pos += 8; + } + + private writeBigUint64(value: bigint) { + this.ensureBufferSizeToWrite(8); + + this.view.setBigUint64(this.pos, value); + this.pos += 8; + } + + private writeBigInt64(value: bigint) { + this.ensureBufferSizeToWrite(8); + + this.view.setBigInt64(this.pos, value); + this.pos += 8; + } +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/ExtData.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/ExtData.ts new file mode 100644 index 0000000..facdddc --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/ExtData.ts @@ -0,0 +1,9 @@ +/** + * ExtData is used to handle Extension Types that are not registered to ExtensionCodec. + */ +export class ExtData { + constructor( + readonly type: number, + readonly data: Uint8Array, + ) {} +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/ExtensionCodec.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/ExtensionCodec.ts new file mode 100644 index 0000000..6ca9495 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/ExtensionCodec.ts @@ -0,0 +1,104 @@ +// ExtensionCodec to handle MessagePack extensions + +import { ExtData } from "./ExtData"; +import { timestampExtension } from "./timestamp"; + +export type ExtensionDecoderType = ( + data: Uint8Array, + extensionType: number, + context: ContextType, +) => unknown; + +export type ExtensionEncoderType = (input: unknown, context: ContextType) => Uint8Array | null; + +// immutable interface to ExtensionCodec +export type ExtensionCodecType = { + // eslint-disable-next-line @typescript-eslint/naming-convention + __brand?: ContextType; + tryToEncode(object: unknown, context: ContextType): ExtData | null; + decode(data: Uint8Array, extType: number, context: ContextType): unknown; +}; + +export class ExtensionCodec implements ExtensionCodecType { + public static readonly defaultCodec: ExtensionCodecType = new ExtensionCodec(); + + // ensures ExtensionCodecType matches ExtensionCodec + // this will make type errors a lot more clear + // eslint-disable-next-line @typescript-eslint/naming-convention + __brand?: ContextType; + + // built-in extensions + private readonly builtInEncoders: Array | undefined | null> = []; + private readonly builtInDecoders: Array | undefined | null> = []; + + // custom extensions + private readonly encoders: Array | undefined | null> = []; + private readonly decoders: Array | undefined | null> = []; + + public constructor() { + this.register(timestampExtension); + } + + public register({ + type, + encode, + decode, + }: { + type: number; + encode: ExtensionEncoderType; + decode: ExtensionDecoderType; + }): void { + if (type >= 0) { + // custom extensions + this.encoders[type] = encode; + this.decoders[type] = decode; + } else { + // built-in extensions + const index = 1 + type; + this.builtInEncoders[index] = encode; + this.builtInDecoders[index] = decode; + } + } + + public tryToEncode(object: unknown, context: ContextType): ExtData | null { + // built-in extensions + for (let i = 0; i < this.builtInEncoders.length; i++) { + const encodeExt = this.builtInEncoders[i]; + if (encodeExt != null) { + const data = encodeExt(object, context); + if (data != null) { + const type = -1 - i; + return new ExtData(type, data); + } + } + } + + // custom extensions + for (let i = 0; i < this.encoders.length; i++) { + const encodeExt = this.encoders[i]; + if (encodeExt != null) { + const data = encodeExt(object, context); + if (data != null) { + const type = i; + return new ExtData(type, data); + } + } + } + + if (object instanceof ExtData) { + // to keep ExtData as is + return object; + } + return null; + } + + public decode(data: Uint8Array, type: number, context: ContextType): unknown { + const decodeExt = type < 0 ? this.builtInDecoders[-1 - type] : this.decoders[type]; + if (decodeExt) { + return decodeExt(data, type, context); + } else { + // decode() does not fail, returns ExtData instead. + return new ExtData(type, data); + } + } +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/context.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/context.ts new file mode 100644 index 0000000..68c4c96 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/context.ts @@ -0,0 +1,14 @@ +/* eslint-disable @typescript-eslint/ban-types */ + +export type SplitTypes = U extends T ? (Exclude extends never ? T : Exclude) : T; + +export type SplitUndefined = SplitTypes; + +export type ContextOf = ContextType extends undefined + ? {} + : { + /** + * Custom user-defined data, read/writable + */ + context: ContextType; + }; diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/decode.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/decode.ts new file mode 100644 index 0000000..0d78a3e --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/decode.ts @@ -0,0 +1,45 @@ +import { Decoder } from "./Decoder"; +import type { DecoderOptions } from "./Decoder"; +import type { SplitUndefined } from "./context"; + +/** + * @deprecated Use {@link DecoderOptions} instead. + */ +export type DecodeOptions = never; + +/** + * @deprecated No longer supported. + */ +export const defaultDecodeOptions: never = undefined as never; + +/** + * It decodes a single MessagePack object in a buffer. + * + * This is a synchronous decoding function. + * See other variants for asynchronous decoding: {@link decodeAsync}, {@link decodeStream}, or {@link decodeArrayStream}. + * + * @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty. + * @throws {@link DecodeError} if the buffer contains invalid data. + */ +export function decode( + buffer: ArrayLike | Uint8Array | ArrayBufferView | ArrayBuffer, + options?: DecoderOptions>, +): unknown { + const decoder = new Decoder(options); + return decoder.decode(buffer); +} + +/** + * It decodes multiple MessagePack objects in a buffer. + * This is corresponding to {@link decodeMultiStream}. + * + * @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty. + * @throws {@link DecodeError} if the buffer contains invalid data. + */ +export function decodeMulti( + buffer: ArrayLike | Uint8Array | ArrayBufferView | ArrayBuffer, + options?: DecoderOptions>, +): Generator { + const decoder = new Decoder(options); + return decoder.decodeMulti(buffer); +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/decodeAsync.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/decodeAsync.ts new file mode 100644 index 0000000..a365fc8 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/decodeAsync.ts @@ -0,0 +1,49 @@ +import { Decoder } from "./Decoder"; +import { ensureAsyncIterable } from "./utils/stream"; +import type { DecoderOptions } from "./Decoder"; +import type { ReadableStreamLike } from "./utils/stream"; +import type { SplitUndefined } from "./context"; + +/** + * @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty. + * @throws {@link DecodeError} if the buffer contains invalid data. + */ +export async function decodeAsync( + streamLike: ReadableStreamLike | Uint8Array | ArrayBufferView | ArrayBuffer>, + options?: DecoderOptions>, +): Promise { + const stream = ensureAsyncIterable(streamLike); + const decoder = new Decoder(options); + return decoder.decodeAsync(stream as AsyncIterable | Uint8Array | ArrayBufferView | ArrayBuffer>); +} + +/** + * @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty. + * @throws {@link DecodeError} if the buffer contains invalid data. + */ +export function decodeArrayStream( + streamLike: ReadableStreamLike | Uint8Array | ArrayBufferView | ArrayBuffer>, + options?: DecoderOptions>, +): AsyncGenerator { + const stream = ensureAsyncIterable(streamLike); + const decoder = new Decoder(options); + return decoder.decodeArrayStream(stream as AsyncIterable | ArrayBufferView>); +} + +/** + * @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty. + * @throws {@link DecodeError} if the buffer contains invalid data. + */ +export function decodeMultiStream( + streamLike: ReadableStreamLike | Uint8Array | ArrayBufferView | ArrayBuffer>, + options?: DecoderOptions>, +): AsyncGenerator { + const stream = ensureAsyncIterable(streamLike); + const decoder = new Decoder(options); + return decoder.decodeStream(stream as AsyncIterable | ArrayBufferView>); +} + +/** + * @deprecated Use {@link decodeMultiStream} instead. + */ +export const decodeStream: never = undefined as never; diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/encode.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/encode.ts new file mode 100644 index 0000000..581c928 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/encode.ts @@ -0,0 +1,27 @@ +import { Encoder } from "./Encoder"; +import type { EncoderOptions } from "./Encoder"; +import type { SplitUndefined } from "./context"; + +/** + * @deprecated Use {@link EncoderOptions} instead. + */ +export type EncodeOptions = never; + +/** + * @deprecated No longer supported. + */ +export const defaultEncodeOptions: never = undefined as never; + +/** + * It encodes `value` in the MessagePack format and + * returns a byte buffer. + * + * The returned buffer is a slice of a larger `ArrayBuffer`, so you have to use its `#byteOffset` and `#byteLength` in order to convert it to another typed arrays including NodeJS `Buffer`. + */ +export function encode( + value: unknown, + options?: EncoderOptions>, +): Uint8Array { + const encoder = new Encoder(options); + return encoder.encodeSharedRef(value); +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/index.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/index.ts new file mode 100644 index 0000000..97529d9 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/index.ts @@ -0,0 +1,60 @@ +// Main Functions: + +import { encode } from "./encode"; +export { encode }; +import type { EncodeOptions } from "./encode"; +export type { EncodeOptions }; + +import { decode, decodeMulti } from "./decode"; +export { decode, decodeMulti }; +import type { DecodeOptions } from "./decode"; +export type { DecodeOptions }; + +import { decodeAsync, decodeArrayStream, decodeMultiStream, decodeStream } from "./decodeAsync"; +export { decodeAsync, decodeArrayStream, decodeMultiStream, decodeStream }; + +import { Decoder, DataViewIndexOutOfBoundsError } from "./Decoder"; +export { Decoder, DataViewIndexOutOfBoundsError }; +import type { DecoderOptions } from "./Decoder"; +export type { DecoderOptions }; +import { DecodeError } from "./DecodeError"; +export { DecodeError }; + +import { Encoder } from "./Encoder"; +export { Encoder }; +import type { EncoderOptions } from "./Encoder"; +export type { EncoderOptions }; + +// Utilities for Extension Types: + +import { ExtensionCodec } from "./ExtensionCodec"; +export { ExtensionCodec }; +import type { ExtensionCodecType, ExtensionDecoderType, ExtensionEncoderType } from "./ExtensionCodec"; +export type { ExtensionCodecType, ExtensionDecoderType, ExtensionEncoderType }; +import { ExtData } from "./ExtData"; +export { ExtData }; + +import { + EXT_TIMESTAMP, + encodeDateToTimeSpec, + encodeTimeSpecToTimestamp, + decodeTimestampToTimeSpec, + encodeTimestampExtension, + decodeTimestampExtension, + TimeSpec, +} from "./timestamp"; +import { getInt64, getUint64, setInt64, setUint64 } from './utils/int'; +import { utf8Count, utf8EncodeJs } from './utils/utf8'; +import { CachedKeyDecoder, KeyDecoder } from './CachedKeyDecoder'; + +export { + EXT_TIMESTAMP, + encodeDateToTimeSpec, + encodeTimeSpecToTimestamp, + decodeTimestampToTimeSpec, + encodeTimestampExtension, + decodeTimestampExtension, + setInt64, getInt64, getUint64, setUint64, + utf8Count, utf8EncodeJs, CachedKeyDecoder, KeyDecoder, + TimeSpec, +}; diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/timestamp.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/timestamp.ts new file mode 100644 index 0000000..e3fe015 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/timestamp.ts @@ -0,0 +1,108 @@ +// https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type +import { DecodeError } from "./DecodeError"; +import { getInt64, setInt64 } from "./utils/int"; + +export const EXT_TIMESTAMP = -1; + +export type TimeSpec = { + sec: number; + nsec: number; +}; + +const TIMESTAMP32_MAX_SEC = 0x100000000 - 1; // 32-bit unsigned int +const TIMESTAMP64_MAX_SEC = 0x400000000 - 1; // 34-bit unsigned int + +export function encodeTimeSpecToTimestamp({ sec, nsec }: TimeSpec): Uint8Array { + if (sec >= 0 && nsec >= 0 && sec <= TIMESTAMP64_MAX_SEC) { + // Here sec >= 0 && nsec >= 0 + if (nsec === 0 && sec <= TIMESTAMP32_MAX_SEC) { + // timestamp 32 = { sec32 (unsigned) } + const rv = new Uint8Array(4); + const view = new DataView(rv.buffer); + view.setUint32(0, sec); + return rv; + } else { + // timestamp 64 = { nsec30 (unsigned), sec34 (unsigned) } + const secHigh = sec / 0x100000000; + const secLow = sec & 0xffffffff; + const rv = new Uint8Array(8); + const view = new DataView(rv.buffer); + // nsec30 | secHigh2 + view.setUint32(0, (nsec << 2) | (secHigh & 0x3)); + // secLow32 + view.setUint32(4, secLow); + return rv; + } + } else { + // timestamp 96 = { nsec32 (unsigned), sec64 (signed) } + const rv = new Uint8Array(12); + const view = new DataView(rv.buffer); + view.setUint32(0, nsec); + setInt64(view, 4, sec); + return rv; + } +} + +export function encodeDateToTimeSpec(date: Date): TimeSpec { + const msec = date.getTime(); + const sec = Math.floor(msec / 1e3); + const nsec = (msec - sec * 1e3) * 1e6; + + // Normalizes { sec, nsec } to ensure nsec is unsigned. + const nsecInSec = Math.floor(nsec / 1e9); + return { + sec: sec + nsecInSec, + nsec: nsec - nsecInSec * 1e9, + }; +} + +export function encodeTimestampExtension(object: unknown): Uint8Array | null { + if (object instanceof Date) { + const timeSpec = encodeDateToTimeSpec(object); + return encodeTimeSpecToTimestamp(timeSpec); + } else { + return null; + } +} + +export function decodeTimestampToTimeSpec(data: Uint8Array): TimeSpec { + const view = new DataView(data.buffer, data.byteOffset, data.byteLength); + + // data may be 32, 64, or 96 bits + switch (data.byteLength) { + case 4: { + // timestamp 32 = { sec32 } + const sec = view.getUint32(0); + const nsec = 0; + return { sec, nsec }; + } + case 8: { + // timestamp 64 = { nsec30, sec34 } + const nsec30AndSecHigh2 = view.getUint32(0); + const secLow32 = view.getUint32(4); + const sec = (nsec30AndSecHigh2 & 0x3) * 0x100000000 + secLow32; + const nsec = nsec30AndSecHigh2 >>> 2; + return { sec, nsec }; + } + case 12: { + // timestamp 96 = { nsec32 (unsigned), sec64 (signed) } + + const sec = getInt64(view, 4); + const nsec = view.getUint32(0); + return { sec, nsec }; + } + default: + throw new DecodeError(`Unrecognized data size for timestamp (expected 4, 8, or 12): ${data.length}`); + } +} + +export function decodeTimestampExtension(data: Uint8Array): Date { + const timeSpec = decodeTimestampToTimeSpec(data); + return new Date(timeSpec.sec * 1e3 + timeSpec.nsec / 1e6); +} + +export const timestampExtension = { + type: EXT_TIMESTAMP, + encode: encodeTimestampExtension, + decode: decodeTimestampExtension, +}; diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/int.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/int.ts new file mode 100644 index 0000000..646ed32 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/int.ts @@ -0,0 +1,48 @@ +/** + * Copyright 2019 The MessagePack Community. + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +// Integer Utility + +export const UINT32_MAX = 0xffff_ffff; + +// DataView extension to handle int64 / uint64, +// where the actual range is 53-bits integer (a.k.a. safe integer) + +export function setUint64(view: DataView, offset: number, value: number): void { + const high = value / 0x1_0000_0000; + const low = value; // high bits are truncated by DataView + view.setUint32(offset, high); + view.setUint32(offset + 4, low); +} + +export function setInt64(view: DataView, offset: number, value: number): void { + const high = Math.floor(value / 0x1_0000_0000); + const low = value; // high bits are truncated by DataView + view.setUint32(offset, high); + view.setUint32(offset + 4, low); +} + +export function getInt64(view: DataView, offset: number): number { + const high = view.getInt32(offset); + const low = view.getUint32(offset + 4); + return high * 0x1_0000_0000 + low; +} + +export function getUint64(view: DataView, offset: number): number { + const high = view.getUint32(offset); + const low = view.getUint32(offset + 4); + return high * 0x1_0000_0000 + low; +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/prettyByte.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/prettyByte.ts new file mode 100644 index 0000000..c598138 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/prettyByte.ts @@ -0,0 +1,3 @@ +export function prettyByte(byte: number): string { + return `${byte < 0 ? "-" : ""}0x${Math.abs(byte).toString(16).padStart(2, "0")}`; +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/stream.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/stream.ts new file mode 100644 index 0000000..3450383 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/stream.ts @@ -0,0 +1,23 @@ +// utility for whatwg streams + +// The living standard of whatwg streams says +// ReadableStream is also AsyncIterable, but +// as of June 2019, no browser implements it. +// See https://streams.spec.whatwg.org/ for details +export type ReadableStreamLike = AsyncIterable; + +export function isAsyncIterable(object: ReadableStreamLike): object is AsyncIterable { + return (object as any)[Symbol.asyncIterator] != null; +} + +function assertNonNull(value: T | null | undefined): asserts value is T { + if (value == null) { + throw new Error("Assertion Failure: value must not be null nor undefined"); + } +} + +export function ensureAsyncIterable(streamLike: ReadableStreamLike): AsyncIterable { + if (isAsyncIterable(streamLike)) { + return streamLike as AsyncIterable; + } +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/typedArrays.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/typedArrays.ts new file mode 100644 index 0000000..6e04c21 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/typedArrays.ts @@ -0,0 +1,21 @@ +export function ensureUint8Array(buffer: ArrayLike | Uint8Array | ArrayBufferView | ArrayBuffer): Uint8Array { + if (buffer instanceof Uint8Array) { + return buffer; + } else if (ArrayBuffer.isView(buffer)) { + return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength); + } else if (buffer instanceof ArrayBuffer) { + return new Uint8Array(buffer); + } else { + // ArrayLike + return Uint8Array.from(buffer); + } +} + +export function createDataView(buffer: ArrayLike | ArrayBufferView | ArrayBuffer): DataView { + if (buffer instanceof ArrayBuffer) { + return new DataView(buffer); + } + + const bufferView = ensureUint8Array(buffer); + return new DataView(bufferView.buffer, bufferView.byteOffset, bufferView.byteLength); +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/utf8.ts b/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/utf8.ts new file mode 100644 index 0000000..291edb5 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/ets/utils/utf8.ts @@ -0,0 +1,179 @@ +import util from '@ohos.util'; + +export function utf8Count(str: string): number { + const strLength = str.length; + + let byteLength = 0; + let pos = 0; + while (pos < strLength) { + let value = str.charCodeAt(pos++); + + if ((value & 0xffffff80) === 0) { + // 1-byte + byteLength++; + continue; + } else if ((value & 0xfffff800) === 0) { + // 2-bytes + byteLength += 2; + } else { + // handle surrogate pair + if (value >= 0xd800 && value <= 0xdbff) { + // high surrogate + if (pos < strLength) { + const extra = str.charCodeAt(pos); + if ((extra & 0xfc00) === 0xdc00) { + ++pos; + value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; + } + } + } + + if ((value & 0xffff0000) === 0) { + // 3-byte + byteLength += 3; + } else { + // 4-byte + byteLength += 4; + } + } + } + return byteLength; +} + +export function utf8EncodeJs(str: string, output: Uint8Array, outputOffset: number): void { + const strLength = str.length; + let offset = outputOffset; + let pos = 0; + while (pos < strLength) { + let value = str.charCodeAt(pos++); + + if ((value & 0xffffff80) === 0) { + // 1-byte + output[offset++] = value; + continue; + } else if ((value & 0xfffff800) === 0) { + // 2-bytes + output[offset++] = ((value >> 6) & 0x1f) | 0xc0; + } else { + // handle surrogate pair + if (value >= 0xd800 && value <= 0xdbff) { + // high surrogate + if (pos < strLength) { + const extra = str.charCodeAt(pos); + if ((extra & 0xfc00) === 0xdc00) { + ++pos; + value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; + } + } + } + + if ((value & 0xffff0000) === 0) { + // 3-byte + output[offset++] = ((value >> 12) & 0x0f) | 0xe0; + output[offset++] = ((value >> 6) & 0x3f) | 0x80; + } else { + // 4-byte + output[offset++] = ((value >> 18) & 0x07) | 0xf0; + output[offset++] = ((value >> 12) & 0x3f) | 0x80; + output[offset++] = ((value >> 6) & 0x3f) | 0x80; + } + } + + output[offset++] = (value & 0x3f) | 0x80; + } +} + +// TextEncoder and TextDecoder are standardized in whatwg encoding: +// https://encoding.spec.whatwg.org/ +// and available in all the modern browsers: +// https://caniuse.com/textencoder +// They are available in Node.js since v12 LTS as well: +// https://nodejs.org/api/globals.html#textencoder + +const sharedTextEncoder = new util.TextEncoder(); + +// This threshold should be determined by benchmarking, which might vary in engines and input data. +// Run `npx ts-node benchmark/encode-string.ts` for details. +const TEXT_ENCODER_THRESHOLD = 50; + +export function utf8EncodeTE(str: string, output: Uint8Array, outputOffset: number): void { + sharedTextEncoder.encodeIntoUint8Array(str, output.subarray(outputOffset)); +} + +export function utf8Encode(str: string, output: Uint8Array, outputOffset: number): void { + if (str.length > TEXT_ENCODER_THRESHOLD) { + utf8EncodeTE(str, output, outputOffset); + } else { + utf8EncodeJs(str, output, outputOffset); + } +} + +const CHUNK_SIZE = 0x1_000; + +export function utf8DecodeJs(bytes: Uint8Array, inputOffset: number, byteLength: number): string { + let offset = inputOffset; + const end = offset + byteLength; + + const units: Array = []; + let result = ""; + while (offset < end) { + const byte1 = bytes[offset++]!; + if ((byte1 & 0x80) === 0) { + // 1 byte + units.push(byte1); + } else if ((byte1 & 0xe0) === 0xc0) { + // 2 bytes + const byte2 = bytes[offset++]! & 0x3f; + units.push(((byte1 & 0x1f) << 6) | byte2); + } else if ((byte1 & 0xf0) === 0xe0) { + // 3 bytes + const byte2 = bytes[offset++]! & 0x3f; + const byte3 = bytes[offset++]! & 0x3f; + units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3); + } else if ((byte1 & 0xf8) === 0xf0) { + // 4 bytes + const byte2 = bytes[offset++]! & 0x3f; + const byte3 = bytes[offset++]! & 0x3f; + const byte4 = bytes[offset++]! & 0x3f; + let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4; + if (unit > 0xffff) { + unit -= 0x10000; + units.push(((unit >>> 10) & 0x3ff) | 0xd800); + unit = 0xdc00 | (unit & 0x3ff); + } + units.push(unit); + } else { + units.push(byte1); + } + + if (units.length >= CHUNK_SIZE) { + result += String.fromCharCode(...units); + units.length = 0; + } + } + + if (units.length > 0) { + result += String.fromCharCode(...units); + } + + return result; +} + +const sharedTextDecoder = util.TextDecoder.create(); + +// This threshold should be determined by benchmarking, which might vary in engines and input data. +// Run `npx ts-node benchmark/decode-string.ts` for details. +const TEXT_DECODER_THRESHOLD = 200; + +export function utf8DecodeTD(bytes: Uint8Array, inputOffset: number, byteLength: number): string { + const stringBytes = bytes.subarray(inputOffset, inputOffset + byteLength); + return sharedTextDecoder.decodeToString(stringBytes); +} + +export function utf8Decode(bytes: Uint8Array, inputOffset: number, byteLength: number): string { + if (byteLength > TEXT_DECODER_THRESHOLD) { + return utf8DecodeTD(bytes, inputOffset, byteLength); + } else { + return utf8DecodeJs(bytes, inputOffset, byteLength); + } +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/module.json5 b/OpenHarmony/ohos_msgpack/library/src/main/module.json5 new file mode 100644 index 0000000..2ccdcbf --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/module.json5 @@ -0,0 +1,10 @@ +{ + "module": { + "name": "library", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ] + } +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/resources/base/element/string.json b/OpenHarmony/ohos_msgpack/library/src/main/resources/base/element/string.json new file mode 100644 index 0000000..1e76de0 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + } + ] +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/resources/en_US/element/string.json b/OpenHarmony/ohos_msgpack/library/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000..1e76de0 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/resources/en_US/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + } + ] +} diff --git a/OpenHarmony/ohos_msgpack/library/src/main/resources/zh_CN/element/string.json b/OpenHarmony/ohos_msgpack/library/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000..1e76de0 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/library/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + } + ] +} diff --git a/OpenHarmony/ohos_msgpack/oh-package.json5 b/OpenHarmony/ohos_msgpack/oh-package.json5 new file mode 100644 index 0000000..d399463 --- /dev/null +++ b/OpenHarmony/ohos_msgpack/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "license": "", + "devDependencies": { + "@ohos/hypium": "1.0.6" + }, + "author": "", + "name": "ohos_msgpack", + "description": "Please describe the basic information.", + "main": "", + "version": "1.0.2-rc.0", + "dependencies": {} +}