Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/common/services/semanticTokensDto.ts
3295 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { VSBuffer } from '../../../base/common/buffer.js';
7
import * as platform from '../../../base/common/platform.js';
8
9
export interface IFullSemanticTokensDto {
10
id: number;
11
type: 'full';
12
data: Uint32Array;
13
}
14
15
export interface IDeltaSemanticTokensDto {
16
id: number;
17
type: 'delta';
18
deltas: { start: number; deleteCount: number; data?: Uint32Array }[];
19
}
20
21
export type ISemanticTokensDto = IFullSemanticTokensDto | IDeltaSemanticTokensDto;
22
23
const enum EncodedSemanticTokensType {
24
Full = 1,
25
Delta = 2
26
}
27
28
function reverseEndianness(arr: Uint8Array): void {
29
for (let i = 0, len = arr.length; i < len; i += 4) {
30
// flip bytes 0<->3 and 1<->2
31
const b0 = arr[i + 0];
32
const b1 = arr[i + 1];
33
const b2 = arr[i + 2];
34
const b3 = arr[i + 3];
35
arr[i + 0] = b3;
36
arr[i + 1] = b2;
37
arr[i + 2] = b1;
38
arr[i + 3] = b0;
39
}
40
}
41
42
function toLittleEndianBuffer(arr: Uint32Array): VSBuffer {
43
const uint8Arr = new Uint8Array(arr.buffer, arr.byteOffset, arr.length * 4);
44
if (!platform.isLittleEndian()) {
45
// the byte order must be changed
46
reverseEndianness(uint8Arr);
47
}
48
return VSBuffer.wrap(uint8Arr);
49
}
50
51
function fromLittleEndianBuffer(buff: VSBuffer): Uint32Array {
52
const uint8Arr = buff.buffer;
53
if (!platform.isLittleEndian()) {
54
// the byte order must be changed
55
reverseEndianness(uint8Arr);
56
}
57
if (uint8Arr.byteOffset % 4 === 0) {
58
return new Uint32Array(uint8Arr.buffer, uint8Arr.byteOffset, uint8Arr.length / 4);
59
} else {
60
// unaligned memory access doesn't work on all platforms
61
const data = new Uint8Array(uint8Arr.byteLength);
62
data.set(uint8Arr);
63
return new Uint32Array(data.buffer, data.byteOffset, data.length / 4);
64
}
65
}
66
67
export function encodeSemanticTokensDto(semanticTokens: ISemanticTokensDto): VSBuffer {
68
const dest = new Uint32Array(encodeSemanticTokensDtoSize(semanticTokens));
69
let offset = 0;
70
dest[offset++] = semanticTokens.id;
71
if (semanticTokens.type === 'full') {
72
dest[offset++] = EncodedSemanticTokensType.Full;
73
dest[offset++] = semanticTokens.data.length;
74
dest.set(semanticTokens.data, offset); offset += semanticTokens.data.length;
75
} else {
76
dest[offset++] = EncodedSemanticTokensType.Delta;
77
dest[offset++] = semanticTokens.deltas.length;
78
for (const delta of semanticTokens.deltas) {
79
dest[offset++] = delta.start;
80
dest[offset++] = delta.deleteCount;
81
if (delta.data) {
82
dest[offset++] = delta.data.length;
83
dest.set(delta.data, offset); offset += delta.data.length;
84
} else {
85
dest[offset++] = 0;
86
}
87
}
88
}
89
return toLittleEndianBuffer(dest);
90
}
91
92
function encodeSemanticTokensDtoSize(semanticTokens: ISemanticTokensDto): number {
93
let result = 0;
94
result += (
95
+ 1 // id
96
+ 1 // type
97
);
98
if (semanticTokens.type === 'full') {
99
result += (
100
+ 1 // data length
101
+ semanticTokens.data.length
102
);
103
} else {
104
result += (
105
+ 1 // delta count
106
);
107
result += (
108
+ 1 // start
109
+ 1 // deleteCount
110
+ 1 // data length
111
) * semanticTokens.deltas.length;
112
for (const delta of semanticTokens.deltas) {
113
if (delta.data) {
114
result += delta.data.length;
115
}
116
}
117
}
118
return result;
119
}
120
121
export function decodeSemanticTokensDto(_buff: VSBuffer): ISemanticTokensDto {
122
const src = fromLittleEndianBuffer(_buff);
123
let offset = 0;
124
const id = src[offset++];
125
const type: EncodedSemanticTokensType = src[offset++];
126
if (type === EncodedSemanticTokensType.Full) {
127
const length = src[offset++];
128
const data = src.subarray(offset, offset + length); offset += length;
129
return {
130
id: id,
131
type: 'full',
132
data: data
133
};
134
}
135
const deltaCount = src[offset++];
136
const deltas: { start: number; deleteCount: number; data?: Uint32Array }[] = [];
137
for (let i = 0; i < deltaCount; i++) {
138
const start = src[offset++];
139
const deleteCount = src[offset++];
140
const length = src[offset++];
141
let data: Uint32Array | undefined;
142
if (length > 0) {
143
data = src.subarray(offset, offset + length); offset += length;
144
}
145
deltas[i] = { start, deleteCount, data };
146
}
147
return {
148
id: id,
149
type: 'delta',
150
deltas: deltas
151
};
152
}
153
154