idlize

Форк
0
/
DeserializerBase.ts 
219 строк · 6.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
import {float32, int32} from "@koalaui/common"
16
import {pointer} from "@koalaui/interop"
17
import {RuntimeType, Tags} from "./SerializerBase";
18
// import { Length } from "@arkoala/arkui"
19

20
export class DeserializerBase {
21
    private position = 0
22
    private readonly buffer: ArrayBuffer
23
    private readonly length: int32
24
    private view: DataView
25
    private static textDecoder = new TextDecoder()
26
    private static customDeserializers: CustomDeserializer | undefined = undefined
27

28
    static registerCustomDeserializer(deserializer: CustomDeserializer) {
29
        let current = DeserializerBase.customDeserializers
30
        if (current == undefined) {
31
            DeserializerBase.customDeserializers = deserializer
32
        } else {
33
            while (current.next != undefined) {
34
                current = current.next
35
            }
36
            current.next = deserializer
37
        }
38
    }
39

40
    constructor(buffer: ArrayBuffer, length: int32) {
41
        this.buffer = buffer
42
        this.length = length
43
        this.view = new DataView(this.buffer)
44
    }
45

46
    asArray(position?: number, length?: number): Uint8Array {
47
        return new Uint8Array(this.buffer, position, length)
48
    }
49

50
    currentPosition(): int32 {
51
        return this.position
52
    }
53

54
    resetCurrentPosition(): void {
55
        this.position = 0
56
    }
57

58
    private checkCapacity(value: int32) {
59
        if (value > this.length) {
60
            throw new Error(`${value} is less than remaining buffer length`)
61
        }
62
    }
63

64
    readInt8(): int32 {
65
        this.checkCapacity(1)
66
        const value = this.view.getInt8(this.position)
67
        this.position += 1
68
        return value
69
    }
70

71
    readInt32(): int32 {
72
        this.checkCapacity(4)
73
        const value = this.view.getInt32(this.position, true)
74
        this.position += 4
75
        return value
76
    }
77

78
    readPointer(): pointer {
79
        this.checkCapacity(8)
80
        const value = this.view.getBigInt64(this.position, true)
81
        this.position += 8
82
        return value
83
    }
84

85
    readFloat32(): float32 {
86
        this.checkCapacity(4)
87
        const value = this.view.getFloat32(this.position, true)
88
        this.position += 4
89
        return value
90
    }
91

92
    readBoolean(): boolean {
93
        this.checkCapacity(1)
94
        const value = this.view.getInt8(this.position)
95
        this.position += 1
96
        return value == 1
97
    }
98

99
    readFunction(): any {
100
        // TODO: not exactly correct.
101
        const id = this.readInt32()
102
        return id
103
    }
104

105
    readMaterialized(): object {
106
        const ptr = this.readPointer()
107
        return { ptr: ptr }
108
    }
109

110
    readString(): string {
111
        const length = this.readInt32()
112
        this.checkCapacity(length)
113
        // read without null-terminated byte
114
        const value = DeserializerBase.textDecoder.decode(this.asArray(this.position, length - 1));
115
        this.position += length
116
        return value
117
    }
118

119
    readCustomObject(kind: string): any {
120
        let current = DeserializerBase.customDeserializers
121
        while (current) {
122
            if (current.supports(kind)) {
123
                return current.deserialize(this, kind)
124
            }
125
            current = current.next
126
        }
127
        // consume tag
128
        const tag = this.readInt8()
129
        return undefined
130
    }
131

132
    readNumber(): number | undefined {
133
        const tag = this.readInt8()
134
        switch (tag) {
135
            case Tags.UNDEFINED:
136
                return undefined;
137
            case Tags.INT32:
138
                return this.readInt32()
139
            case Tags.FLOAT32:
140
                return this.readFloat32()
141
            default:
142
                throw new Error(`Unknown number tag: ${tag}`)
143
                break
144
        }
145
    }
146

147
    readLength(): Length | undefined {
148
        this.checkCapacity(1)
149
        const valueType = this.readInt8()
150
        switch (valueType) {
151
            case RuntimeType.OBJECT:
152
                return {
153
                    id: this.readInt32(),
154
                    bundleName: "",
155
                    moduleName: ""
156
                }
157
            case RuntimeType.STRING:
158
                return this.readString()
159
            case RuntimeType.NUMBER:
160
                return this.readFloat32()
161
        }
162
        return undefined
163
    }
164

165
    static lengthUnitFromInt(unit: int32): string {
166
        let suffix: string
167
        switch (unit) {
168
            case 0:
169
                suffix = "px"
170
                break
171
            case 1:
172
                suffix = "vp"
173
                break
174
            case 3:
175
                suffix = "%"
176
                break
177
            case 4:
178
                suffix = "lpx"
179
                break
180
            default:
181
                suffix = "<unknown>"
182
        }
183
        return suffix
184
    }
185
}
186

187
export abstract class CustomDeserializer {
188
    protected constructor(protected supported: Array<string>) {
189
    }
190

191
    supports(kind: string): boolean {
192
        return this.supported.includes(kind)
193
    }
194

195
    abstract deserialize(serializer: DeserializerBase, kind: string): any
196

197
    next: CustomDeserializer | undefined = undefined
198
}
199

200
class OurCustomDeserializer extends CustomDeserializer {
201
    constructor() {
202
        super(["Resource", "Pixmap"])
203
    }
204
    deserialize(deserializer: DeserializerBase, kind: string): any {
205
        return JSON.parse(deserializer.readString())
206
    }
207
}
208
DeserializerBase.registerCustomDeserializer(new OurCustomDeserializer())
209

210
class DateDeserializer extends CustomDeserializer {
211
    constructor() {
212
        super(["Date"]);
213
    }
214

215
    deserialize(serializer: DeserializerBase, kind: string): any {
216
        return new Date(serializer.readString())
217
    }
218
}
219
DeserializerBase.registerCustomDeserializer(new DateDeserializer())
220

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

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

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

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