muschema
Version:
Schemas for mudb
341 lines • 13.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var constants_1 = require("./constants");
var muPrimitiveTypes = Object.keys(constants_1.muPrimitiveSize);
var MuStruct = (function () {
function MuStruct(spec) {
this.muType = 'struct';
this.copy = function (source, target) { };
var structProps = Object.keys(spec).sort(function (a, b) {
var ai = muPrimitiveTypes.indexOf(spec[a].muType);
var bi = muPrimitiveTypes.indexOf(spec[b].muType);
return (bi - ai) || (a < b ? -1 : (b < a) ? 1 : 0);
});
var structTypes = structProps.map(function (propName) { return spec[propName]; });
var structJSON = {
type: 'struct',
subTypes: {},
};
structProps.forEach(function (prop) {
structJSON.subTypes[prop] = spec[prop].json;
});
var params = [];
var args = [];
var tokenCounter = 0;
function token() {
return '_v' + (++tokenCounter);
}
function inject(x) {
for (var i = 0; i < args.length; ++i) {
if (args[i] === x) {
return params[i];
}
}
var result = token();
params.push(result);
args.push(x);
return result;
}
var propRefs = structProps.map(inject);
var typeRefs = structTypes.map(inject);
function block() {
var vars = [];
var body = [];
return {
vars: vars,
body: body,
toString: function () {
var localVars = (vars.length > 0) ? "var " + vars.join() + ";" : '';
return localVars + body.join('');
},
def: function (value) {
var tok = token();
vars.push(tok);
if (value != undefined) {
body.push(tok + "=" + value + ";");
}
return tok;
},
append: function () {
var code = [];
for (var _i = 0; _i < arguments.length; _i++) {
code[_i] = arguments[_i];
}
body.push.apply(body, code);
},
};
}
var prelude = block();
var epilog = block();
function func(name, params_) {
var b = block();
var baseToString = b.toString;
b.toString = function () {
return "function " + name + "(" + params_.join() + "){" + baseToString() + "}";
};
return b;
}
var methods = {
alloc: func('alloc', []),
free: func('free', ['x']),
equal: func('equal', ['a', 'b']),
clone: func('clone', ['x']),
copy: func('copy', ['s', 't']),
diff: func('diff', ['b', 't', 's']),
patch: func('patch', ['b', 's']),
};
var poolRef = prelude.def('[]');
prelude.append('function MuStruct(){');
propRefs.forEach(function (propRef, i) {
var type = structTypes[i];
switch (type.muType) {
case 'boolean':
case 'float32':
case 'float64':
case 'int8':
case 'int16':
case 'int32':
case 'uint8':
case 'uint16':
case 'uint32':
prelude.append("this[" + propRef + "]=" + type.identity + ";");
break;
case 'ascii':
case 'string':
prelude.append("this[" + propRef + "]=" + inject(type.identity) + ";");
break;
default:
prelude.append("this[" + propRef + "]=null;");
}
});
prelude.append("}function _alloc(){if(" + poolRef + ".length > 0){return " + poolRef + ".pop()}return new MuStruct()}");
var identityRef = prelude.def('_alloc()');
propRefs.forEach(function (propRef, i) {
var type = structTypes[i];
switch (type.muType) {
case 'ascii':
case 'boolean':
case 'float32':
case 'float64':
case 'int8':
case 'int16':
case 'int32':
case 'string':
case 'uint8':
case 'uint16':
case 'uint32':
break;
default:
prelude.append(identityRef + "[" + propRef + "]=" + typeRefs[i] + ".clone(" + inject(type.identity) + ");");
break;
}
});
methods.alloc.append("var result=_alloc();");
propRefs.forEach(function (propRef, i) {
var type = structTypes[i];
switch (type.muType) {
case 'ascii':
case 'boolean':
case 'float32':
case 'float64':
case 'int8':
case 'int16':
case 'int32':
case 'string':
case 'uint8':
case 'uint16':
case 'uint32':
break;
default:
methods.alloc.append("result[" + propRef + "]=" + typeRefs[i] + ".alloc();");
break;
}
});
methods.alloc.append("return result");
methods.free.append(poolRef + ".push(x);");
propRefs.forEach(function (propRef, i) {
var type = structTypes[i];
switch (type.muType) {
case 'ascii':
case 'boolean':
case 'float32':
case 'float64':
case 'int8':
case 'int16':
case 'int32':
case 'string':
case 'uint8':
case 'uint16':
case 'uint32':
break;
default:
methods.free.append(typeRefs[i] + ".free(x[" + propRef + "]);");
break;
}
});
propRefs.forEach(function (propRef, i) {
var type = structTypes[i];
switch (type.muType) {
case 'ascii':
case 'boolean':
case 'float32':
case 'float64':
case 'int8':
case 'int16':
case 'int32':
case 'string':
case 'uint8':
case 'uint16':
case 'uint32':
methods.equal.append("if(a[" + propRef + "]!==b[" + propRef + "]){return false}");
break;
default:
methods.equal.append("if(!" + typeRefs[i] + ".equal(a[" + propRef + "],b[" + propRef + "])){return false}");
}
});
methods.equal.append("return true;");
methods.clone.append("var result=_alloc();");
propRefs.forEach(function (propRef, i) {
var type = structTypes[i];
switch (type.muType) {
case 'ascii':
case 'boolean':
case 'float32':
case 'float64':
case 'int8':
case 'int16':
case 'int32':
case 'string':
case 'uint8':
case 'uint16':
case 'uint32':
methods.clone.append("result[" + propRef + "]=x[" + propRef + "];");
break;
default:
methods.clone.append("result[" + propRef + "]=" + typeRefs[i] + ".clone(x[" + propRef + "]);");
break;
}
});
methods.clone.append('return result');
propRefs.forEach(function (propRef, i) {
var type = structTypes[i];
switch (type.muType) {
case 'ascii':
case 'boolean':
case 'fixed-ascii':
case 'float32':
case 'float64':
case 'int8':
case 'int16':
case 'int32':
case 'string':
case 'uint8':
case 'uint16':
case 'uint32':
methods.copy.append("t[" + propRef + "]=s[" + propRef + "];");
break;
default:
methods.copy.append(typeRefs[i] + ".copy(s[" + propRef + "],t[" + propRef + "]);");
}
});
var numProps = structProps.length;
var trackerBytes = Math.ceil(numProps / 8);
var dTrackerOffset = methods.diff.def(0);
var dTracker = methods.diff.def(0);
var numPatch = methods.diff.def(0);
var baseSize = trackerBytes;
propRefs.forEach(function (p, i) {
var muType = structTypes[i].muType;
if (muType in constants_1.muPrimitiveSize) {
baseSize += constants_1.muPrimitiveSize[muType];
}
});
methods.diff.append(dTrackerOffset + "=s.offset;s.grow(" + baseSize + ");s.offset+=" + trackerBytes + ";");
propRefs.forEach(function (propRef, i) {
var muType = structTypes[i].muType;
switch (muType) {
case 'boolean':
methods.diff.append("if(b[" + propRef + "]!==t[" + propRef + "]){s.writeUint8(t[" + propRef + "]?1:0);++" + numPatch + ";" + dTracker + "|=" + (1 << (i & 7)) + "}");
break;
case 'float32':
case 'float64':
case 'int8':
case 'int16':
case 'int32':
case 'uint8':
case 'uint16':
case 'uint32':
methods.diff.append("if(b[" + propRef + "]!==t[" + propRef + "]){s." + constants_1.muType2WriteMethod[muType] + "(t[" + propRef + "]);++" + numPatch + ";" + dTracker + "|=" + (1 << (i & 7)) + "}");
break;
default:
methods.diff.append("if(" + typeRefs[i] + ".diff(b[" + propRef + "],t[" + propRef + "],s)){++" + numPatch + ";" + dTracker + "|=" + (1 << (i & 7)) + "}");
}
if ((i & 7) === 7) {
methods.diff.append("s.writeUint8At(" + dTrackerOffset + "+" + (i >> 3) + "," + dTracker + ");" + dTracker + "=0;");
}
});
if (numProps & 7) {
methods.diff.append("s.writeUint8At(" + dTrackerOffset + "+" + (trackerBytes - 1) + "," + dTracker + ");");
}
methods.diff.append("if(" + numPatch + "){return true;}else{s.offset=" + dTrackerOffset + ";return false;}");
var pTrackerOffset = methods.patch.def('s.offset');
var pTracker = methods.patch.def(0);
methods.patch.append(";s.offset+=" + trackerBytes + ";var result=_alloc(b);");
propRefs.forEach(function (propRef, i) {
if (!(i & 7)) {
methods.patch.append(pTracker + "=s.readUint8At(" + pTrackerOffset + "+" + (i >> 3) + ");");
}
var muType = structTypes[i].muType;
methods.patch.append(";result[" + propRef + "]=(" + pTracker + "&" + (1 << (i & 7)) + ")?");
switch (muType) {
case 'ascii':
methods.patch.append("s.readASCII():b[" + propRef + "];");
break;
case 'boolean':
methods.patch.append("!!s.readUint8():b[" + propRef + "];");
break;
case 'float32':
case 'float64':
case 'int8':
case 'int16':
case 'int32':
case 'string':
case 'uint8':
case 'uint16':
case 'uint32':
methods.patch.append("s." + constants_1.muType2ReadMethod[muType] + "():b[" + propRef + "];");
break;
default:
methods.patch.append(typeRefs[i] + ".patch(b[" + propRef + "],s):" + typeRefs[i] + ".clone(b[" + propRef + "]);");
}
});
methods.patch.append("return result");
var muDataRef = prelude.def('{}');
propRefs.forEach(function (propRef, i) {
prelude.append(muDataRef + "[" + propRef + "]=" + typeRefs[i] + ";");
});
epilog.append("return {identity:" + identityRef + ",muData:" + muDataRef + ",");
Object.keys(methods).forEach(function (name) {
prelude.append(methods[name].toString());
epilog.append(name + ",");
});
epilog.append('}');
prelude.append(epilog.toString());
params.push(prelude.toString());
var proc = Function.apply(null, params);
var compiled = proc.apply(null, args);
this.json = structJSON;
this.muData = compiled.muData;
this.identity = compiled.identity;
this.alloc = compiled.alloc;
this.free = compiled.free;
this.equal = compiled.equal;
this.clone = compiled.clone;
this.copy = compiled.copy;
this.diff = compiled.diff;
this.patch = compiled.patch;
}
return MuStruct;
}());
exports.MuStruct = MuStruct;
//# sourceMappingURL=struct.js.map