UNPKG

@jsonjoy.com/json-type

Version:

High-performance JSON Pointer implementation

255 lines (254 loc) 9.52 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NumberType = void 0; const util_1 = require("../../util"); const validate_1 = require("../../schema/validate"); const constants_1 = require("../../constants"); const AbstractType_1 = require("./AbstractType"); class NumberType extends AbstractType_1.AbstractType { constructor(schema) { super(); this.schema = schema; } toJsonSchema(ctx) { const schema = this.getSchema(); const jsonSchema = { type: 'number', ...super.toJsonSchema(ctx), }; if (schema.format && util_1.ints.has(schema.format)) jsonSchema.type = 'integer'; if (schema.gt !== undefined) jsonSchema.exclusiveMinimum = schema.gt; if (schema.gte !== undefined) jsonSchema.minimum = schema.gte; if (schema.lt !== undefined) jsonSchema.exclusiveMaximum = schema.lt; if (schema.lte !== undefined) jsonSchema.maximum = schema.lte; return jsonSchema; } validateSchema() { const schema = this.getSchema(); (0, validate_1.validateTType)(schema, 'num'); (0, validate_1.validateWithValidator)(schema); const { format, gt, gte, lt, lte } = schema; if (gt !== undefined && typeof gt !== 'number') throw new Error('GT_TYPE'); if (gte !== undefined && typeof gte !== 'number') throw new Error('GTE_TYPE'); if (lt !== undefined && typeof lt !== 'number') throw new Error('LT_TYPE'); if (lte !== undefined && typeof lte !== 'number') throw new Error('LTE_TYPE'); if (gt !== undefined && gte !== undefined) throw new Error('GT_GTE'); if (lt !== undefined && lte !== undefined) throw new Error('LT_LTE'); if ((gt !== undefined || gte !== undefined) && (lt !== undefined || lte !== undefined)) if ((gt ?? gte) > (lt ?? lte)) throw new Error('GT_LT'); if (format !== undefined) { if (typeof format !== 'string') throw new Error('FORMAT_TYPE'); if (!format) throw new Error('FORMAT_EMPTY'); switch (format) { case 'i': case 'u': case 'f': case 'i8': case 'i16': case 'i32': case 'i64': case 'u8': case 'u16': case 'u32': case 'u64': case 'f32': case 'f64': break; default: throw new Error('FORMAT_INVALID'); } } } codegenValidator(ctx, path, r) { const { format, gt, gte, lt, lte } = this.schema; if (format && util_1.ints.has(format)) { const errInt = ctx.err(constants_1.ValidationError.INT, path); ctx.js(/* js */ `if(!Number.isInteger(${r})) return ${errInt};`); if (util_1.uints.has(format)) { const err = ctx.err(constants_1.ValidationError.UINT, path); ctx.js(/* js */ `if(${r} < 0) return ${err};`); switch (format) { case 'u8': { ctx.js(/* js */ `if(${r} > 0xFF) return ${err};`); break; } case 'u16': { ctx.js(/* js */ `if(${r} > 0xFFFF) return ${err};`); break; } case 'u32': { ctx.js(/* js */ `if(${r} > 0xFFFFFFFF) return ${err};`); break; } } } else { switch (format) { case 'i8': { ctx.js(/* js */ `if(${r} > 0x7F || ${r} < -0x80) return ${errInt};`); break; } case 'i16': { ctx.js(/* js */ `if(${r} > 0x7FFF || ${r} < -0x8000) return ${errInt};`); break; } case 'i32': { ctx.js(/* js */ `if(${r} > 0x7FFFFFFF || ${r} < -0x80000000) return ${errInt};`); break; } } } } else if (util_1.floats.has(format)) { const err = ctx.err(constants_1.ValidationError.NUM, path); ctx.codegen.js(/* js */ `if(!Number.isFinite(${r})) return ${err};`); } else { const err = ctx.err(constants_1.ValidationError.NUM, path); ctx.codegen.js(/* js */ `if(typeof ${r} !== "number") return ${err};`); } if (gt !== undefined) { const err = ctx.err(constants_1.ValidationError.GT, path); ctx.codegen.js(/* js */ `if(${r} <= ${gt}) return ${err};`); } if (gte !== undefined) { const err = ctx.err(constants_1.ValidationError.GTE, path); ctx.codegen.js(/* js */ `if(${r} < ${gte}) return ${err};`); } if (lt !== undefined) { const err = ctx.err(constants_1.ValidationError.LT, path); ctx.codegen.js(/* js */ `if(${r} >= ${lt}) return ${err};`); } if (lte !== undefined) { const err = ctx.err(constants_1.ValidationError.LTE, path); ctx.codegen.js(/* js */ `if(${r} > ${lte}) return ${err};`); } ctx.emitCustomValidators(this, path, r); } codegenJsonTextEncoder(ctx, value) { ctx.js(/* js */ `s += ${value.use()};`); } codegenBinaryEncoder(ctx, value) { const { format } = this.schema; const v = value.use(); if (util_1.uints.has(format)) ctx.js(/* js */ `encoder.writeUInteger(${v});`); else if (util_1.ints.has(format)) ctx.js(/* js */ `encoder.writeInteger(${v});`); else if (util_1.floats.has(format)) ctx.js(/* js */ `encoder.writeFloat(${v});`); else ctx.js(/* js */ `encoder.writeNumber(${v});`); } codegenCborEncoder(ctx, value) { this.codegenBinaryEncoder(ctx, value); } codegenMessagePackEncoder(ctx, value) { this.codegenBinaryEncoder(ctx, value); } codegenJsonEncoder(ctx, value) { this.codegenBinaryEncoder(ctx, value); } codegenCapacityEstimator(ctx, value) { ctx.inc(22 /* MaxEncodingOverhead.Number */); } random() { let num = Math.random(); let min = Number.MIN_SAFE_INTEGER; let max = Number.MAX_SAFE_INTEGER; if (this.schema.gt !== undefined) min = this.schema.gt; if (this.schema.gte !== undefined) min = this.schema.gte + 0.000000000000001; if (this.schema.lt !== undefined) max = this.schema.lt; if (this.schema.lte !== undefined) max = this.schema.lte - 0.000000000000001; if (this.schema.format) { switch (this.schema.format) { case 'i8': min = Math.max(min, -0x80); max = Math.min(max, 0x7f); break; case 'i16': min = Math.max(min, -0x8000); max = Math.min(max, 0x7fff); break; case 'i32': min = Math.max(min, -0x80000000); max = Math.min(max, 0x7fffffff); break; case 'i64': case 'i': min = Math.max(min, -0x8000000000); max = Math.min(max, 0x7fffffffff); break; case 'u8': min = Math.max(min, 0); max = Math.min(max, 0xff); break; case 'u16': min = Math.max(min, 0); max = Math.min(max, 0xffff); break; case 'u32': min = Math.max(min, 0); max = Math.min(max, 0xffffffff); break; case 'u64': case 'u': min = Math.max(min, 0); max = Math.min(max, 0xffffffffffff); break; } return Math.round(num * (max - min)) + min; } num = num * (max - min) + min; if (Math.random() > 0.7) num = Math.round(num); if (num === 0) return 0; return num; } toTypeScriptAst() { return { node: 'NumberKeyword' }; } toJson(value, system = this.system) { return ('' + value); } toJtdForm() { switch (this.schema.format) { case 'u8': return { type: 'uint8' }; case 'u16': return { type: 'uint16' }; case 'u32': return { type: 'uint32' }; case 'i8': return { type: 'int8' }; case 'i16': return { type: 'int16' }; case 'i32': return { type: 'int32' }; case 'f32': return { type: 'float32' }; default: return { type: 'float64' }; } } } exports.NumberType = NumberType;