module

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

bigint_cmp_float(digits : String, f : Float64) : Int32

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.

Source
parse(text : String) : JSON::Any
Source