Krikri::BigJson
The bigint-aware JSON parse for module (plugin) wire results.
A plugin's stdout is parsed into the JSON::Any tree everything downstream (registered variables, templating, filters, display) carries - and JSON::Any's raw union tops out at Int64, so plain JSON.parse raises "Invalid Int64" the moment a module returns a wider integer (an RSA modulus, an EC coordinate, a big certificate serial number - the exact bytes the real modules print). This parser first rewrites every integer literal that does not fit Int64 into the BIGINT_SENTINEL_PREFIX-marked decimal string (quoted, with the marker escaped) and then lets plain JSON.parse build the tree, so the wide value arrives as a marked string that every renderer taught about the sentinel prints back as bare unquoted digits - the text Ansible's Python ints produce.
The rewrite is a small scanner rather than a pull-parser walk:
JSON::PullParser lexes wide integers fine, but its skip desyncs the
token buffer inside nested containers (the next object key comes
back stale), so a manual tree build over it is not trustworthy. The
scanner walks the text once, tracks JSON string literals (with
escapes) so a number inside a string is never touched, and rewrites
only bare -digits tokens; anything with a fraction or exponent is
a float and goes through verbatim. Behavior otherwise mirrors
JSON.parse exactly - same tree shapes, last-wins duplicate keys, and
identical errors (the rewrite only ever ADDS quoting around digits),
so the callers' rescue paths keep working unchanged.
Class methods
Exact ordering of a wide integer (the decimal digits of a
BIGINT_SENTINEL_PREFIX-marked value, sign included) against a
Float64. The naive route - converting the digits to Float64 and
using <=> - raises "Invalid Float64" the moment the integer
overflows Float64's range (a 617-digit RSA modulus), and even in
range it would round. Python's int/float comparison is exact
arithmetic, so this is too: the float decomposes exactly as
mantissa * 2^exponent (Math.frexp is exact for IEEE doubles), both
sides are scaled to integers with a BigInt shift, and the compare
is a plain digit compare. A magnitude pre-gate on digit count
(|big| lies in [10^(d-1), 10^d)) settles everything outside the
one-decade band around the float without building a BigInt at all.