UNPKG

@jawis/shared-buffer-store

Version:

Store for variable sized buffers to use in concurrent programs.

164 lines (163 loc) 5.45 kB
"use strict"; 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;