UNPKG

@jsonjoy.com/json-type

Version:

High-performance JSON Pointer implementation

103 lines (102 loc) 3.67 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Discriminator = void 0; const classes_1 = require("./classes"); class Discriminator { static findConst(type) { if (type instanceof classes_1.ConType) return new Discriminator('', type); else if (type instanceof classes_1.TupType) { const types = type.types; for (let i = 0; i < types.length; i++) { const t = types[i]; const d = Discriminator.findConst(t); if (d) return new Discriminator('/' + i + d.path, d.type); } } else if (type instanceof classes_1.ObjType) { const fields = type.fields; for (let i = 0; i < fields.length; i++) { const f = fields[i]; const d = Discriminator.findConst(f.value); if (d) return new Discriminator('/' + f.key + d.path, d.type); } } return undefined; } static find(type) { const constDiscriminator = Discriminator.findConst(type); return constDiscriminator ?? new Discriminator('', type); } static createExpression(types) { const length = types.length; const specifiers = new Set(); const discriminators = []; for (let i = 1; i < length; i++) { const type = types[i]; const d = Discriminator.find(type); const specifier = d.toSpecifier(); if (specifiers.has(specifier)) throw new Error('Duplicate discriminator: ' + specifier); specifiers.add(specifier); discriminators.push(d); } let expr = 0; for (let i = 0; i < discriminators.length; i++) { const d = discriminators[i]; expr = ['?', d.condition(), i + 1, expr]; } return expr; } constructor(path, type) { this.path = path; this.type = type; } condition() { if (this.type instanceof classes_1.ConType) return ['==', this.type.value(), ['$', this.path]]; if (this.type instanceof classes_1.BoolType) return ['==', ['type', ['$', this.path]], 'boolean']; if (this.type instanceof classes_1.NumType) return ['==', ['type', ['$', this.path]], 'number']; if (this.type instanceof classes_1.StrType) return ['==', ['type', ['$', this.path]], 'string']; switch (this.typeSpecifier()) { case 'obj': return ['==', ['type', ['$', this.path]], 'object']; case 'arr': return ['==', ['type', ['$', this.path]], 'array']; } throw new Error('Cannot create condition for discriminator: ' + this.toSpecifier()); } typeSpecifier() { const mnemonic = this.type.getTypeName(); switch (mnemonic) { case 'bool': case 'str': case 'num': case 'con': return mnemonic; case 'obj': case 'map': return 'obj'; case 'arr': case 'tup': return 'arr'; case 'fn': case 'fn$': return 'fn'; } return ''; } toSpecifier() { const type = this.type; const path = this.path; const typeSpecifier = this.typeSpecifier(); const value = type instanceof classes_1.ConType ? type.value() : 0; return JSON.stringify([path, typeSpecifier, value]); } } exports.Discriminator = Discriminator;