Text and JSON¶
Deliberate text parsing¶
Start with Integer("123") to read a decimal integer. By default, the parser
accepts a sign and leading zeros, but rejects surrounding whitespace,
underscores, prefixes, and trailing characters. You can choose the same
parsing options in the constructor and in Integer.parse.
base=0 detects 0b, 0o, and 0x prefixes, using decimal when none is
present. With an explicit base, allow_prefix=True permits its matching
prefix. allow_whitespace=True accepts surrounding ASCII whitespace, and
allow_underscores=True permits separators between digits.
Keep every digit in storage¶
Integers print in decimal, and rationals as reduced fractions or whole
numbers. Floats and complex components print the shortest decimal that reads
back as the same value in its format, such as 0.1 or 3.0.
to_string() offers the formatting options for each type: for Floats,
positional or scientific notation, a digit count, and the exact hexadecimal
form for tests and interchange.
JSON preserves both values and format metadata for integers, rationals,
floats, complex numbers, and their batches. Large numeric fields are strings,
so a reader can preserve them even if its native number type is too small.
Decode with the matching from_json() method. Real and complex balls also
have scalar JSON formats; ball batches currently support text output only.
ExactComplex saves its two rational parts exactly; see the
complex-fraction example.
"""Decimal text, JSON and conversion limits for Integers."""
from apn_mojo import Batch, Integer, ConversionLimits
def main() raises:
var limits = ConversionLimits(
max_input_bytes=4096,
max_output_bytes=4096,
max_digits=1000,
max_values=100,
max_allocated_bytes=65536,
)
var value = Integer(
" -0xFF_FF ", base=0, allow_whitespace=True,
allow_underscores=True, limits=limits,
)
print("decimal:", value)
print("hex:", value.to_string(16, prefix=True, uppercase=True, limits=limits))
var document = value.to_json(limits=limits)
print("JSON:", document)
print("round trip:", Integer.from_json(document, limits=limits) == value)
var batch = Batch[Integer]([value, Integer(2) ** 80])
var restored = Batch[Integer].from_json(batch[::-1].to_json(), limits=limits)
print("restored:", restored[0], restored[1])
Run from the repository root pixi run mojo run -I src docs/examples/conversion.mojo
Output
decimal: -65535
hex: -0XFFFF
JSON: {"version":1,"family":"integer","value":"-65535"}
round trip: True
restored: 1208925819614629174706176 -65535
For native Mojo numbers instead of serialized text, see native batch output. That conversion can round values or discard interval bounds; it serves a different purpose from saving an APN value and its metadata.
Bounding conversions¶
To bound the work a conversion can do, pass limits=ConversionLimits(...).
You can reuse the limits object: each call gets a fresh budget, and the
resulting value does not retain it. An unset field (None) is unlimited;
zero allows none of that resource.
| Setting | What it bounds |
|---|---|
max_input_bytes |
Raw input bytes before trimming or unescaping |
max_output_bytes |
Bytes in the returned text |
max_digits |
Numeric digits parsed or written, as defined by the format |
max_values |
Logical values, including batch elements |
max_allocated_bytes |
Cumulative allocation requests during conversion |
Apply transport or file-size limits before buffering large payloads, since conversion limits cannot recover memory already used to receive the input. Reject an oversized record; truncating it could change its value. The policy does not cap later arithmetic, retained snapshots, or process execution time.
See the conversion reference for grammars, JSON records, and exactly what each limit counts.