@rickosborne/rebound
Version:
Rick Osborne's utilities for working with bounded numbers
138 lines (137 loc) • 5.21 kB
JavaScript
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
import { computeIfAbsent, lowerFirst } from "@rickosborne/foundation";
import { scrubStackTrace } from "@rickosborne/guard";
import { assertForBounds } from "./assert-bounded.mjs";
import { fromNumberForBounds } from "./from-number-bounded.mjs";
import { guardForBounds } from "./guard-bounded.mjs";
import { CEIL, FLOOR, integerFrom, ROUND, TRUNC } from "./integer-from.mjs";
import { integerGenerator } from "./integer-generator.mjs";
import { randomBounded } from "./random-bounded.mjs";
import { ReboundBuilder } from "./rebound-builder.mjs";
import { BOUNDS } from "./spec.mjs";
import { ifIfPresent } from "./util.mjs";
const _Rebound = class _Rebound {
static buildType(typeName) {
return new ReboundBuilder(
{},
(_config, range) => new _Rebound(typeName, range)
);
}
fnCache = /* @__PURE__ */ new Map();
isInt;
isLowerInc;
isUpperInc;
label;
lower;
numberType = NaN;
outOfBoundsErrorProvider;
range;
typeName;
upper;
constructor(typeName, range) {
this.range = range;
this.typeName = typeName;
this.isInt = range.isInt;
this.isUpperInc = range.isUpperInc;
this.isLowerInc = range.isLowerInc;
this.lower = range.lower;
this.upper = range.upper;
this.label = range.label;
this.outOfBoundsErrorProvider = (v, n) => this.outOfRangeError(v, n);
}
get assert() {
return this.assertWith();
}
assertWith(options) {
const config = this.withOptions(options, "assert");
const guard = ifIfPresent(config.ifPresent, this.guardWith({ ifPresent: true }), this.guard);
return this.cacheFn(config, () => assertForBounds(guard, config.errorProvider, config.ifPresent));
}
cacheFn(options, compute) {
const key = options.defaultName.concat(":", options.fnName, ":", options.errorProvider.name);
return computeIfAbsent(key, this.fnCache, compute);
}
get ceil() {
return this.toIntWith({ strategy: CEIL });
}
get floor() {
return this.toIntWith({ strategy: FLOOR });
}
get fromNumber() {
return this.fromNumberWith({ ifPresent: false });
}
fromNumberWith(options) {
const config = this.withOptions(options, "", "FromNumber");
return this.cacheFn(config, () => fromNumberForBounds(this.guard, config.errorProvider, config.ifPresent, config.fnName));
}
get guard() {
return this.guardWith({ ifPresent: false });
}
guardWith(options) {
const config = this.withOptions(options, "is");
return this.cacheFn(
config,
() => guardForBounds(this.range, this.typeName, config.fnName, config.ifPresent)
);
}
get integers() {
return this.integersWith();
}
integersWith(options = {}) {
return integerGenerator(this.range, options);
}
outOfRangeError(value, name) {
const type = value === null ? "null" : value === void 0 ? "undefined" : typeof value;
return scrubStackTrace(new RangeError(`Expected ${name == null ? "" : name.concat(":")} ${this.typeName} ${this.range.toString()}, actual: ${type === "number" ? value : type}`), /at ((?:Rebound[.])?outOfRangeError|buildError)/);
}
get random() {
return this.randomWith();
}
randomWith(options = {}) {
const defaultName = `random${this.typeName}`;
const {
fnName = defaultName,
rng
} = options;
return this.cacheFn({
defaultName,
errorProvider: this.outOfBoundsErrorProvider,
fnName: (options == null ? void 0 : options.fnName) ?? defaultName,
ifPresent: false
}, () => randomBounded(this.typeName, this.range.label, this.range.isLowerInc, this.range.lower, this.range.isInt, this.range.upper, this.range.isUpperInc, rng, fnName));
}
get round() {
return this.toIntWith({ strategy: ROUND });
}
toIntWith(options) {
const config = this.withIntStrategy(options);
const { errorProvider, fnName, ifPresent, strategy } = config;
return this.cacheFn(config, () => integerFrom(this.typeName, this.range, errorProvider, ifPresent, strategy, fnName));
}
get trunc() {
return this.toIntWith({ strategy: TRUNC });
}
withIntStrategy(options) {
const prefix = typeof (options == null ? void 0 : options.strategy) === "function" ? "toInt" : (options == null ? void 0 : options.strategy) ?? ROUND;
const config = this.withOptions(options, prefix);
const strategy = (options == null ? void 0 : options.strategy) ?? ROUND;
return { ...config, strategy };
}
withOptions(options, prefix, suffix = "") {
const ifPresent = (options == null ? void 0 : options.ifPresent) ?? false;
const errorProvider = (options == null ? void 0 : options.errorProvider) ?? this.outOfBoundsErrorProvider;
const defaultName = `${prefix}${prefix === "" ? lowerFirst(this.typeName) : this.typeName}${suffix}${ifPresent ? "IfPresent" : ""}`;
const fnName = (options == null ? void 0 : options.fnName) ?? defaultName;
return { defaultName, errorProvider, fnName, ifPresent };
}
get [BOUNDS]() {
return this;
}
};
__name(_Rebound, "Rebound");
let Rebound = _Rebound;
export {
Rebound
};
//# sourceMappingURL=rebound.mjs.map