Erster Docker-Stand

This commit is contained in:
Ali
2026-02-20 16:06:40 +09:00
commit f31e2e8ed3
8818 changed files with 1605323 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { Stream } from '../../stream/Stream.js';
const AdaptedValue = Symbol('adapted-value');
function toAdapterValue(rawValue, adapter) {
const adapted = adapter(rawValue.value_);
if (!adapted.adapted) {
return rawValue;
}
return new Value(adapted.value, AdaptedValue);
}
class AdapterArbitrary extends Arbitrary {
constructor(sourceArb, adapter) {
super();
this.sourceArb = sourceArb;
this.adapter = adapter;
this.adaptValue = (rawValue) => toAdapterValue(rawValue, adapter);
}
generate(mrng, biasFactor) {
const rawValue = this.sourceArb.generate(mrng, biasFactor);
return this.adaptValue(rawValue);
}
canShrinkWithoutContext(value) {
return this.sourceArb.canShrinkWithoutContext(value) && !this.adapter(value).adapted;
}
shrink(value, context) {
if (context === AdaptedValue) {
if (!this.sourceArb.canShrinkWithoutContext(value)) {
return Stream.nil();
}
return this.sourceArb.shrink(value, undefined).map(this.adaptValue);
}
return this.sourceArb.shrink(value, context).map(this.adaptValue);
}
}
export function adapter(sourceArb, adapter) {
return new AdapterArbitrary(sourceArb, adapter);
}

View File

@@ -0,0 +1,23 @@
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Stream } from '../../stream/Stream.js';
import { noUndefinedAsContext, UndefinedContextPlaceholder } from './helpers/NoUndefinedAsContext.js';
export class AlwaysShrinkableArbitrary extends Arbitrary {
constructor(arb) {
super();
this.arb = arb;
}
generate(mrng, biasFactor) {
const value = this.arb.generate(mrng, biasFactor);
return noUndefinedAsContext(value);
}
canShrinkWithoutContext(value) {
return true;
}
shrink(value, context) {
if (context === undefined && !this.arb.canShrinkWithoutContext(value)) {
return Stream.nil();
}
const safeContext = context !== UndefinedContextPlaceholder ? context : undefined;
return this.arb.shrink(value, safeContext).map(noUndefinedAsContext);
}
}

View File

@@ -0,0 +1,219 @@
import { Stream } from '../../stream/Stream.js';
import { cloneIfNeeded, cloneMethod } from '../../check/symbols.js';
import { integer } from '../integer.js';
import { makeLazy } from '../../stream/LazyIterableIterator.js';
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { getDepthContextFor } from './helpers/DepthContext.js';
import { buildSlicedGenerator } from './helpers/BuildSlicedGenerator.js';
import { safeMap, safePush, safeSlice } from '../../utils/globals.js';
const safeMathFloor = Math.floor;
const safeMathLog = Math.log;
const safeMathMax = Math.max;
const safeArrayIsArray = Array.isArray;
function biasedMaxLength(minLength, maxLength) {
if (minLength === maxLength) {
return minLength;
}
return minLength + safeMathFloor(safeMathLog(maxLength - minLength) / safeMathLog(2));
}
export class ArrayArbitrary extends Arbitrary {
constructor(arb, minLength, maxGeneratedLength, maxLength, depthIdentifier, setBuilder, customSlices) {
super();
this.arb = arb;
this.minLength = minLength;
this.maxGeneratedLength = maxGeneratedLength;
this.maxLength = maxLength;
this.setBuilder = setBuilder;
this.customSlices = customSlices;
this.lengthArb = integer({ min: minLength, max: maxGeneratedLength });
this.depthContext = getDepthContextFor(depthIdentifier);
}
preFilter(tab) {
if (this.setBuilder === undefined) {
return tab;
}
const s = this.setBuilder();
for (let index = 0; index !== tab.length; ++index) {
s.tryAdd(tab[index]);
}
return s.getData();
}
static makeItCloneable(vs, shrinkables) {
vs[cloneMethod] = () => {
const cloned = [];
for (let idx = 0; idx !== shrinkables.length; ++idx) {
safePush(cloned, shrinkables[idx].value);
}
this.makeItCloneable(cloned, shrinkables);
return cloned;
};
return vs;
}
generateNItemsNoDuplicates(setBuilder, N, mrng, biasFactorItems) {
let numSkippedInRow = 0;
const s = setBuilder();
const slicedGenerator = buildSlicedGenerator(this.arb, mrng, this.customSlices, biasFactorItems);
while (s.size() < N && numSkippedInRow < this.maxGeneratedLength) {
const current = slicedGenerator.next();
if (s.tryAdd(current)) {
numSkippedInRow = 0;
}
else {
numSkippedInRow += 1;
}
}
return s.getData();
}
safeGenerateNItemsNoDuplicates(setBuilder, N, mrng, biasFactorItems) {
const depthImpact = safeMathMax(0, N - biasedMaxLength(this.minLength, this.maxGeneratedLength));
this.depthContext.depth += depthImpact;
try {
return this.generateNItemsNoDuplicates(setBuilder, N, mrng, biasFactorItems);
}
finally {
this.depthContext.depth -= depthImpact;
}
}
generateNItems(N, mrng, biasFactorItems) {
const items = [];
const slicedGenerator = buildSlicedGenerator(this.arb, mrng, this.customSlices, biasFactorItems);
slicedGenerator.attemptExact(N);
for (let index = 0; index !== N; ++index) {
const current = slicedGenerator.next();
safePush(items, current);
}
return items;
}
safeGenerateNItems(N, mrng, biasFactorItems) {
const depthImpact = safeMathMax(0, N - biasedMaxLength(this.minLength, this.maxGeneratedLength));
this.depthContext.depth += depthImpact;
try {
return this.generateNItems(N, mrng, biasFactorItems);
}
finally {
this.depthContext.depth -= depthImpact;
}
}
wrapper(itemsRaw, shrunkOnce, itemsRawLengthContext, startIndex) {
const items = shrunkOnce ? this.preFilter(itemsRaw) : itemsRaw;
let cloneable = false;
const vs = [];
const itemsContexts = [];
for (let idx = 0; idx !== items.length; ++idx) {
const s = items[idx];
cloneable = cloneable || s.hasToBeCloned;
safePush(vs, s.value);
safePush(itemsContexts, s.context);
}
if (cloneable) {
ArrayArbitrary.makeItCloneable(vs, items);
}
const context = {
shrunkOnce,
lengthContext: itemsRaw.length === items.length && itemsRawLengthContext !== undefined
? itemsRawLengthContext
: undefined,
itemsContexts,
startIndex,
};
return new Value(vs, context);
}
generate(mrng, biasFactor) {
const biasMeta = this.applyBias(mrng, biasFactor);
const targetSize = biasMeta.size;
const items = this.setBuilder !== undefined
? this.safeGenerateNItemsNoDuplicates(this.setBuilder, targetSize, mrng, biasMeta.biasFactorItems)
: this.safeGenerateNItems(targetSize, mrng, biasMeta.biasFactorItems);
return this.wrapper(items, false, undefined, 0);
}
applyBias(mrng, biasFactor) {
if (biasFactor === undefined) {
return { size: this.lengthArb.generate(mrng, undefined).value };
}
if (this.minLength === this.maxGeneratedLength) {
return { size: this.lengthArb.generate(mrng, undefined).value, biasFactorItems: biasFactor };
}
if (mrng.nextInt(1, biasFactor) !== 1) {
return { size: this.lengthArb.generate(mrng, undefined).value };
}
if (mrng.nextInt(1, biasFactor) !== 1 || this.minLength === this.maxGeneratedLength) {
return { size: this.lengthArb.generate(mrng, undefined).value, biasFactorItems: biasFactor };
}
const maxBiasedLength = biasedMaxLength(this.minLength, this.maxGeneratedLength);
const targetSizeValue = integer({ min: this.minLength, max: maxBiasedLength }).generate(mrng, undefined);
return { size: targetSizeValue.value, biasFactorItems: biasFactor };
}
canShrinkWithoutContext(value) {
if (!safeArrayIsArray(value) || this.minLength > value.length || value.length > this.maxLength) {
return false;
}
for (let index = 0; index !== value.length; ++index) {
if (!(index in value)) {
return false;
}
if (!this.arb.canShrinkWithoutContext(value[index])) {
return false;
}
}
const filtered = this.preFilter(safeMap(value, (item) => new Value(item, undefined)));
return filtered.length === value.length;
}
shrinkItemByItem(value, safeContext, endIndex) {
const shrinks = [];
for (let index = safeContext.startIndex; index < endIndex; ++index) {
safePush(shrinks, makeLazy(() => this.arb.shrink(value[index], safeContext.itemsContexts[index]).map((v) => {
const beforeCurrent = safeMap(safeSlice(value, 0, index), (v, i) => new Value(cloneIfNeeded(v), safeContext.itemsContexts[i]));
const afterCurrent = safeMap(safeSlice(value, index + 1), (v, i) => new Value(cloneIfNeeded(v), safeContext.itemsContexts[i + index + 1]));
return [
[...beforeCurrent, v, ...afterCurrent],
undefined,
index,
];
})));
}
return Stream.nil().join(...shrinks);
}
shrinkImpl(value, context) {
if (value.length === 0) {
return Stream.nil();
}
const safeContext = context !== undefined
? context
: { shrunkOnce: false, lengthContext: undefined, itemsContexts: [], startIndex: 0 };
return (this.lengthArb
.shrink(value.length, safeContext.lengthContext)
.drop(safeContext.shrunkOnce && safeContext.lengthContext === undefined && value.length > this.minLength + 1
? 1
: 0)
.map((lengthValue) => {
const sliceStart = value.length - lengthValue.value;
return [
safeMap(safeSlice(value, sliceStart), (v, index) => new Value(cloneIfNeeded(v), safeContext.itemsContexts[index + sliceStart])),
lengthValue.context,
0,
];
})
.join(makeLazy(() => value.length > this.minLength
? this.shrinkItemByItem(value, safeContext, 1)
: this.shrinkItemByItem(value, safeContext, value.length)))
.join(value.length > this.minLength
? makeLazy(() => {
const subContext = {
shrunkOnce: false,
lengthContext: undefined,
itemsContexts: safeSlice(safeContext.itemsContexts, 1),
startIndex: 0,
};
return this.shrinkImpl(safeSlice(value, 1), subContext)
.filter((v) => this.minLength <= v[0].length + 1)
.map((v) => {
return [[new Value(cloneIfNeeded(value[0]), safeContext.itemsContexts[0]), ...v[0]], undefined, 0];
});
})
: Stream.nil()));
}
shrink(value, context) {
return this.shrinkImpl(value, context).map((contextualValue) => this.wrapper(contextualValue[0], true, contextualValue[1], contextualValue[2]));
}
}

View File

@@ -0,0 +1,124 @@
import { stream, Stream } from '../../stream/Stream.js';
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { add64, halve64, isEqual64, isStrictlyNegative64, isStrictlyPositive64, isStrictlySmaller64, isZero64, logLike64, substract64, Unit64, Zero64, } from './helpers/ArrayInt64.js';
class ArrayInt64Arbitrary extends Arbitrary {
constructor(min, max) {
super();
this.min = min;
this.max = max;
this.biasedRanges = null;
}
generate(mrng, biasFactor) {
const range = this.computeGenerateRange(mrng, biasFactor);
const uncheckedValue = mrng.nextArrayInt(range.min, range.max);
if (uncheckedValue.data.length === 1) {
uncheckedValue.data.unshift(0);
}
return new Value(uncheckedValue, undefined);
}
computeGenerateRange(mrng, biasFactor) {
if (biasFactor === undefined || mrng.nextInt(1, biasFactor) !== 1) {
return { min: this.min, max: this.max };
}
const ranges = this.retrieveBiasedRanges();
if (ranges.length === 1) {
return ranges[0];
}
const id = mrng.nextInt(-2 * (ranges.length - 1), ranges.length - 2);
return id < 0 ? ranges[0] : ranges[id + 1];
}
canShrinkWithoutContext(value) {
const unsafeValue = value;
return (typeof value === 'object' &&
value !== null &&
(unsafeValue.sign === -1 || unsafeValue.sign === 1) &&
Array.isArray(unsafeValue.data) &&
unsafeValue.data.length === 2 &&
((isStrictlySmaller64(this.min, unsafeValue) && isStrictlySmaller64(unsafeValue, this.max)) ||
isEqual64(this.min, unsafeValue) ||
isEqual64(this.max, unsafeValue)));
}
shrinkArrayInt64(value, target, tryTargetAsap) {
const realGap = substract64(value, target);
function* shrinkGen() {
let previous = tryTargetAsap ? undefined : target;
const gap = tryTargetAsap ? realGap : halve64(realGap);
for (let toremove = gap; !isZero64(toremove); toremove = halve64(toremove)) {
const next = substract64(value, toremove);
yield new Value(next, previous);
previous = next;
}
}
return stream(shrinkGen());
}
shrink(current, context) {
if (!ArrayInt64Arbitrary.isValidContext(current, context)) {
const target = this.defaultTarget();
return this.shrinkArrayInt64(current, target, true);
}
if (this.isLastChanceTry(current, context)) {
return Stream.of(new Value(context, undefined));
}
return this.shrinkArrayInt64(current, context, false);
}
defaultTarget() {
if (!isStrictlyPositive64(this.min) && !isStrictlyNegative64(this.max)) {
return Zero64;
}
return isStrictlyNegative64(this.min) ? this.max : this.min;
}
isLastChanceTry(current, context) {
if (isZero64(current)) {
return false;
}
if (current.sign === 1) {
return isEqual64(current, add64(context, Unit64)) && isStrictlyPositive64(substract64(current, this.min));
}
else {
return isEqual64(current, substract64(context, Unit64)) && isStrictlyNegative64(substract64(current, this.max));
}
}
static isValidContext(_current, context) {
if (context === undefined) {
return false;
}
if (typeof context !== 'object' || context === null || !('sign' in context) || !('data' in context)) {
throw new Error(`Invalid context type passed to ArrayInt64Arbitrary (#1)`);
}
return true;
}
retrieveBiasedRanges() {
if (this.biasedRanges != null) {
return this.biasedRanges;
}
if (isEqual64(this.min, this.max)) {
this.biasedRanges = [{ min: this.min, max: this.max }];
return this.biasedRanges;
}
const minStrictlySmallerZero = isStrictlyNegative64(this.min);
const maxStrictlyGreaterZero = isStrictlyPositive64(this.max);
if (minStrictlySmallerZero && maxStrictlyGreaterZero) {
const logMin = logLike64(this.min);
const logMax = logLike64(this.max);
this.biasedRanges = [
{ min: logMin, max: logMax },
{ min: substract64(this.max, logMax), max: this.max },
{ min: this.min, max: substract64(this.min, logMin) },
];
}
else {
const logGap = logLike64(substract64(this.max, this.min));
const arbCloseToMin = { min: this.min, max: add64(this.min, logGap) };
const arbCloseToMax = { min: substract64(this.max, logGap), max: this.max };
this.biasedRanges = minStrictlySmallerZero
? [arbCloseToMax, arbCloseToMin]
: [arbCloseToMin, arbCloseToMax];
}
return this.biasedRanges;
}
}
export function arrayInt64(min, max) {
const arb = new ArrayInt64Arbitrary(min, max);
return arb;
}

View File

@@ -0,0 +1,67 @@
import { Stream } from '../../stream/Stream.js';
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { biasNumericRange, bigIntLogLike } from './helpers/BiasNumericRange.js';
import { shrinkBigInt } from './helpers/ShrinkBigInt.js';
import { BigInt } from '../../utils/globals.js';
export class BigIntArbitrary extends Arbitrary {
constructor(min, max) {
super();
this.min = min;
this.max = max;
}
generate(mrng, biasFactor) {
const range = this.computeGenerateRange(mrng, biasFactor);
return new Value(mrng.nextBigInt(range.min, range.max), undefined);
}
computeGenerateRange(mrng, biasFactor) {
if (biasFactor === undefined || mrng.nextInt(1, biasFactor) !== 1) {
return { min: this.min, max: this.max };
}
const ranges = biasNumericRange(this.min, this.max, bigIntLogLike);
if (ranges.length === 1) {
return ranges[0];
}
const id = mrng.nextInt(-2 * (ranges.length - 1), ranges.length - 2);
return id < 0 ? ranges[0] : ranges[id + 1];
}
canShrinkWithoutContext(value) {
return typeof value === 'bigint' && this.min <= value && value <= this.max;
}
shrink(current, context) {
if (!BigIntArbitrary.isValidContext(current, context)) {
const target = this.defaultTarget();
return shrinkBigInt(current, target, true);
}
if (this.isLastChanceTry(current, context)) {
return Stream.of(new Value(context, undefined));
}
return shrinkBigInt(current, context, false);
}
defaultTarget() {
if (this.min <= 0 && this.max >= 0) {
return BigInt(0);
}
return this.min < 0 ? this.max : this.min;
}
isLastChanceTry(current, context) {
if (current > 0)
return current === context + BigInt(1) && current > this.min;
if (current < 0)
return current === context - BigInt(1) && current < this.max;
return false;
}
static isValidContext(current, context) {
if (context === undefined) {
return false;
}
if (typeof context !== 'bigint') {
throw new Error(`Invalid context type passed to BigIntArbitrary (#1)`);
}
const differentSigns = (current > 0 && context < 0) || (current < 0 && context > 0);
if (context !== BigInt(0) && differentSigns) {
throw new Error(`Invalid context value passed to BigIntArbitrary (#2)`);
}
return true;
}
}

View File

@@ -0,0 +1,80 @@
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { cloneMethod } from '../../check/symbols.js';
import { Stream } from '../../stream/Stream.js';
import { safeMap, safePush } from '../../utils/globals.js';
const safeSymbolIterator = Symbol.iterator;
const safeIsArray = Array.isArray;
const safeObjectIs = Object.is;
export class CloneArbitrary extends Arbitrary {
constructor(arb, numValues) {
super();
this.arb = arb;
this.numValues = numValues;
}
generate(mrng, biasFactor) {
const items = [];
if (this.numValues <= 0) {
return this.wrapper(items);
}
for (let idx = 0; idx !== this.numValues - 1; ++idx) {
safePush(items, this.arb.generate(mrng.clone(), biasFactor));
}
safePush(items, this.arb.generate(mrng, biasFactor));
return this.wrapper(items);
}
canShrinkWithoutContext(value) {
if (!safeIsArray(value) || value.length !== this.numValues) {
return false;
}
if (value.length === 0) {
return true;
}
for (let index = 1; index < value.length; ++index) {
if (!safeObjectIs(value[0], value[index])) {
return false;
}
}
return this.arb.canShrinkWithoutContext(value[0]);
}
shrink(value, context) {
if (value.length === 0) {
return Stream.nil();
}
return new Stream(this.shrinkImpl(value, context !== undefined ? context : [])).map((v) => this.wrapper(v));
}
*shrinkImpl(value, contexts) {
const its = safeMap(value, (v, idx) => this.arb.shrink(v, contexts[idx])[safeSymbolIterator]());
let cur = safeMap(its, (it) => it.next());
while (!cur[0].done) {
yield safeMap(cur, (c) => c.value);
cur = safeMap(its, (it) => it.next());
}
}
static makeItCloneable(vs, shrinkables) {
vs[cloneMethod] = () => {
const cloned = [];
for (let idx = 0; idx !== shrinkables.length; ++idx) {
safePush(cloned, shrinkables[idx].value);
}
this.makeItCloneable(cloned, shrinkables);
return cloned;
};
return vs;
}
wrapper(items) {
let cloneable = false;
const vs = [];
const contexts = [];
for (let idx = 0; idx !== items.length; ++idx) {
const s = items[idx];
cloneable = cloneable || s.hasToBeCloned;
safePush(vs, s.value);
safePush(contexts, s.context);
}
if (cloneable) {
CloneArbitrary.makeItCloneable(vs, items);
}
return new Value(vs, contexts);
}
}

View File

@@ -0,0 +1,106 @@
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { CommandsIterable } from '../../check/model/commands/CommandsIterable.js';
import { CommandWrapper } from '../../check/model/commands/CommandWrapper.js';
import { ReplayPath } from '../../check/model/ReplayPath.js';
import { makeLazy } from '../../stream/LazyIterableIterator.js';
import { Stream } from '../../stream/Stream.js';
import { oneof } from '../oneof.js';
import { restrictedIntegerArbitraryBuilder } from './builders/RestrictedIntegerArbitraryBuilder.js';
export class CommandsArbitrary extends Arbitrary {
constructor(commandArbs, maxGeneratedCommands, maxCommands, sourceReplayPath, disableReplayLog) {
super();
this.sourceReplayPath = sourceReplayPath;
this.disableReplayLog = disableReplayLog;
this.oneCommandArb = oneof(...commandArbs).map((c) => new CommandWrapper(c));
this.lengthArb = restrictedIntegerArbitraryBuilder(0, maxGeneratedCommands, maxCommands);
this.replayPath = [];
this.replayPathPosition = 0;
}
metadataForReplay() {
return this.disableReplayLog ? '' : `replayPath=${JSON.stringify(ReplayPath.stringify(this.replayPath))}`;
}
buildValueFor(items, shrunkOnce) {
const commands = items.map((item) => item.value_);
const context = { shrunkOnce, items };
return new Value(new CommandsIterable(commands, () => this.metadataForReplay()), context);
}
generate(mrng) {
const size = this.lengthArb.generate(mrng, undefined);
const sizeValue = size.value;
const items = Array(sizeValue);
for (let idx = 0; idx !== sizeValue; ++idx) {
const item = this.oneCommandArb.generate(mrng, undefined);
items[idx] = item;
}
this.replayPathPosition = 0;
return this.buildValueFor(items, false);
}
canShrinkWithoutContext(value) {
return false;
}
filterOnExecution(itemsRaw) {
const items = [];
for (const c of itemsRaw) {
if (c.value_.hasRan) {
this.replayPath.push(true);
items.push(c);
}
else
this.replayPath.push(false);
}
return items;
}
filterOnReplay(itemsRaw) {
return itemsRaw.filter((c, idx) => {
const state = this.replayPath[this.replayPathPosition + idx];
if (state === undefined)
throw new Error(`Too short replayPath`);
if (!state && c.value_.hasRan)
throw new Error(`Mismatch between replayPath and real execution`);
return state;
});
}
filterForShrinkImpl(itemsRaw) {
if (this.replayPathPosition === 0) {
this.replayPath = this.sourceReplayPath !== null ? ReplayPath.parse(this.sourceReplayPath) : [];
}
const items = this.replayPathPosition < this.replayPath.length
? this.filterOnReplay(itemsRaw)
: this.filterOnExecution(itemsRaw);
this.replayPathPosition += itemsRaw.length;
return items;
}
shrink(_value, context) {
if (context === undefined) {
return Stream.nil();
}
const safeContext = context;
const shrunkOnce = safeContext.shrunkOnce;
const itemsRaw = safeContext.items;
const items = this.filterForShrinkImpl(itemsRaw);
if (items.length === 0) {
return Stream.nil();
}
const rootShrink = shrunkOnce
? Stream.nil()
: new Stream([[]][Symbol.iterator]());
const nextShrinks = [];
for (let numToKeep = 0; numToKeep !== items.length; ++numToKeep) {
nextShrinks.push(makeLazy(() => {
const fixedStart = items.slice(0, numToKeep);
return this.lengthArb
.shrink(items.length - 1 - numToKeep, undefined)
.map((l) => fixedStart.concat(items.slice(items.length - (l.value + 1))));
}));
}
for (let itemAt = 0; itemAt !== items.length; ++itemAt) {
nextShrinks.push(makeLazy(() => this.oneCommandArb
.shrink(items[itemAt].value_, items[itemAt].context)
.map((v) => items.slice(0, itemAt).concat([v], items.slice(itemAt + 1)))));
}
return rootShrink.join(...nextShrinks).map((shrinkables) => {
return this.buildValueFor(shrinkables.map((c) => new Value(c.value_.clone(), c.context)), true);
});
}
}

View File

@@ -0,0 +1,61 @@
import { Stream } from '../../stream/Stream.js';
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { cloneMethod, hasCloneMethod } from '../../check/symbols.js';
import { Set, safeHas } from '../../utils/globals.js';
const safeObjectIs = Object.is;
export class ConstantArbitrary extends Arbitrary {
constructor(values) {
super();
this.values = values;
}
generate(mrng, _biasFactor) {
const idx = this.values.length === 1 ? 0 : mrng.nextInt(0, this.values.length - 1);
const value = this.values[idx];
if (!hasCloneMethod(value)) {
return new Value(value, idx);
}
return new Value(value, idx, () => value[cloneMethod]());
}
canShrinkWithoutContext(value) {
if (this.values.length === 1) {
return safeObjectIs(this.values[0], value);
}
if (this.fastValues === undefined) {
this.fastValues = new FastConstantValuesLookup(this.values);
}
return this.fastValues.has(value);
}
shrink(value, context) {
if (context === 0 || safeObjectIs(value, this.values[0])) {
return Stream.nil();
}
return Stream.of(new Value(this.values[0], 0));
}
}
class FastConstantValuesLookup {
constructor(values) {
this.values = values;
this.fastValues = new Set(this.values);
let hasMinusZero = false;
let hasPlusZero = false;
if (safeHas(this.fastValues, 0)) {
for (let idx = 0; idx !== this.values.length; ++idx) {
const value = this.values[idx];
hasMinusZero = hasMinusZero || safeObjectIs(value, -0);
hasPlusZero = hasPlusZero || safeObjectIs(value, 0);
}
}
this.hasMinusZero = hasMinusZero;
this.hasPlusZero = hasPlusZero;
}
has(value) {
if (value === 0) {
if (safeObjectIs(value, 0)) {
return this.hasPlusZero;
}
return this.hasMinusZero;
}
return safeHas(this.fastValues, value);
}
}

View File

@@ -0,0 +1,162 @@
import { Stream } from '../../stream/Stream.js';
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { getDepthContextFor } from './helpers/DepthContext.js';
import { depthBiasFromSizeForArbitrary } from './helpers/MaxLengthFromMinLength.js';
import { safePush } from '../../utils/globals.js';
const safePositiveInfinity = Number.POSITIVE_INFINITY;
const safeMaxSafeInteger = Number.MAX_SAFE_INTEGER;
const safeNumberIsInteger = Number.isInteger;
const safeMathFloor = Math.floor;
const safeMathPow = Math.pow;
const safeMathMin = Math.min;
export class FrequencyArbitrary extends Arbitrary {
static from(warbs, constraints, label) {
if (warbs.length === 0) {
throw new Error(`${label} expects at least one weighted arbitrary`);
}
let totalWeight = 0;
for (let idx = 0; idx !== warbs.length; ++idx) {
const currentArbitrary = warbs[idx].arbitrary;
if (currentArbitrary === undefined) {
throw new Error(`${label} expects arbitraries to be specified`);
}
const currentWeight = warbs[idx].weight;
totalWeight += currentWeight;
if (!safeNumberIsInteger(currentWeight)) {
throw new Error(`${label} expects weights to be integer values`);
}
if (currentWeight < 0) {
throw new Error(`${label} expects weights to be superior or equal to 0`);
}
}
if (totalWeight <= 0) {
throw new Error(`${label} expects the sum of weights to be strictly superior to 0`);
}
const sanitizedConstraints = {
depthBias: depthBiasFromSizeForArbitrary(constraints.depthSize, constraints.maxDepth !== undefined),
maxDepth: constraints.maxDepth != undefined ? constraints.maxDepth : safePositiveInfinity,
withCrossShrink: !!constraints.withCrossShrink,
};
return new FrequencyArbitrary(warbs, sanitizedConstraints, getDepthContextFor(constraints.depthIdentifier));
}
constructor(warbs, constraints, context) {
super();
this.warbs = warbs;
this.constraints = constraints;
this.context = context;
let currentWeight = 0;
this.cumulatedWeights = [];
for (let idx = 0; idx !== warbs.length; ++idx) {
currentWeight += warbs[idx].weight;
safePush(this.cumulatedWeights, currentWeight);
}
this.totalWeight = currentWeight;
}
generate(mrng, biasFactor) {
if (this.mustGenerateFirst()) {
return this.safeGenerateForIndex(mrng, 0, biasFactor);
}
const selected = mrng.nextInt(this.computeNegDepthBenefit(), this.totalWeight - 1);
for (let idx = 0; idx !== this.cumulatedWeights.length; ++idx) {
if (selected < this.cumulatedWeights[idx]) {
return this.safeGenerateForIndex(mrng, idx, biasFactor);
}
}
throw new Error(`Unable to generate from fc.frequency`);
}
canShrinkWithoutContext(value) {
return this.canShrinkWithoutContextIndex(value) !== -1;
}
shrink(value, context) {
if (context !== undefined) {
const safeContext = context;
const selectedIndex = safeContext.selectedIndex;
const originalBias = safeContext.originalBias;
const originalArbitrary = this.warbs[selectedIndex].arbitrary;
const originalShrinks = originalArbitrary
.shrink(value, safeContext.originalContext)
.map((v) => this.mapIntoValue(selectedIndex, v, null, originalBias));
if (safeContext.clonedMrngForFallbackFirst !== null) {
if (safeContext.cachedGeneratedForFirst === undefined) {
safeContext.cachedGeneratedForFirst = this.safeGenerateForIndex(safeContext.clonedMrngForFallbackFirst, 0, originalBias);
}
const valueFromFirst = safeContext.cachedGeneratedForFirst;
return Stream.of(valueFromFirst).join(originalShrinks);
}
return originalShrinks;
}
const potentialSelectedIndex = this.canShrinkWithoutContextIndex(value);
if (potentialSelectedIndex === -1) {
return Stream.nil();
}
return this.defaultShrinkForFirst(potentialSelectedIndex).join(this.warbs[potentialSelectedIndex].arbitrary
.shrink(value, undefined)
.map((v) => this.mapIntoValue(potentialSelectedIndex, v, null, undefined)));
}
defaultShrinkForFirst(selectedIndex) {
++this.context.depth;
try {
if (!this.mustFallbackToFirstInShrink(selectedIndex) || this.warbs[0].fallbackValue === undefined) {
return Stream.nil();
}
}
finally {
--this.context.depth;
}
const rawShrinkValue = new Value(this.warbs[0].fallbackValue.default, undefined);
return Stream.of(this.mapIntoValue(0, rawShrinkValue, null, undefined));
}
canShrinkWithoutContextIndex(value) {
if (this.mustGenerateFirst()) {
return this.warbs[0].arbitrary.canShrinkWithoutContext(value) ? 0 : -1;
}
try {
++this.context.depth;
for (let idx = 0; idx !== this.warbs.length; ++idx) {
const warb = this.warbs[idx];
if (warb.weight !== 0 && warb.arbitrary.canShrinkWithoutContext(value)) {
return idx;
}
}
return -1;
}
finally {
--this.context.depth;
}
}
mapIntoValue(idx, value, clonedMrngForFallbackFirst, biasFactor) {
const context = {
selectedIndex: idx,
originalBias: biasFactor,
originalContext: value.context,
clonedMrngForFallbackFirst,
};
return new Value(value.value, context);
}
safeGenerateForIndex(mrng, idx, biasFactor) {
++this.context.depth;
try {
const value = this.warbs[idx].arbitrary.generate(mrng, biasFactor);
const clonedMrngForFallbackFirst = this.mustFallbackToFirstInShrink(idx) ? mrng.clone() : null;
return this.mapIntoValue(idx, value, clonedMrngForFallbackFirst, biasFactor);
}
finally {
--this.context.depth;
}
}
mustGenerateFirst() {
return this.constraints.maxDepth <= this.context.depth;
}
mustFallbackToFirstInShrink(idx) {
return idx !== 0 && this.constraints.withCrossShrink && this.warbs[0].weight !== 0;
}
computeNegDepthBenefit() {
const depthBias = this.constraints.depthBias;
if (depthBias <= 0 || this.warbs[0].weight === 0) {
return 0;
}
const depthBenefit = safeMathFloor(safeMathPow(1 + depthBias, this.context.depth)) - 1;
return -safeMathMin(this.totalWeight * depthBenefit, safeMaxSafeInteger) || 0;
}
}

View File

@@ -0,0 +1,40 @@
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Stream } from '../../stream/Stream.js';
import { safeMap } from '../../utils/globals.js';
import { buildGeneratorValue } from './builders/GeneratorValueBuilder.js';
import { buildStableArbitraryGeneratorCache, naiveIsEqual } from './builders/StableArbitraryGeneratorCache.js';
import { tupleShrink } from './TupleArbitrary.js';
export class GeneratorArbitrary extends Arbitrary {
constructor() {
super(...arguments);
this.arbitraryCache = buildStableArbitraryGeneratorCache(naiveIsEqual);
}
generate(mrng, biasFactor) {
return buildGeneratorValue(mrng, biasFactor, () => [], this.arbitraryCache);
}
canShrinkWithoutContext(value) {
return false;
}
shrink(_value, context) {
if (context === undefined) {
return Stream.nil();
}
const safeContext = context;
const mrng = safeContext.mrng;
const biasFactor = safeContext.biasFactor;
const history = safeContext.history;
return tupleShrink(history.map((c) => c.arb), history.map((c) => c.value), history.map((c) => c.context)).map((shrink) => {
function computePreBuiltValues() {
const subValues = shrink.value;
const subContexts = shrink.context;
return safeMap(history, (entry, index) => ({
arb: entry.arb,
value: subValues[index],
context: subContexts[index],
mrng: entry.mrng,
}));
}
return buildGeneratorValue(mrng, biasFactor, computePreBuiltValues, this.arbitraryCache);
});
}
}

View File

@@ -0,0 +1,72 @@
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { Stream } from '../../stream/Stream.js';
import { integerLogLike, biasNumericRange } from './helpers/BiasNumericRange.js';
import { shrinkInteger } from './helpers/ShrinkInteger.js';
const safeMathSign = Math.sign;
const safeNumberIsInteger = Number.isInteger;
const safeObjectIs = Object.is;
export class IntegerArbitrary extends Arbitrary {
constructor(min, max) {
super();
this.min = min;
this.max = max;
}
generate(mrng, biasFactor) {
const range = this.computeGenerateRange(mrng, biasFactor);
return new Value(mrng.nextInt(range.min, range.max), undefined);
}
canShrinkWithoutContext(value) {
return (typeof value === 'number' &&
safeNumberIsInteger(value) &&
!safeObjectIs(value, -0) &&
this.min <= value &&
value <= this.max);
}
shrink(current, context) {
if (!IntegerArbitrary.isValidContext(current, context)) {
const target = this.defaultTarget();
return shrinkInteger(current, target, true);
}
if (this.isLastChanceTry(current, context)) {
return Stream.of(new Value(context, undefined));
}
return shrinkInteger(current, context, false);
}
defaultTarget() {
if (this.min <= 0 && this.max >= 0) {
return 0;
}
return this.min < 0 ? this.max : this.min;
}
computeGenerateRange(mrng, biasFactor) {
if (biasFactor === undefined || mrng.nextInt(1, biasFactor) !== 1) {
return { min: this.min, max: this.max };
}
const ranges = biasNumericRange(this.min, this.max, integerLogLike);
if (ranges.length === 1) {
return ranges[0];
}
const id = mrng.nextInt(-2 * (ranges.length - 1), ranges.length - 2);
return id < 0 ? ranges[0] : ranges[id + 1];
}
isLastChanceTry(current, context) {
if (current > 0)
return current === context + 1 && current > this.min;
if (current < 0)
return current === context - 1 && current < this.max;
return false;
}
static isValidContext(current, context) {
if (context === undefined) {
return false;
}
if (typeof context !== 'number') {
throw new Error(`Invalid context type passed to IntegerArbitrary (#1)`);
}
if (context !== 0 && safeMathSign(current) !== safeMathSign(context)) {
throw new Error(`Invalid context value passed to IntegerArbitrary (#2)`);
}
return true;
}
}

View File

@@ -0,0 +1,26 @@
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
export class LazyArbitrary extends Arbitrary {
constructor(name) {
super();
this.name = name;
this.underlying = null;
}
generate(mrng, biasFactor) {
if (!this.underlying) {
throw new Error(`Lazy arbitrary ${JSON.stringify(this.name)} not correctly initialized`);
}
return this.underlying.generate(mrng, biasFactor);
}
canShrinkWithoutContext(value) {
if (!this.underlying) {
throw new Error(`Lazy arbitrary ${JSON.stringify(this.name)} not correctly initialized`);
}
return this.underlying.canShrinkWithoutContext(value);
}
shrink(value, context) {
if (!this.underlying) {
throw new Error(`Lazy arbitrary ${JSON.stringify(this.name)} not correctly initialized`);
}
return this.underlying.shrink(value, context);
}
}

View File

@@ -0,0 +1,50 @@
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { Stream } from '../../stream/Stream.js';
import { zipIterableIterators } from './helpers/ZipIterableIterators.js';
function* iotaFrom(startValue) {
let value = startValue;
while (true) {
yield value;
++value;
}
}
export class LimitedShrinkArbitrary extends Arbitrary {
constructor(arb, maxShrinks) {
super();
this.arb = arb;
this.maxShrinks = maxShrinks;
}
generate(mrng, biasFactor) {
const value = this.arb.generate(mrng, biasFactor);
return this.valueMapper(value, 0);
}
canShrinkWithoutContext(value) {
return this.arb.canShrinkWithoutContext(value);
}
shrink(value, context) {
if (this.isSafeContext(context)) {
return this.safeShrink(value, context.originalContext, context.length);
}
return this.safeShrink(value, undefined, 0);
}
safeShrink(value, originalContext, currentLength) {
const remaining = this.maxShrinks - currentLength;
if (remaining <= 0) {
return Stream.nil();
}
return new Stream(zipIterableIterators(this.arb.shrink(value, originalContext), iotaFrom(currentLength + 1)))
.take(remaining)
.map((valueAndLength) => this.valueMapper(valueAndLength[0], valueAndLength[1]));
}
valueMapper(v, newLength) {
const context = { originalContext: v.context, length: newLength };
return new Value(v.value, context);
}
isSafeContext(context) {
return (context != null &&
typeof context === 'object' &&
'originalContext' in context &&
'length' in context);
}
}

View File

@@ -0,0 +1,91 @@
import { bigUintN } from '../bigUintN.js';
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { makeLazy } from '../../stream/LazyIterableIterator.js';
import { applyFlagsOnChars, computeFlagsFromChars, computeNextFlags, computeTogglePositions, } from './helpers/ToggleFlags.js';
import { safeJoin, safeSlice } from '../../utils/globals.js';
import { BigInt } from '../../utils/globals.js';
export class MixedCaseArbitrary extends Arbitrary {
constructor(stringArb, toggleCase, untoggleAll) {
super();
this.stringArb = stringArb;
this.toggleCase = toggleCase;
this.untoggleAll = untoggleAll;
}
buildContextFor(rawStringValue, flagsValue) {
return {
rawString: rawStringValue.value,
rawStringContext: rawStringValue.context,
flags: flagsValue.value,
flagsContext: flagsValue.context,
};
}
generate(mrng, biasFactor) {
const rawStringValue = this.stringArb.generate(mrng, biasFactor);
const chars = [...rawStringValue.value];
const togglePositions = computeTogglePositions(chars, this.toggleCase);
const flagsArb = bigUintN(togglePositions.length);
const flagsValue = flagsArb.generate(mrng, undefined);
applyFlagsOnChars(chars, flagsValue.value, togglePositions, this.toggleCase);
return new Value(safeJoin(chars, ''), this.buildContextFor(rawStringValue, flagsValue));
}
canShrinkWithoutContext(value) {
if (typeof value !== 'string') {
return false;
}
return this.untoggleAll !== undefined
? this.stringArb.canShrinkWithoutContext(this.untoggleAll(value))
:
this.stringArb.canShrinkWithoutContext(value);
}
shrink(value, context) {
let contextSafe;
if (context !== undefined) {
contextSafe = context;
}
else {
if (this.untoggleAll !== undefined) {
const untoggledValue = this.untoggleAll(value);
const valueChars = [...value];
const untoggledValueChars = [...untoggledValue];
const togglePositions = computeTogglePositions(untoggledValueChars, this.toggleCase);
contextSafe = {
rawString: untoggledValue,
rawStringContext: undefined,
flags: computeFlagsFromChars(untoggledValueChars, valueChars, togglePositions),
flagsContext: undefined,
};
}
else {
contextSafe = {
rawString: value,
rawStringContext: undefined,
flags: BigInt(0),
flagsContext: undefined,
};
}
}
const rawString = contextSafe.rawString;
const flags = contextSafe.flags;
return this.stringArb
.shrink(rawString, contextSafe.rawStringContext)
.map((nRawStringValue) => {
const nChars = [...nRawStringValue.value];
const nTogglePositions = computeTogglePositions(nChars, this.toggleCase);
const nFlags = computeNextFlags(flags, nTogglePositions.length);
applyFlagsOnChars(nChars, nFlags, nTogglePositions, this.toggleCase);
return new Value(safeJoin(nChars, ''), this.buildContextFor(nRawStringValue, new Value(nFlags, undefined)));
})
.join(makeLazy(() => {
const chars = [...rawString];
const togglePositions = computeTogglePositions(chars, this.toggleCase);
return bigUintN(togglePositions.length)
.shrink(flags, contextSafe.flagsContext)
.map((nFlagsValue) => {
const nChars = safeSlice(chars);
applyFlagsOnChars(nChars, nFlagsValue.value, togglePositions, this.toggleCase);
return new Value(safeJoin(nChars, ''), this.buildContextFor(new Value(rawString, contextSafe.rawStringContext), nFlagsValue));
});
}));
}
}

View File

@@ -0,0 +1,28 @@
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { Stream } from '../../stream/Stream.js';
import { SchedulerImplem } from './implementations/SchedulerImplem.js';
function buildNextTaskIndex(mrng) {
const clonedMrng = mrng.clone();
return {
clone: () => buildNextTaskIndex(clonedMrng),
nextTaskIndex: (scheduledTasks) => {
return mrng.nextInt(0, scheduledTasks.length - 1);
},
};
}
export class SchedulerArbitrary extends Arbitrary {
constructor(act) {
super();
this.act = act;
}
generate(mrng, _biasFactor) {
return new Value(new SchedulerImplem(this.act, buildNextTaskIndex(mrng.clone())), undefined);
}
canShrinkWithoutContext(value) {
return false;
}
shrink(_value, _context) {
return Stream.nil();
}
}

View File

@@ -0,0 +1,43 @@
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { cloneMethod } from '../../check/symbols.js';
import { Stream } from '../../stream/Stream.js';
import { safeJoin, safePush } from '../../utils/globals.js';
import { asyncStringify, asyncToStringMethod, stringify, toStringMethod } from '../../utils/stringify.js';
const safeObjectDefineProperties = Object.defineProperties;
function prettyPrint(seenValuesStrings) {
return `Stream(${safeJoin(seenValuesStrings, ',')}…)`;
}
export class StreamArbitrary extends Arbitrary {
constructor(arb) {
super();
this.arb = arb;
}
generate(mrng, biasFactor) {
const appliedBiasFactor = biasFactor !== undefined && mrng.nextInt(1, biasFactor) === 1 ? biasFactor : undefined;
const enrichedProducer = () => {
const seenValues = [];
const g = function* (arb, clonedMrng) {
while (true) {
const value = arb.generate(clonedMrng, appliedBiasFactor).value;
safePush(seenValues, value);
yield value;
}
};
const s = new Stream(g(this.arb, mrng.clone()));
return safeObjectDefineProperties(s, {
toString: { value: () => prettyPrint(seenValues.map(stringify)) },
[toStringMethod]: { value: () => prettyPrint(seenValues.map(stringify)) },
[asyncToStringMethod]: { value: async () => prettyPrint(await Promise.all(seenValues.map(asyncStringify))) },
[cloneMethod]: { value: enrichedProducer, enumerable: true },
});
};
return new Value(enrichedProducer(), undefined);
}
canShrinkWithoutContext(value) {
return false;
}
shrink(_value, _context) {
return Stream.nil();
}
}

View File

@@ -0,0 +1,42 @@
import { safeNormalize, safePush } from '../../utils/globals.js';
import { mapToConstant } from '../mapToConstant.js';
import { asciiAlphabetRanges, autonomousDecomposableGraphemeRanges, autonomousGraphemeRanges, fullAlphabetRanges, } from './data/GraphemeRanges.js';
import { convertGraphemeRangeToMapToConstantEntry, intersectGraphemeRanges } from './helpers/GraphemeRangesHelpers.js';
const registeredStringUnitInstancesMap = Object.create(null);
function getAlphabetRanges(alphabet) {
switch (alphabet) {
case 'full':
return fullAlphabetRanges;
case 'ascii':
return asciiAlphabetRanges;
}
}
function getOrCreateStringUnitInstance(type, alphabet) {
const key = `${type}:${alphabet}`;
const registered = registeredStringUnitInstancesMap[key];
if (registered !== undefined) {
return registered;
}
const alphabetRanges = getAlphabetRanges(alphabet);
const ranges = type === 'binary' ? alphabetRanges : intersectGraphemeRanges(alphabetRanges, autonomousGraphemeRanges);
const entries = [];
for (const range of ranges) {
safePush(entries, convertGraphemeRangeToMapToConstantEntry(range));
}
if (type === 'grapheme') {
const decomposedRanges = intersectGraphemeRanges(alphabetRanges, autonomousDecomposableGraphemeRanges);
for (const range of decomposedRanges) {
const rawEntry = convertGraphemeRangeToMapToConstantEntry(range);
safePush(entries, {
num: rawEntry.num,
build: (idInGroup) => safeNormalize(rawEntry.build(idInGroup), 'NFD'),
});
}
}
const stringUnitInstance = mapToConstant(...entries);
registeredStringUnitInstancesMap[key] = stringUnitInstance;
return stringUnitInstance;
}
export function stringUnit(type, alphabet) {
return getOrCreateStringUnitInstance(type, alphabet);
}

View File

@@ -0,0 +1,70 @@
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { makeLazy } from '../../stream/LazyIterableIterator.js';
import { Stream } from '../../stream/Stream.js';
import { safeMap, safePush, safeSlice, safeSort, safeSplice } from '../../utils/globals.js';
import { isSubarrayOf } from './helpers/IsSubarrayOf.js';
import { IntegerArbitrary } from './IntegerArbitrary.js';
const safeMathFloor = Math.floor;
const safeMathLog = Math.log;
const safeArrayIsArray = Array.isArray;
export class SubarrayArbitrary extends Arbitrary {
constructor(originalArray, isOrdered, minLength, maxLength) {
super();
this.originalArray = originalArray;
this.isOrdered = isOrdered;
this.minLength = minLength;
this.maxLength = maxLength;
if (minLength < 0 || minLength > originalArray.length)
throw new Error('fc.*{s|S}ubarrayOf expects the minimal length to be between 0 and the size of the original array');
if (maxLength < 0 || maxLength > originalArray.length)
throw new Error('fc.*{s|S}ubarrayOf expects the maximal length to be between 0 and the size of the original array');
if (minLength > maxLength)
throw new Error('fc.*{s|S}ubarrayOf expects the minimal length to be inferior or equal to the maximal length');
this.lengthArb = new IntegerArbitrary(minLength, maxLength);
this.biasedLengthArb =
minLength !== maxLength
? new IntegerArbitrary(minLength, minLength + safeMathFloor(safeMathLog(maxLength - minLength) / safeMathLog(2)))
: this.lengthArb;
}
generate(mrng, biasFactor) {
const lengthArb = biasFactor !== undefined && mrng.nextInt(1, biasFactor) === 1 ? this.biasedLengthArb : this.lengthArb;
const size = lengthArb.generate(mrng, undefined);
const sizeValue = size.value;
const remainingElements = safeMap(this.originalArray, (_v, idx) => idx);
const ids = [];
for (let index = 0; index !== sizeValue; ++index) {
const selectedIdIndex = mrng.nextInt(0, remainingElements.length - 1);
safePush(ids, remainingElements[selectedIdIndex]);
safeSplice(remainingElements, selectedIdIndex, 1);
}
if (this.isOrdered) {
safeSort(ids, (a, b) => a - b);
}
return new Value(safeMap(ids, (i) => this.originalArray[i]), size.context);
}
canShrinkWithoutContext(value) {
if (!safeArrayIsArray(value)) {
return false;
}
if (!this.lengthArb.canShrinkWithoutContext(value.length)) {
return false;
}
return isSubarrayOf(this.originalArray, value);
}
shrink(value, context) {
if (value.length === 0) {
return Stream.nil();
}
return this.lengthArb
.shrink(value.length, context)
.map((newSize) => {
return new Value(safeSlice(value, value.length - newSize.value), newSize.context);
})
.join(value.length > this.minLength
? makeLazy(() => this.shrink(safeSlice(value, 1), undefined)
.filter((newValue) => this.minLength <= newValue.value.length + 1)
.map((newValue) => new Value([value[0], ...newValue.value], undefined)))
: Stream.nil());
}
}

View File

@@ -0,0 +1,81 @@
import { Stream } from '../../stream/Stream.js';
import { cloneIfNeeded, cloneMethod } from '../../check/symbols.js';
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
import { safeMap, safePush, safeSlice } from '../../utils/globals.js';
import { makeLazy } from '../../stream/LazyIterableIterator.js';
const safeArrayIsArray = Array.isArray;
const safeObjectDefineProperty = Object.defineProperty;
function tupleMakeItCloneable(vs, values) {
return safeObjectDefineProperty(vs, cloneMethod, {
value: () => {
const cloned = [];
for (let idx = 0; idx !== values.length; ++idx) {
safePush(cloned, values[idx].value);
}
tupleMakeItCloneable(cloned, values);
return cloned;
},
});
}
function tupleWrapper(values) {
let cloneable = false;
const vs = [];
const ctxs = [];
for (let idx = 0; idx !== values.length; ++idx) {
const v = values[idx];
cloneable = cloneable || v.hasToBeCloned;
safePush(vs, v.value);
safePush(ctxs, v.context);
}
if (cloneable) {
tupleMakeItCloneable(vs, values);
}
return new Value(vs, ctxs);
}
export function tupleShrink(arbs, value, context) {
const shrinks = [];
const safeContext = safeArrayIsArray(context) ? context : [];
for (let idx = 0; idx !== arbs.length; ++idx) {
safePush(shrinks, makeLazy(() => arbs[idx]
.shrink(value[idx], safeContext[idx])
.map((v) => {
const nextValues = safeMap(value, (v, idx) => new Value(cloneIfNeeded(v), safeContext[idx]));
return [...safeSlice(nextValues, 0, idx), v, ...safeSlice(nextValues, idx + 1)];
})
.map(tupleWrapper)));
}
return Stream.nil().join(...shrinks);
}
export class TupleArbitrary extends Arbitrary {
constructor(arbs) {
super();
this.arbs = arbs;
for (let idx = 0; idx !== arbs.length; ++idx) {
const arb = arbs[idx];
if (arb == null || arb.generate == null)
throw new Error(`Invalid parameter encountered at index ${idx}: expecting an Arbitrary`);
}
}
generate(mrng, biasFactor) {
const mapped = [];
for (let idx = 0; idx !== this.arbs.length; ++idx) {
safePush(mapped, this.arbs[idx].generate(mrng, biasFactor));
}
return tupleWrapper(mapped);
}
canShrinkWithoutContext(value) {
if (!safeArrayIsArray(value) || value.length !== this.arbs.length) {
return false;
}
for (let index = 0; index !== this.arbs.length; ++index) {
if (!this.arbs[index].canShrinkWithoutContext(value[index])) {
return false;
}
}
return true;
}
shrink(value, context) {
return tupleShrink(this.arbs, value, context);
}
}

View File

@@ -0,0 +1,39 @@
import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js';
import { Value } from '../../check/arbitrary/definition/Value.js';
function isSafeContext(context) {
return context !== undefined;
}
function toGeneratorValue(value) {
if (value.hasToBeCloned) {
return new Value(value.value_, { generatorContext: value.context }, () => value.value);
}
return new Value(value.value_, { generatorContext: value.context });
}
function toShrinkerValue(value) {
if (value.hasToBeCloned) {
return new Value(value.value_, { shrinkerContext: value.context }, () => value.value);
}
return new Value(value.value_, { shrinkerContext: value.context });
}
export class WithShrinkFromOtherArbitrary extends Arbitrary {
constructor(generatorArbitrary, shrinkerArbitrary) {
super();
this.generatorArbitrary = generatorArbitrary;
this.shrinkerArbitrary = shrinkerArbitrary;
}
generate(mrng, biasFactor) {
return toGeneratorValue(this.generatorArbitrary.generate(mrng, biasFactor));
}
canShrinkWithoutContext(value) {
return this.shrinkerArbitrary.canShrinkWithoutContext(value);
}
shrink(value, context) {
if (!isSafeContext(context)) {
return this.shrinkerArbitrary.shrink(value, undefined).map(toShrinkerValue);
}
if ('generatorContext' in context) {
return this.generatorArbitrary.shrink(value, context.generatorContext).map(toGeneratorValue);
}
return this.shrinkerArbitrary.shrink(value, context.shrinkerContext).map(toShrinkerValue);
}
}

View File

@@ -0,0 +1,66 @@
import { stringify } from '../../../utils/stringify.js';
import { array } from '../../array.js';
import { oneof } from '../../oneof.js';
import { tuple } from '../../tuple.js';
import { bigInt } from '../../bigInt.js';
import { date } from '../../date.js';
import { float32Array } from '../../float32Array.js';
import { float64Array } from '../../float64Array.js';
import { int16Array } from '../../int16Array.js';
import { int32Array } from '../../int32Array.js';
import { int8Array } from '../../int8Array.js';
import { uint16Array } from '../../uint16Array.js';
import { uint32Array } from '../../uint32Array.js';
import { uint8Array } from '../../uint8Array.js';
import { uint8ClampedArray } from '../../uint8ClampedArray.js';
import { sparseArray } from '../../sparseArray.js';
import { arrayToMapMapper, arrayToMapUnmapper } from '../mappers/ArrayToMap.js';
import { arrayToSetMapper, arrayToSetUnmapper } from '../mappers/ArrayToSet.js';
import { letrec } from '../../letrec.js';
import { uniqueArray } from '../../uniqueArray.js';
import { createDepthIdentifier } from '../helpers/DepthContext.js';
import { dictionary } from '../../dictionary.js';
function mapOf(ka, va, maxKeys, size, depthIdentifier) {
return uniqueArray(tuple(ka, va), {
maxLength: maxKeys,
size,
comparator: 'SameValueZero',
selector: (t) => t[0],
depthIdentifier,
}).map(arrayToMapMapper, arrayToMapUnmapper);
}
function dictOf(ka, va, maxKeys, size, depthIdentifier, withNullPrototype) {
return dictionary(ka, va, {
maxKeys,
noNullPrototype: !withNullPrototype,
size,
depthIdentifier,
});
}
function setOf(va, maxKeys, size, depthIdentifier) {
return uniqueArray(va, { maxLength: maxKeys, size, comparator: 'SameValueZero', depthIdentifier }).map(arrayToSetMapper, arrayToSetUnmapper);
}
function typedArray(constraints) {
return oneof(int8Array(constraints), uint8Array(constraints), uint8ClampedArray(constraints), int16Array(constraints), uint16Array(constraints), int32Array(constraints), uint32Array(constraints), float32Array(constraints), float64Array(constraints));
}
export function anyArbitraryBuilder(constraints) {
const arbitrariesForBase = constraints.values;
const depthSize = constraints.depthSize;
const depthIdentifier = createDepthIdentifier();
const maxDepth = constraints.maxDepth;
const maxKeys = constraints.maxKeys;
const size = constraints.size;
const baseArb = oneof(...arbitrariesForBase, ...(constraints.withBigInt ? [bigInt()] : []), ...(constraints.withDate ? [date()] : []));
return letrec((tie) => ({
anything: oneof({ maxDepth, depthSize, depthIdentifier }, baseArb, tie('array'), tie('object'), ...(constraints.withMap ? [tie('map')] : []), ...(constraints.withSet ? [tie('set')] : []), ...(constraints.withObjectString ? [tie('anything').map((o) => stringify(o))] : []), ...(constraints.withTypedArray ? [typedArray({ maxLength: maxKeys, size })] : []), ...(constraints.withSparseArray
? [sparseArray(tie('anything'), { maxNumElements: maxKeys, size, depthIdentifier })]
: [])),
keys: constraints.withObjectString
? oneof({ arbitrary: constraints.key, weight: 10 }, { arbitrary: tie('anything').map((o) => stringify(o)), weight: 1 })
: constraints.key,
array: array(tie('anything'), { maxLength: maxKeys, size, depthIdentifier }),
set: setOf(tie('anything'), maxKeys, size, depthIdentifier),
map: oneof(mapOf(tie('keys'), tie('anything'), maxKeys, size, depthIdentifier), mapOf(tie('anything'), tie('anything'), maxKeys, size, depthIdentifier)),
object: dictOf(tie('keys'), tie('anything'), maxKeys, size, depthIdentifier, constraints.withNullPrototype),
})).anything;
}

View File

@@ -0,0 +1,4 @@
import { unboxedToBoxedMapper, unboxedToBoxedUnmapper } from '../mappers/UnboxedToBoxed.js';
export function boxedArbitraryBuilder(arb) {
return arb.map(unboxedToBoxedMapper, unboxedToBoxedUnmapper);
}

View File

@@ -0,0 +1,5 @@
import { integer } from '../../integer.js';
import { indexToCharStringMapper, indexToCharStringUnmapper } from '../mappers/IndexToCharString.js';
export function buildCharacterArbitrary(min, max, mapToCode, unmapFromCode) {
return integer({ min, max }).map((n) => indexToCharStringMapper(mapToCode(n)), (c) => unmapFromCode(indexToCharStringUnmapper(c)));
}

View File

@@ -0,0 +1,61 @@
import { fullUnicode } from '../../fullUnicode.js';
import { oneof } from '../../oneof.js';
import { mapToConstant } from '../../mapToConstant.js';
import { safeCharCodeAt, safeNumberToString, encodeURIComponent, safeMapGet, safeMapSet } from '../../../utils/globals.js';
const SMap = Map;
const safeStringFromCharCode = String.fromCharCode;
const lowerCaseMapper = { num: 26, build: (v) => safeStringFromCharCode(v + 0x61) };
const upperCaseMapper = { num: 26, build: (v) => safeStringFromCharCode(v + 0x41) };
const numericMapper = { num: 10, build: (v) => safeStringFromCharCode(v + 0x30) };
function percentCharArbMapper(c) {
const encoded = encodeURIComponent(c);
return c !== encoded ? encoded : `%${safeNumberToString(safeCharCodeAt(c, 0), 16)}`;
}
function percentCharArbUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Unsupported');
}
const decoded = decodeURIComponent(value);
return decoded;
}
const percentCharArb = fullUnicode().map(percentCharArbMapper, percentCharArbUnmapper);
let lowerAlphaArbitrary = undefined;
export function getOrCreateLowerAlphaArbitrary() {
if (lowerAlphaArbitrary === undefined) {
lowerAlphaArbitrary = mapToConstant(lowerCaseMapper);
}
return lowerAlphaArbitrary;
}
let lowerAlphaNumericArbitraries = undefined;
export function getOrCreateLowerAlphaNumericArbitrary(others) {
if (lowerAlphaNumericArbitraries === undefined) {
lowerAlphaNumericArbitraries = new SMap();
}
let match = safeMapGet(lowerAlphaNumericArbitraries, others);
if (match === undefined) {
match = mapToConstant(lowerCaseMapper, numericMapper, {
num: others.length,
build: (v) => others[v],
});
safeMapSet(lowerAlphaNumericArbitraries, others, match);
}
return match;
}
function buildAlphaNumericArbitrary(others) {
return mapToConstant(lowerCaseMapper, upperCaseMapper, numericMapper, {
num: others.length,
build: (v) => others[v],
});
}
let alphaNumericPercentArbitraries = undefined;
export function getOrCreateAlphaNumericPercentArbitrary(others) {
if (alphaNumericPercentArbitraries === undefined) {
alphaNumericPercentArbitraries = new SMap();
}
let match = safeMapGet(alphaNumericPercentArbitraries, others);
if (match === undefined) {
match = oneof({ weight: 10, arbitrary: buildAlphaNumericArbitrary(others) }, { weight: 1, arbitrary: percentCharArb });
safeMapSet(alphaNumericPercentArbitraries, others, match);
}
return match;
}

View File

@@ -0,0 +1,43 @@
import { escapeForMultilineComments } from '../helpers/TextEscaper.js';
import { cloneMethod } from '../../../check/symbols.js';
import { hash } from '../../../utils/hash.js';
import { stringify } from '../../../utils/stringify.js';
import { integer } from '../../integer.js';
import { noShrink } from '../../noShrink.js';
import { tuple } from '../../tuple.js';
import { safeJoin } from '../../../utils/globals.js';
const safeObjectAssign = Object.assign;
const safeObjectKeys = Object.keys;
export function buildCompareFunctionArbitrary(cmp) {
return tuple(noShrink(integer()), noShrink(integer({ min: 1, max: 0xffffffff }))).map(([seed, hashEnvSize]) => {
const producer = () => {
const recorded = {};
const f = (a, b) => {
const reprA = stringify(a);
const reprB = stringify(b);
const hA = hash(`${seed}${reprA}`) % hashEnvSize;
const hB = hash(`${seed}${reprB}`) % hashEnvSize;
const val = cmp(hA, hB);
recorded[`[${reprA},${reprB}]`] = val;
return val;
};
return safeObjectAssign(f, {
toString: () => {
const seenValues = safeObjectKeys(recorded)
.sort()
.map((k) => `${k} => ${stringify(recorded[k])}`)
.map((line) => `/* ${escapeForMultilineComments(line)} */`);
return `function(a, b) {
// With hash and stringify coming from fast-check${seenValues.length !== 0 ? `\n ${safeJoin(seenValues, '\n ')}` : ''}
const cmp = ${cmp};
const hA = hash('${seed}' + stringify(a)) % ${hashEnvSize};
const hB = hash('${seed}' + stringify(b)) % ${hashEnvSize};
return cmp(hA, hB);
}`;
},
[cloneMethod]: producer,
});
};
return producer();
});
}

View File

@@ -0,0 +1,38 @@
import { Value } from '../../../check/arbitrary/definition/Value.js';
import { cloneMethod } from '../../../check/symbols.js';
import { safeMap, safePush } from '../../../utils/globals.js';
import { stringify, toStringMethod } from '../../../utils/stringify.js';
const safeObjectAssign = Object.assign;
export function buildGeneratorValue(mrng, biasFactor, computePreBuiltValues, arbitraryCache) {
const preBuiltValues = computePreBuiltValues();
let localMrng = mrng.clone();
const context = { mrng: mrng.clone(), biasFactor, history: [] };
const valueFunction = (arb) => {
const preBuiltValue = preBuiltValues[context.history.length];
if (preBuiltValue !== undefined && preBuiltValue.arb === arb) {
const value = preBuiltValue.value;
safePush(context.history, { arb, value, context: preBuiltValue.context, mrng: preBuiltValue.mrng });
localMrng = preBuiltValue.mrng.clone();
return value;
}
const g = arb.generate(localMrng, biasFactor);
safePush(context.history, { arb, value: g.value_, context: g.context, mrng: localMrng.clone() });
return g.value;
};
const memoedValueFunction = (arb, ...args) => {
return valueFunction(arbitraryCache(arb, args));
};
const valueMethods = {
values() {
return safeMap(context.history, (c) => c.value);
},
[cloneMethod]() {
return buildGeneratorValue(mrng, biasFactor, computePreBuiltValues, arbitraryCache).value;
},
[toStringMethod]() {
return stringify(safeMap(context.history, (c) => c.value));
},
};
const value = safeObjectAssign(memoedValueFunction, valueMethods);
return new Value(value, context);
}

View File

@@ -0,0 +1,5 @@
import { integer } from '../../integer.js';
import { numberToPaddedEightMapper, numberToPaddedEightUnmapper } from '../mappers/NumberToPaddedEight.js';
export function buildPaddedNumberArbitrary(min, max) {
return integer({ min, max }).map(numberToPaddedEightMapper, numberToPaddedEightUnmapper);
}

View File

@@ -0,0 +1,23 @@
import { safeIndexOf, safePush } from '../../../utils/globals.js';
import { boolean } from '../../boolean.js';
import { constant } from '../../constant.js';
import { option } from '../../option.js';
import { tuple } from '../../tuple.js';
import { extractEnumerableKeys } from '../helpers/EnumerableKeysExtractor.js';
import { buildValuesAndSeparateKeysToObjectMapper, buildValuesAndSeparateKeysToObjectUnmapper, } from '../mappers/ValuesAndSeparateKeysToObject.js';
const noKeyValue = Symbol('no-key');
export function buildPartialRecordArbitrary(recordModel, requiredKeys, noNullPrototype) {
const keys = extractEnumerableKeys(recordModel);
const arbs = [];
for (let index = 0; index !== keys.length; ++index) {
const k = keys[index];
const requiredArbitrary = recordModel[k];
if (requiredKeys === undefined || safeIndexOf(requiredKeys, k) !== -1) {
safePush(arbs, requiredArbitrary);
}
else {
safePush(arbs, option(requiredArbitrary, { nil: noKeyValue }));
}
}
return tuple(tuple(...arbs), noNullPrototype ? constant(false) : boolean()).map(buildValuesAndSeparateKeysToObjectMapper(keys, noKeyValue), buildValuesAndSeparateKeysToObjectUnmapper(keys, noKeyValue));
}

View File

@@ -0,0 +1,10 @@
import { integer } from '../../integer.js';
import { WithShrinkFromOtherArbitrary } from '../WithShrinkFromOtherArbitrary.js';
export function restrictedIntegerArbitraryBuilder(min, maxGenerated, max) {
const generatorArbitrary = integer({ min, max: maxGenerated });
if (maxGenerated === max) {
return generatorArbitrary;
}
const shrinkerArbitrary = integer({ min, max });
return new WithShrinkFromOtherArbitrary(generatorArbitrary, shrinkerArbitrary);
}

View File

@@ -0,0 +1,52 @@
import { Map, safeMapGet, safeMapSet, safePush } from '../../../utils/globals.js';
const safeArrayIsArray = Array.isArray;
const safeObjectKeys = Object.keys;
const safeObjectIs = Object.is;
export function buildStableArbitraryGeneratorCache(isEqual) {
const previousCallsPerBuilder = new Map();
return function stableArbitraryGeneratorCache(builder, args) {
const entriesForBuilder = safeMapGet(previousCallsPerBuilder, builder);
if (entriesForBuilder === undefined) {
const newValue = builder(...args);
safeMapSet(previousCallsPerBuilder, builder, [{ args, value: newValue }]);
return newValue;
}
const safeEntriesForBuilder = entriesForBuilder;
for (const entry of safeEntriesForBuilder) {
if (isEqual(args, entry.args)) {
return entry.value;
}
}
const newValue = builder(...args);
safePush(safeEntriesForBuilder, { args, value: newValue });
return newValue;
};
}
export function naiveIsEqual(v1, v2) {
if (v1 !== null && typeof v1 === 'object' && v2 !== null && typeof v2 === 'object') {
if (safeArrayIsArray(v1)) {
if (!safeArrayIsArray(v2))
return false;
if (v1.length !== v2.length)
return false;
}
else if (safeArrayIsArray(v2)) {
return false;
}
if (safeObjectKeys(v1).length !== safeObjectKeys(v2).length) {
return false;
}
for (const index in v1) {
if (!(index in v2)) {
return false;
}
if (!naiveIsEqual(v1[index], v2[index])) {
return false;
}
}
return true;
}
else {
return safeObjectIs(v1, v2);
}
}

View File

@@ -0,0 +1,7 @@
import { constantFrom } from '../../constantFrom.js';
import { nat } from '../../nat.js';
import { tuple } from '../../tuple.js';
import { natToStringifiedNatMapper, natToStringifiedNatUnmapper } from '../mappers/NatToStringifiedNat.js';
export function buildStringifiedNatArbitrary(maxValue) {
return tuple(constantFrom('dec', 'oct', 'hex'), nat(maxValue)).map(natToStringifiedNatMapper, natToStringifiedNatUnmapper);
}

View File

@@ -0,0 +1,30 @@
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { array } from '../../array.js';
export function typedIntArrayArbitraryArbitraryBuilder(constraints, defaultMin, defaultMax, TypedArrayClass, arbitraryBuilder) {
const generatorName = TypedArrayClass.name;
const { min = defaultMin, max = defaultMax } = constraints, arrayConstraints = __rest(constraints, ["min", "max"]);
if (min > max) {
throw new Error(`Invalid range passed to ${generatorName}: min must be lower than or equal to max`);
}
if (min < defaultMin) {
throw new Error(`Invalid min value passed to ${generatorName}: min must be greater than or equal to ${defaultMin}`);
}
if (max > defaultMax) {
throw new Error(`Invalid max value passed to ${generatorName}: max must be lower than or equal to ${defaultMax}`);
}
return array(arbitraryBuilder({ min, max }), arrayConstraints).map((data) => TypedArrayClass.from(data), (value) => {
if (!(value instanceof TypedArrayClass))
throw new Error('Invalid type');
return [...value];
});
}

View File

@@ -0,0 +1,28 @@
import { webSegment } from '../../webSegment.js';
import { array } from '../../array.js';
import { segmentsToPathMapper, segmentsToPathUnmapper } from '../mappers/SegmentsToPath.js';
import { oneof } from '../../oneof.js';
function sqrtSize(size) {
switch (size) {
case 'xsmall':
return ['xsmall', 'xsmall'];
case 'small':
return ['small', 'xsmall'];
case 'medium':
return ['small', 'small'];
case 'large':
return ['medium', 'small'];
case 'xlarge':
return ['medium', 'medium'];
}
}
function buildUriPathArbitraryInternal(segmentSize, numSegmentSize) {
return array(webSegment({ size: segmentSize }), { size: numSegmentSize }).map(segmentsToPathMapper, segmentsToPathUnmapper);
}
export function buildUriPathArbitrary(resolvedSize) {
const [segmentSize, numSegmentSize] = sqrtSize(resolvedSize);
if (segmentSize === numSegmentSize) {
return buildUriPathArbitraryInternal(segmentSize, numSegmentSize);
}
return oneof(buildUriPathArbitraryInternal(segmentSize, numSegmentSize), buildUriPathArbitraryInternal(numSegmentSize, segmentSize));
}

View File

@@ -0,0 +1,5 @@
import { getOrCreateAlphaNumericPercentArbitrary } from './CharacterRangeArbitraryBuilder.js';
import { string } from '../../string.js';
export function buildUriQueryOrFragmentArbitrary(size) {
return string({ unit: getOrCreateAlphaNumericPercentArbitrary("-._~!$&'()*+,;=:@/?"), size });
}

View File

@@ -0,0 +1,985 @@
export const asciiAlphabetRanges = [[0x00, 0x7f]];
export const fullAlphabetRanges = [
[0x0000, 0xd7ff],
[0xe000, 0x10ffff],
];
export const autonomousGraphemeRanges = [
[0x20, 0x7e],
[0xa0, 0xac],
[0xae, 0x2ff],
[0x370, 0x377],
[0x37a, 0x37f],
[0x384, 0x38a],
[0x38c],
[0x38e, 0x3a1],
[0x3a3, 0x482],
[0x48a, 0x52f],
[0x531, 0x556],
[0x559, 0x58a],
[0x58d, 0x58f],
[0x5be],
[0x5c0],
[0x5c3],
[0x5c6],
[0x5d0, 0x5ea],
[0x5ef, 0x5f4],
[0x606, 0x60f],
[0x61b],
[0x61d, 0x64a],
[0x660, 0x66f],
[0x671, 0x6d5],
[0x6de],
[0x6e5, 0x6e6],
[0x6e9],
[0x6ee, 0x70d],
[0x710],
[0x712, 0x72f],
[0x74d, 0x7a5],
[0x7b1],
[0x7c0, 0x7ea],
[0x7f4, 0x7fa],
[0x7fe, 0x815],
[0x81a],
[0x824],
[0x828],
[0x830, 0x83e],
[0x840, 0x858],
[0x85e],
[0x860, 0x86a],
[0x870, 0x88e],
[0x8a0, 0x8c9],
[0x904, 0x939],
[0x93d],
[0x950],
[0x958, 0x961],
[0x964, 0x980],
[0x985, 0x98c],
[0x98f, 0x990],
[0x993, 0x9a8],
[0x9aa, 0x9b0],
[0x9b2],
[0x9b6, 0x9b9],
[0x9bd],
[0x9ce],
[0x9dc, 0x9dd],
[0x9df, 0x9e1],
[0x9e6, 0x9fd],
[0xa05, 0xa0a],
[0xa0f, 0xa10],
[0xa13, 0xa28],
[0xa2a, 0xa30],
[0xa32, 0xa33],
[0xa35, 0xa36],
[0xa38, 0xa39],
[0xa59, 0xa5c],
[0xa5e],
[0xa66, 0xa6f],
[0xa72, 0xa74],
[0xa76],
[0xa85, 0xa8d],
[0xa8f, 0xa91],
[0xa93, 0xaa8],
[0xaaa, 0xab0],
[0xab2, 0xab3],
[0xab5, 0xab9],
[0xabd],
[0xad0],
[0xae0, 0xae1],
[0xae6, 0xaf1],
[0xaf9],
[0xb05, 0xb0c],
[0xb0f, 0xb10],
[0xb13, 0xb28],
[0xb2a, 0xb30],
[0xb32, 0xb33],
[0xb35, 0xb39],
[0xb3d],
[0xb5c, 0xb5d],
[0xb5f, 0xb61],
[0xb66, 0xb77],
[0xb83],
[0xb85, 0xb8a],
[0xb8e, 0xb90],
[0xb92, 0xb95],
[0xb99, 0xb9a],
[0xb9c],
[0xb9e, 0xb9f],
[0xba3, 0xba4],
[0xba8, 0xbaa],
[0xbae, 0xbb9],
[0xbd0],
[0xbe6, 0xbfa],
[0xc05, 0xc0c],
[0xc0e, 0xc10],
[0xc12, 0xc28],
[0xc2a, 0xc39],
[0xc3d],
[0xc58, 0xc5a],
[0xc5d],
[0xc60, 0xc61],
[0xc66, 0xc6f],
[0xc77, 0xc80],
[0xc84, 0xc8c],
[0xc8e, 0xc90],
[0xc92, 0xca8],
[0xcaa, 0xcb3],
[0xcb5, 0xcb9],
[0xcbd],
[0xcdd, 0xcde],
[0xce0, 0xce1],
[0xce6, 0xcef],
[0xcf1, 0xcf2],
[0xd04, 0xd0c],
[0xd0e, 0xd10],
[0xd12, 0xd3a],
[0xd3d],
[0xd4f],
[0xd54, 0xd56],
[0xd58, 0xd61],
[0xd66, 0xd7f],
[0xd85, 0xd96],
[0xd9a, 0xdb1],
[0xdb3, 0xdbb],
[0xdbd],
[0xdc0, 0xdc6],
[0xde6, 0xdef],
[0xdf4],
[0xe01, 0xe30],
[0xe32],
[0xe3f, 0xe46],
[0xe4f, 0xe5b],
[0xe81, 0xe82],
[0xe84],
[0xe86, 0xe8a],
[0xe8c, 0xea3],
[0xea5],
[0xea7, 0xeb0],
[0xeb2],
[0xebd],
[0xec0, 0xec4],
[0xec6],
[0xed0, 0xed9],
[0xedc, 0xedf],
[0xf00, 0xf17],
[0xf1a, 0xf34],
[0xf36],
[0xf38],
[0xf3a, 0xf3d],
[0xf40, 0xf47],
[0xf49, 0xf6c],
[0xf85],
[0xf88, 0xf8c],
[0xfbe, 0xfc5],
[0xfc7, 0xfcc],
[0xfce, 0xfda],
[0x1000, 0x102a],
[0x103f, 0x1055],
[0x105a, 0x105d],
[0x1061],
[0x1065, 0x1066],
[0x106e, 0x1070],
[0x1075, 0x1081],
[0x108e],
[0x1090, 0x1099],
[0x109e, 0x10c5],
[0x10c7],
[0x10cd],
[0x10d0, 0x10ff],
[0x1200, 0x1248],
[0x124a, 0x124d],
[0x1250, 0x1256],
[0x1258],
[0x125a, 0x125d],
[0x1260, 0x1288],
[0x128a, 0x128d],
[0x1290, 0x12b0],
[0x12b2, 0x12b5],
[0x12b8, 0x12be],
[0x12c0],
[0x12c2, 0x12c5],
[0x12c8, 0x12d6],
[0x12d8, 0x1310],
[0x1312, 0x1315],
[0x1318, 0x135a],
[0x1360, 0x137c],
[0x1380, 0x1399],
[0x13a0, 0x13f5],
[0x13f8, 0x13fd],
[0x1400, 0x169c],
[0x16a0, 0x16f8],
[0x1700, 0x1711],
[0x171f, 0x1731],
[0x1735, 0x1736],
[0x1740, 0x1751],
[0x1760, 0x176c],
[0x176e, 0x1770],
[0x1780, 0x17b3],
[0x17d4, 0x17dc],
[0x17e0, 0x17e9],
[0x17f0, 0x17f9],
[0x1800, 0x180a],
[0x1810, 0x1819],
[0x1820, 0x1878],
[0x1880, 0x1884],
[0x1887, 0x18a8],
[0x18aa],
[0x18b0, 0x18f5],
[0x1900, 0x191e],
[0x1940],
[0x1944, 0x196d],
[0x1970, 0x1974],
[0x1980, 0x19ab],
[0x19b0, 0x19c9],
[0x19d0, 0x19da],
[0x19de, 0x1a16],
[0x1a1e, 0x1a54],
[0x1a80, 0x1a89],
[0x1a90, 0x1a99],
[0x1aa0, 0x1aad],
[0x1b05, 0x1b33],
[0x1b45, 0x1b4c],
[0x1b50, 0x1b6a],
[0x1b74, 0x1b7e],
[0x1b83, 0x1ba0],
[0x1bae, 0x1be5],
[0x1bfc, 0x1c23],
[0x1c3b, 0x1c49],
[0x1c4d, 0x1c88],
[0x1c90, 0x1cba],
[0x1cbd, 0x1cc7],
[0x1cd3],
[0x1ce9, 0x1cec],
[0x1cee, 0x1cf3],
[0x1cf5, 0x1cf6],
[0x1cfa],
[0x1d00, 0x1dbf],
[0x1e00, 0x1f15],
[0x1f18, 0x1f1d],
[0x1f20, 0x1f45],
[0x1f48, 0x1f4d],
[0x1f50, 0x1f57],
[0x1f59],
[0x1f5b],
[0x1f5d],
[0x1f5f, 0x1f7d],
[0x1f80, 0x1fb4],
[0x1fb6, 0x1fc4],
[0x1fc6, 0x1fd3],
[0x1fd6, 0x1fdb],
[0x1fdd, 0x1fef],
[0x1ff2, 0x1ff4],
[0x1ff6, 0x1ffe],
[0x2000, 0x200a],
[0x2010, 0x2029],
[0x202f, 0x205f],
[0x2070, 0x2071],
[0x2074, 0x208e],
[0x2090, 0x209c],
[0x20a0, 0x20c0],
[0x2100, 0x218b],
[0x2190, 0x2426],
[0x2440, 0x244a],
[0x2460, 0x2b73],
[0x2b76, 0x2b95],
[0x2b97, 0x2cee],
[0x2cf2, 0x2cf3],
[0x2cf9, 0x2d25],
[0x2d27],
[0x2d2d],
[0x2d30, 0x2d67],
[0x2d6f, 0x2d70],
[0x2d80, 0x2d96],
[0x2da0, 0x2da6],
[0x2da8, 0x2dae],
[0x2db0, 0x2db6],
[0x2db8, 0x2dbe],
[0x2dc0, 0x2dc6],
[0x2dc8, 0x2dce],
[0x2dd0, 0x2dd6],
[0x2dd8, 0x2dde],
[0x2e00, 0x2e5d],
[0x2e80, 0x2e99],
[0x2e9b, 0x2ef3],
[0x2f00, 0x2fd5],
[0x2ff0, 0x3029],
[0x3030, 0x303f],
[0x3041, 0x3096],
[0x309b, 0x30ff],
[0x3105, 0x312f],
[0x3131, 0x318e],
[0x3190, 0x31e3],
[0x31ef, 0x321e],
[0x3220, 0x3400],
[0x4dbf, 0x4e00],
[0x9fff, 0xa48c],
[0xa490, 0xa4c6],
[0xa4d0, 0xa62b],
[0xa640, 0xa66e],
[0xa673],
[0xa67e, 0xa69d],
[0xa6a0, 0xa6ef],
[0xa6f2, 0xa6f7],
[0xa700, 0xa7ca],
[0xa7d0, 0xa7d1],
[0xa7d3],
[0xa7d5, 0xa7d9],
[0xa7f2, 0xa801],
[0xa803, 0xa805],
[0xa807, 0xa80a],
[0xa80c, 0xa822],
[0xa828, 0xa82b],
[0xa830, 0xa839],
[0xa840, 0xa877],
[0xa882, 0xa8b3],
[0xa8ce, 0xa8d9],
[0xa8f2, 0xa8fe],
[0xa900, 0xa925],
[0xa92e, 0xa946],
[0xa95f],
[0xa984, 0xa9b2],
[0xa9c1, 0xa9cd],
[0xa9cf, 0xa9d9],
[0xa9de, 0xa9e4],
[0xa9e6, 0xa9fe],
[0xaa00, 0xaa28],
[0xaa40, 0xaa42],
[0xaa44, 0xaa4b],
[0xaa50, 0xaa59],
[0xaa5c, 0xaa7a],
[0xaa7e, 0xaaaf],
[0xaab1],
[0xaab5, 0xaab6],
[0xaab9, 0xaabd],
[0xaac0],
[0xaac2],
[0xaadb, 0xaaea],
[0xaaf0, 0xaaf4],
[0xab01, 0xab06],
[0xab09, 0xab0e],
[0xab11, 0xab16],
[0xab20, 0xab26],
[0xab28, 0xab2e],
[0xab30, 0xab6b],
[0xab70, 0xabe2],
[0xabeb],
[0xabf0, 0xabf9],
[0xac00],
[0xd7a3],
[0xf900, 0xfa6d],
[0xfa70, 0xfad9],
[0xfb00, 0xfb06],
[0xfb13, 0xfb17],
[0xfb1d],
[0xfb1f, 0xfb36],
[0xfb38, 0xfb3c],
[0xfb3e],
[0xfb40, 0xfb41],
[0xfb43, 0xfb44],
[0xfb46, 0xfbc2],
[0xfbd3, 0xfd8f],
[0xfd92, 0xfdc7],
[0xfdcf],
[0xfdf0, 0xfdff],
[0xfe10, 0xfe19],
[0xfe30, 0xfe52],
[0xfe54, 0xfe66],
[0xfe68, 0xfe6b],
[0xfe70, 0xfe74],
[0xfe76, 0xfefc],
[0xff01, 0xff9d],
[0xffa0, 0xffbe],
[0xffc2, 0xffc7],
[0xffca, 0xffcf],
[0xffd2, 0xffd7],
[0xffda, 0xffdc],
[0xffe0, 0xffe6],
[0xffe8, 0xffee],
[0xfffc, 0xfffd],
[0x10000, 0x1000b],
[0x1000d, 0x10026],
[0x10028, 0x1003a],
[0x1003c, 0x1003d],
[0x1003f, 0x1004d],
[0x10050, 0x1005d],
[0x10080, 0x100fa],
[0x10100, 0x10102],
[0x10107, 0x10133],
[0x10137, 0x1018e],
[0x10190, 0x1019c],
[0x101a0],
[0x101d0, 0x101fc],
[0x10280, 0x1029c],
[0x102a0, 0x102d0],
[0x102e1, 0x102fb],
[0x10300, 0x10323],
[0x1032d, 0x1034a],
[0x10350, 0x10375],
[0x10380, 0x1039d],
[0x1039f, 0x103c3],
[0x103c8, 0x103d5],
[0x10400, 0x1049d],
[0x104a0, 0x104a9],
[0x104b0, 0x104d3],
[0x104d8, 0x104fb],
[0x10500, 0x10527],
[0x10530, 0x10563],
[0x1056f, 0x1057a],
[0x1057c, 0x1058a],
[0x1058c, 0x10592],
[0x10594, 0x10595],
[0x10597, 0x105a1],
[0x105a3, 0x105b1],
[0x105b3, 0x105b9],
[0x105bb, 0x105bc],
[0x10600, 0x10736],
[0x10740, 0x10755],
[0x10760, 0x10767],
[0x10780, 0x10785],
[0x10787, 0x107b0],
[0x107b2, 0x107ba],
[0x10800, 0x10805],
[0x10808],
[0x1080a, 0x10835],
[0x10837, 0x10838],
[0x1083c],
[0x1083f, 0x10855],
[0x10857, 0x1089e],
[0x108a7, 0x108af],
[0x108e0, 0x108f2],
[0x108f4, 0x108f5],
[0x108fb, 0x1091b],
[0x1091f, 0x10939],
[0x1093f],
[0x10980, 0x109b7],
[0x109bc, 0x109cf],
[0x109d2, 0x10a00],
[0x10a10, 0x10a13],
[0x10a15, 0x10a17],
[0x10a19, 0x10a35],
[0x10a40, 0x10a48],
[0x10a50, 0x10a58],
[0x10a60, 0x10a9f],
[0x10ac0, 0x10ae4],
[0x10aeb, 0x10af6],
[0x10b00, 0x10b35],
[0x10b39, 0x10b55],
[0x10b58, 0x10b72],
[0x10b78, 0x10b91],
[0x10b99, 0x10b9c],
[0x10ba9, 0x10baf],
[0x10c00, 0x10c48],
[0x10c80, 0x10cb2],
[0x10cc0, 0x10cf2],
[0x10cfa, 0x10d23],
[0x10d30, 0x10d39],
[0x10e60, 0x10e7e],
[0x10e80, 0x10ea9],
[0x10ead],
[0x10eb0, 0x10eb1],
[0x10f00, 0x10f27],
[0x10f30, 0x10f45],
[0x10f51, 0x10f59],
[0x10f70, 0x10f81],
[0x10f86, 0x10f89],
[0x10fb0, 0x10fcb],
[0x10fe0, 0x10ff6],
[0x11003, 0x11037],
[0x11047, 0x1104d],
[0x11052, 0x1106f],
[0x11071, 0x11072],
[0x11075],
[0x11083, 0x110af],
[0x110bb, 0x110bc],
[0x110be, 0x110c1],
[0x110d0, 0x110e8],
[0x110f0, 0x110f9],
[0x11103, 0x11126],
[0x11136, 0x11144],
[0x11147],
[0x11150, 0x11172],
[0x11174, 0x11176],
[0x11183, 0x111b2],
[0x111c1],
[0x111c4, 0x111c8],
[0x111cd],
[0x111d0, 0x111df],
[0x111e1, 0x111f4],
[0x11200, 0x11211],
[0x11213, 0x1122b],
[0x11238, 0x1123d],
[0x1123f, 0x11240],
[0x11280, 0x11286],
[0x11288],
[0x1128a, 0x1128d],
[0x1128f, 0x1129d],
[0x1129f, 0x112a9],
[0x112b0, 0x112de],
[0x112f0, 0x112f9],
[0x11305, 0x1130c],
[0x1130f, 0x11310],
[0x11313, 0x11328],
[0x1132a, 0x11330],
[0x11332, 0x11333],
[0x11335, 0x11339],
[0x1133d],
[0x11350],
[0x1135d, 0x11361],
[0x11400, 0x11434],
[0x11447, 0x1145b],
[0x1145d],
[0x1145f, 0x11461],
[0x11480, 0x114af],
[0x114c4, 0x114c7],
[0x114d0, 0x114d9],
[0x11580, 0x115ae],
[0x115c1, 0x115db],
[0x11600, 0x1162f],
[0x11641, 0x11644],
[0x11650, 0x11659],
[0x11660, 0x1166c],
[0x11680, 0x116aa],
[0x116b8, 0x116b9],
[0x116c0, 0x116c9],
[0x11700, 0x1171a],
[0x11730, 0x11746],
[0x11800, 0x1182b],
[0x1183b],
[0x118a0, 0x118f2],
[0x118ff, 0x11906],
[0x11909],
[0x1190c, 0x11913],
[0x11915, 0x11916],
[0x11918, 0x1192f],
[0x11944, 0x11946],
[0x11950, 0x11959],
[0x119a0, 0x119a7],
[0x119aa, 0x119d0],
[0x119e1, 0x119e3],
[0x11a00],
[0x11a0b, 0x11a32],
[0x11a3f, 0x11a46],
[0x11a50],
[0x11a5c, 0x11a83],
[0x11a9a, 0x11aa2],
[0x11ab0, 0x11af8],
[0x11b00, 0x11b09],
[0x11c00, 0x11c08],
[0x11c0a, 0x11c2e],
[0x11c40, 0x11c45],
[0x11c50, 0x11c6c],
[0x11c70, 0x11c8f],
[0x11d00, 0x11d06],
[0x11d08, 0x11d09],
[0x11d0b, 0x11d30],
[0x11d50, 0x11d59],
[0x11d60, 0x11d65],
[0x11d67, 0x11d68],
[0x11d6a, 0x11d89],
[0x11d98],
[0x11da0, 0x11da9],
[0x11ee0, 0x11ef2],
[0x11ef7, 0x11ef8],
[0x11f04, 0x11f10],
[0x11f12, 0x11f33],
[0x11f43, 0x11f59],
[0x11fb0],
[0x11fc0, 0x11ff1],
[0x11fff, 0x12399],
[0x12400, 0x1246e],
[0x12470, 0x12474],
[0x12480, 0x12543],
[0x12f90, 0x12ff2],
[0x13000, 0x1342f],
[0x13441, 0x13446],
[0x14400, 0x14646],
[0x16800, 0x16a38],
[0x16a40, 0x16a5e],
[0x16a60, 0x16a69],
[0x16a6e, 0x16abe],
[0x16ac0, 0x16ac9],
[0x16ad0, 0x16aed],
[0x16af5],
[0x16b00, 0x16b2f],
[0x16b37, 0x16b45],
[0x16b50, 0x16b59],
[0x16b5b, 0x16b61],
[0x16b63, 0x16b77],
[0x16b7d, 0x16b8f],
[0x16e40, 0x16e9a],
[0x16f00, 0x16f4a],
[0x16f50],
[0x16f93, 0x16f9f],
[0x16fe0, 0x16fe3],
[0x17000],
[0x187f7],
[0x18800, 0x18cd5],
[0x18d00],
[0x18d08],
[0x1aff0, 0x1aff3],
[0x1aff5, 0x1affb],
[0x1affd, 0x1affe],
[0x1b000, 0x1b122],
[0x1b132],
[0x1b150, 0x1b152],
[0x1b155],
[0x1b164, 0x1b167],
[0x1b170, 0x1b2fb],
[0x1bc00, 0x1bc6a],
[0x1bc70, 0x1bc7c],
[0x1bc80, 0x1bc88],
[0x1bc90, 0x1bc99],
[0x1bc9c],
[0x1bc9f],
[0x1cf50, 0x1cfc3],
[0x1d000, 0x1d0f5],
[0x1d100, 0x1d126],
[0x1d129, 0x1d164],
[0x1d16a, 0x1d16c],
[0x1d183, 0x1d184],
[0x1d18c, 0x1d1a9],
[0x1d1ae, 0x1d1ea],
[0x1d200, 0x1d241],
[0x1d245],
[0x1d2c0, 0x1d2d3],
[0x1d2e0, 0x1d2f3],
[0x1d300, 0x1d356],
[0x1d360, 0x1d378],
[0x1d400, 0x1d454],
[0x1d456, 0x1d49c],
[0x1d49e, 0x1d49f],
[0x1d4a2],
[0x1d4a5, 0x1d4a6],
[0x1d4a9, 0x1d4ac],
[0x1d4ae, 0x1d4b9],
[0x1d4bb],
[0x1d4bd, 0x1d4c3],
[0x1d4c5, 0x1d505],
[0x1d507, 0x1d50a],
[0x1d50d, 0x1d514],
[0x1d516, 0x1d51c],
[0x1d51e, 0x1d539],
[0x1d53b, 0x1d53e],
[0x1d540, 0x1d544],
[0x1d546],
[0x1d54a, 0x1d550],
[0x1d552, 0x1d6a5],
[0x1d6a8, 0x1d7cb],
[0x1d7ce, 0x1d9ff],
[0x1da37, 0x1da3a],
[0x1da6d, 0x1da74],
[0x1da76, 0x1da83],
[0x1da85, 0x1da8b],
[0x1df00, 0x1df1e],
[0x1df25, 0x1df2a],
[0x1e030, 0x1e06d],
[0x1e100, 0x1e12c],
[0x1e137, 0x1e13d],
[0x1e140, 0x1e149],
[0x1e14e, 0x1e14f],
[0x1e290, 0x1e2ad],
[0x1e2c0, 0x1e2eb],
[0x1e2f0, 0x1e2f9],
[0x1e2ff],
[0x1e4d0, 0x1e4eb],
[0x1e4f0, 0x1e4f9],
[0x1e7e0, 0x1e7e6],
[0x1e7e8, 0x1e7eb],
[0x1e7ed, 0x1e7ee],
[0x1e7f0, 0x1e7fe],
[0x1e800, 0x1e8c4],
[0x1e8c7, 0x1e8cf],
[0x1e900, 0x1e943],
[0x1e94b],
[0x1e950, 0x1e959],
[0x1e95e, 0x1e95f],
[0x1ec71, 0x1ecb4],
[0x1ed01, 0x1ed3d],
[0x1ee00, 0x1ee03],
[0x1ee05, 0x1ee1f],
[0x1ee21, 0x1ee22],
[0x1ee24],
[0x1ee27],
[0x1ee29, 0x1ee32],
[0x1ee34, 0x1ee37],
[0x1ee39],
[0x1ee3b],
[0x1ee42],
[0x1ee47],
[0x1ee49],
[0x1ee4b],
[0x1ee4d, 0x1ee4f],
[0x1ee51, 0x1ee52],
[0x1ee54],
[0x1ee57],
[0x1ee59],
[0x1ee5b],
[0x1ee5d],
[0x1ee5f],
[0x1ee61, 0x1ee62],
[0x1ee64],
[0x1ee67, 0x1ee6a],
[0x1ee6c, 0x1ee72],
[0x1ee74, 0x1ee77],
[0x1ee79, 0x1ee7c],
[0x1ee7e],
[0x1ee80, 0x1ee89],
[0x1ee8b, 0x1ee9b],
[0x1eea1, 0x1eea3],
[0x1eea5, 0x1eea9],
[0x1eeab, 0x1eebb],
[0x1eef0, 0x1eef1],
[0x1f000, 0x1f02b],
[0x1f030, 0x1f093],
[0x1f0a0, 0x1f0ae],
[0x1f0b1, 0x1f0bf],
[0x1f0c1, 0x1f0cf],
[0x1f0d1, 0x1f0f5],
[0x1f100, 0x1f1ad],
[0x1f200, 0x1f202],
[0x1f210, 0x1f23b],
[0x1f240, 0x1f248],
[0x1f250, 0x1f251],
[0x1f260, 0x1f265],
[0x1f300, 0x1f3fa],
[0x1f400, 0x1f6d7],
[0x1f6dc, 0x1f6ec],
[0x1f6f0, 0x1f6fc],
[0x1f700, 0x1f776],
[0x1f77b, 0x1f7d9],
[0x1f7e0, 0x1f7eb],
[0x1f7f0],
[0x1f800, 0x1f80b],
[0x1f810, 0x1f847],
[0x1f850, 0x1f859],
[0x1f860, 0x1f887],
[0x1f890, 0x1f8ad],
[0x1f8b0, 0x1f8b1],
[0x1f900, 0x1fa53],
[0x1fa60, 0x1fa6d],
[0x1fa70, 0x1fa7c],
[0x1fa80, 0x1fa88],
[0x1fa90, 0x1fabd],
[0x1fabf, 0x1fac5],
[0x1face, 0x1fadb],
[0x1fae0, 0x1fae8],
[0x1faf0, 0x1faf8],
[0x1fb00, 0x1fb92],
[0x1fb94, 0x1fbca],
[0x1fbf0, 0x1fbf9],
[0x20000],
[0x2a6df],
[0x2a700],
[0x2b739],
[0x2b740],
[0x2b81d],
[0x2b820],
[0x2cea1],
[0x2ceb0],
[0x2ebe0],
[0x2ebf0],
[0x2ee5d],
[0x2f800, 0x2fa1d],
[0x30000],
[0x3134a],
[0x31350],
[0x323af],
];
export const autonomousDecomposableGraphemeRanges = [
[0xc0, 0xc5],
[0xc7, 0xcf],
[0xd1, 0xd6],
[0xd9, 0xdd],
[0xe0, 0xe5],
[0xe7, 0xef],
[0xf1, 0xf6],
[0xf9, 0xfd],
[0xff, 0x10f],
[0x112, 0x125],
[0x128, 0x130],
[0x134, 0x137],
[0x139, 0x13e],
[0x143, 0x148],
[0x14c, 0x151],
[0x154, 0x165],
[0x168, 0x17e],
[0x1a0, 0x1a1],
[0x1af, 0x1b0],
[0x1cd, 0x1dc],
[0x1de, 0x1e3],
[0x1e6, 0x1f0],
[0x1f4, 0x1f5],
[0x1f8, 0x21b],
[0x21e, 0x21f],
[0x226, 0x233],
[0x385, 0x386],
[0x388, 0x38a],
[0x38c],
[0x38e, 0x390],
[0x3aa, 0x3b0],
[0x3ca, 0x3ce],
[0x3d3, 0x3d4],
[0x400, 0x401],
[0x403],
[0x407],
[0x40c, 0x40e],
[0x419],
[0x439],
[0x450, 0x451],
[0x453],
[0x457],
[0x45c, 0x45e],
[0x476, 0x477],
[0x4c1, 0x4c2],
[0x4d0, 0x4d3],
[0x4d6, 0x4d7],
[0x4da, 0x4df],
[0x4e2, 0x4e7],
[0x4ea, 0x4f5],
[0x4f8, 0x4f9],
[0x622, 0x626],
[0x6c0],
[0x6c2],
[0x6d3],
[0x929],
[0x931],
[0x934],
[0x958, 0x95f],
[0x9dc, 0x9dd],
[0x9df],
[0xa33],
[0xa36],
[0xa59, 0xa5b],
[0xa5e],
[0xb5c, 0xb5d],
[0xb94],
[0xf43],
[0xf4d],
[0xf52],
[0xf57],
[0xf5c],
[0xf69],
[0x1026],
[0x1b06],
[0x1b08],
[0x1b0a],
[0x1b0c],
[0x1b0e],
[0x1b12],
[0x1e00, 0x1e99],
[0x1e9b],
[0x1ea0, 0x1ef9],
[0x1f00, 0x1f15],
[0x1f18, 0x1f1d],
[0x1f20, 0x1f45],
[0x1f48, 0x1f4d],
[0x1f50, 0x1f57],
[0x1f59],
[0x1f5b],
[0x1f5d],
[0x1f5f, 0x1f70],
[0x1f72],
[0x1f74],
[0x1f76],
[0x1f78],
[0x1f7a],
[0x1f7c],
[0x1f80, 0x1fb4],
[0x1fb6, 0x1fba],
[0x1fbc],
[0x1fc1, 0x1fc4],
[0x1fc6, 0x1fc8],
[0x1fca],
[0x1fcc, 0x1fd2],
[0x1fd6, 0x1fda],
[0x1fdd, 0x1fe2],
[0x1fe4, 0x1fea],
[0x1fec, 0x1fed],
[0x1ff2, 0x1ff4],
[0x1ff6, 0x1ff8],
[0x1ffa],
[0x1ffc],
[0x219a, 0x219b],
[0x21ae],
[0x21cd, 0x21cf],
[0x2204],
[0x2209],
[0x220c],
[0x2224],
[0x2226],
[0x2241],
[0x2244],
[0x2247],
[0x2249],
[0x2260],
[0x2262],
[0x226d, 0x2271],
[0x2274, 0x2275],
[0x2278, 0x2279],
[0x2280, 0x2281],
[0x2284, 0x2285],
[0x2288, 0x2289],
[0x22ac, 0x22af],
[0x22e0, 0x22e3],
[0x22ea, 0x22ed],
[0x2adc],
[0x304c],
[0x304e],
[0x3050],
[0x3052],
[0x3054],
[0x3056],
[0x3058],
[0x305a],
[0x305c],
[0x305e],
[0x3060],
[0x3062],
[0x3065],
[0x3067],
[0x3069],
[0x3070, 0x3071],
[0x3073, 0x3074],
[0x3076, 0x3077],
[0x3079, 0x307a],
[0x307c, 0x307d],
[0x3094],
[0x309e],
[0x30ac],
[0x30ae],
[0x30b0],
[0x30b2],
[0x30b4],
[0x30b6],
[0x30b8],
[0x30ba],
[0x30bc],
[0x30be],
[0x30c0],
[0x30c2],
[0x30c5],
[0x30c7],
[0x30c9],
[0x30d0, 0x30d1],
[0x30d3, 0x30d4],
[0x30d6, 0x30d7],
[0x30d9, 0x30da],
[0x30dc, 0x30dd],
[0x30f4],
[0x30f7, 0x30fa],
[0x30fe],
[0xac00],
[0xd7a3],
[0xfb1d],
[0xfb1f],
[0xfb2a, 0xfb36],
[0xfb38, 0xfb3c],
[0xfb3e],
[0xfb40, 0xfb41],
[0xfb43, 0xfb44],
[0xfb46, 0xfb4e],
[0x1109a],
[0x1109c],
[0x110ab],
[0x1d15e, 0x1d164],
[0x1d1bb, 0x1d1c0],
];

View File

@@ -0,0 +1,86 @@
export const Zero64 = { sign: 1, data: [0, 0] };
export const Unit64 = { sign: 1, data: [0, 1] };
export function isZero64(a) {
return a.data[0] === 0 && a.data[1] === 0;
}
export function isStrictlyNegative64(a) {
return a.sign === -1 && !isZero64(a);
}
export function isStrictlyPositive64(a) {
return a.sign === 1 && !isZero64(a);
}
export function isEqual64(a, b) {
if (a.data[0] === b.data[0] && a.data[1] === b.data[1]) {
return a.sign === b.sign || (a.data[0] === 0 && a.data[1] === 0);
}
return false;
}
function isStrictlySmaller64Internal(a, b) {
return a[0] < b[0] || (a[0] === b[0] && a[1] < b[1]);
}
export function isStrictlySmaller64(a, b) {
if (a.sign === b.sign) {
return a.sign === 1
? isStrictlySmaller64Internal(a.data, b.data)
: isStrictlySmaller64Internal(b.data, a.data);
}
return a.sign === -1 && (!isZero64(a) || !isZero64(b));
}
export function clone64(a) {
return { sign: a.sign, data: [a.data[0], a.data[1]] };
}
function substract64DataInternal(a, b) {
let reminderLow = 0;
let low = a[1] - b[1];
if (low < 0) {
reminderLow = 1;
low = low >>> 0;
}
return [a[0] - b[0] - reminderLow, low];
}
function substract64Internal(a, b) {
if (a.sign === 1 && b.sign === -1) {
const low = a.data[1] + b.data[1];
const high = a.data[0] + b.data[0] + (low > 0xffffffff ? 1 : 0);
return { sign: 1, data: [high >>> 0, low >>> 0] };
}
return {
sign: 1,
data: a.sign === 1 ? substract64DataInternal(a.data, b.data) : substract64DataInternal(b.data, a.data),
};
}
export function substract64(arrayIntA, arrayIntB) {
if (isStrictlySmaller64(arrayIntA, arrayIntB)) {
const out = substract64Internal(arrayIntB, arrayIntA);
out.sign = -1;
return out;
}
return substract64Internal(arrayIntA, arrayIntB);
}
export function negative64(arrayIntA) {
return {
sign: -arrayIntA.sign,
data: [arrayIntA.data[0], arrayIntA.data[1]],
};
}
export function add64(arrayIntA, arrayIntB) {
if (isZero64(arrayIntB)) {
if (isZero64(arrayIntA)) {
return clone64(Zero64);
}
return clone64(arrayIntA);
}
return substract64(arrayIntA, negative64(arrayIntB));
}
export function halve64(a) {
return {
sign: a.sign,
data: [Math.floor(a.data[0] / 2), (a.data[0] % 2 === 1 ? 0x80000000 : 0) + Math.floor(a.data[1] / 2)],
};
}
export function logLike64(a) {
return {
sign: a.sign,
data: [0, Math.floor(Math.log(a.data[0] * 0x100000000 + a.data[1]) / Math.log(2))],
};
}

View File

@@ -0,0 +1,32 @@
import { BigInt, String } from '../../../utils/globals.js';
const safeMathFloor = Math.floor;
const safeMathLog = Math.log;
export function integerLogLike(v) {
return safeMathFloor(safeMathLog(v) / safeMathLog(2));
}
export function bigIntLogLike(v) {
if (v === BigInt(0))
return BigInt(0);
return BigInt(String(v).length);
}
function biasNumericRange(min, max, logLike) {
if (min === max) {
return [{ min: min, max: max }];
}
if (min < 0 && max > 0) {
const logMin = logLike(-min);
const logMax = logLike(max);
return [
{ min: -logMin, max: logMax },
{ min: (max - logMax), max: max },
{ min: min, max: min + logMin },
];
}
const logGap = logLike((max - min));
const arbCloseToMin = { min: min, max: min + logGap };
const arbCloseToMax = { min: (max - logGap), max: max };
return min < 0
? [arbCloseToMax, arbCloseToMin]
: [arbCloseToMin, arbCloseToMax];
}
export { biasNumericRange };

View File

@@ -0,0 +1,21 @@
import { SchedulerImplem } from '../implementations/SchedulerImplem.js';
function buildNextTaskIndex(ordering) {
let numTasks = 0;
return {
clone: () => buildNextTaskIndex(ordering),
nextTaskIndex: (scheduledTasks) => {
if (ordering.length <= numTasks) {
throw new Error(`Invalid schedulerFor defined: too many tasks have been scheduled`);
}
const taskIndex = scheduledTasks.findIndex((t) => t.taskId === ordering[numTasks]);
if (taskIndex === -1) {
throw new Error(`Invalid schedulerFor defined: unable to find next task`);
}
++numTasks;
return taskIndex;
},
};
}
export function buildSchedulerFor(act, ordering) {
return new SchedulerImplem(act, buildNextTaskIndex(ordering));
}

View File

@@ -0,0 +1,8 @@
import { NoopSlicedGenerator } from '../implementations/NoopSlicedGenerator.js';
import { SlicedBasedGenerator } from '../implementations/SlicedBasedGenerator.js';
export function buildSlicedGenerator(arb, mrng, slices, biasFactor) {
if (biasFactor === undefined || slices.length === 0 || mrng.nextInt(1, biasFactor) !== 1) {
return new NoopSlicedGenerator(arb, mrng, biasFactor);
}
return new SlicedBasedGenerator(arb, mrng, slices, biasFactor);
}

View File

@@ -0,0 +1,22 @@
import { safePush } from '../../../utils/globals.js';
export class CustomEqualSet {
constructor(isEqual) {
this.isEqual = isEqual;
this.data = [];
}
tryAdd(value) {
for (let idx = 0; idx !== this.data.length; ++idx) {
if (this.isEqual(this.data[idx], value)) {
return false;
}
}
safePush(this.data, value);
return true;
}
size() {
return this.data.length;
}
getData() {
return this.data;
}
}

View File

@@ -0,0 +1,21 @@
import { safeMapGet, safeMapSet } from '../../../utils/globals.js';
const depthContextCache = new Map();
export function getDepthContextFor(contextMeta) {
if (contextMeta === undefined) {
return { depth: 0 };
}
if (typeof contextMeta !== 'string') {
return contextMeta;
}
const cachedContext = safeMapGet(depthContextCache, contextMeta);
if (cachedContext !== undefined) {
return cachedContext;
}
const context = { depth: 0 };
safeMapSet(depthContextCache, contextMeta, context);
return context;
}
export function createDepthIdentifier() {
const identifier = { depth: 0 };
return identifier;
}

View File

@@ -0,0 +1,85 @@
import { clone64, isEqual64 } from './ArrayInt64.js';
const safeNegativeInfinity = Number.NEGATIVE_INFINITY;
const safePositiveInfinity = Number.POSITIVE_INFINITY;
const safeEpsilon = Number.EPSILON;
const INDEX_POSITIVE_INFINITY = { sign: 1, data: [2146435072, 0] };
const INDEX_NEGATIVE_INFINITY = { sign: -1, data: [2146435072, 1] };
const f64 = new Float64Array(1);
const u32 = new Uint32Array(f64.buffer, f64.byteOffset);
function bitCastDoubleToUInt64(f) {
f64[0] = f;
return [u32[1], u32[0]];
}
export function decomposeDouble(d) {
const { 0: hi, 1: lo } = bitCastDoubleToUInt64(d);
const signBit = hi >>> 31;
const exponentBits = (hi >>> 20) & 0x7ff;
const significandBits = (hi & 0xfffff) * 0x100000000 + lo;
const exponent = exponentBits === 0 ? -1022 : exponentBits - 1023;
let significand = exponentBits === 0 ? 0 : 1;
significand += significandBits / 2 ** 52;
significand *= signBit === 0 ? 1 : -1;
return { exponent, significand };
}
function positiveNumberToInt64(n) {
return [~~(n / 0x100000000), n >>> 0];
}
function indexInDoubleFromDecomp(exponent, significand) {
if (exponent === -1022) {
const rescaledSignificand = significand * 2 ** 52;
return positiveNumberToInt64(rescaledSignificand);
}
const rescaledSignificand = (significand - 1) * 2 ** 52;
const exponentOnlyHigh = (exponent + 1023) * 2 ** 20;
const index = positiveNumberToInt64(rescaledSignificand);
index[0] += exponentOnlyHigh;
return index;
}
export function doubleToIndex(d) {
if (d === safePositiveInfinity) {
return clone64(INDEX_POSITIVE_INFINITY);
}
if (d === safeNegativeInfinity) {
return clone64(INDEX_NEGATIVE_INFINITY);
}
const decomp = decomposeDouble(d);
const exponent = decomp.exponent;
const significand = decomp.significand;
if (d > 0 || (d === 0 && 1 / d === safePositiveInfinity)) {
return { sign: 1, data: indexInDoubleFromDecomp(exponent, significand) };
}
else {
const indexOpposite = indexInDoubleFromDecomp(exponent, -significand);
if (indexOpposite[1] === 0xffffffff) {
indexOpposite[0] += 1;
indexOpposite[1] = 0;
}
else {
indexOpposite[1] += 1;
}
return { sign: -1, data: indexOpposite };
}
}
export function indexToDouble(index) {
if (index.sign === -1) {
const indexOpposite = { sign: 1, data: [index.data[0], index.data[1]] };
if (indexOpposite.data[1] === 0) {
indexOpposite.data[0] -= 1;
indexOpposite.data[1] = 0xffffffff;
}
else {
indexOpposite.data[1] -= 1;
}
return -indexToDouble(indexOpposite);
}
if (isEqual64(index, INDEX_POSITIVE_INFINITY)) {
return safePositiveInfinity;
}
if (index.data[0] < 0x200000) {
return (index.data[0] * 0x100000000 + index.data[1]) * 2 ** -1074;
}
const postIndexHigh = index.data[0] - 0x200000;
const exponent = -1021 + (postIndexHigh >> 20);
const significand = 1 + ((postIndexHigh & 0xfffff) * 2 ** 32 + index.data[1]) * safeEpsilon;
return significand * 2 ** exponent;
}

View File

@@ -0,0 +1,25 @@
import { refineConstraintsForFloatingOnly } from './FloatingOnlyHelpers.js';
const safeNegativeInfinity = Number.NEGATIVE_INFINITY;
const safePositiveInfinity = Number.POSITIVE_INFINITY;
const safeMaxValue = Number.MAX_VALUE;
export const maxNonIntegerValue = 4503599627370495.5;
export const onlyIntegersAfterThisValue = 4503599627370496;
export function refineConstraintsForDoubleOnly(constraints) {
return refineConstraintsForFloatingOnly(constraints, safeMaxValue, maxNonIntegerValue, onlyIntegersAfterThisValue);
}
export function doubleOnlyMapper(value) {
return value === onlyIntegersAfterThisValue
? safePositiveInfinity
: value === -onlyIntegersAfterThisValue
? safeNegativeInfinity
: value;
}
export function doubleOnlyUnmapper(value) {
if (typeof value !== 'number')
throw new Error('Unsupported type');
return value === safePositiveInfinity
? onlyIntegersAfterThisValue
: value === safeNegativeInfinity
? -onlyIntegersAfterThisValue
: value;
}

View File

@@ -0,0 +1,15 @@
const safeObjectKeys = Object.keys;
const safeObjectGetOwnPropertySymbols = Object.getOwnPropertySymbols;
const safeObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
export function extractEnumerableKeys(instance) {
const keys = safeObjectKeys(instance);
const symbols = safeObjectGetOwnPropertySymbols(instance);
for (let index = 0; index !== symbols.length; ++index) {
const symbol = symbols[index];
const descriptor = safeObjectGetOwnPropertyDescriptor(instance, symbol);
if (descriptor && descriptor.enumerable) {
keys.push(symbol);
}
}
return keys;
}

View File

@@ -0,0 +1,62 @@
const safeNegativeInfinity = Number.NEGATIVE_INFINITY;
const safePositiveInfinity = Number.POSITIVE_INFINITY;
export const MIN_VALUE_32 = 2 ** -126 * 2 ** -23;
export const MAX_VALUE_32 = 2 ** 127 * (1 + (2 ** 23 - 1) / 2 ** 23);
export const EPSILON_32 = 2 ** -23;
const INDEX_POSITIVE_INFINITY = 2139095040;
const INDEX_NEGATIVE_INFINITY = -2139095041;
const f32 = new Float32Array(1);
const u32 = new Uint32Array(f32.buffer, f32.byteOffset);
function bitCastFloatToUInt32(f) {
f32[0] = f;
return u32[0];
}
export function decomposeFloat(f) {
const bits = bitCastFloatToUInt32(f);
const signBit = bits >>> 31;
const exponentBits = (bits >>> 23) & 0xff;
const significandBits = bits & 0x7fffff;
const exponent = exponentBits === 0 ? -126 : exponentBits - 127;
let significand = exponentBits === 0 ? 0 : 1;
significand += significandBits / 2 ** 23;
significand *= signBit === 0 ? 1 : -1;
return { exponent, significand };
}
function indexInFloatFromDecomp(exponent, significand) {
if (exponent === -126) {
return significand * 0x800000;
}
return (exponent + 127) * 0x800000 + (significand - 1) * 0x800000;
}
export function floatToIndex(f) {
if (f === safePositiveInfinity) {
return INDEX_POSITIVE_INFINITY;
}
if (f === safeNegativeInfinity) {
return INDEX_NEGATIVE_INFINITY;
}
const decomp = decomposeFloat(f);
const exponent = decomp.exponent;
const significand = decomp.significand;
if (f > 0 || (f === 0 && 1 / f === safePositiveInfinity)) {
return indexInFloatFromDecomp(exponent, significand);
}
else {
return -indexInFloatFromDecomp(exponent, -significand) - 1;
}
}
export function indexToFloat(index) {
if (index < 0) {
return -indexToFloat(-index - 1);
}
if (index === INDEX_POSITIVE_INFINITY) {
return safePositiveInfinity;
}
if (index < 0x1000000) {
return index * 2 ** -149;
}
const postIndex = index - 0x1000000;
const exponent = -125 + (postIndex >> 23);
const significand = 1 + (postIndex & 0x7fffff) / 0x800000;
return significand * 2 ** exponent;
}

View File

@@ -0,0 +1,26 @@
import { MAX_VALUE_32 } from './FloatHelpers.js';
import { refineConstraintsForFloatingOnly } from './FloatingOnlyHelpers.js';
const safeNegativeInfinity = Number.NEGATIVE_INFINITY;
const safePositiveInfinity = Number.POSITIVE_INFINITY;
const safeMaxValue = MAX_VALUE_32;
export const maxNonIntegerValue = 8388607.5;
export const onlyIntegersAfterThisValue = 8388608;
export function refineConstraintsForFloatOnly(constraints) {
return refineConstraintsForFloatingOnly(constraints, safeMaxValue, maxNonIntegerValue, onlyIntegersAfterThisValue);
}
export function floatOnlyMapper(value) {
return value === onlyIntegersAfterThisValue
? safePositiveInfinity
: value === -onlyIntegersAfterThisValue
? safeNegativeInfinity
: value;
}
export function floatOnlyUnmapper(value) {
if (typeof value !== 'number')
throw new Error('Unsupported type');
return value === safePositiveInfinity
? onlyIntegersAfterThisValue
: value === safeNegativeInfinity
? -onlyIntegersAfterThisValue
: value;
}

View File

@@ -0,0 +1,30 @@
const safeNumberIsInteger = Number.isInteger;
const safeObjectIs = Object.is;
const safeNegativeInfinity = Number.NEGATIVE_INFINITY;
const safePositiveInfinity = Number.POSITIVE_INFINITY;
export function refineConstraintsForFloatingOnly(constraints, maxValue, maxNonIntegerValue, onlyIntegersAfterThisValue) {
const { noDefaultInfinity = false, minExcluded = false, maxExcluded = false, min = noDefaultInfinity ? -maxValue : safeNegativeInfinity, max = noDefaultInfinity ? maxValue : safePositiveInfinity, } = constraints;
const effectiveMin = minExcluded
? min < -maxNonIntegerValue
? -onlyIntegersAfterThisValue
: Math.max(min, -maxNonIntegerValue)
: min === safeNegativeInfinity
? Math.max(min, -onlyIntegersAfterThisValue)
: Math.max(min, -maxNonIntegerValue);
const effectiveMax = maxExcluded
? max > maxNonIntegerValue
? onlyIntegersAfterThisValue
: Math.min(max, maxNonIntegerValue)
: max === safePositiveInfinity
? Math.min(max, onlyIntegersAfterThisValue)
: Math.min(max, maxNonIntegerValue);
const fullConstraints = {
noDefaultInfinity: false,
minExcluded: minExcluded || ((min !== safeNegativeInfinity || minExcluded) && safeNumberIsInteger(effectiveMin)),
maxExcluded: maxExcluded || ((max !== safePositiveInfinity || maxExcluded) && safeNumberIsInteger(effectiveMax)),
min: safeObjectIs(effectiveMin, -0) ? 0 : effectiveMin,
max: safeObjectIs(effectiveMax, 0) ? -0 : effectiveMax,
noNaN: constraints.noNaN || false,
};
return fullConstraints;
}

View File

@@ -0,0 +1,51 @@
import { safePop, safePush } from '../../../utils/globals.js';
const safeStringFromCodePoint = String.fromCodePoint;
const safeMathMin = Math.min;
const safeMathMax = Math.max;
export function convertGraphemeRangeToMapToConstantEntry(range) {
if (range.length === 1) {
const codePointString = safeStringFromCodePoint(range[0]);
return { num: 1, build: () => codePointString };
}
const rangeStart = range[0];
return { num: range[1] - range[0] + 1, build: (idInGroup) => safeStringFromCodePoint(rangeStart + idInGroup) };
}
export function intersectGraphemeRanges(rangesA, rangesB) {
const mergedRanges = [];
let cursorA = 0;
let cursorB = 0;
while (cursorA < rangesA.length && cursorB < rangesB.length) {
const rangeA = rangesA[cursorA];
const rangeAMin = rangeA[0];
const rangeAMax = rangeA.length === 1 ? rangeA[0] : rangeA[1];
const rangeB = rangesB[cursorB];
const rangeBMin = rangeB[0];
const rangeBMax = rangeB.length === 1 ? rangeB[0] : rangeB[1];
if (rangeAMax < rangeBMin) {
cursorA += 1;
}
else if (rangeBMax < rangeAMin) {
cursorB += 1;
}
else {
let min = safeMathMax(rangeAMin, rangeBMin);
const max = safeMathMin(rangeAMax, rangeBMax);
if (mergedRanges.length >= 1) {
const lastMergedRange = mergedRanges[mergedRanges.length - 1];
const lastMergedRangeMax = lastMergedRange.length === 1 ? lastMergedRange[0] : lastMergedRange[1];
if (lastMergedRangeMax + 1 === min) {
min = lastMergedRange[0];
safePop(mergedRanges);
}
}
safePush(mergedRanges, min === max ? [min] : [min, max]);
if (rangeAMax <= max) {
cursorA += 1;
}
if (rangeBMax <= max) {
cursorB += 1;
}
}
}
return mergedRanges;
}

View File

@@ -0,0 +1,10 @@
export function filterInvalidSubdomainLabel(subdomainLabel) {
if (subdomainLabel.length > 63) {
return false;
}
return (subdomainLabel.length < 4 ||
subdomainLabel[0] !== 'x' ||
subdomainLabel[1] !== 'n' ||
subdomainLabel[2] !== '-' ||
subdomainLabel[3] !== '-');
}

View File

@@ -0,0 +1,33 @@
import { Map, safeMapGet, safeMapSet } from '../../../utils/globals.js';
const safeObjectIs = Object.is;
export function isSubarrayOf(source, small) {
const countMap = new Map();
let countMinusZero = 0;
for (const sourceEntry of source) {
if (safeObjectIs(sourceEntry, -0)) {
++countMinusZero;
}
else {
const oldCount = safeMapGet(countMap, sourceEntry) || 0;
safeMapSet(countMap, sourceEntry, oldCount + 1);
}
}
for (let index = 0; index !== small.length; ++index) {
if (!(index in small)) {
return false;
}
const smallEntry = small[index];
if (safeObjectIs(smallEntry, -0)) {
if (countMinusZero === 0)
return false;
--countMinusZero;
}
else {
const oldCount = safeMapGet(countMap, smallEntry) || 0;
if (oldCount === 0)
return false;
safeMapSet(countMap, smallEntry, oldCount - 1);
}
}
return true;
}

View File

@@ -0,0 +1,14 @@
import { boolean } from '../../boolean.js';
import { constant } from '../../constant.js';
import { double } from '../../double.js';
export function jsonConstraintsBuilder(stringArbitrary, constraints) {
const { depthSize, maxDepth } = constraints;
const key = stringArbitrary;
const values = [
boolean(),
double({ noDefaultInfinity: true, noNaN: true }),
stringArbitrary,
constant(null),
];
return { key, values, depthSize, maxDepth };
}

View File

@@ -0,0 +1,83 @@
import { readConfigureGlobal } from '../../../check/runner/configuration/GlobalParameters.js';
import { safeIndexOf } from '../../../utils/globals.js';
const safeMathFloor = Math.floor;
const safeMathMin = Math.min;
export const MaxLengthUpperBound = 0x7fffffff;
const orderedSize = ['xsmall', 'small', 'medium', 'large', 'xlarge'];
const orderedRelativeSize = ['-4', '-3', '-2', '-1', '=', '+1', '+2', '+3', '+4'];
export const DefaultSize = 'small';
export function maxLengthFromMinLength(minLength, size) {
switch (size) {
case 'xsmall':
return safeMathFloor(1.1 * minLength) + 1;
case 'small':
return 2 * minLength + 10;
case 'medium':
return 11 * minLength + 100;
case 'large':
return 101 * minLength + 1000;
case 'xlarge':
return 1001 * minLength + 10000;
default:
throw new Error(`Unable to compute lengths based on received size: ${size}`);
}
}
export function relativeSizeToSize(size, defaultSize) {
const sizeInRelative = safeIndexOf(orderedRelativeSize, size);
if (sizeInRelative === -1) {
return size;
}
const defaultSizeInSize = safeIndexOf(orderedSize, defaultSize);
if (defaultSizeInSize === -1) {
throw new Error(`Unable to offset size based on the unknown defaulted one: ${defaultSize}`);
}
const resultingSizeInSize = defaultSizeInSize + sizeInRelative - 4;
return resultingSizeInSize < 0
? orderedSize[0]
: resultingSizeInSize >= orderedSize.length
? orderedSize[orderedSize.length - 1]
: orderedSize[resultingSizeInSize];
}
export function maxGeneratedLengthFromSizeForArbitrary(size, minLength, maxLength, specifiedMaxLength) {
const { baseSize: defaultSize = DefaultSize, defaultSizeToMaxWhenMaxSpecified } = readConfigureGlobal() || {};
const definedSize = size !== undefined ? size : specifiedMaxLength && defaultSizeToMaxWhenMaxSpecified ? 'max' : defaultSize;
if (definedSize === 'max') {
return maxLength;
}
const finalSize = relativeSizeToSize(definedSize, defaultSize);
return safeMathMin(maxLengthFromMinLength(minLength, finalSize), maxLength);
}
export function depthBiasFromSizeForArbitrary(depthSizeOrSize, specifiedMaxDepth) {
if (typeof depthSizeOrSize === 'number') {
return 1 / depthSizeOrSize;
}
const { baseSize: defaultSize = DefaultSize, defaultSizeToMaxWhenMaxSpecified } = readConfigureGlobal() || {};
const definedSize = depthSizeOrSize !== undefined
? depthSizeOrSize
: specifiedMaxDepth && defaultSizeToMaxWhenMaxSpecified
? 'max'
: defaultSize;
if (definedSize === 'max') {
return 0;
}
const finalSize = relativeSizeToSize(definedSize, defaultSize);
switch (finalSize) {
case 'xsmall':
return 1;
case 'small':
return 0.5;
case 'medium':
return 0.25;
case 'large':
return 0.125;
case 'xlarge':
return 0.0625;
}
}
export function resolveSize(size) {
const { baseSize: defaultSize = DefaultSize } = readConfigureGlobal() || {};
if (size === undefined) {
return defaultSize;
}
return relativeSizeToSize(size, defaultSize);
}

View File

@@ -0,0 +1,11 @@
import { Value } from '../../../check/arbitrary/definition/Value.js';
export const UndefinedContextPlaceholder = Symbol('UndefinedContextPlaceholder');
export function noUndefinedAsContext(value) {
if (value.context !== undefined) {
return value;
}
if (value.hasToBeCloned) {
return new Value(value.value_, UndefinedContextPlaceholder, () => value.value);
}
return new Value(value.value_, UndefinedContextPlaceholder);
}

View File

@@ -0,0 +1,46 @@
import { boolean } from '../../boolean.js';
import { constant } from '../../constant.js';
import { double } from '../../double.js';
import { fullUnicodeString } from '../../fullUnicodeString.js';
import { maxSafeInteger } from '../../maxSafeInteger.js';
import { oneof } from '../../oneof.js';
import { string } from '../../string.js';
import { boxedArbitraryBuilder } from '../builders/BoxedArbitraryBuilder.js';
function defaultValues(constraints, stringArbitrary) {
return [
boolean(),
maxSafeInteger(),
double(),
stringArbitrary(constraints),
oneof(stringArbitrary(constraints), constant(null), constant(undefined)),
];
}
function boxArbitraries(arbs) {
return arbs.map((arb) => boxedArbitraryBuilder(arb));
}
function boxArbitrariesIfNeeded(arbs, boxEnabled) {
return boxEnabled ? boxArbitraries(arbs).concat(arbs) : arbs;
}
export function toQualifiedObjectConstraints(settings = {}) {
function orDefault(optionalValue, defaultValue) {
return optionalValue !== undefined ? optionalValue : defaultValue;
}
const stringArbitrary = 'stringUnit' in settings ? string : settings.withUnicodeString ? fullUnicodeString : string;
const valueConstraints = { size: settings.size, unit: settings.stringUnit };
return {
key: orDefault(settings.key, stringArbitrary(valueConstraints)),
values: boxArbitrariesIfNeeded(orDefault(settings.values, defaultValues(valueConstraints, stringArbitrary)), orDefault(settings.withBoxedValues, false)),
depthSize: settings.depthSize,
maxDepth: settings.maxDepth,
maxKeys: settings.maxKeys,
size: settings.size,
withSet: orDefault(settings.withSet, false),
withMap: orDefault(settings.withMap, false),
withObjectString: orDefault(settings.withObjectString, false),
withNullPrototype: orDefault(settings.withNullPrototype, false),
withBigInt: orDefault(settings.withBigInt, false),
withDate: orDefault(settings.withDate, false),
withTypedArray: orDefault(settings.withTypedArray, false),
withSparseArray: orDefault(settings.withSparseArray, false),
};
}

View File

@@ -0,0 +1,207 @@
function charSizeAt(text, pos) {
return text[pos] >= '\uD800' && text[pos] <= '\uDBFF' && text[pos + 1] >= '\uDC00' && text[pos + 1] <= '\uDFFF'
? 2
: 1;
}
function isHexaDigit(char) {
return (char >= '0' && char <= '9') || (char >= 'a' && char <= 'f') || (char >= 'A' && char <= 'F');
}
function isDigit(char) {
return char >= '0' && char <= '9';
}
function squaredBracketBlockContentEndFrom(text, from) {
for (let index = from; index !== text.length; ++index) {
const char = text[index];
if (char === '\\') {
index += 1;
}
else if (char === ']') {
return index;
}
}
throw new Error(`Missing closing ']'`);
}
function parenthesisBlockContentEndFrom(text, from) {
let numExtraOpened = 0;
for (let index = from; index !== text.length; ++index) {
const char = text[index];
if (char === '\\') {
index += 1;
}
else if (char === ')') {
if (numExtraOpened === 0) {
return index;
}
numExtraOpened -= 1;
}
else if (char === '[') {
index = squaredBracketBlockContentEndFrom(text, index);
}
else if (char === '(') {
numExtraOpened += 1;
}
}
throw new Error(`Missing closing ')'`);
}
function curlyBracketBlockContentEndFrom(text, from) {
let foundComma = false;
for (let index = from; index !== text.length; ++index) {
const char = text[index];
if (isDigit(char)) {
}
else if (from === index) {
return -1;
}
else if (char === ',') {
if (foundComma) {
return -1;
}
foundComma = true;
}
else if (char === '}') {
return index;
}
else {
return -1;
}
}
return -1;
}
export var TokenizerBlockMode;
(function (TokenizerBlockMode) {
TokenizerBlockMode[TokenizerBlockMode["Full"] = 0] = "Full";
TokenizerBlockMode[TokenizerBlockMode["Character"] = 1] = "Character";
})(TokenizerBlockMode || (TokenizerBlockMode = {}));
function blockEndFrom(text, from, unicodeMode, mode) {
switch (text[from]) {
case '[': {
if (mode === TokenizerBlockMode.Character) {
return from + 1;
}
return squaredBracketBlockContentEndFrom(text, from + 1) + 1;
}
case '{': {
if (mode === TokenizerBlockMode.Character) {
return from + 1;
}
const foundEnd = curlyBracketBlockContentEndFrom(text, from + 1);
if (foundEnd === -1) {
return from + 1;
}
return foundEnd + 1;
}
case '(': {
if (mode === TokenizerBlockMode.Character) {
return from + 1;
}
return parenthesisBlockContentEndFrom(text, from + 1) + 1;
}
case ']':
case '}':
case ')':
return from + 1;
case '\\': {
const next1 = text[from + 1];
switch (next1) {
case 'x':
if (isHexaDigit(text[from + 2]) && isHexaDigit(text[from + 3])) {
return from + 4;
}
throw new Error(`Unexpected token '${text.substring(from, from + 4)}' found`);
case 'u':
if (text[from + 2] === '{') {
if (!unicodeMode) {
return from + 2;
}
if (text[from + 4] === '}') {
if (isHexaDigit(text[from + 3])) {
return from + 5;
}
throw new Error(`Unexpected token '${text.substring(from, from + 5)}' found`);
}
if (text[from + 5] === '}') {
if (isHexaDigit(text[from + 3]) && isHexaDigit(text[from + 4])) {
return from + 6;
}
throw new Error(`Unexpected token '${text.substring(from, from + 6)}' found`);
}
if (text[from + 6] === '}') {
if (isHexaDigit(text[from + 3]) && isHexaDigit(text[from + 4]) && isHexaDigit(text[from + 5])) {
return from + 7;
}
throw new Error(`Unexpected token '${text.substring(from, from + 7)}' found`);
}
if (text[from + 7] === '}') {
if (isHexaDigit(text[from + 3]) &&
isHexaDigit(text[from + 4]) &&
isHexaDigit(text[from + 5]) &&
isHexaDigit(text[from + 6])) {
return from + 8;
}
throw new Error(`Unexpected token '${text.substring(from, from + 8)}' found`);
}
if (text[from + 8] === '}' &&
isHexaDigit(text[from + 3]) &&
isHexaDigit(text[from + 4]) &&
isHexaDigit(text[from + 5]) &&
isHexaDigit(text[from + 6]) &&
isHexaDigit(text[from + 7])) {
return from + 9;
}
throw new Error(`Unexpected token '${text.substring(from, from + 9)}' found`);
}
if (isHexaDigit(text[from + 2]) &&
isHexaDigit(text[from + 3]) &&
isHexaDigit(text[from + 4]) &&
isHexaDigit(text[from + 5])) {
return from + 6;
}
throw new Error(`Unexpected token '${text.substring(from, from + 6)}' found`);
case 'p':
case 'P': {
if (!unicodeMode) {
return from + 2;
}
let subIndex = from + 2;
for (; subIndex < text.length && text[subIndex] !== '}'; subIndex += text[subIndex] === '\\' ? 2 : 1) {
}
if (text[subIndex] !== '}') {
throw new Error(`Invalid \\P definition`);
}
return subIndex + 1;
}
case 'k': {
let subIndex = from + 2;
for (; subIndex < text.length && text[subIndex] !== '>'; ++subIndex) {
}
if (text[subIndex] !== '>') {
if (!unicodeMode) {
return from + 2;
}
throw new Error(`Invalid \\k definition`);
}
return subIndex + 1;
}
default: {
if (isDigit(next1)) {
const maxIndex = unicodeMode ? text.length : Math.min(from + 4, text.length);
let subIndex = from + 2;
for (; subIndex < maxIndex && isDigit(text[subIndex]); ++subIndex) {
}
return subIndex;
}
const charSize = unicodeMode ? charSizeAt(text, from + 1) : 1;
return from + charSize + 1;
}
}
}
default: {
const charSize = unicodeMode ? charSizeAt(text, from) : 1;
return from + charSize;
}
}
}
export function readFrom(text, from, unicodeMode, mode) {
const to = blockEndFrom(text, from, unicodeMode, mode);
return text.substring(from, to);
}

View File

@@ -0,0 +1,34 @@
import { Set, safeAdd, safePush } from '../../../utils/globals.js';
const safeObjectIs = Object.is;
export class SameValueSet {
constructor(selector) {
this.selector = selector;
this.selectedItemsExceptMinusZero = new Set();
this.data = [];
this.hasMinusZero = false;
}
tryAdd(value) {
const selected = this.selector(value);
if (safeObjectIs(selected, -0)) {
if (this.hasMinusZero) {
return false;
}
safePush(this.data, value);
this.hasMinusZero = true;
return true;
}
const sizeBefore = this.selectedItemsExceptMinusZero.size;
safeAdd(this.selectedItemsExceptMinusZero, selected);
if (sizeBefore !== this.selectedItemsExceptMinusZero.size) {
safePush(this.data, value);
return true;
}
return false;
}
size() {
return this.data.length;
}
getData() {
return this.data;
}
}

View File

@@ -0,0 +1,24 @@
import { Set, safeAdd, safePush } from '../../../utils/globals.js';
export class SameValueZeroSet {
constructor(selector) {
this.selector = selector;
this.selectedItems = new Set();
this.data = [];
}
tryAdd(value) {
const selected = this.selector(value);
const sizeBefore = this.selectedItems.size;
safeAdd(this.selectedItems, selected);
if (sizeBefore !== this.selectedItems.size) {
safePush(this.data, value);
return true;
}
return false;
}
size() {
return this.data.length;
}
getData() {
return this.data;
}
}

View File

@@ -0,0 +1,81 @@
import { stringify } from '../../../utils/stringify.js';
function raiseUnsupportedASTNode(astNode) {
return new Error(`Unsupported AST node! Received: ${stringify(astNode)}`);
}
function addMissingDotStarTraversalAddMissing(astNode, isFirst, isLast) {
if (!isFirst && !isLast) {
return astNode;
}
const traversalResults = { hasStart: false, hasEnd: false };
const revampedNode = addMissingDotStarTraversal(astNode, isFirst, isLast, traversalResults);
const missingStart = isFirst && !traversalResults.hasStart;
const missingEnd = isLast && !traversalResults.hasEnd;
if (!missingStart && !missingEnd) {
return revampedNode;
}
const expressions = [];
if (missingStart) {
expressions.push({ type: 'Assertion', kind: '^' });
expressions.push({
type: 'Repetition',
quantifier: { type: 'Quantifier', kind: '*', greedy: true },
expression: { type: 'Char', kind: 'meta', symbol: '.', value: '.', codePoint: Number.NaN },
});
}
expressions.push(revampedNode);
if (missingEnd) {
expressions.push({
type: 'Repetition',
quantifier: { type: 'Quantifier', kind: '*', greedy: true },
expression: { type: 'Char', kind: 'meta', symbol: '.', value: '.', codePoint: Number.NaN },
});
expressions.push({ type: 'Assertion', kind: '$' });
}
return { type: 'Group', capturing: false, expression: { type: 'Alternative', expressions } };
}
function addMissingDotStarTraversal(astNode, isFirst, isLast, traversalResults) {
switch (astNode.type) {
case 'Char':
return astNode;
case 'Repetition':
return astNode;
case 'Quantifier':
throw new Error(`Wrongly defined AST tree, Quantifier nodes not supposed to be scanned!`);
case 'Alternative':
traversalResults.hasStart = true;
traversalResults.hasEnd = true;
return Object.assign(Object.assign({}, astNode), { expressions: astNode.expressions.map((node, index) => addMissingDotStarTraversalAddMissing(node, isFirst && index === 0, isLast && index === astNode.expressions.length - 1)) });
case 'CharacterClass':
return astNode;
case 'ClassRange':
return astNode;
case 'Group': {
return Object.assign(Object.assign({}, astNode), { expression: addMissingDotStarTraversal(astNode.expression, isFirst, isLast, traversalResults) });
}
case 'Disjunction': {
traversalResults.hasStart = true;
traversalResults.hasEnd = true;
return Object.assign(Object.assign({}, astNode), { left: astNode.left !== null ? addMissingDotStarTraversalAddMissing(astNode.left, isFirst, isLast) : null, right: astNode.right !== null ? addMissingDotStarTraversalAddMissing(astNode.right, isFirst, isLast) : null });
}
case 'Assertion': {
if (astNode.kind === '^' || astNode.kind === 'Lookahead') {
traversalResults.hasStart = true;
return astNode;
}
else if (astNode.kind === '$' || astNode.kind === 'Lookbehind') {
traversalResults.hasEnd = true;
return astNode;
}
else {
throw new Error(`Assertions of kind ${astNode.kind} not implemented yet!`);
}
}
case 'Backreference':
return astNode;
default:
throw raiseUnsupportedASTNode(astNode);
}
}
export function addMissingDotStar(astNode) {
return addMissingDotStarTraversalAddMissing(astNode, true, true);
}

View File

@@ -0,0 +1,28 @@
import { stream } from '../../../stream/Stream.js';
import { Value } from '../../../check/arbitrary/definition/Value.js';
import { BigInt } from '../../../utils/globals.js';
function halveBigInt(n) {
return n / BigInt(2);
}
export function shrinkBigInt(current, target, tryTargetAsap) {
const realGap = current - target;
function* shrinkDecr() {
let previous = tryTargetAsap ? undefined : target;
const gap = tryTargetAsap ? realGap : halveBigInt(realGap);
for (let toremove = gap; toremove > 0; toremove = halveBigInt(toremove)) {
const next = current - toremove;
yield new Value(next, previous);
previous = next;
}
}
function* shrinkIncr() {
let previous = tryTargetAsap ? undefined : target;
const gap = tryTargetAsap ? realGap : halveBigInt(realGap);
for (let toremove = gap; toremove < 0; toremove = halveBigInt(toremove)) {
const next = current - toremove;
yield new Value(next, previous);
previous = next;
}
}
return realGap > 0 ? stream(shrinkDecr()) : stream(shrinkIncr());
}

View File

@@ -0,0 +1,32 @@
import { Value } from '../../../check/arbitrary/definition/Value.js';
import { stream } from '../../../stream/Stream.js';
const safeMathCeil = Math.ceil;
const safeMathFloor = Math.floor;
function halvePosInteger(n) {
return safeMathFloor(n / 2);
}
function halveNegInteger(n) {
return safeMathCeil(n / 2);
}
export function shrinkInteger(current, target, tryTargetAsap) {
const realGap = current - target;
function* shrinkDecr() {
let previous = tryTargetAsap ? undefined : target;
const gap = tryTargetAsap ? realGap : halvePosInteger(realGap);
for (let toremove = gap; toremove > 0; toremove = halvePosInteger(toremove)) {
const next = toremove === realGap ? target : current - toremove;
yield new Value(next, previous);
previous = next;
}
}
function* shrinkIncr() {
let previous = tryTargetAsap ? undefined : target;
const gap = tryTargetAsap ? realGap : halveNegInteger(realGap);
for (let toremove = gap; toremove < 0; toremove = halveNegInteger(toremove)) {
const next = toremove === realGap ? target : current - toremove;
yield new Value(next, previous);
previous = next;
}
}
return realGap > 0 ? stream(shrinkDecr()) : stream(shrinkIncr());
}

View File

@@ -0,0 +1,78 @@
import { safeGet, safePush, safeSet } from '../../../utils/globals.js';
import { patternsToStringUnmapperIsValidLength } from '../mappers/PatternsToString.js';
import { MaxLengthUpperBound } from './MaxLengthFromMinLength.js';
import { tokenizeString } from './TokenizeString.js';
const dangerousStrings = [
'__defineGetter__',
'__defineSetter__',
'__lookupGetter__',
'__lookupSetter__',
'__proto__',
'constructor',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'toLocaleString',
'toString',
'valueOf',
'apply',
'arguments',
'bind',
'call',
'caller',
'length',
'name',
'prototype',
'key',
'ref',
];
function computeCandidateStringLegacy(dangerous, charArbitrary, stringSplitter) {
let candidate;
try {
candidate = stringSplitter(dangerous);
}
catch (err) {
return undefined;
}
for (const entry of candidate) {
if (!charArbitrary.canShrinkWithoutContext(entry)) {
return undefined;
}
}
return candidate;
}
export function createSlicesForStringLegacy(charArbitrary, stringSplitter) {
const slicesForString = [];
for (const dangerous of dangerousStrings) {
const candidate = computeCandidateStringLegacy(dangerous, charArbitrary, stringSplitter);
if (candidate !== undefined) {
safePush(slicesForString, candidate);
}
}
return slicesForString;
}
const slicesPerArbitrary = new WeakMap();
function createSlicesForStringNoConstraints(charArbitrary) {
const slicesForString = [];
for (const dangerous of dangerousStrings) {
const candidate = tokenizeString(charArbitrary, dangerous, 0, MaxLengthUpperBound);
if (candidate !== undefined) {
safePush(slicesForString, candidate);
}
}
return slicesForString;
}
export function createSlicesForString(charArbitrary, constraints) {
let slices = safeGet(slicesPerArbitrary, charArbitrary);
if (slices === undefined) {
slices = createSlicesForStringNoConstraints(charArbitrary);
safeSet(slicesPerArbitrary, charArbitrary, slices);
}
const slicesForConstraints = [];
for (const slice of slices) {
if (patternsToStringUnmapperIsValidLength(slice, constraints)) {
safePush(slicesForConstraints, slice);
}
}
return slicesForConstraints;
}

View File

@@ -0,0 +1,29 @@
import { safeAdd, safePush, Set } from '../../../utils/globals.js';
const safeNumberIsNaN = Number.isNaN;
export class StrictlyEqualSet {
constructor(selector) {
this.selector = selector;
this.selectedItemsExceptNaN = new Set();
this.data = [];
}
tryAdd(value) {
const selected = this.selector(value);
if (safeNumberIsNaN(selected)) {
safePush(this.data, value);
return true;
}
const sizeBefore = this.selectedItemsExceptNaN.size;
safeAdd(this.selectedItemsExceptNaN, selected);
if (sizeBefore !== this.selectedItemsExceptNaN.size) {
safePush(this.data, value);
return true;
}
return false;
}
size() {
return this.data.length;
}
getData() {
return this.data;
}
}

View File

@@ -0,0 +1,6 @@
export function escapeForTemplateString(originalText) {
return originalText.replace(/([$`\\])/g, '\\$1').replace(/\r/g, '\\r');
}
export function escapeForMultilineComments(originalText) {
return originalText.replace(/\*\//g, '*\\/');
}

View File

@@ -0,0 +1,46 @@
import { BigInt, safePush } from '../../../utils/globals.js';
export function countToggledBits(n) {
let count = 0;
while (n > BigInt(0)) {
if (n & BigInt(1))
++count;
n >>= BigInt(1);
}
return count;
}
export function computeNextFlags(flags, nextSize) {
const allowedMask = (BigInt(1) << BigInt(nextSize)) - BigInt(1);
const preservedFlags = flags & allowedMask;
let numMissingFlags = countToggledBits(flags - preservedFlags);
let nFlags = preservedFlags;
for (let mask = BigInt(1); mask <= allowedMask && numMissingFlags !== 0; mask <<= BigInt(1)) {
if (!(nFlags & mask)) {
nFlags |= mask;
--numMissingFlags;
}
}
return nFlags;
}
export function computeTogglePositions(chars, toggleCase) {
const positions = [];
for (let idx = chars.length - 1; idx !== -1; --idx) {
if (toggleCase(chars[idx]) !== chars[idx])
safePush(positions, idx);
}
return positions;
}
export function computeFlagsFromChars(untoggledChars, toggledChars, togglePositions) {
let flags = BigInt(0);
for (let idx = 0, mask = BigInt(1); idx !== togglePositions.length; ++idx, mask <<= BigInt(1)) {
if (untoggledChars[togglePositions[idx]] !== toggledChars[togglePositions[idx]]) {
flags |= mask;
}
}
return flags;
}
export function applyFlagsOnChars(chars, flags, togglePositions, toggleCase) {
for (let idx = 0, mask = BigInt(1); idx !== togglePositions.length; ++idx, mask <<= BigInt(1)) {
if (flags & mask)
chars[togglePositions[idx]] = toggleCase(chars[togglePositions[idx]]);
}
}

View File

@@ -0,0 +1,320 @@
import { safeIndexOf } from '../../../utils/globals.js';
import { TokenizerBlockMode, readFrom } from './ReadRegex.js';
const safeStringFromCodePoint = String.fromCodePoint;
function safePop(tokens) {
const previous = tokens.pop();
if (previous === undefined) {
throw new Error('Unable to extract token preceeding the currently parsed one');
}
return previous;
}
function isDigit(char) {
return char >= '0' && char <= '9';
}
function simpleChar(char, escaped) {
return {
type: 'Char',
kind: 'simple',
symbol: char,
value: char,
codePoint: char.codePointAt(0) || -1,
escaped,
};
}
function metaEscapedChar(block, symbol) {
return {
type: 'Char',
kind: 'meta',
symbol,
value: block,
codePoint: symbol.codePointAt(0) || -1,
};
}
function toSingleToken(tokens, allowEmpty) {
if (tokens.length > 1) {
return {
type: 'Alternative',
expressions: tokens,
};
}
if (!allowEmpty && tokens.length === 0) {
throw new Error(`Unsupported no token`);
}
return tokens[0];
}
function blockToCharToken(block) {
if (block[0] === '\\') {
const next = block[1];
switch (next) {
case 'x': {
const allDigits = block.substring(2);
const codePoint = Number.parseInt(allDigits, 16);
const symbol = safeStringFromCodePoint(codePoint);
return { type: 'Char', kind: 'hex', symbol, value: block, codePoint };
}
case 'u': {
if (block === '\\u') {
return simpleChar('u', true);
}
const allDigits = block[2] === '{' ? block.substring(3, block.length - 1) : block.substring(2);
const codePoint = Number.parseInt(allDigits, 16);
const symbol = safeStringFromCodePoint(codePoint);
return { type: 'Char', kind: 'unicode', symbol, value: block, codePoint };
}
case '0': {
return metaEscapedChar(block, '\0');
}
case 'n': {
return metaEscapedChar(block, '\n');
}
case 'f': {
return metaEscapedChar(block, '\f');
}
case 'r': {
return metaEscapedChar(block, '\r');
}
case 't': {
return metaEscapedChar(block, '\t');
}
case 'v': {
return metaEscapedChar(block, '\v');
}
case 'w':
case 'W':
case 'd':
case 'D':
case 's':
case 'S':
case 'b':
case 'B': {
return { type: 'Char', kind: 'meta', symbol: undefined, value: block, codePoint: Number.NaN };
}
default: {
if (isDigit(next)) {
const allDigits = block.substring(1);
const codePoint = Number(allDigits);
const symbol = safeStringFromCodePoint(codePoint);
return { type: 'Char', kind: 'decimal', symbol, value: block, codePoint };
}
if (block.length > 2 && (next === 'p' || next === 'P')) {
throw new Error(`UnicodeProperty not implemented yet!`);
}
const char = block.substring(1);
return simpleChar(char, true);
}
}
}
return simpleChar(block);
}
function pushTokens(tokens, regexSource, unicodeMode, groups) {
let disjunctions = null;
for (let index = 0, block = readFrom(regexSource, index, unicodeMode, TokenizerBlockMode.Full); index !== regexSource.length; index += block.length, block = readFrom(regexSource, index, unicodeMode, TokenizerBlockMode.Full)) {
const firstInBlock = block[0];
switch (firstInBlock) {
case '|': {
if (disjunctions === null) {
disjunctions = [];
}
disjunctions.push(toSingleToken(tokens.splice(0), true) || null);
break;
}
case '.': {
tokens.push({ type: 'Char', kind: 'meta', symbol: block, value: block, codePoint: Number.NaN });
break;
}
case '*':
case '+': {
const previous = safePop(tokens);
tokens.push({
type: 'Repetition',
expression: previous,
quantifier: { type: 'Quantifier', kind: firstInBlock, greedy: true },
});
break;
}
case '?': {
const previous = safePop(tokens);
if (previous.type === 'Repetition') {
previous.quantifier.greedy = false;
tokens.push(previous);
}
else {
tokens.push({
type: 'Repetition',
expression: previous,
quantifier: { type: 'Quantifier', kind: firstInBlock, greedy: true },
});
}
break;
}
case '{': {
if (block === '{') {
tokens.push(simpleChar(block));
break;
}
const previous = safePop(tokens);
const quantifierText = block.substring(1, block.length - 1);
const quantifierTokens = quantifierText.split(',');
const from = Number(quantifierTokens[0]);
const to = quantifierTokens.length === 1
? from
: quantifierTokens[1].length !== 0
? Number(quantifierTokens[1])
: undefined;
tokens.push({
type: 'Repetition',
expression: previous,
quantifier: { type: 'Quantifier', kind: 'Range', greedy: true, from, to },
});
break;
}
case '[': {
const blockContent = block.substring(1, block.length - 1);
const subTokens = [];
let negative = undefined;
let previousWasSimpleDash = false;
for (let subIndex = 0, subBlock = readFrom(blockContent, subIndex, unicodeMode, TokenizerBlockMode.Character); subIndex !== blockContent.length; subIndex += subBlock.length,
subBlock = readFrom(blockContent, subIndex, unicodeMode, TokenizerBlockMode.Character)) {
if (subIndex === 0 && subBlock === '^') {
negative = true;
continue;
}
const newToken = blockToCharToken(subBlock);
if (subBlock === '-') {
subTokens.push(newToken);
previousWasSimpleDash = true;
}
else {
const operand1Token = subTokens.length >= 2 ? subTokens[subTokens.length - 2] : undefined;
if (previousWasSimpleDash && operand1Token !== undefined && operand1Token.type === 'Char') {
subTokens.pop();
subTokens.pop();
subTokens.push({ type: 'ClassRange', from: operand1Token, to: newToken });
}
else {
subTokens.push(newToken);
}
previousWasSimpleDash = false;
}
}
tokens.push({ type: 'CharacterClass', expressions: subTokens, negative });
break;
}
case '(': {
const blockContent = block.substring(1, block.length - 1);
const subTokens = [];
if (blockContent[0] === '?') {
if (blockContent[1] === ':') {
pushTokens(subTokens, blockContent.substring(2), unicodeMode, groups);
tokens.push({
type: 'Group',
capturing: false,
expression: toSingleToken(subTokens),
});
}
else if (blockContent[1] === '=' || blockContent[1] === '!') {
pushTokens(subTokens, blockContent.substring(2), unicodeMode, groups);
tokens.push({
type: 'Assertion',
kind: 'Lookahead',
negative: blockContent[1] === '!' ? true : undefined,
assertion: toSingleToken(subTokens),
});
}
else if (blockContent[1] === '<' && (blockContent[2] === '=' || blockContent[2] === '!')) {
pushTokens(subTokens, blockContent.substring(3), unicodeMode, groups);
tokens.push({
type: 'Assertion',
kind: 'Lookbehind',
negative: blockContent[2] === '!' ? true : undefined,
assertion: toSingleToken(subTokens),
});
}
else {
const chunks = blockContent.split('>');
if (chunks.length < 2 || chunks[0][1] !== '<') {
throw new Error(`Unsupported regex content found at ${JSON.stringify(block)}`);
}
const groupIndex = ++groups.lastIndex;
const nameRaw = chunks[0].substring(2);
groups.named.set(nameRaw, groupIndex);
pushTokens(subTokens, chunks.slice(1).join('>'), unicodeMode, groups);
tokens.push({
type: 'Group',
capturing: true,
nameRaw,
name: nameRaw,
number: groupIndex,
expression: toSingleToken(subTokens),
});
}
}
else {
const groupIndex = ++groups.lastIndex;
pushTokens(subTokens, blockContent, unicodeMode, groups);
tokens.push({
type: 'Group',
capturing: true,
number: groupIndex,
expression: toSingleToken(subTokens),
});
}
break;
}
default: {
if (block === '^') {
tokens.push({ type: 'Assertion', kind: block });
}
else if (block === '$') {
tokens.push({ type: 'Assertion', kind: block });
}
else if (block[0] === '\\' && isDigit(block[1])) {
const reference = Number(block.substring(1));
if (unicodeMode || reference <= groups.lastIndex) {
tokens.push({ type: 'Backreference', kind: 'number', number: reference, reference });
}
else {
tokens.push(blockToCharToken(block));
}
}
else if (block[0] === '\\' && block[1] === 'k' && block.length !== 2) {
const referenceRaw = block.substring(3, block.length - 1);
tokens.push({
type: 'Backreference',
kind: 'name',
number: groups.named.get(referenceRaw) || 0,
referenceRaw,
reference: referenceRaw,
});
}
else {
tokens.push(blockToCharToken(block));
}
break;
}
}
}
if (disjunctions !== null) {
disjunctions.push(toSingleToken(tokens.splice(0), true) || null);
let currentDisjunction = {
type: 'Disjunction',
left: disjunctions[0],
right: disjunctions[1],
};
for (let index = 2; index < disjunctions.length; ++index) {
currentDisjunction = {
type: 'Disjunction',
left: currentDisjunction,
right: disjunctions[index],
};
}
tokens.push(currentDisjunction);
}
}
export function tokenizeRegex(regex) {
const unicodeMode = safeIndexOf([...regex.flags], 'u') !== -1;
const regexSource = regex.source;
const tokens = [];
pushTokens(tokens, regexSource, unicodeMode, { lastIndex: 0, named: new Map() });
return toSingleToken(tokens);
}

View File

@@ -0,0 +1,34 @@
import { safePop, safePush, safeSubstring } from '../../../utils/globals.js';
export function tokenizeString(patternsArb, value, minLength, maxLength) {
if (value.length === 0) {
if (minLength > 0) {
return undefined;
}
return [];
}
if (maxLength <= 0) {
return undefined;
}
const stack = [{ endIndexChunks: 0, nextStartIndex: 1, chunks: [] }];
while (stack.length > 0) {
const last = safePop(stack);
for (let index = last.nextStartIndex; index <= value.length; ++index) {
const chunk = safeSubstring(value, last.endIndexChunks, index);
if (patternsArb.canShrinkWithoutContext(chunk)) {
const newChunks = [...last.chunks, chunk];
if (index === value.length) {
if (newChunks.length < minLength) {
break;
}
return newChunks;
}
safePush(stack, { endIndexChunks: last.endIndexChunks, nextStartIndex: index + 1, chunks: last.chunks });
if (newChunks.length < maxLength) {
safePush(stack, { endIndexChunks: index, nextStartIndex: index + 1, chunks: newChunks });
}
break;
}
}
}
return undefined;
}

View File

@@ -0,0 +1,27 @@
function initZippedValues(its) {
const vs = [];
for (let index = 0; index !== its.length; ++index) {
vs.push(its[index].next());
}
return vs;
}
function nextZippedValues(its, vs) {
for (let index = 0; index !== its.length; ++index) {
vs[index] = its[index].next();
}
}
function isDoneZippedValues(vs) {
for (let index = 0; index !== vs.length; ++index) {
if (vs[index].done) {
return true;
}
}
return false;
}
export function* zipIterableIterators(...its) {
const vs = initZippedValues(its);
while (!isDoneZippedValues(vs)) {
yield vs.map((v) => v.value);
nextZippedValues(its, vs);
}
}

View File

@@ -0,0 +1,13 @@
export class NoopSlicedGenerator {
constructor(arb, mrng, biasFactor) {
this.arb = arb;
this.mrng = mrng;
this.biasFactor = biasFactor;
}
attemptExact() {
return;
}
next() {
return this.arb.generate(this.mrng, this.biasFactor);
}
}

View File

@@ -0,0 +1,192 @@
import { escapeForTemplateString } from '../helpers/TextEscaper.js';
import { cloneMethod } from '../../../check/symbols.js';
import { stringify } from '../../../utils/stringify.js';
const defaultSchedulerAct = (f) => f();
export class SchedulerImplem {
constructor(act, taskSelector) {
this.act = act;
this.taskSelector = taskSelector;
this.lastTaskId = 0;
this.sourceTaskSelector = taskSelector.clone();
this.scheduledTasks = [];
this.triggeredTasks = [];
this.scheduledWatchers = [];
}
static buildLog(reportItem) {
return `[task\${${reportItem.taskId}}] ${reportItem.label.length !== 0 ? `${reportItem.schedulingType}::${reportItem.label}` : reportItem.schedulingType} ${reportItem.status}${reportItem.outputValue !== undefined ? ` with value ${escapeForTemplateString(reportItem.outputValue)}` : ''}`;
}
log(schedulingType, taskId, label, metadata, status, data) {
this.triggeredTasks.push({
status,
schedulingType,
taskId,
label,
metadata,
outputValue: data !== undefined ? stringify(data) : undefined,
});
}
scheduleInternal(schedulingType, label, task, metadata, customAct, thenTaskToBeAwaited) {
let trigger = null;
const taskId = ++this.lastTaskId;
const scheduledPromise = new Promise((resolve, reject) => {
trigger = () => {
(thenTaskToBeAwaited ? task.then(() => thenTaskToBeAwaited()) : task).then((data) => {
this.log(schedulingType, taskId, label, metadata, 'resolved', data);
return resolve(data);
}, (err) => {
this.log(schedulingType, taskId, label, metadata, 'rejected', err);
return reject(err);
});
};
});
this.scheduledTasks.push({
original: task,
scheduled: scheduledPromise,
trigger: trigger,
schedulingType,
taskId,
label,
metadata,
customAct,
});
if (this.scheduledWatchers.length !== 0) {
this.scheduledWatchers[0]();
}
return scheduledPromise;
}
schedule(task, label, metadata, customAct) {
return this.scheduleInternal('promise', label || '', task, metadata, customAct || defaultSchedulerAct);
}
scheduleFunction(asyncFunction, customAct) {
return (...args) => this.scheduleInternal('function', `${asyncFunction.name}(${args.map(stringify).join(',')})`, asyncFunction(...args), undefined, customAct || defaultSchedulerAct);
}
scheduleSequence(sequenceBuilders, customAct) {
const status = { done: false, faulty: false };
const dummyResolvedPromise = { then: (f) => f() };
let resolveSequenceTask = () => { };
const sequenceTask = new Promise((resolve) => (resolveSequenceTask = resolve));
sequenceBuilders
.reduce((previouslyScheduled, item) => {
const [builder, label, metadata] = typeof item === 'function' ? [item, item.name, undefined] : [item.builder, item.label, item.metadata];
return previouslyScheduled.then(() => {
const scheduled = this.scheduleInternal('sequence', label, dummyResolvedPromise, metadata, customAct || defaultSchedulerAct, () => builder());
scheduled.catch(() => {
status.faulty = true;
resolveSequenceTask();
});
return scheduled;
});
}, dummyResolvedPromise)
.then(() => {
status.done = true;
resolveSequenceTask();
}, () => {
});
return Object.assign(status, {
task: Promise.resolve(sequenceTask).then(() => {
return { done: status.done, faulty: status.faulty };
}),
});
}
count() {
return this.scheduledTasks.length;
}
internalWaitOne() {
if (this.scheduledTasks.length === 0) {
throw new Error('No task scheduled');
}
const taskIndex = this.taskSelector.nextTaskIndex(this.scheduledTasks);
const [scheduledTask] = this.scheduledTasks.splice(taskIndex, 1);
return scheduledTask.customAct(async () => {
scheduledTask.trigger();
try {
await scheduledTask.scheduled;
}
catch (_err) {
}
});
}
async waitOne(customAct) {
const waitAct = customAct || defaultSchedulerAct;
await this.act(() => waitAct(async () => await this.internalWaitOne()));
}
async waitAll(customAct) {
while (this.scheduledTasks.length > 0) {
await this.waitOne(customAct);
}
}
async waitFor(unscheduledTask, customAct) {
let taskResolved = false;
let awaiterPromise = null;
const awaiter = async () => {
while (!taskResolved && this.scheduledTasks.length > 0) {
await this.waitOne(customAct);
}
awaiterPromise = null;
};
const handleNotified = () => {
if (awaiterPromise !== null) {
return;
}
awaiterPromise = Promise.resolve().then(awaiter);
};
const clearAndReplaceWatcher = () => {
const handleNotifiedIndex = this.scheduledWatchers.indexOf(handleNotified);
if (handleNotifiedIndex !== -1) {
this.scheduledWatchers.splice(handleNotifiedIndex, 1);
}
if (handleNotifiedIndex === 0 && this.scheduledWatchers.length !== 0) {
this.scheduledWatchers[0]();
}
};
const rewrappedTask = unscheduledTask.then((ret) => {
taskResolved = true;
if (awaiterPromise === null) {
clearAndReplaceWatcher();
return ret;
}
return awaiterPromise.then(() => {
clearAndReplaceWatcher();
return ret;
});
}, (err) => {
taskResolved = true;
if (awaiterPromise === null) {
clearAndReplaceWatcher();
throw err;
}
return awaiterPromise.then(() => {
clearAndReplaceWatcher();
throw err;
});
});
if (this.scheduledTasks.length > 0 && this.scheduledWatchers.length === 0) {
handleNotified();
}
this.scheduledWatchers.push(handleNotified);
return rewrappedTask;
}
report() {
return [
...this.triggeredTasks,
...this.scheduledTasks.map((t) => ({
status: 'pending',
schedulingType: t.schedulingType,
taskId: t.taskId,
label: t.label,
metadata: t.metadata,
})),
];
}
toString() {
return ('schedulerFor()`\n' +
this.report()
.map(SchedulerImplem.buildLog)
.map((log) => `-> ${log}`)
.join('\n') +
'`');
}
[cloneMethod]() {
return new SchedulerImplem(this.act, this.sourceTaskSelector);
}
}

View File

@@ -0,0 +1,52 @@
import { Value } from '../../../check/arbitrary/definition/Value.js';
import { safePush } from '../../../utils/globals.js';
const safeMathMin = Math.min;
const safeMathMax = Math.max;
export class SlicedBasedGenerator {
constructor(arb, mrng, slices, biasFactor) {
this.arb = arb;
this.mrng = mrng;
this.slices = slices;
this.biasFactor = biasFactor;
this.activeSliceIndex = 0;
this.nextIndexInSlice = 0;
this.lastIndexInSlice = -1;
}
attemptExact(targetLength) {
if (targetLength !== 0 && this.mrng.nextInt(1, this.biasFactor) === 1) {
const eligibleIndices = [];
for (let index = 0; index !== this.slices.length; ++index) {
const slice = this.slices[index];
if (slice.length === targetLength) {
safePush(eligibleIndices, index);
}
}
if (eligibleIndices.length === 0) {
return;
}
this.activeSliceIndex = eligibleIndices[this.mrng.nextInt(0, eligibleIndices.length - 1)];
this.nextIndexInSlice = 0;
this.lastIndexInSlice = targetLength - 1;
}
}
next() {
if (this.nextIndexInSlice <= this.lastIndexInSlice) {
return new Value(this.slices[this.activeSliceIndex][this.nextIndexInSlice++], undefined);
}
if (this.mrng.nextInt(1, this.biasFactor) !== 1) {
return this.arb.generate(this.mrng, this.biasFactor);
}
this.activeSliceIndex = this.mrng.nextInt(0, this.slices.length - 1);
const slice = this.slices[this.activeSliceIndex];
if (this.mrng.nextInt(1, this.biasFactor) !== 1) {
this.nextIndexInSlice = 1;
this.lastIndexInSlice = slice.length - 1;
return new Value(slice[0], undefined);
}
const rangeBoundaryA = this.mrng.nextInt(0, slice.length - 1);
const rangeBoundaryB = this.mrng.nextInt(0, slice.length - 1);
this.nextIndexInSlice = safeMathMin(rangeBoundaryA, rangeBoundaryB);
this.lastIndexInSlice = safeMathMax(rangeBoundaryA, rangeBoundaryB);
return new Value(slice[this.nextIndexInSlice++], undefined);
}
}

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,12 @@
export function arrayToMapMapper(data) {
return new Map(data);
}
export function arrayToMapUnmapper(value) {
if (typeof value !== 'object' || value === null) {
throw new Error('Incompatible instance received: should be a non-null object');
}
if (!('constructor' in value) || value.constructor !== Map) {
throw new Error('Incompatible instance received: should be of exact type Map');
}
return Array.from(value);
}

View File

@@ -0,0 +1,12 @@
export function arrayToSetMapper(data) {
return new Set(data);
}
export function arrayToSetUnmapper(value) {
if (typeof value !== 'object' || value === null) {
throw new Error('Incompatible instance received: should be a non-null object');
}
if (!('constructor' in value) || value.constructor !== Set) {
throw new Error('Incompatible instance received: should be of exact type Set');
}
return Array.from(value);
}

View File

@@ -0,0 +1,10 @@
import { safeJoin, safeSplit } from '../../../utils/globals.js';
export function charsToStringMapper(tab) {
return safeJoin(tab, '');
}
export function charsToStringUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Cannot unmap the passed value');
}
return safeSplit(value, '');
}

View File

@@ -0,0 +1,10 @@
import { safeJoin } from '../../../utils/globals.js';
export function codePointsToStringMapper(tab) {
return safeJoin(tab, '');
}
export function codePointsToStringUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Cannot unmap the passed value');
}
return [...value];
}

View File

@@ -0,0 +1,71 @@
import { safeEndsWith, safeJoin, safeSlice, safeSplit, safeStartsWith, safeSubstring } from '../../../utils/globals.js';
function readBh(value) {
if (value.length === 0)
return [];
else
return safeSplit(value, ':');
}
function extractEhAndL(value) {
const valueSplits = safeSplit(value, ':');
if (valueSplits.length >= 2 && valueSplits[valueSplits.length - 1].length <= 4) {
return [
safeSlice(valueSplits, 0, valueSplits.length - 2),
`${valueSplits[valueSplits.length - 2]}:${valueSplits[valueSplits.length - 1]}`,
];
}
return [safeSlice(valueSplits, 0, valueSplits.length - 1), valueSplits[valueSplits.length - 1]];
}
export function fullySpecifiedMapper(data) {
return `${safeJoin(data[0], ':')}:${data[1]}`;
}
export function fullySpecifiedUnmapper(value) {
if (typeof value !== 'string')
throw new Error('Invalid type');
return extractEhAndL(value);
}
export function onlyTrailingMapper(data) {
return `::${safeJoin(data[0], ':')}:${data[1]}`;
}
export function onlyTrailingUnmapper(value) {
if (typeof value !== 'string')
throw new Error('Invalid type');
if (!safeStartsWith(value, '::'))
throw new Error('Invalid value');
return extractEhAndL(safeSubstring(value, 2));
}
export function multiTrailingMapper(data) {
return `${safeJoin(data[0], ':')}::${safeJoin(data[1], ':')}:${data[2]}`;
}
export function multiTrailingUnmapper(value) {
if (typeof value !== 'string')
throw new Error('Invalid type');
const [bhString, trailingString] = safeSplit(value, '::', 2);
const [eh, l] = extractEhAndL(trailingString);
return [readBh(bhString), eh, l];
}
export function multiTrailingMapperOne(data) {
return multiTrailingMapper([data[0], [data[1]], data[2]]);
}
export function multiTrailingUnmapperOne(value) {
const out = multiTrailingUnmapper(value);
return [out[0], safeJoin(out[1], ':'), out[2]];
}
export function singleTrailingMapper(data) {
return `${safeJoin(data[0], ':')}::${data[1]}`;
}
export function singleTrailingUnmapper(value) {
if (typeof value !== 'string')
throw new Error('Invalid type');
const [bhString, trailing] = safeSplit(value, '::', 2);
return [readBh(bhString), trailing];
}
export function noTrailingMapper(data) {
return `${safeJoin(data[0], ':')}::`;
}
export function noTrailingUnmapper(value) {
if (typeof value !== 'string')
throw new Error('Invalid type');
if (!safeEndsWith(value, '::'))
throw new Error('Invalid value');
return [readBh(safeSubstring(value, 0, value.length - 2))];
}

View File

@@ -0,0 +1,19 @@
import { safeCharCodeAt } from '../../../utils/globals.js';
export const indexToCharStringMapper = String.fromCodePoint;
export function indexToCharStringUnmapper(c) {
if (typeof c !== 'string') {
throw new Error('Cannot unmap non-string');
}
if (c.length === 0 || c.length > 2) {
throw new Error('Cannot unmap string with more or less than one character');
}
const c1 = safeCharCodeAt(c, 0);
if (c.length === 1) {
return c1;
}
const c2 = safeCharCodeAt(c, 1);
if (c1 < 0xd800 || c1 > 0xdbff || c2 < 0xdc00 || c2 > 0xdfff) {
throw new Error('Cannot unmap invalid surrogate pairs');
}
return c.codePointAt(0);
}

View File

@@ -0,0 +1,67 @@
import { Error, Number, Map, safeMapGet, safeMapSet } from '../../../utils/globals.js';
const safeObjectIs = Object.is;
function buildDichotomyEntries(entries) {
let currentFrom = 0;
const dichotomyEntries = [];
for (const entry of entries) {
const from = currentFrom;
currentFrom = from + entry.num;
const to = currentFrom - 1;
dichotomyEntries.push({ from, to, entry });
}
return dichotomyEntries;
}
function findDichotomyEntry(dichotomyEntries, choiceIndex) {
let min = 0;
let max = dichotomyEntries.length;
while (max - min > 1) {
const mid = ~~((min + max) / 2);
if (choiceIndex < dichotomyEntries[mid].from) {
max = mid;
}
else {
min = mid;
}
}
return dichotomyEntries[min];
}
export function indexToMappedConstantMapperFor(entries) {
const dichotomyEntries = buildDichotomyEntries(entries);
return function indexToMappedConstantMapper(choiceIndex) {
const dichotomyEntry = findDichotomyEntry(dichotomyEntries, choiceIndex);
return dichotomyEntry.entry.build(choiceIndex - dichotomyEntry.from);
};
}
function buildReverseMapping(entries) {
const reverseMapping = { mapping: new Map(), negativeZeroIndex: undefined };
let choiceIndex = 0;
for (let entryIdx = 0; entryIdx !== entries.length; ++entryIdx) {
const entry = entries[entryIdx];
for (let idxInEntry = 0; idxInEntry !== entry.num; ++idxInEntry) {
const value = entry.build(idxInEntry);
if (value === 0 && 1 / value === Number.NEGATIVE_INFINITY) {
reverseMapping.negativeZeroIndex = choiceIndex;
}
else {
safeMapSet(reverseMapping.mapping, value, choiceIndex);
}
++choiceIndex;
}
}
return reverseMapping;
}
export function indexToMappedConstantUnmapperFor(entries) {
let reverseMapping = null;
return function indexToMappedConstantUnmapper(value) {
if (reverseMapping === null) {
reverseMapping = buildReverseMapping(entries);
}
const choiceIndex = safeObjectIs(value, -0)
? reverseMapping.negativeZeroIndex
: safeMapGet(reverseMapping.mapping, value);
if (choiceIndex === undefined) {
throw new Error('Unknown value encountered cannot be built using this mapToConstant');
}
return choiceIndex;
};
}

View File

@@ -0,0 +1,14 @@
export function indexToPrintableIndexMapper(v) {
if (v < 95)
return v + 0x20;
if (v <= 0x7e)
return v - 95;
return v;
}
export function indexToPrintableIndexUnmapper(v) {
if (v >= 0x20 && v <= 0x7e)
return v - 0x20;
if (v >= 0 && v <= 0x1f)
return v + 95;
return v;
}

View File

@@ -0,0 +1,48 @@
import { Error, safeEvery } from '../../../utils/globals.js';
const safeObjectCreate = Object.create;
const safeObjectDefineProperty = Object.defineProperty;
const safeObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
const safeObjectGetPrototypeOf = Object.getPrototypeOf;
const safeObjectGetOwnPropertySymbols = Object.getOwnPropertySymbols;
const safeObjectGetOwnPropertyNames = Object.getOwnPropertyNames;
const safeObjectEntries = Object.entries;
export function keyValuePairsToObjectMapper(definition) {
const obj = definition[1] ? safeObjectCreate(null) : {};
for (const keyValue of definition[0]) {
safeObjectDefineProperty(obj, keyValue[0], {
enumerable: true,
configurable: true,
writable: true,
value: keyValue[1],
});
}
return obj;
}
function buildIsValidPropertyNameFilter(obj) {
return function isValidPropertyNameFilter(key) {
const descriptor = safeObjectGetOwnPropertyDescriptor(obj, key);
return (descriptor !== undefined &&
!!descriptor.configurable &&
!!descriptor.enumerable &&
!!descriptor.writable &&
descriptor.get === undefined &&
descriptor.set === undefined);
};
}
export function keyValuePairsToObjectUnmapper(value) {
if (typeof value !== 'object' || value === null) {
throw new Error('Incompatible instance received: should be a non-null object');
}
const hasNullPrototype = safeObjectGetPrototypeOf(value) === null;
const hasObjectPrototype = 'constructor' in value && value.constructor === Object;
if (!hasNullPrototype && !hasObjectPrototype) {
throw new Error('Incompatible instance received: should be of exact type Object');
}
if (safeObjectGetOwnPropertySymbols(value).length > 0) {
throw new Error('Incompatible instance received: should contain symbols');
}
if (!safeEvery(safeObjectGetOwnPropertyNames(value), buildIsValidPropertyNameFilter(value))) {
throw new Error('Incompatible instance received: should contain only c/e/w properties without get/set');
}
return [safeObjectEntries(value), hasNullPrototype];
}

View File

@@ -0,0 +1,33 @@
import { safeNumberToString, safeSubstring } from '../../../utils/globals.js';
const safeNumberParseInt = Number.parseInt;
export function natToStringifiedNatMapper(options) {
const [style, v] = options;
switch (style) {
case 'oct':
return `0${safeNumberToString(v, 8)}`;
case 'hex':
return `0x${safeNumberToString(v, 16)}`;
case 'dec':
default:
return `${v}`;
}
}
export function tryParseStringifiedNat(stringValue, radix) {
const parsedNat = safeNumberParseInt(stringValue, radix);
if (safeNumberToString(parsedNat, radix) !== stringValue) {
throw new Error('Invalid value');
}
return parsedNat;
}
export function natToStringifiedNatUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Invalid type');
}
if (value.length >= 2 && value[0] === '0') {
if (value[1] === 'x') {
return ['hex', tryParseStringifiedNat(safeSubstring(value, 2), 16)];
}
return ['oct', tryParseStringifiedNat(safeSubstring(value, 1), 8)];
}
return ['dec', tryParseStringifiedNat(value, 10)];
}

View File

@@ -0,0 +1,17 @@
import { safeNumberToString, safePadStart } from '../../../utils/globals.js';
export function numberToPaddedEightMapper(n) {
return safePadStart(safeNumberToString(n, 16), 8, '0');
}
export function numberToPaddedEightUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Unsupported type');
}
if (value.length !== 8) {
throw new Error('Unsupported value: invalid length');
}
const n = parseInt(value, 16);
if (value !== numberToPaddedEightMapper(n)) {
throw new Error('Unsupported value: invalid content');
}
return n;
}

View File

@@ -0,0 +1,15 @@
import { safeSubstring } from '../../../utils/globals.js';
export function paddedEightsToUuidMapper(t) {
return `${t[0]}-${safeSubstring(t[1], 4)}-${safeSubstring(t[1], 0, 4)}-${safeSubstring(t[2], 0, 4)}-${safeSubstring(t[2], 4)}${t[3]}`;
}
const UuidRegex = /^([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})$/;
export function paddedEightsToUuidUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Unsupported type');
}
const m = UuidRegex.exec(value);
if (m === null) {
throw new Error('Unsupported type');
}
return [m[1], m[3] + m[2], m[4] + safeSubstring(m[5], 0, 4), safeSubstring(m[5], 4)];
}

View File

@@ -0,0 +1,28 @@
export function partsToUrlMapper(data) {
const [scheme, authority, path] = data;
const query = data[3] === null ? '' : `?${data[3]}`;
const fragments = data[4] === null ? '' : `#${data[4]}`;
return `${scheme}://${authority}${path}${query}${fragments}`;
}
const UrlSplitRegex = /^([[A-Za-z][A-Za-z0-9+.-]*):\/\/([^/?#]*)([^?#]*)(\?[A-Za-z0-9\-._~!$&'()*+,;=:@/?%]*)?(#[A-Za-z0-9\-._~!$&'()*+,;=:@/?%]*)?$/;
export function partsToUrlUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Incompatible value received: type');
}
const m = UrlSplitRegex.exec(value);
if (m === null) {
throw new Error('Incompatible value received');
}
const scheme = m[1];
const authority = m[2];
const path = m[3];
const query = m[4];
const fragments = m[5];
return [
scheme,
authority,
path,
query !== undefined ? query.substring(1) : null,
fragments !== undefined ? fragments.substring(1) : null,
];
}

View File

@@ -0,0 +1,27 @@
import { MaxLengthUpperBound } from '../helpers/MaxLengthFromMinLength.js';
import { safeJoin, Error } from '../../../utils/globals.js';
import { tokenizeString } from '../helpers/TokenizeString.js';
export function patternsToStringMapper(tab) {
return safeJoin(tab, '');
}
function minLengthFrom(constraints) {
return constraints.minLength !== undefined ? constraints.minLength : 0;
}
function maxLengthFrom(constraints) {
return constraints.maxLength !== undefined ? constraints.maxLength : MaxLengthUpperBound;
}
export function patternsToStringUnmapperIsValidLength(tokens, constraints) {
return minLengthFrom(constraints) <= tokens.length && tokens.length <= maxLengthFrom(constraints);
}
export function patternsToStringUnmapperFor(patternsArb, constraints) {
return function patternsToStringUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Unsupported value');
}
const tokens = tokenizeString(patternsArb, value, minLengthFrom(constraints), maxLengthFrom(constraints));
if (tokens === undefined) {
throw new Error('Unable to unmap received string');
}
return tokens;
};
}

View File

@@ -0,0 +1,13 @@
import { safeJoin, safeMap, safeSplice, safeSplit } from '../../../utils/globals.js';
export function segmentsToPathMapper(segments) {
return safeJoin(safeMap(segments, (v) => `/${v}`), '');
}
export function segmentsToPathUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Incompatible value received: type');
}
if (value.length !== 0 && value[0] !== '/') {
throw new Error('Incompatible value received: start');
}
return safeSplice(safeSplit(value, '/'), 1);
}

View File

@@ -0,0 +1,27 @@
import { safeSubstring } from '../../../utils/globals.js';
export function stringToBase64Mapper(s) {
switch (s.length % 4) {
case 0:
return s;
case 3:
return `${s}=`;
case 2:
return `${s}==`;
default:
return safeSubstring(s, 1);
}
}
export function stringToBase64Unmapper(value) {
if (typeof value !== 'string' || value.length % 4 !== 0) {
throw new Error('Invalid string received');
}
const lastTrailingIndex = value.indexOf('=');
if (lastTrailingIndex === -1) {
return value;
}
const numTrailings = value.length - lastTrailingIndex;
if (numTrailings > 2) {
throw new Error('Cannot unmap the passed value');
}
return safeSubstring(value, 0, lastTrailingIndex);
}

View File

@@ -0,0 +1,23 @@
import { Date, Error, safeGetTime } from '../../../utils/globals.js';
const safeNaN = Number.NaN;
const safeNumberIsNaN = Number.isNaN;
export function timeToDateMapper(time) {
return new Date(time);
}
export function timeToDateUnmapper(value) {
if (!(value instanceof Date) || value.constructor !== Date) {
throw new Error('Not a valid value for date unmapper');
}
return safeGetTime(value);
}
export function timeToDateMapperWithNaN(valueForNaN) {
return (time) => {
return time === valueForNaN ? new Date(safeNaN) : timeToDateMapper(time);
};
}
export function timeToDateUnmapperWithNaN(valueForNaN) {
return (value) => {
const time = timeToDateUnmapper(value);
return safeNumberIsNaN(time) ? valueForNaN : time;
};
}

View File

@@ -0,0 +1,106 @@
import { Error, String } from '../../../utils/globals.js';
const encodeSymbolLookupTable = {
10: 'A',
11: 'B',
12: 'C',
13: 'D',
14: 'E',
15: 'F',
16: 'G',
17: 'H',
18: 'J',
19: 'K',
20: 'M',
21: 'N',
22: 'P',
23: 'Q',
24: 'R',
25: 'S',
26: 'T',
27: 'V',
28: 'W',
29: 'X',
30: 'Y',
31: 'Z',
};
const decodeSymbolLookupTable = {
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9,
A: 10,
B: 11,
C: 12,
D: 13,
E: 14,
F: 15,
G: 16,
H: 17,
J: 18,
K: 19,
M: 20,
N: 21,
P: 22,
Q: 23,
R: 24,
S: 25,
T: 26,
V: 27,
W: 28,
X: 29,
Y: 30,
Z: 31,
};
function encodeSymbol(symbol) {
return symbol < 10 ? String(symbol) : encodeSymbolLookupTable[symbol];
}
function pad(value, paddingLength) {
let extraPadding = '';
while (value.length + extraPadding.length < paddingLength) {
extraPadding += '0';
}
return extraPadding + value;
}
function smallUintToBase32StringMapper(num) {
let base32Str = '';
for (let remaining = num; remaining !== 0;) {
const next = remaining >> 5;
const current = remaining - (next << 5);
base32Str = encodeSymbol(current) + base32Str;
remaining = next;
}
return base32Str;
}
export function uintToBase32StringMapper(num, paddingLength) {
const head = ~~(num / 0x40000000);
const tail = num & 0x3fffffff;
return pad(smallUintToBase32StringMapper(head), paddingLength - 6) + pad(smallUintToBase32StringMapper(tail), 6);
}
export function paddedUintToBase32StringMapper(paddingLength) {
return function padded(num) {
return uintToBase32StringMapper(num, paddingLength);
};
}
export function uintToBase32StringUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Unsupported type');
}
let accumulated = 0;
let power = 1;
for (let index = value.length - 1; index >= 0; --index) {
const char = value[index];
const numericForChar = decodeSymbolLookupTable[char];
if (numericForChar === undefined) {
throw new Error('Unsupported type');
}
accumulated += numericForChar * power;
power *= 32;
}
return accumulated;
}

View File

@@ -0,0 +1,21 @@
import { Boolean, Number, String } from '../../../utils/globals.js';
export function unboxedToBoxedMapper(value) {
switch (typeof value) {
case 'boolean':
return new Boolean(value);
case 'number':
return new Number(value);
case 'string':
return new String(value);
default:
return value;
}
}
export function unboxedToBoxedUnmapper(value) {
if (typeof value !== 'object' || value === null || !('constructor' in value)) {
return value;
}
return value.constructor === Boolean || value.constructor === Number || value.constructor === String
? value.valueOf()
: value;
}

View File

@@ -0,0 +1,59 @@
import { safePush } from '../../../utils/globals.js';
const safeObjectCreate = Object.create;
const safeObjectDefineProperty = Object.defineProperty;
const safeObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
const safeObjectGetOwnPropertyNames = Object.getOwnPropertyNames;
const safeObjectGetOwnPropertySymbols = Object.getOwnPropertySymbols;
export function buildValuesAndSeparateKeysToObjectMapper(keys, noKeyValue) {
return function valuesAndSeparateKeysToObjectMapper(definition) {
const obj = definition[1] ? safeObjectCreate(null) : {};
for (let idx = 0; idx !== keys.length; ++idx) {
const valueWrapper = definition[0][idx];
if (valueWrapper !== noKeyValue) {
safeObjectDefineProperty(obj, keys[idx], {
value: valueWrapper,
configurable: true,
enumerable: true,
writable: true,
});
}
}
return obj;
};
}
export function buildValuesAndSeparateKeysToObjectUnmapper(keys, noKeyValue) {
return function valuesAndSeparateKeysToObjectUnmapper(value) {
if (typeof value !== 'object' || value === null) {
throw new Error('Incompatible instance received: should be a non-null object');
}
const hasNullPrototype = Object.getPrototypeOf(value) === null;
const hasObjectPrototype = 'constructor' in value && value.constructor === Object;
if (!hasNullPrototype && !hasObjectPrototype) {
throw new Error('Incompatible instance received: should be of exact type Object');
}
let extractedPropertiesCount = 0;
const extractedValues = [];
for (let idx = 0; idx !== keys.length; ++idx) {
const descriptor = safeObjectGetOwnPropertyDescriptor(value, keys[idx]);
if (descriptor !== undefined) {
if (!descriptor.configurable || !descriptor.enumerable || !descriptor.writable) {
throw new Error('Incompatible instance received: should contain only c/e/w properties');
}
if (descriptor.get !== undefined || descriptor.set !== undefined) {
throw new Error('Incompatible instance received: should contain only no get/set properties');
}
++extractedPropertiesCount;
safePush(extractedValues, descriptor.value);
}
else {
safePush(extractedValues, noKeyValue);
}
}
const namePropertiesCount = safeObjectGetOwnPropertyNames(value).length;
const symbolPropertiesCount = safeObjectGetOwnPropertySymbols(value).length;
if (extractedPropertiesCount !== namePropertiesCount + symbolPropertiesCount) {
throw new Error('Incompatible instance received: should not contain extra properties');
}
return [extractedValues, hasNullPrototype];
};
}

View File

@@ -0,0 +1,26 @@
import { Error, safeSubstring } from '../../../utils/globals.js';
const quickNumberToHexaString = '0123456789abcdef';
export function buildVersionsAppliersForUuid(versions) {
const mapping = {};
const reversedMapping = {};
for (let index = 0; index !== versions.length; ++index) {
const from = quickNumberToHexaString[index];
const to = quickNumberToHexaString[versions[index]];
mapping[from] = to;
reversedMapping[to] = from;
}
function versionsApplierMapper(value) {
return mapping[value[0]] + safeSubstring(value, 1);
}
function versionsApplierUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Cannot produce non-string values');
}
const rev = reversedMapping[value[0]];
if (rev === undefined) {
throw new Error('Cannot produce strings not starting by the version in hexa code');
}
return rev + safeSubstring(value, 1);
}
return { versionsApplierMapper, versionsApplierUnmapper };
}

View File

@@ -0,0 +1,67 @@
import { safeJoin, safeMap, safePush, safeSplit, safeSubstring, safeToLowerCase, safeToUpperCase, } from '../../../utils/globals.js';
export function wordsToJoinedStringMapper(words) {
return safeJoin(safeMap(words, (w) => (w[w.length - 1] === ',' ? safeSubstring(w, 0, w.length - 1) : w)), ' ');
}
export function wordsToJoinedStringUnmapperFor(wordsArbitrary) {
return function wordsToJoinedStringUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Unsupported type');
}
const words = [];
for (const candidate of safeSplit(value, ' ')) {
if (wordsArbitrary.canShrinkWithoutContext(candidate))
safePush(words, candidate);
else if (wordsArbitrary.canShrinkWithoutContext(candidate + ','))
safePush(words, candidate + ',');
else
throw new Error('Unsupported word');
}
return words;
};
}
export function wordsToSentenceMapper(words) {
let sentence = safeJoin(words, ' ');
if (sentence[sentence.length - 1] === ',') {
sentence = safeSubstring(sentence, 0, sentence.length - 1);
}
return safeToUpperCase(sentence[0]) + safeSubstring(sentence, 1) + '.';
}
export function wordsToSentenceUnmapperFor(wordsArbitrary) {
return function wordsToSentenceUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Unsupported type');
}
if (value.length < 2 ||
value[value.length - 1] !== '.' ||
value[value.length - 2] === ',' ||
safeToUpperCase(safeToLowerCase(value[0])) !== value[0]) {
throw new Error('Unsupported value');
}
const adaptedValue = safeToLowerCase(value[0]) + safeSubstring(value, 1, value.length - 1);
const words = [];
const candidates = safeSplit(adaptedValue, ' ');
for (let idx = 0; idx !== candidates.length; ++idx) {
const candidate = candidates[idx];
if (wordsArbitrary.canShrinkWithoutContext(candidate))
safePush(words, candidate);
else if (idx === candidates.length - 1 && wordsArbitrary.canShrinkWithoutContext(candidate + ','))
safePush(words, candidate + ',');
else
throw new Error('Unsupported word');
}
return words;
};
}
export function sentencesToParagraphMapper(sentences) {
return safeJoin(sentences, ' ');
}
export function sentencesToParagraphUnmapper(value) {
if (typeof value !== 'string') {
throw new Error('Unsupported type');
}
const sentences = safeSplit(value, '. ');
for (let idx = 0; idx < sentences.length - 1; ++idx) {
sentences[idx] += '.';
}
return sentences;
}