diff options
| author | Arnaud Bailly <arnaud@pankzsoft.com> | 2026-08-30 18:13:01 +0200 |
|---|---|---|
| committer | Arnaud Bailly <arnaud@pankzsoft.com> | 2026-09-01 07:59:01 +0200 |
| commit | 32f9be77d18d3ad0cb86e7290c6df7c51ab99ca5 (patch) | |
| tree | 6633ba3302f8f294e4609aedf9ffdd3693b2ac11 /pbt/ts/src/gen.ts | |
| parent | b3285b3f5878d705fcbeb7165097b6623a02f553 (diff) | |
| download | lambda-nantes-32f9be77d18d3ad0cb86e7290c6df7c51ab99ca5.tar.gz | |
Flesh out simple integrated shrinker
Diffstat (limited to 'pbt/ts/src/gen.ts')
| -rw-r--r-- | pbt/ts/src/gen.ts | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/pbt/ts/src/gen.ts b/pbt/ts/src/gen.ts new file mode 100644 index 0000000..531a118 --- /dev/null +++ b/pbt/ts/src/gen.ts @@ -0,0 +1,73 @@ +import {Option, none, some} from 'fp-ts/lib/Option.js'; +import Prando from 'prando'; + +// a shrinkable generator needs to maintain some state, +// namely the sequence of generated values in order to be +// able to backtrack and shrink. + +type GenMode = 'gen' | 'shrink'; + +export interface Gen<A> { + generate(): A; + + generateN(n: number): A[]; +} + +export interface GenBytes { + generate(n: number): number[]; +} + +export class BytesGen implements GenBytes { + prng: Prando; + bytes: number[][]; // the internal sequence of generated values + + constructor(prng: Prando) { + this.prng = prng; + this.bytes = []; + } + + generate(n: number): number[] { + if (n <= 0) { + throw new Error('n must be greater than 0'); + } + return this.generateBytes(n); + } + + generateBytes(n: number): number[] { + const gens = []; + for (let i = 0; i < n; i++) { + gens.push(this.prng.nextInt(0, 255)); + } + this.bytes.push([...gens]); + return gens; + } + + replay(): GenBytes { + return new ReplayBytes(this.bytes); + } +} + +export class ReplayBytes implements GenBytes { + bytes: number[][]; // the internal sequence of generated values + index: number = 0; // the current index in the sequence of generated values + + constructor(bytes: number[][]) { + this.bytes = bytes; + this.index = 0; + } + + generate(n: number): number[] { + if (this.index >= this.bytes.length) { + throw new Error('No more bytes to shrink'); + } + + const chunk = [...this.bytes[this.index++]]; + + if (chunk.length < n) { + const zeros = new Array(n - chunk.length).fill(0); + chunk.unshift(...zeros); + } + + return chunk; + } +} |
