improve string (de)serialization

This commit is contained in:
Tobias Koppers 2020-12-13 23:20:05 +01:00
parent 57c3a7eb05
commit 227c16b9a8
2 changed files with 61 additions and 37 deletions

View File

@ -35,7 +35,7 @@ BooleansSection -> TrueHeaderByte | FalseHeaderByte | BooleansSectionHeaderByte
F64NumbersSection -> F64NumbersSectionHeaderByte f64* F64NumbersSection -> F64NumbersSectionHeaderByte f64*
I32NumbersSection -> I32NumbersSectionHeaderByte i32* I32NumbersSection -> I32NumbersSectionHeaderByte i32*
I8NumbersSection -> I8NumbersSectionHeaderByte i8* I8NumbersSection -> I8NumbersSectionHeaderByte i8*
ShortStringSection -> ShortStringSectionHeaderByte utf8-byte* ShortStringSection -> ShortStringSectionHeaderByte ascii-byte*
StringSection -> StringSectionHeaderByte i32:length utf8-byte* StringSection -> StringSectionHeaderByte i32:length utf8-byte*
BufferSection -> BufferSectionHeaderByte i32:length byte* BufferSection -> BufferSectionHeaderByte i32:length byte*
NopSection --> NopSectionHeaderByte NopSection --> NopSectionHeaderByte
@ -250,15 +250,16 @@ class BinaryMiddleware extends SerializerMiddleware {
} }
case "string": { case "string": {
const len = Buffer.byteLength(thing); const len = Buffer.byteLength(thing);
if (len >= 128) { if (len >= 128 || len !== thing.length) {
allocate(len + HEADER_SIZE + I32_SIZE); allocate(len + HEADER_SIZE + I32_SIZE);
writeU8(STRING_HEADER); writeU8(STRING_HEADER);
writeU32(len); writeU32(len);
currentBuffer.write(thing, currentPosition);
} else { } else {
allocate(len + HEADER_SIZE); allocate(len + HEADER_SIZE);
writeU8(SHORT_STRING_HEADER | len); writeU8(SHORT_STRING_HEADER | len);
currentBuffer.write(thing, currentPosition, "latin1");
} }
currentBuffer.write(thing, currentPosition);
currentPosition += len; currentPosition += len;
break; break;
} }
@ -670,8 +671,20 @@ class BinaryMiddleware extends SerializerMiddleware {
} }
case STRING_HEADER: { case STRING_HEADER: {
const len = readU32(); const len = readU32();
if (isInCurrentBuffer(len)) {
result.push(
currentBuffer.toString(
undefined,
currentPosition,
currentPosition + len
)
);
currentPosition += len;
checkOverflow();
} else {
const buf = read(len); const buf = read(len);
result.push(buf.toString()); result.push(buf.toString());
}
break; break;
} }
default: default:
@ -681,9 +694,19 @@ class BinaryMiddleware extends SerializerMiddleware {
const len = header & SHORT_STRING_LENGTH_MASK; const len = header & SHORT_STRING_LENGTH_MASK;
if (len === 0) { if (len === 0) {
result.push(""); result.push("");
} else if (isInCurrentBuffer(len)) {
result.push(
currentBuffer.toString(
"latin1",
currentPosition,
currentPosition + len
)
);
currentPosition += len;
checkOverflow();
} else { } else {
const buf = read(len); const buf = read(len);
result.push(buf.toString()); result.push(buf.toString("latin1"));
} }
} else if ((header & NUMBERS_HEADER_MASK) === F64_HEADER) { } else if ((header & NUMBERS_HEADER_MASK) === F64_HEADER) {
const len = (header & NUMBERS_COUNT_MASK) + 1; const len = (header & NUMBERS_COUNT_MASK) + 1;

View File

@ -9,20 +9,28 @@ const cont = (base, count) => {
}; };
describe("BinaryMiddleware", () => { describe("BinaryMiddleware", () => {
const items = [
undefined,
true,
false,
null,
"",
"hi",
"hi".repeat(200),
"😀",
"😀".repeat(200),
Buffer.from("hello"),
1,
11,
0x100,
-1,
-11,
-0x100,
-1.25
];
const cases = [ const cases = [
[true], ...items.map(item => [item]),
[false],
[null],
[""],
["hi"],
[Buffer.from("hello")],
[1],
[11],
[0x100],
[-1],
[-11],
[-0x100],
[-1.25],
[true, true], [true, true],
[false, true], [false, true],
[true, false], [true, false],
@ -44,24 +52,16 @@ describe("BinaryMiddleware", () => {
cont([false, true, false, true], 133), cont([false, true, false, true], 133),
cont([false, true, false, true], 134), cont([false, true, false, true], 134),
cont([false, true, false, true], 135), cont([false, true, false, true], 135),
cont([true], 135) cont([true], 135),
]; [null],
[null, null],
const items = [ [null, null, null],
undefined, cont([null], 4),
true, cont([null], 100),
false, cont([null], 300),
null, cont([-20], 20),
"", cont([400], 20),
"hi", cont([5.5], 20)
Buffer.from("hello"),
1,
11,
0x100,
-1,
-11,
-0x100,
-1.25
]; ];
for (const caseData of cases) { for (const caseData of cases) {
@ -70,6 +70,7 @@ describe("BinaryMiddleware", () => {
const data = [prepend, ...caseData, append].filter( const data = [prepend, ...caseData, append].filter(
x => x !== undefined x => x !== undefined
); );
if (data.length === 0) continue;
const key = JSON.stringify(data); const key = JSON.stringify(data);
it(`should serialize ${key} (${data.length}) correctly`, () => { it(`should serialize ${key} (${data.length}) correctly`, () => {
const mw = new BinaryMiddleware(); const mw = new BinaryMiddleware();