capnp-js
Version:
Capnproto run-time decoding and encoding for Node
165 lines (164 loc) • 6.79 kB
JavaScript
var reader = require('../reader/layout/structure');
var methods = require('../reader/methods');
var builder = require('./layout/structure');
var copy = require('./copy/pointer');
var fields = require('./fields');
var upgrade = require('./upgrade');
module.exports = function(Reader) {
var t = Reader._TYPE;
var ct = Reader._CT;
var Structure = function(arena, isOrphan, layout) {
this._arena = arena;
this._isOrphan = isOrphan;
this._segment = layout.segment;
this._dataSection = layout.dataSection;
this._pointersSection = layout.pointersSection;
this._end = layout.end;
};
Structure._READER = Reader;
Structure._TYPE = t;
Structure._CT = ct;
Structure._FIELD = {};
Structure._HASH = Reader._HASH;
Structure._LIST_CT = Reader._LIST_CT;
Structure._deref = function(arena, pointer) {
var instance = new Structure(arena, false, reader.unsafe(arena, pointer));
// Upgrade the blob if the pointer derived from an old version.
var rt = instance._rt();
if (rt.dataBytes < ct.dataBytes || rt.pointersBytes < ct.pointersBytes) {
upgrade.structure(instance._arena, pointer, ct);
return new Structure(arena, false, reader.unsafe(arena, pointer));
}
return instance;
};
Structure._init = function(arena, pointer) {
var ctSize = ct.dataBytes + ct.pointersBytes;
var blob = arena._preallocate(pointer.segment, ctSize);
arena._zero(blob, ctSize);
builder.preallocated(pointer, blob, ct);
return new Structure(arena, false, reader.unsafe(arena, pointer));
};
Structure._initOrphan = function(arena) {
var ctSize = ct.dataBytes + ct.pointersBytes;
var blob = arena._allocateOrphan(ctSize);
arena._zero(blob, ctSize);
return new Structure(arena, true, {
segment: blob.segment,
dataSection: blob.position,
pointersSection: blob.position + ct.dataBytes,
end: blob.position + ctSize
});
};
Structure._set = function(arena, pointer, value) {
if (!value._TYPE.equiv(t)) throw new TypeError();
copy.setStructPointer(value._arena, value._layout(), arena, pointer);
};
var adopt = fields.struct.adopt();
Structure._FIELD.adopt = function(offset) {
return function(value) {
if (!value._TYPE.equiv(t)) throw new TypeError();
if (!value._isOrphan) throw new ValueError("Cannot adopt a non-orphan");
if (!this._arena.isEquivTo(value._arena)) throw new ValueError("Cannot adopt from a different arena");
adopt(this, offset, value);
};
};
Structure._FIELD.unionAdopt = function(discr, offset) {
return function(value) {
if (!Structure._TYPE.equiv(value._TYPE)) throw new TypeError();
if (!value._isOrphan) throw new ValueError("Cannot adopt a non-orphan");
if (!this._arena.isEquivTo(value._arena)) throw new ValueError("Cannot adopt from a different arena");
this._setWhich(discr);
adopt(this, offset, value);
};
};
var disown = fields.pointer.disown(Structure);
Structure._FIELD.disown = function(offset) {
return function() {
return disown(this, offset);
};
};
Structure._FIELD.unionDisown = function(discr, offset) {
return function() {
fields.throwOnInactive(this.which(), discr);
return disown(this, offset);
};
};
var disownReader = fields.pointer.disownReader(Reader);
Structure._FIELD.disownReader = function(offset) {
return function() {
return disownReader(this, offset);
};
};
Structure._FIELD.unionDisownReader = function(discr, offset) {
return function() {
fields.throwOnInactive(this.which(), discr);
return disownReader(this, offset);
};
};
var get = fields.struct.get(Structure);
Structure._FIELD.get = function(offset, defaultPosition) {
return function() {
return get(defaultPosition, this, offset);
};
};
Structure._FIELD.unionGet = function(discr, offset, defaultPosition) {
return function() {
fields.throwOnInactive(this.which(), discr);
return get(defaultPosition, this, offset);
};
};
var has = fields.pointer.has();
Structure._FIELD.has = function(offset) {
return function() {
return has(this, offset);
};
};
Structure._FIELD.unionHas = function(discr, offset) {
return function() {
fields.throwOnInactive(this.which(), discr);
return has(this, offset);
};
};
var init = fields.struct.init(Structure);
Structure._FIELD.init = function(offset) {
return function() {
return init(this, offset);
};
};
Structure._FIELD.unionInit = function(discr, offset) {
return function() {
this._setWhich(discr);
return init(this, offset);
};
};
var set = fields.struct.set(Structure);
Structure._FIELD.set = function(offset) {
return function(value) {
if (Structure._TYPE !== value._TYPE) throw new TypeError();
set(this, offset, value);
};
};
Structure._FIELD.unionSet = function(discr, offset) {
return function(value) {
if (Structure._TYPE !== value._TYPE) throw new TypeError();
this._setWhich(discr);
set(this, offset, value);
};
};
Structure.prototype = {
_TYPE: t,
_CT: ct,
_rt: methods.rt,
_layout: methods.layout
};
Structure.prototype._maskData = function(position, mask) {
this._segment[this._dataSection + position] &= mask;
};
Structure.prototype._zeroData = function(position, length) {
this._arena._zero({
segment: this._segment,
position: this._dataSection + position
}, length);
};
return Structure;
};