idlize

Форк
0
/
Interop.ts 
181 строка · 5.1 Кб
1
/*
2
 * Copyright (c) 2024 Huawei Device Co., Ltd.
3
 * Licensed under the Apache License, Version 2.0 (the "License");
4
 * you may not use this file except in compliance with the License.
5
 * You may obtain a copy of the License at
6
 *
7
 * http://www.apache.org/licenses/LICENSE-2.0
8
 *
9
 * Unless required by applicable law or agreed to in writing, software
10
 * distributed under the License is distributed on an "AS IS" BASIS,
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
 * See the License for the specific language governing permissions and
13
 * limitations under the License.
14
 */
15

16
import { pointer, KUint8ArrayPtr, KPointer, int32, TypedArray } from "./types"
17

18
export function decodeToString(array: Uint8Array): string {
19
    return decoder.decode(array)
20
}
21

22
export function isNullPtr(value: KPointer): boolean {
23
    return value === nullptr
24
}
25

26
export function className(object?: Object): string {
27
    return object?.constructor.name ?? "<null>"
28
}
29

30
export function ptrToString(ptr: KPointer) {
31
    return `0x${ptr!.toString(16).padStart(8, "0")}`
32
}
33

34
interface WithStreamOption {
35
    stream?: boolean | undefined;
36
}
37

38
interface SystemTextDecoder {
39
    decode(
40
        input?: ArrayBuffer,
41
        options?: WithStreamOption
42
    ): string;
43
}
44
export class CustomTextDecoder {
45
    static cpArrayMaxSize = 128
46
    constructor(decoder?: SystemTextDecoder) {
47
        this.decoder = decoder ?? new TextDecoder()
48
    }
49

50
    private readonly decoder: SystemTextDecoder
51

52
    decode(input: Uint8Array): string {
53
        if (this.decoder !== undefined) {
54
            return this.decoder!.decode(input)
55
        }
56
        const cpSize = Math.min(CustomTextDecoder.cpArrayMaxSize, input.length)
57
        let codePoints = new Int32Array(cpSize)
58
        let cpIndex = 0;
59
        let index = 0
60
        let result = ""
61
        while (index < input.length) {
62
            let elem = input[index]
63
            let lead = elem & 0xff
64
            let count = 0
65
            let value = 0
66
            if (lead < 0x80) {
67
                count = 1
68
                value = elem
69
            } else if ((lead >> 5) == 0x6) {
70
                value = ((elem << 6) & 0x7ff) + (input[index + 1] & 0x3f)
71
                count = 2
72
            } else if ((lead >> 4) == 0xe) {
73
                value = ((elem << 12) & 0xffff) + ((input[index + 1] << 6) & 0xfff) +
74
                    (input[index + 2] & 0x3f)
75
                count = 3
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)
79
                count = 4
80
            }
81
            codePoints[cpIndex++] = value
82
            if (cpIndex == cpSize) {
83
                cpIndex = 0
84
                result += String.fromCodePoint(...codePoints)
85
            }
86
            index += count
87
        }
88
        if (cpIndex > 0) {
89
            result += String.fromCodePoint(...codePoints.slice(0, cpIndex))
90
        }
91
        return result
92
    }
93
}
94

95

96
const decoder = new CustomTextDecoder()
97

98

99
export class Wrapper {
100
    protected ptr: KPointer
101
    constructor(ptr: KPointer) {
102
        if (ptr == null)
103
            throw new Error(`Init <${className(this)}> with null native peer`)
104
        this.ptr = ptr
105
    }
106
    toString(): string {
107
        return `[native object <${className(this)}> at ${ptrToString(this.ptr)}]`
108
    }
109
}
110

111
export abstract class NativeStringBase extends Wrapper {
112
    constructor(ptr: KPointer) {
113
        super(ptr)
114
    }
115

116
    protected abstract bytesLength(): int32
117
    protected abstract getData(data: Uint8Array): void
118

119
    toString(): string {
120
        let length = this.bytesLength()
121
        let data = new Uint8Array(length)
122
        this.getData(data)
123
        return decodeToString(data)
124
    }
125

126
    abstract close(): void
127
}
128

129
export const nullptr: pointer = BigInt(0)
130

131
export class Finalizable {
132
    constructor(public ptr: pointer) {
133
    }
134
}
135

136
export class PeerNode extends Finalizable {
137
    constructor() {
138
        // TODO: rework
139
        super(BigInt(42))
140
    }
141
    applyAttributes(attrs: Object) {}
142
}
143

144
export interface PlatformDefinedData {
145
    nativeString(ptr: KPointer): NativeStringBase
146
}
147

148
let platformData: PlatformDefinedData|undefined = undefined
149

150
export function providePlatformDefinedData(platformDataParam: PlatformDefinedData) {
151
    platformData = platformDataParam
152
}
153

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()
159
    return result
160
}
161

162
export enum Access {
163
    READ = 1 << 0,
164
    WRITE = 1 << 1,
165
    READWRITE = READ | WRITE
166
}
167

168
export type ExecWithLength<P, R> = (pointer: P, length: int32) => R
169

170
function withArray<C extends TypedArray, R>(
171
    data: C | undefined,
172
    exec: ExecWithLength<C | null, R>
173
): R {
174
    return exec(data ?? null, data?.length ?? 0)
175
}
176

177
export function withUint8Array<T>(data: Uint8Array | undefined, access: Access, exec: ExecWithLength<Uint8Array | null, T>) {
178
    return withArray(data, exec)
179
}
180

181
export const withByteArray = withUint8Array
182

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.