idlize

Форк
0
207 строк · 6.0 Кб
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 { int32, float32 } from "@koalaui/common"
17

18
export type NodePointer = pointer // todo: move to NativeModule
19

20
export type KStringPtr = int32 | string | null
21
export type KStringPtrArray = int32 | Uint8Array | null
22
export type KUint8ArrayPtr = int32 | Uint8Array | null
23
export type KInt32ArrayPtr = int32 | Int32Array | null
24
export type KFloat32ArrayPtr = int32 | Float32Array | null
25
export type KInt = int32
26
export type KUInt = int32
27
export type KBoolean = int32
28
export type KFloat = float32
29
export type KPointer = number | bigint
30
export type pointer = KPointer
31
export type KNativePointer = KPointer
32

33
export type TypedArray = // todo: move to interop-smth
34
    Uint8Array
35
    | Int8Array
36
    | Uint16Array
37
    | Int16Array
38
    | Uint32Array
39
    | Int32Array
40
    | Float32Array
41
    | Float64Array
42

43
export function decodeToString(array: Uint8Array): string {
44
    return decoder.decode(array)
45
}
46

47
export function isNullPtr(value: KPointer): boolean {
48
    return value === nullptr
49
}
50

51
export function className(object?: Object): string {
52
    return object?.constructor.name ?? "<null>"
53
}
54

55
export function ptrToString(ptr: KPointer) {
56
    return `0x${ptr!.toString(16).padStart(8, "0")}`
57
}
58

59
interface WithStreamOption {
60
    stream?: boolean | undefined;
61
}
62

63
interface SystemTextDecoder {
64
    decode(
65
        input?: ArrayBuffer,
66
        options?: WithStreamOption
67
    ): string;
68
}
69
export class CustomTextDecoder {
70
    static cpArrayMaxSize = 128
71
    constructor(decoder?: SystemTextDecoder) {
72
        this.decoder = decoder ?? new TextDecoder()
73
    }
74

75
    private readonly decoder: SystemTextDecoder
76

77
    decode(input: Uint8Array): string {
78
        if (this.decoder !== undefined) {
79
            return this.decoder!.decode(input)
80
        }
81
        const cpSize = Math.min(CustomTextDecoder.cpArrayMaxSize, input.length)
82
        let codePoints = new Int32Array(cpSize)
83
        let cpIndex = 0;
84
        let index = 0
85
        let result = ""
86
        while (index < input.length) {
87
            let elem = input[index]
88
            let lead = elem & 0xff
89
            let count = 0
90
            let value = 0
91
            if (lead < 0x80) {
92
                count = 1
93
                value = elem
94
            } else if ((lead >> 5) == 0x6) {
95
                value = ((elem << 6) & 0x7ff) + (input[index + 1] & 0x3f)
96
                count = 2
97
            } else if ((lead >> 4) == 0xe) {
98
                value = ((elem << 12) & 0xffff) + ((input[index + 1] << 6) & 0xfff) +
99
                    (input[index + 2] & 0x3f)
100
                count = 3
101
            } else if ((lead >> 3) == 0x1e) {
102
                value = ((elem << 18) & 0x1fffff) + ((input[index + 1] << 12) & 0x3ffff) +
103
                    ((input[index + 2] << 6) & 0xfff) + (input[index + 3] & 0x3f)
104
                count = 4
105
            }
106
            codePoints[cpIndex++] = value
107
            if (cpIndex == cpSize) {
108
                cpIndex = 0
109
                result += String.fromCodePoint(...codePoints)
110
            }
111
            index += count
112
        }
113
        if (cpIndex > 0) {
114
            result += String.fromCodePoint(...codePoints.slice(0, cpIndex))
115
        }
116
        return result
117
    }
118
}
119

120
const decoder = new CustomTextDecoder()
121

122
export class Wrapper {
123
    protected ptr: KPointer
124
    constructor(ptr: KPointer) {
125
        if (ptr == null)
126
            throw new Error(`Init <${className(this)}> with null native peer`)
127
        this.ptr = ptr
128
    }
129
    toString(): string {
130
        return `[native object <${className(this)}> at ${ptrToString(this.ptr)}]`
131
    }
132
}
133

134
export abstract class NativeStringBase extends Wrapper {
135
    constructor(ptr: KPointer) {
136
        super(ptr)
137
    }
138

139
    protected abstract bytesLength(): int32
140
    protected abstract getData(data: Uint8Array): void
141

142
    toString(): string {
143
        let length = this.bytesLength()
144
        let data = new Uint8Array(length)
145
        this.getData(data)
146
        return decodeToString(data)
147
    }
148

149
    abstract close(): void
150
}
151

152
export const nullptr: pointer = BigInt(0)
153

154
export interface PlatformDefinedData {
155
    nativeString(ptr: KPointer): NativeStringBase
156
    nativeStringArrayDecoder(ptr: KPointer): ArrayDecoder<NativeStringBase>
157
    callbackRegistry(): CallbackRegistry | undefined
158
}
159

160
let platformData: PlatformDefinedData | undefined = undefined
161

162
export function providePlatformDefinedData(platformDataParam: PlatformDefinedData) {
163
    platformData = platformDataParam
164
}
165

166
export function withStringResult(ptr: KPointer): string|undefined {
167
    if (isNullPtr(ptr)) return undefined
168
    let managedString = platformData!.nativeString(ptr)
169
    let result = managedString?.toString()
170
    managedString?.close()
171
    return result
172
}
173

174
export enum Access {
175
    READ = 1 << 0,
176
    WRITE = 1 << 1,
177
    READWRITE = READ | WRITE
178
}
179

180
export type ExecWithLength<P, R> = (pointer: P, length: int32) => R
181

182
function withArray<C extends TypedArray, R>(
183
    data: C | undefined,
184
    exec: ExecWithLength<C | null, R>
185
): R {
186
    return exec(data ?? null, data?.length ?? 0)
187
}
188

189
export function withUint8Array<T>(data: Uint8Array | undefined, access: Access, exec: ExecWithLength<Uint8Array | null, T>) {
190
    return withArray(data, exec)
191
}
192

193
export const withByteArray = withUint8Array
194

195
export abstract class ArrayDecoder<T> {
196
    abstract getArraySize(blob: KPointer): int32
197
    abstract disposeArray(blob: KPointer): void
198
    abstract getArrayElement(blob: KPointer, index: int32): T
199

200
    decode(blob: KPointer): Array<T> {
201
        throw new Error(`TODO`)
202
    }
203
}
204

205
export interface CallbackRegistry {
206
    registerCallback(callback: any, obj: any): KPointer
207
}
208

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

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

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

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