@jawis/shared-buffer-store
Version:
Store for variable sized buffers to use in concurrent programs.
164 lines (163 loc) • 5.45 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.HeaderUtil = void 0;
const _jab_1 = require("^jab");
const _shared_algs_1 = require("^shared-algs");
const BUFFER_LENGTH_BYTES = 4;
const HEADER_LENGTH_OFFSET = 0;
const ALIGNMENT_OFFSET = HEADER_LENGTH_OFFSET + 1;
const VERSION_OFFSET = ALIGNMENT_OFFSET + 1;
const BUFFER_LENGTH_OFFSET = VERSION_OFFSET + 1;
const HEADER_BYTES_WITHOUT_PADDING = BUFFER_LENGTH_OFFSET + BUFFER_LENGTH_BYTES;
/**
*
*/
class HeaderUtil {
/**
*
*/
constructor(deps) {
this.deps = deps;
/**
*
*/
this.getDataIndex = (index, dataLength, headerLength) => {
(0, _jab_1.assertEq)(HEADER_BYTES_WITHOUT_PADDING, headerLength, "Not sure it works without this condition"); // prettier-ignore
if (this.deps.direction === "right") {
return index + headerLength;
}
else {
return index - dataLength + HEADER_BYTES_WITHOUT_PADDING - headerLength;
}
};
/**
*
*/
this.delete = (ref) => {
const index = this.decodeRef(ref);
this.deps.sharedArray[index + VERSION_OFFSET] = 0;
};
/**
*
*/
this.encode = (oldFreePointer, version) => {
//calculate index of the header.
let index;
if (this.deps.direction === "right") {
index = oldFreePointer;
}
else {
index = oldFreePointer - HEADER_BYTES_WITHOUT_PADDING;
}
//check
if (version > 15) {
throw new Error("Version too high");
}
if (index > 2e28) {
throw new Error("Buffer index is too high to store.");
}
return { index, ref: version + (index << 4) };
};
/**
*
*/
this.decodeRef = (ref) => {
const version = ref & 0xf;
const index = (ref & 0xfffffff0) >> 4;
const expVersion = this.deps.sharedArray[index + VERSION_OFFSET];
(0, _jab_1.assert)(index >= 0 && index < this.deps.byteSize && expVersion === version, "Buffer index isn't valid: ", {
ref,
index,
version,
expVersion,
});
return index;
};
}
/**
* Calculates the data to be stored in the header.
*
* - The result is an array of bytes.
* - Doesn't have to check that numbers fit in each byte, because it's checked at write to buffer.
* - Can return a different amount of bytes, than is stored in headerlength. Because of padding.
*
*/
prepare(index, header) {
if (header.alignment !== 1 &&
header.alignment !== 2 &&
header.alignment !== 4 &&
header.alignment !== 8) {
throw new Error("This alignment value not implemented: " + header.alignment);
}
//header length
const res = [0]; //headerLength will be updated below.
//alignment
res.push(header.alignment);
//version
res.push(header.version);
//data length
let tmp2 = header.bufferLength;
for (let i = 0; i < BUFFER_LENGTH_BYTES; i++) {
res.push(tmp2 & 0xff);
tmp2 = tmp2 >> 8;
}
//figure alignment.
if (this.deps.direction === "right") {
this.makeRightPadding(res, index, header);
}
else {
this.makeLeftPadding(res, index, header);
}
//set header length.
res[0] = res.length;
return res;
}
/**
* Pad the header. (in right direction mode)
*
* - The header size is increased enough, so the dataIndex is moved enough to the right.
*/
makeRightPadding(res, index, header) {
const mask = header.alignment - 1; // for align=4, this becomes 00000011
const dataIndex = index + res.length;
const tooMuch = dataIndex & mask;
const padding = tooMuch === 0 ? 0 : header.alignment - tooMuch;
for (let i = 0; i < padding; i++) {
res.push(0);
}
}
/**
* Pad the header. (in left direction mode)
*
* - The header size is increased enough, so the dataIndex is moved enough to the left.
* - Note this technique works without knowning whether to right edge is aligned to 8 bytes.
*/
makeLeftPadding(res, index, header) {
const mask = header.alignment - 1; // for align=4, this becomes 00000011
const dataIndex = index - res.length - header.bufferLength;
const tooMuch = dataIndex & mask;
for (let i = 0; i < tooMuch; i++) {
res.push(0);
}
}
/**
*
*/
set(index, header) {
if (this.deps.direction === "right") {
index = index + HEADER_BYTES_WITHOUT_PADDING - header.length;
}
this.deps.sharedArray.set(header, index);
}
/**
*
*/
get(index) {
const bufferLength = (0, _shared_algs_1.readNumber)(this.deps.sharedArray, index + BUFFER_LENGTH_OFFSET, BUFFER_LENGTH_BYTES);
return {
headerLength: this.deps.sharedArray[index + HEADER_LENGTH_OFFSET],
bufferLength,
};
}
}
exports.HeaderUtil = HeaderUtil;