@jsonjoy.com/json-type
Version:
High-performance JSON Pointer implementation
103 lines (102 loc) • 3.67 kB
JavaScript
;
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;