UNPKG

capnp-js

Version:

Capnproto run-time decoding and encoding for Node

79 lines (78 loc) 3.61 kB
var far = require('../far'); var structure = require('./structure'); var noncompositeLo = function(pointer, layout, length) { pointer.segment[pointer.position + 4] = layout | length << 3; pointer.segment[pointer.position + 5] = length >>> 5; pointer.segment[pointer.position + 6] = length >>> 13; pointer.segment[pointer.position + 7] = length >>> 21; }; var compositeLo = function(pointer, blob, meta, length) { noncompositeLo(pointer, 7, length * (meta.dataBytes + meta.pointersBytes >>> 3)); // Leading tag on the list's blob blob.segment[blob.position] = length << 2; blob.segment[blob.position + 1] = length >>> 6; blob.segment[blob.position + 2] = length >>> 14; blob.segment[blob.position + 3] = length >>> 22; structure.wordCounts(blob, meta.dataBytes >>> 3, meta.pointersBytes >>> 3); }; var intrasegment = function(pointer, blob, meta, length) { // Non-bitshift to avoid possible sign-bit truncation. var offset = (blob.position - pointer.position - 8) / 8; pointer.segment[pointer.position] = offset << 2 | 1; pointer.segment[pointer.position + 1] = offset >>> 6; pointer.segment[pointer.position + 2] = offset >>> 14; pointer.segment[pointer.position + 3] = offset >>> 22; if (meta.layout === 7) compositeLo(pointer, blob, meta, length); else noncompositeLo(pointer, meta.layout, length); }; var preallocated = function(pointer, blob, meta, length) { if (pointer.segment === blob.segment) { intrasegment(pointer, blob, meta, length); } else { var land = { segment: blob.segment, position: blob.position - 8 }; // Build the local pointer. land.segment[land.position] = 1; land.segment[land.position + 1] = 0; land.segment[land.position + 2] = 0; land.segment[land.position + 3] = 0; if (meta.layout === 7) compositeLo(land, blob, meta, length); else noncompositeLo(land, meta.layout, length); // Point at the off-segment blob's local pointer. far.terminal(pointer, land); } }; var intersegment = function(arena, pointer, blob, meta, length) { var land = arena._preallocate(blob.segment, 8); if (land.segment === blob.segment) { // Single hop allocation success. far.terminal(pointer, land); intrasegment(land, blob, meta, length); } else { // Double hop fallback. // `land` references the far pointer's tag word. land.segment[land.position] = 1; if (meta.layout === 7) { compositeLo(land, blob, meta, length); } else { noncompositeLo(land, meta.layout, length); } // Update `land` to reference the far pointer's landing pad. land.position -= 8; far.preterminal(pointer, land); far.terminal(land, blob); } }; var nonpreallocated = function(arena, pointer, blob, meta, length) { if (pointer.segment === blob.segment) { // Local reference. intrasegment(pointer, blob, meta, length); } else { // Nonlocal reference. intersegment(arena, pointer, blob, meta, length); } }; exports.preallocated = preallocated; exports.nonpreallocated = nonpreallocated; exports.intrasegment = intrasegment; exports.intersegment = intersegment;