Path: blob/main/src/vs/editor/common/services/semanticTokensDto.ts
3295 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { VSBuffer } from '../../../base/common/buffer.js';6import * as platform from '../../../base/common/platform.js';78export interface IFullSemanticTokensDto {9id: number;10type: 'full';11data: Uint32Array;12}1314export interface IDeltaSemanticTokensDto {15id: number;16type: 'delta';17deltas: { start: number; deleteCount: number; data?: Uint32Array }[];18}1920export type ISemanticTokensDto = IFullSemanticTokensDto | IDeltaSemanticTokensDto;2122const enum EncodedSemanticTokensType {23Full = 1,24Delta = 225}2627function reverseEndianness(arr: Uint8Array): void {28for (let i = 0, len = arr.length; i < len; i += 4) {29// flip bytes 0<->3 and 1<->230const b0 = arr[i + 0];31const b1 = arr[i + 1];32const b2 = arr[i + 2];33const b3 = arr[i + 3];34arr[i + 0] = b3;35arr[i + 1] = b2;36arr[i + 2] = b1;37arr[i + 3] = b0;38}39}4041function toLittleEndianBuffer(arr: Uint32Array): VSBuffer {42const uint8Arr = new Uint8Array(arr.buffer, arr.byteOffset, arr.length * 4);43if (!platform.isLittleEndian()) {44// the byte order must be changed45reverseEndianness(uint8Arr);46}47return VSBuffer.wrap(uint8Arr);48}4950function fromLittleEndianBuffer(buff: VSBuffer): Uint32Array {51const uint8Arr = buff.buffer;52if (!platform.isLittleEndian()) {53// the byte order must be changed54reverseEndianness(uint8Arr);55}56if (uint8Arr.byteOffset % 4 === 0) {57return new Uint32Array(uint8Arr.buffer, uint8Arr.byteOffset, uint8Arr.length / 4);58} else {59// unaligned memory access doesn't work on all platforms60const data = new Uint8Array(uint8Arr.byteLength);61data.set(uint8Arr);62return new Uint32Array(data.buffer, data.byteOffset, data.length / 4);63}64}6566export function encodeSemanticTokensDto(semanticTokens: ISemanticTokensDto): VSBuffer {67const dest = new Uint32Array(encodeSemanticTokensDtoSize(semanticTokens));68let offset = 0;69dest[offset++] = semanticTokens.id;70if (semanticTokens.type === 'full') {71dest[offset++] = EncodedSemanticTokensType.Full;72dest[offset++] = semanticTokens.data.length;73dest.set(semanticTokens.data, offset); offset += semanticTokens.data.length;74} else {75dest[offset++] = EncodedSemanticTokensType.Delta;76dest[offset++] = semanticTokens.deltas.length;77for (const delta of semanticTokens.deltas) {78dest[offset++] = delta.start;79dest[offset++] = delta.deleteCount;80if (delta.data) {81dest[offset++] = delta.data.length;82dest.set(delta.data, offset); offset += delta.data.length;83} else {84dest[offset++] = 0;85}86}87}88return toLittleEndianBuffer(dest);89}9091function encodeSemanticTokensDtoSize(semanticTokens: ISemanticTokensDto): number {92let result = 0;93result += (94+ 1 // id95+ 1 // type96);97if (semanticTokens.type === 'full') {98result += (99+ 1 // data length100+ semanticTokens.data.length101);102} else {103result += (104+ 1 // delta count105);106result += (107+ 1 // start108+ 1 // deleteCount109+ 1 // data length110) * semanticTokens.deltas.length;111for (const delta of semanticTokens.deltas) {112if (delta.data) {113result += delta.data.length;114}115}116}117return result;118}119120export function decodeSemanticTokensDto(_buff: VSBuffer): ISemanticTokensDto {121const src = fromLittleEndianBuffer(_buff);122let offset = 0;123const id = src[offset++];124const type: EncodedSemanticTokensType = src[offset++];125if (type === EncodedSemanticTokensType.Full) {126const length = src[offset++];127const data = src.subarray(offset, offset + length); offset += length;128return {129id: id,130type: 'full',131data: data132};133}134const deltaCount = src[offset++];135const deltas: { start: number; deleteCount: number; data?: Uint32Array }[] = [];136for (let i = 0; i < deltaCount; i++) {137const start = src[offset++];138const deleteCount = src[offset++];139const length = src[offset++];140let data: Uint32Array | undefined;141if (length > 0) {142data = src.subarray(offset, offset + length); offset += length;143}144deltas[i] = { start, deleteCount, data };145}146return {147id: id,148type: 'delta',149deltas: deltas150};151}152153154