UNPKG

typia

Version:

Superfast runtime validators with only one line

528 lines • 33.3 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProtobufEncodeProgrammer = void 0; var typescript_1 = __importDefault(require("typescript")); var ExpressionFactory_1 = require("../../factories/ExpressionFactory"); var IdentifierFactory_1 = require("../../factories/IdentifierFactory"); var MetadataCollection_1 = require("../../factories/MetadataCollection"); var NumericRangeFactory_1 = require("../../factories/NumericRangeFactory"); var ProtobufFactory_1 = require("../../factories/ProtobufFactory"); var StatementFactory_1 = require("../../factories/StatementFactory"); var TypeFactory_1 = require("../../factories/TypeFactory"); var Metadata_1 = require("../../schemas/metadata/Metadata"); var MetadataAtomic_1 = require("../../schemas/metadata/MetadataAtomic"); var MetadataProperty_1 = require("../../schemas/metadata/MetadataProperty"); var FeatureProgrammer_1 = require("../FeatureProgrammer"); var IsProgrammer_1 = require("../IsProgrammer"); var FunctionImporter_1 = require("../helpers/FunctionImporter"); var ProtobufUtil_1 = require("../helpers/ProtobufUtil"); var UnionPredicator_1 = require("../helpers/UnionPredicator"); var decode_union_object_1 = require("../internal/decode_union_object"); var ProtobufEncodeProgrammer; (function (ProtobufEncodeProgrammer) { ProtobufEncodeProgrammer.decompose = function (props) { var _a; var collection = new MetadataCollection_1.MetadataCollection(); var meta = ProtobufFactory_1.ProtobufFactory.metadata(props.modulo.getText())(props.project.checker, props.project.context)(collection)(props.type); var callEncoder = function (writer) { return function (factory) { return StatementFactory_1.StatementFactory.constant(writer, typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier("encoder"), undefined, [factory, typescript_1.default.factory.createIdentifier("input")])); }; }; return { functions: { encoder: StatementFactory_1.StatementFactory.constant(props.importer.useLocal("encoder"), write_encoder(props.project)(props.importer)(collection)(meta)), }, statements: [], arrow: typescript_1.default.factory.createArrowFunction(undefined, undefined, [ IdentifierFactory_1.IdentifierFactory.parameter("input", typescript_1.default.factory.createTypeReferenceNode((_a = props.name) !== null && _a !== void 0 ? _a : TypeFactory_1.TypeFactory.getFullName(props.project.checker)(props.type))), ], typescript_1.default.factory.createTypeReferenceNode("Uint8Array"), undefined, typescript_1.default.factory.createBlock([ callEncoder("sizer")(typescript_1.default.factory.createNewExpression(props.importer.use("Sizer"), undefined, [])), callEncoder("writer")(typescript_1.default.factory.createNewExpression(props.importer.use("Writer"), undefined, [typescript_1.default.factory.createIdentifier("sizer")])), typescript_1.default.factory.createReturnStatement(typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(WRITER())("buffer"), undefined, undefined)), ], true)), }; }; ProtobufEncodeProgrammer.write = function (project) { return function (modulo) { return function (type, name) { var importer = new FunctionImporter_1.FunctionImporter(modulo.getText()); var result = ProtobufEncodeProgrammer.decompose({ project: project, modulo: modulo, importer: importer, type: type, name: name, }); return FeatureProgrammer_1.FeatureProgrammer.writeDecomposed({ modulo: modulo, importer: importer, result: result, }); }; }; }; var write_encoder = function (project) { return function (importer) { return function (collection) { return function (meta) { var functors = collection .objects() .filter(function (obj) { return ProtobufUtil_1.ProtobufUtil.isStaticObject(obj); }) .map(function (obj) { return StatementFactory_1.StatementFactory.constant("".concat(PREFIX, "o").concat(obj.index), write_object_function(project)(importer)(typescript_1.default.factory.createIdentifier("input"), obj, { source: "function", from: "object", tracable: false, postfix: "", })); }); var main = decode(project)(importer)(null)(typescript_1.default.factory.createIdentifier("input"), meta, { source: "top", from: "top", tracable: false, postfix: "", }); return typescript_1.default.factory.createArrowFunction(undefined, undefined, [ IdentifierFactory_1.IdentifierFactory.parameter("writer"), IdentifierFactory_1.IdentifierFactory.parameter("input"), ], TypeFactory_1.TypeFactory.keyword("any"), undefined, typescript_1.default.factory.createBlock(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(importer.declareUnions()), false), __read(functors), false), __read(IsProgrammer_1.IsProgrammer.write_function_statements(project)(importer)(collection)), false), __read(main.statements), false), [ typescript_1.default.factory.createReturnStatement(typescript_1.default.factory.createIdentifier("writer")), ], false), true)); }; }; }; }; var write_object_function = function (project) { return function (importer) { return function (input, obj, explore) { var index = 1; var body = obj.properties .map(function (p) { var block = decode(project)(importer)(index)(IdentifierFactory_1.IdentifierFactory.access(input)(p.key.getSoleLiteral()), p.value, explore); index += ProtobufUtil_1.ProtobufUtil.size(p.value); return __spreadArray([ typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createIdentifier("// property \"".concat(p.key.getSoleLiteral(), "\""))) ], __read(block.statements), false); }) .flat(); return typescript_1.default.factory.createArrowFunction(undefined, undefined, [IdentifierFactory_1.IdentifierFactory.parameter("input")], TypeFactory_1.TypeFactory.keyword("any"), undefined, typescript_1.default.factory.createBlock(body, true)); }; }; }; /* ----------------------------------------------------------- DECODERS ----------------------------------------------------------- */ var decode = function (project) { return function (importer) { return function (index) { return function (input, meta, explore) { var e_1, _a; var wrapper = meta.isRequired() && meta.nullable === false ? function (block) { return block; } : meta.isRequired() === false && meta.nullable === true ? function (block) { return typescript_1.default.factory.createBlock([ typescript_1.default.factory.createIfStatement(typescript_1.default.factory.createLogicalAnd(typescript_1.default.factory.createStrictInequality(typescript_1.default.factory.createIdentifier("undefined"), input), typescript_1.default.factory.createStrictInequality(typescript_1.default.factory.createNull(), input)), block), ], true); } : meta.isRequired() === false ? function (block) { return typescript_1.default.factory.createBlock([ typescript_1.default.factory.createIfStatement(typescript_1.default.factory.createStrictInequality(typescript_1.default.factory.createIdentifier("undefined"), input), block), ], true); } : function (block) { return typescript_1.default.factory.createBlock([ typescript_1.default.factory.createIfStatement(typescript_1.default.factory.createStrictInequality(typescript_1.default.factory.createNull(), input), block), ], true); }; // STARTS FROM ATOMIC TYPES var unions = []; var numbers = ProtobufUtil_1.ProtobufUtil.getNumbers(meta); var bigints = ProtobufUtil_1.ProtobufUtil.getBigints(meta); var _loop_1 = function (atom) { if (atom === "bool") unions.push({ type: "bool", is: function () { return typescript_1.default.factory.createStrictEquality(typescript_1.default.factory.createStringLiteral("boolean"), typescript_1.default.factory.createTypeOfExpression(input)); }, value: function (index) { return decode_bool(index)(input); }, }); else if (atom === "int32" || atom === "uint32" || atom === "float" || atom === "double") unions.push(decode_number(numbers)(atom)(input)); else if (atom === "int64" || atom === "uint64") if (numbers.some(function (n) { return n === atom; })) unions.push(decode_number(numbers)(atom)(input)); else unions.push(decode_bigint(bigints)(atom)(input)); else if (atom === "string") unions.push({ type: "string", is: function () { return typescript_1.default.factory.createStrictEquality(typescript_1.default.factory.createStringLiteral("string"), typescript_1.default.factory.createTypeOfExpression(input)); }, value: function (index) { return decode_bytes("string")(index)(input); }, }); }; try { for (var _b = __values(ProtobufUtil_1.ProtobufUtil.getAtomics(meta)), _c = _b.next(); !_c.done; _c = _b.next()) { var atom = _c.value; _loop_1(atom); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } // CONSIDER BYTES if (meta.natives.length) unions.push({ type: "bytes", is: function () { return ExpressionFactory_1.ExpressionFactory.isInstanceOf("Uint8Array")(input); }, value: function (index) { return decode_bytes("bytes")(index)(input); }, }); // CONSIDER ARRAYS if (meta.arrays.length) unions.push({ type: "array", is: function () { return ExpressionFactory_1.ExpressionFactory.isArray(input); }, value: function (index) { return decode_array(project)(importer)(index)(input, meta.arrays[0], __assign(__assign({}, explore), { from: "array" })); }, }); // CONSIDER MAPS if (meta.maps.length) unions.push({ type: "map", is: function () { return ExpressionFactory_1.ExpressionFactory.isInstanceOf("Map")(input); }, value: function (index) { return decode_map(project)(importer)(index)(input, meta.maps[0], __assign(__assign({}, explore), { from: "array" })); }, }); // CONSIDER OBJECTS if (meta.objects.length) unions.push({ type: "object", is: function () { return ExpressionFactory_1.ExpressionFactory.isObject({ checkNull: true, checkArray: false, })(input); }, value: function (index) { return explore_objects(project)(importer)(0)(index)(input, meta.objects, __assign(__assign({}, explore), { from: "object" })); }, }); // RETURNS if (unions.length === 1) return wrapper(unions[0].value(index)); else return wrapper(iterate(importer)(index)(unions)(meta.getName())(input)); }; }; }; }; var iterate = function (importer) { return function (index) { return function (unions) { return function (expected) { return function (input) { return typescript_1.default.factory.createBlock([ unions .map(function (u, i) { return typescript_1.default.factory.createIfStatement(u.is(), u.value(index ? index + i : null), i === unions.length - 1 ? create_throw_error(importer)(expected)(input) : undefined); }) .reverse() .reduce(function (a, b) { return typescript_1.default.factory.createIfStatement(b.expression, b.thenStatement, a); }), ], true); }; }; }; }; }; var decode_map = function (project) { return function (importer) { return function (index) { return function (input, map, explore) { var each = __spreadArray(__spreadArray(__spreadArray([ typescript_1.default.factory.createExpressionStatement(decode_tag(2 /* ProtobufWire.LEN */)(index)), typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(WRITER())("fork"), undefined, undefined)) ], __read(decode(project)(importer)(1)(typescript_1.default.factory.createIdentifier("key"), map.key, explore).statements), false), __read(decode(project)(importer)(2)(typescript_1.default.factory.createIdentifier("value"), map.value, explore).statements), false), [ typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(WRITER())("ldelim"), undefined, undefined)), ], false); return typescript_1.default.factory.createBlock([ typescript_1.default.factory.createForOfStatement(undefined, StatementFactory_1.StatementFactory.entry("key")("value"), input, typescript_1.default.factory.createBlock(each)), ], true); }; }; }; }; var decode_object = function (project) { return function (importer) { return function (index) { return function (input, object, explore) { var top = object.properties[0]; if (top.key.isSoleLiteral() === false) return decode_map(project)(importer)(index)(typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier("Object.entries"), [], [input]), MetadataProperty_1.MetadataProperty.create(__assign(__assign({}, top), { key: (function () { var key = Metadata_1.Metadata.initialize(); key.atomics.push(MetadataAtomic_1.MetadataAtomic.create({ type: "string", tags: [], })); return key; })() })), explore); return typescript_1.default.factory.createBlock(__spreadArray(__spreadArray(__spreadArray([ typescript_1.default.factory.createIdentifier("//".concat(index !== null ? " ".concat(index, " -> ") : "").concat(object.name)) ], __read((index !== null ? [ decode_tag(2 /* ProtobufWire.LEN */)(index), typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(WRITER())("fork"), undefined, undefined), ] : [])), false), [ typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier(importer.useLocal("".concat(PREFIX, "o").concat(object.index))), [], [input]) ], false), __read((index !== null ? [ typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(WRITER())("ldelim"), undefined, undefined), ] : [])), false).map(function (expr) { return typescript_1.default.factory.createExpressionStatement(expr); }), true); }; }; }; }; var decode_array = function (project) { return function (importer) { return function (index) { return function (input, array, explore) { var wire = get_standalone_wire(array.type.value); var forLoop = function (index) { return typescript_1.default.factory.createForOfStatement(undefined, typescript_1.default.factory.createVariableDeclarationList([typescript_1.default.factory.createVariableDeclaration("elem")], typescript_1.default.NodeFlags.Const), input, decode(project)(importer)(index)(typescript_1.default.factory.createIdentifier("elem"), array.type.value, explore)); }; var length = function (block) { return typescript_1.default.factory.createBlock([ typescript_1.default.factory.createIfStatement(typescript_1.default.factory.createStrictInequality(ExpressionFactory_1.ExpressionFactory.number(0), IdentifierFactory_1.IdentifierFactory.access(input)("length")), block), ], true); }; if (wire === 2 /* ProtobufWire.LEN */) return length(typescript_1.default.factory.createBlock([forLoop(index)], true)); return length(typescript_1.default.factory.createBlock([ typescript_1.default.factory.createExpressionStatement(decode_tag(2 /* ProtobufWire.LEN */)(index)), typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(WRITER())("fork"), undefined, undefined)), forLoop(null), typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(WRITER())("ldelim"), undefined, undefined)), ], true)); }; }; }; }; var decode_bool = function (index) { return function (input) { return typescript_1.default.factory.createBlock(__spreadArray(__spreadArray([], __read((index !== null ? [decode_tag(0 /* ProtobufWire.VARIANT */)(index)] : [])), false), [ typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(WRITER())("bool"), undefined, [input]), ], false).map(function (exp) { return typescript_1.default.factory.createExpressionStatement(exp); }), true); }; }; var decode_number = function (candidates) { return function (type) { return function (input) { return ({ type: type, is: function () { return candidates.length === 1 ? typescript_1.default.factory.createStrictEquality(typescript_1.default.factory.createStringLiteral("number"), typescript_1.default.factory.createTypeOfExpression(input)) : typescript_1.default.factory.createLogicalAnd(typescript_1.default.factory.createStrictEquality(typescript_1.default.factory.createStringLiteral("number"), typescript_1.default.factory.createTypeOfExpression(input)), NumericRangeFactory_1.NumericRangeFactory.number(type)(input)); }, value: function (index) { return typescript_1.default.factory.createBlock(__spreadArray(__spreadArray([], __read((index !== null ? [decode_tag(get_numeric_wire(type))(index)] : [])), false), [ typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(WRITER())(type), undefined, [input]), ], false).map(function (exp) { return typescript_1.default.factory.createExpressionStatement(exp); }), true); }, }); }; }; }; var decode_bigint = function (candidates) { return function (type) { return function (input) { return ({ type: type, is: function () { return candidates.length === 1 ? typescript_1.default.factory.createStrictEquality(typescript_1.default.factory.createStringLiteral("bigint"), typescript_1.default.factory.createTypeOfExpression(input)) : typescript_1.default.factory.createLogicalAnd(typescript_1.default.factory.createStrictEquality(typescript_1.default.factory.createStringLiteral("bigint"), typescript_1.default.factory.createTypeOfExpression(input)), NumericRangeFactory_1.NumericRangeFactory.bigint(type)(input)); }, value: function (index) { return typescript_1.default.factory.createBlock(__spreadArray(__spreadArray([], __read((index !== null ? [decode_tag(0 /* ProtobufWire.VARIANT */)(index)] : [])), false), [ typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(WRITER())(type), undefined, [input]), ], false).map(function (exp) { return typescript_1.default.factory.createExpressionStatement(exp); }), true); }, }); }; }; }; var decode_bytes = function (method) { return function (index) { return function (input) { return typescript_1.default.factory.createBlock([ decode_tag(2 /* ProtobufWire.LEN */)(index), typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(WRITER())(method), undefined, [input]), ].map(function (expr) { return typescript_1.default.factory.createExpressionStatement(expr); }), true); }; }; }; var decode_tag = function (wire) { return function (index) { return typescript_1.default.factory.createCallExpression(IdentifierFactory_1.IdentifierFactory.access(WRITER())("uint32"), undefined, [ExpressionFactory_1.ExpressionFactory.number((index << 3) | wire)]); }; }; var get_standalone_wire = function (meta) { if (meta.arrays.length || meta.objects.length || meta.maps.length || meta.natives.length) return 2 /* ProtobufWire.LEN */; var v = ProtobufUtil_1.ProtobufUtil.getAtomics(meta)[0]; if (v === "string") return 2 /* ProtobufWire.LEN */; else if (v === "bool" || v === "int32" || v === "uint32" || v === "int64" || v === "uint64") return 0 /* ProtobufWire.VARIANT */; else if (v === "float") return 5 /* ProtobufWire.I32 */; return 1 /* ProtobufWire.I64 */; }; var get_numeric_wire = function (type) { return type === "double" ? 1 /* ProtobufWire.I64 */ : type === "float" ? 5 /* ProtobufWire.I32 */ : 0 /* ProtobufWire.VARIANT */; }; /* ----------------------------------------------------------- EXPLORERS ----------------------------------------------------------- */ var explore_objects = function (project) { return function (importer) { return function (level) { return function (index) { return function (input, targets, explore, indexes) { if (targets.length === 1) return decode_object(project)(importer)(indexes ? indexes.get(targets[0]) : index)(input, targets[0], explore); var expected = "(".concat(targets.map(function (t) { return t.name; }).join(" | "), ")"); // POSSIBLE TO SPECIALIZE? var specList = UnionPredicator_1.UnionPredicator.object(targets); indexes !== null && indexes !== void 0 ? indexes : (indexes = new Map(targets.map(function (t, i) { return [t, index + i]; }))); if (specList.length === 0) { var condition_1 = (0, decode_union_object_1.decode_union_object)(IsProgrammer_1.IsProgrammer.decode_object(project)(importer))(function (i, o, e) { return ExpressionFactory_1.ExpressionFactory.selfCall(decode_object(project)(importer)(indexes.get(o))(i, o, e)); })(function (expr) { return expr; })(function (value, expected) { return create_throw_error(importer)(expected)(value); })(input, targets, explore); return StatementFactory_1.StatementFactory.block(condition_1); } var remained = targets.filter(function (t) { return specList.find(function (s) { return s.object === t; }) === undefined; }); // DO SPECIALIZE var condition = specList .filter(function (spec) { return spec.property.key.getSoleLiteral() !== null; }) .map(function (spec, i, array) { var key = spec.property.key.getSoleLiteral(); var accessor = IdentifierFactory_1.IdentifierFactory.access(input)(key); var pred = spec.neighbour ? IsProgrammer_1.IsProgrammer.decode(project)(importer)(accessor, spec.property.value, __assign(__assign({}, explore), { tracable: false, postfix: IdentifierFactory_1.IdentifierFactory.postfix(key) })) : ExpressionFactory_1.ExpressionFactory.isRequired(accessor); return typescript_1.default.factory.createIfStatement(pred, typescript_1.default.factory.createExpressionStatement(ExpressionFactory_1.ExpressionFactory.selfCall(decode_object(project)(importer)(indexes.get(spec.object))(input, spec.object, explore))), i === array.length - 1 ? remained.length ? typescript_1.default.factory.createExpressionStatement(ExpressionFactory_1.ExpressionFactory.selfCall(explore_objects(project)(importer)(level + 1)(index)(input, remained, explore, indexes))) : create_throw_error(importer)(expected)(input) : undefined); }) .reverse() .reduce(function (a, b) { return typescript_1.default.factory.createIfStatement(b.expression, b.thenStatement, a); }); // RETURNS WITH CONDITIONS return typescript_1.default.factory.createBlock([condition], true); }; }; }; }; }; /* ----------------------------------------------------------- CONFIGURATIONS ----------------------------------------------------------- */ var PREFIX = "$pe"; var create_throw_error = function (importer) { return function (expected) { return function (value) { return typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createCallExpression(importer.use("throws"), [], [ typescript_1.default.factory.createObjectLiteralExpression([ typescript_1.default.factory.createPropertyAssignment("expected", typescript_1.default.factory.createStringLiteral(expected)), typescript_1.default.factory.createPropertyAssignment("value", value), ], true), ])); }; }; }; })(ProtobufEncodeProgrammer || (exports.ProtobufEncodeProgrammer = ProtobufEncodeProgrammer = {})); var WRITER = function () { return typescript_1.default.factory.createIdentifier("writer"); }; //# sourceMappingURL=ProtobufEncodeProgrammer.js.map