Use subarrays if the platform is little endian

This commit is contained in:
Alex Dima
2020-03-24 10:57:36 +01:00
parent c952ac25a9
commit c0f2ad1dcd
3 changed files with 72 additions and 16 deletions

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { VSBuffer } from 'vs/base/common/buffer';
import * as platform from 'vs/base/common/platform';
export interface IFullSemanticTokensDto {
id: number;
@@ -24,26 +25,45 @@ const enum EncodedSemanticTokensType {
Delta = 2
}
function toUint8Array(arr: Uint32Array): Uint8Array {
return new Uint8Array(arr.buffer, arr.byteOffset, arr.length * 4);
}
function toUint32Array(arr: Uint8Array, byteOffset: number, length: number): Uint32Array {
return new Uint32Array(arr.buffer, arr.byteOffset + byteOffset, length);
}
export function encodeSemanticTokensDto(semanticTokens: ISemanticTokensDto): VSBuffer {
const isLittleEndian = platform.isLittleEndian();
const buff = VSBuffer.alloc(encodeSemanticTokensDtoSize(semanticTokens));
let offset = 0;
buff.writeUInt32LE(semanticTokens.id, offset); offset += 4;
if (semanticTokens.type === 'full') {
buff.writeUInt8(EncodedSemanticTokensType.Full, offset); offset += 1;
buff.writeUInt32LE(EncodedSemanticTokensType.Full, offset); offset += 4;
buff.writeUInt32LE(semanticTokens.data.length, offset); offset += 4;
for (const uint of semanticTokens.data) {
buff.writeUInt32LE(uint, offset); offset += 4;
if (isLittleEndian) {
const uint8Arr = toUint8Array(semanticTokens.data);
buff.set(uint8Arr, offset); offset += uint8Arr.length;
} else {
for (const uint of semanticTokens.data) {
buff.writeUInt32LE(uint, offset); offset += 4;
}
}
} else {
buff.writeUInt8(EncodedSemanticTokensType.Delta, offset); offset += 1;
buff.writeUInt32LE(EncodedSemanticTokensType.Delta, offset); offset += 4;
buff.writeUInt32LE(semanticTokens.deltas.length, offset); offset += 4;
for (const delta of semanticTokens.deltas) {
buff.writeUInt32LE(delta.start, offset); offset += 4;
buff.writeUInt32LE(delta.deleteCount, offset); offset += 4;
if (delta.data) {
buff.writeUInt32LE(delta.data.length, offset); offset += 4;
for (const uint of delta.data) {
buff.writeUInt32LE(uint, offset); offset += 4;
if (isLittleEndian) {
const uint8Arr = toUint8Array(delta.data);
buff.set(uint8Arr, offset); offset += uint8Arr.length;
} else {
for (const uint of delta.data) {
buff.writeUInt32LE(uint, offset); offset += 4;
}
}
} else {
buff.writeUInt32LE(0, offset); offset += 4;
@@ -56,7 +76,7 @@ export function encodeSemanticTokensDto(semanticTokens: ISemanticTokensDto): VSB
function encodeSemanticTokensDtoSize(semanticTokens: ISemanticTokensDto): number {
let result = 0;
result += 4; // id
result += 1; // type
result += 4; // type
if (semanticTokens.type === 'full') {
result += 4; // data length
result += semanticTokens.data.byteLength;
@@ -75,14 +95,20 @@ function encodeSemanticTokensDtoSize(semanticTokens: ISemanticTokensDto): number
}
export function decodeSemanticTokensDto(buff: VSBuffer): ISemanticTokensDto {
const isLittleEndian = platform.isLittleEndian();
let offset = 0;
const id = buff.readUInt32LE(offset); offset += 4;
const type: EncodedSemanticTokensType = buff.readUInt8(offset); offset += 1;
const type: EncodedSemanticTokensType = buff.readUInt32LE(offset); offset += 4;
if (type === EncodedSemanticTokensType.Full) {
const length = buff.readUInt32LE(offset); offset += 4;
const data = new Uint32Array(length);
for (let j = 0; j < length; j++) {
data[j] = buff.readUInt32LE(offset); offset += 4;
let data: Uint32Array;
if (isLittleEndian) {
data = toUint32Array(buff.buffer, offset, length); offset += 4 * length;
} else {
data = new Uint32Array(length);
for (let j = 0; j < length; j++) {
data[j] = buff.readUInt32LE(offset); offset += 4;
}
}
return {
id: id,
@@ -98,9 +124,13 @@ export function decodeSemanticTokensDto(buff: VSBuffer): ISemanticTokensDto {
const length = buff.readUInt32LE(offset); offset += 4;
let data: Uint32Array | undefined;
if (length > 0) {
data = new Uint32Array(length);
for (let j = 0; j < length; j++) {
data[j] = buff.readUInt32LE(offset); offset += 4;
if (isLittleEndian) {
data = toUint32Array(buff.buffer, offset, length); offset += 4 * length;
} else {
data = new Uint32Array(length);
for (let j = 0; j < length; j++) {
data[j] = buff.readUInt32LE(offset); offset += 4;
}
}
}
deltas[i] = { start, deleteCount, data };