feat(core): event queue, Ethernet, switch, ARP, IPv4, ICMP, routing and firewall
First slice of the TypeScript port of the filius-ipad runtime engine, with 29 tests ported from the Swift suite. Parts not ported yet throw NotPortedError instead of guessing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
// Ported from filius-ipad (GPLv2/GPLv3):
|
||||
// State/TopologyNetworkRuntimeEngine.swift (TopologyJavaCompatibleRandom)
|
||||
// A bit-exact java.util.Random: the 48-bit linear congruential generator
|
||||
// Java FILIUS draws its RIP beacon jitter and ephemeral ports from. BigInt
|
||||
// keeps the 48-bit arithmetic exact; a double would lose the low bits.
|
||||
|
||||
const MULTIPLIER = 0x5deece66dn;
|
||||
const ADDEND = 0xbn;
|
||||
const MASK = (1n << 48n) - 1n;
|
||||
const INT32_MAX = 2147483647n;
|
||||
|
||||
export class JavaCompatibleRandom {
|
||||
private state: bigint;
|
||||
|
||||
constructor(seed: bigint | number) {
|
||||
this.state = (BigInt.asUintN(64, BigInt(seed)) ^ MULTIPLIER) & MASK;
|
||||
}
|
||||
|
||||
/** The internal 48-bit state, for tests and for copying a generator. */
|
||||
get seed(): bigint {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
clone(): JavaCompatibleRandom {
|
||||
const copy = new JavaCompatibleRandom(0);
|
||||
copy.state = this.state;
|
||||
return copy;
|
||||
}
|
||||
|
||||
next(bits: number): number {
|
||||
if (!(bits > 0 && bits <= 32)) throw new RangeError(`bits out of range: ${bits}`);
|
||||
this.state = (this.state * MULTIPLIER + ADDEND) & MASK;
|
||||
return Number(this.state >> BigInt(48 - bits));
|
||||
}
|
||||
|
||||
nextInt(upperBound: number): number {
|
||||
if (!(upperBound > 0)) throw new RangeError(`upperBound must be positive: ${upperBound}`);
|
||||
const bound = BigInt(upperBound);
|
||||
if ((upperBound & -upperBound) === upperBound) {
|
||||
return Number((bound * BigInt(this.next(31))) >> 31n);
|
||||
}
|
||||
for (;;) {
|
||||
const bits = BigInt(this.next(31));
|
||||
const value = bits % bound;
|
||||
if (bits - value + (bound - 1n) <= INT32_MAX) return Number(value);
|
||||
}
|
||||
}
|
||||
|
||||
nextFloat(): number {
|
||||
return Math.fround(this.next(24) / (1 << 24));
|
||||
}
|
||||
|
||||
/** Java RIP: 30 s · (f/3 + 0.84), truncated — somewhere between 25.2 s and 35.2 s. */
|
||||
nextRipJitterMilliseconds(): number {
|
||||
const javaFloat = this.nextFloat();
|
||||
return Math.trunc(30_000.0 * (javaFloat / 3.0 + 0.84));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user