2
* Copyright (c) 2024 Huawei Device Co., Ltd.
3
* Licensed under the Apache License, Version 2.0 (the "License");
4
* you may not use this file except in compliance with the License.
5
* You may obtain a copy of the License at
7
* http://www.apache.org/licenses/LICENSE-2.0
9
* Unless required by applicable law or agreed to in writing, software
10
* distributed under the License is distributed on an "AS IS" BASIS,
11
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
* See the License for the specific language governing permissions and
13
* limitations under the License.
16
import { pointer, KUint8ArrayPtr, KPointer, int32, TypedArray } from "./types"
18
export function decodeToString(array: Uint8Array): string {
19
return decoder.decode(array)
22
export function isNullPtr(value: KPointer): boolean {
23
return value === nullptr
26
export function className(object?: Object): string {
27
return object?.constructor.name ?? "<null>"
30
export function ptrToString(ptr: KPointer) {
31
return `0x${ptr!.toString(16).padStart(8, "0")}`
34
interface WithStreamOption {
35
stream?: boolean | undefined;
38
interface SystemTextDecoder {
41
options?: WithStreamOption
44
export class CustomTextDecoder {
45
static cpArrayMaxSize = 128
46
constructor(decoder?: SystemTextDecoder) {
47
this.decoder = decoder ?? new TextDecoder()
50
private readonly decoder: SystemTextDecoder
52
decode(input: Uint8Array): string {
53
if (this.decoder !== undefined) {
54
return this.decoder!.decode(input)
56
const cpSize = Math.min(CustomTextDecoder.cpArrayMaxSize, input.length)
57
let codePoints = new Int32Array(cpSize)
61
while (index < input.length) {
62
let elem = input[index]
63
let lead = elem & 0xff
69
} else if ((lead >> 5) == 0x6) {
70
value = ((elem << 6) & 0x7ff) + (input[index + 1] & 0x3f)
72
} else if ((lead >> 4) == 0xe) {
73
value = ((elem << 12) & 0xffff) + ((input[index + 1] << 6) & 0xfff) +
74
(input[index + 2] & 0x3f)
76
} else if ((lead >> 3) == 0x1e) {
77
value = ((elem << 18) & 0x1fffff) + ((input[index + 1] << 12) & 0x3ffff) +
78
((input[index + 2] << 6) & 0xfff) + (input[index + 3] & 0x3f)
81
codePoints[cpIndex++] = value
82
if (cpIndex == cpSize) {
84
result += String.fromCodePoint(...codePoints)
89
result += String.fromCodePoint(...codePoints.slice(0, cpIndex))
96
const decoder = new CustomTextDecoder()
100
protected ptr: KPointer
101
constructor(ptr: KPointer) {
103
throw new Error(`Init <${className(this)}> with null native peer`)
107
return `[native object <${className(this)}> at ${ptrToString(this.ptr)}]`
111
export abstract class NativeStringBase extends Wrapper {
112
constructor(ptr: KPointer) {
116
protected abstract bytesLength(): int32
117
protected abstract getData(data: Uint8Array): void
120
let length = this.bytesLength()
121
let data = new Uint8Array(length)
123
return decodeToString(data)
126
abstract close(): void
129
export const nullptr: pointer = BigInt(0)
131
export class Finalizable {
132
constructor(public ptr: pointer) {
136
export class PeerNode extends Finalizable {
141
applyAttributes(attrs: Object) {}
144
export interface PlatformDefinedData {
145
nativeString(ptr: KPointer): NativeStringBase
148
let platformData: PlatformDefinedData|undefined = undefined
150
export function providePlatformDefinedData(platformDataParam: PlatformDefinedData) {
151
platformData = platformDataParam
154
export function withStringResult(ptr: KPointer): string|undefined {
155
if (isNullPtr(ptr)) return undefined
156
let managedString = platformData!.nativeString(ptr)
157
let result = managedString?.toString()
158
managedString?.close()
165
READWRITE = READ | WRITE
168
export type ExecWithLength<P, R> = (pointer: P, length: int32) => R
170
function withArray<C extends TypedArray, R>(
172
exec: ExecWithLength<C | null, R>
174
return exec(data ?? null, data?.length ?? 0)
177
export function withUint8Array<T>(data: Uint8Array | undefined, access: Access, exec: ExecWithLength<Uint8Array | null, T>) {
178
return withArray(data, exec)
181
export const withByteArray = withUint8Array