UNPKG

muschema

Version:
341 lines 13.6 kB
"use strict"; 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