95 lines
3.3 KiB
TypeScript
95 lines
3.3 KiB
TypeScript
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
export namespace TextMessageFormat {
|
|
|
|
const RecordSeparator = String.fromCharCode(0x1e);
|
|
|
|
export function write(output: string): string {
|
|
return `${output}${RecordSeparator}`;
|
|
}
|
|
|
|
export function parse(input: string): string[] {
|
|
if (input[input.length - 1] != RecordSeparator) {
|
|
throw new Error("Message is incomplete.");
|
|
}
|
|
|
|
let messages = input.split(RecordSeparator);
|
|
messages.pop();
|
|
return messages;
|
|
}
|
|
}
|
|
|
|
export namespace BinaryMessageFormat {
|
|
|
|
// The length prefix of binary messages is encoded as VarInt. Read the comment in
|
|
// the BinaryMessageParser.TryParseMessage for details.
|
|
|
|
export function write(output: Uint8Array): ArrayBuffer {
|
|
// msgpack5 uses returns Buffer instead of Uint8Array on IE10 and some other browser
|
|
// in which case .byteLength does will be undefined
|
|
let size = output.byteLength || output.length;
|
|
let lenBuffer = [];
|
|
do
|
|
{
|
|
let sizePart = size & 0x7f;
|
|
size = size >> 7;
|
|
if (size > 0) {
|
|
sizePart |= 0x80;
|
|
}
|
|
lenBuffer.push(sizePart);
|
|
}
|
|
while (size > 0);
|
|
|
|
// msgpack5 uses returns Buffer instead of Uint8Array on IE10 and some other browser
|
|
// in which case .byteLength does will be undefined
|
|
size = output.byteLength || output.length;
|
|
|
|
let buffer = new Uint8Array(lenBuffer.length + size);
|
|
buffer.set(lenBuffer, 0);
|
|
buffer.set(output, lenBuffer.length);
|
|
return buffer.buffer;
|
|
}
|
|
|
|
export function parse(input: ArrayBuffer): Uint8Array[] {
|
|
let result: Uint8Array[] = [];
|
|
let uint8Array = new Uint8Array(input);
|
|
const maxLengthPrefixSize = 5;
|
|
const numBitsToShift = [0, 7, 14, 21, 28 ];
|
|
|
|
for (let offset = 0; offset < input.byteLength;) {
|
|
let numBytes = 0;
|
|
let size = 0;
|
|
let byteRead;
|
|
do
|
|
{
|
|
byteRead = uint8Array[offset + numBytes];
|
|
size = size | ((byteRead & 0x7f) << (numBitsToShift[numBytes]));
|
|
numBytes++;
|
|
}
|
|
while (numBytes < Math.min(maxLengthPrefixSize, input.byteLength - offset) && (byteRead & 0x80) != 0);
|
|
|
|
if ((byteRead & 0x80) !== 0 && numBytes < maxLengthPrefixSize) {
|
|
throw new Error("Cannot read message size.");
|
|
}
|
|
|
|
if (numBytes === maxLengthPrefixSize && byteRead > 7) {
|
|
throw new Error("Messages bigger than 2GB are not supported.");
|
|
}
|
|
|
|
if (uint8Array.byteLength >= (offset + numBytes + size)) {
|
|
// IE does not support .slice() so use subarray
|
|
result.push(uint8Array.slice
|
|
? uint8Array.slice(offset + numBytes, offset + numBytes + size)
|
|
: uint8Array.subarray(offset + numBytes, offset + numBytes + size));
|
|
}
|
|
else {
|
|
throw new Error("Incomplete message.");
|
|
}
|
|
|
|
offset = offset + numBytes + size;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
} |