System I/O and serialization kernels
Environment-variable access, pure-string path and URL parsing, weighted/stratified random sampling, MessagePack binary serialization, and the histogram/dedup pair a richer, mostly-undispatchable conta
Six modules that don't share a numerical domain so much as a job: get a value in or out of the process without leaning on Mojo's own standard library for it. env reads process environment variables — the only module on this page that touches Python at all. filepath.pathlib and net.url parse and reassemble filesystem paths and URLs as pure string operations, with zero filesystem or network calls of their own. random_utils extends std.random's single uniform generator into the sampling primitives a Monte Carlo caller actually needs — weighted choice, shuffle, bootstrap, stratified sampling. serialization.msgpack is a from-scratch MessagePack encoder/decoder that picks the most compact wire tag for each value. And structs.containers, despite its name, is mostly a module the runtime contract doesn't expose: its real Mojo source defines a min-heap, a ring buffer, and a sorted list, but only two free functions — counter and unique — are registered in the dispatch table runtime.execute actually calls into.
from algenta import MojoRuntime
runtime = MojoRuntime(mode="local")
runtime.execute("filepath.pathlib", "path_normalize", ["/usr/local/../bin"])["result"]
# "/usr/bin" -- ".." pops the preceding component; the root itself is never popped past
runtime.execute("serialization.msgpack", "msgpack_encode_int", [200])["result"]
# [204, 200] -- 200 doesn't fit a positive fixint (0-127), so it's tagged 0xcc (204) + the byteThe modules
env
reads process environment variables through Python's os.environ, with typed _int/_float/_bool accessors and an existence check
filepath.pathlib
pure-string path manipulation (join, split, basename, dirname, extension, stem, absolute check, ./.. normalization) with zero filesystem calls
net.url
URL parsing into a URL struct, reconstruction back to a string, percent-encode/decode, and query-string parse/get/build
random_utils
weighted choice, Fisher-Yates shuffle, sampling with and without replacement, a uniform random integer, a random permutation, and stratified sampling, all built on std.random's one uniform generator
serialization.msgpack
a MessagePack encoder/decoder for ints, floats, strings, bools, nil, and array/map headers, each choosing the most compact wire format for its value
structs.containers
a min-heap, ring buffer, and sorted list in the Mojo source, plus the two functions the runtime contract actually exposes: counter (histogram binning) and unique (sorted dedup)
env: read-once-at-startup config, not hot-path code
The module's own docstring says as much: it is "designed for read-once-at-startup config, not hot-path code," and it is the one module in this family that imports Python (Python.import_module("os")) — every other module here runs with zero Python imports.
env_get(key, default="")
Raw string value, or default if the variable is unset.
env_get_int(key, default=0)
Parses the value with conv.parse_int; default if unset, empty, or unparsable.
env_get_float(key, default=0.0)
Same, via conv.parse_float64.
env_get_bool(key, default=False)
Case-insensitive "true"/"1"/"yes" → True; "false"/"0"/"no"/"" → False; anything else → default.
env_is_set(key)
True if the key exists in the environment at all, regardless of its value.
Both lines above are the literal assertions tests/mojo/test_wave8.mojo pins: env_get("PATH", "") is checked non-empty, env_is_set("PATH") is True, env_is_set("NONEXISTENT_VAR_12345") is False, and each env_get_* variant returns its supplied default for that same nonexistent key.
filepath.pathlib: string surgery, no filesystem underneath
Every function operates on the path text alone — path_is_absolute never checks whether the path exists, and path_normalize never resolves symlinks; it only collapses . and .. lexically. The eight functions and their real, test-pinned values (tests/mojo/test_wave6.mojo, on /usr/local/bin/mojo and related paths):
path_basename(path)
path_basename("/usr/local/bin/mojo") → "mojo"
path_dirname(path)
path_dirname("/usr/local/bin/mojo") → "/usr/local/bin"; path_dirname("file.txt") → "." (no directory component)
path_extension(path)
path_extension("file.mojo") → ".mojo"; path_extension("Makefile") → "" (no dot at all)
path_stem(path)
path_stem("file.mojo") → "file"
path_is_absolute(path)
path_is_absolute("/usr/bin") → True; path_is_absolute("relative/path") → False
path_join(parts)
path_join(["usr", "local", "bin"]) → "usr/local/bin"
path_split(path)
path_split("/usr/local/bin") → ["/", "usr", "local", "bin"] (4 elements; a leading / becomes its own element)
path_normalize(path)
path_normalize("/usr/local/../bin") → "/usr/bin"; path_normalize("/a/b/c/../../d") → "/a/d"
Two edge cases fall out of reading the source directly rather than the pinned test, and were hand-traced against pathlib.mojo's real logic before being stated here:
A leading dot doesn't count as an extension marker.
path_extensionandpath_stemboth guardlast_dot <= 0— a dot at position0(a hidden file) is treated as "no extension," sopath_extension(".bashrc")is""andpath_stem(".bashrc")returns the whole name unchanged,.bashrc", rather than splitting it into a stem and an extension.path_normalizeresolves..differently for absolute and relative paths. For an absolute path, a..that would walk above the root is simply dropped —/a/b/c/../../dcollapses to/a/d, never/../d. For a relative path there is no known root to walk above, so an excess..is kept literally instead of discarded: tracing the algorithm on"a/../../b"step by step —apushed, the first..pops it back off, the second..finds nothing left to pop and is appended as-is,bis pushed after it — produces"../b", a real upward reference the absolute-path case would never emit for the equivalent input.
net.url: authority-form URLs, not general URIs
URL is a plain six-field struct (scheme, host, port, path, query, fragment); port defaults to 0, meaning "unspecified" — url_parse never infers 80 or 443 from the scheme, and url_to_string only emits :port when port > 0, so a URL parsed without an explicit port round-trips without one too.
The parse/split/encode/decode behavior above is exercised by tests/mojo/test_wave7.mojo (with a neutral placeholder host substituted here for the test's own literal string), including the round-trip check (url_to_string(url_parse("https://example.com/path")) reproduces the original string exactly) and the port-omitted case (url_parse("http://example.com/test").port == 0).
url_parse's own docstring is explicit that it "handles: scheme://host[:port][/path][?query] [#fragment]" — an authority-form URL. Feeding it a colon-scheme URI with no //, like "mailto:foo@bar.com", is outside that shape and gets silently misread rather than rejected: tracing url_parse on that string by hand — no "://" means scheme stays ""; no / means the whole string becomes the "authority"; the last colon in "mailto:foo@bar.com" is the one right after mailto, so host becomes "mailto" and the port-parser is handed "foo@bar.com", whose leading non-digit character makes _string_to_int return 0 immediately. The result is {scheme: "", host: "mailto", port: 0, path: "", query: "", fragment: ""} — a parse that completes without error and is simply the wrong shape for that input, not a crash the caller would notice.
random_utils: sampling built on one uniform generator, no seed anywhere
Every function here calls std.random.random_float64() directly or indirectly; none of the seven contract functions takes a seed argument, so there is no way to make two calls reproduce the same draw through runtime.execute — determinism has to come from the caller re-deriving the same random state some other way, not from this module.
random_choice(weights)
Weighted-index draw: normalizes weights implicitly by walking the cumulative sum against one uniform draw scaled by the total.
random_shuffle(data)
In-place Fisher-Yates shuffle. Mutates its argument (see below).
random_sample(data, n)
n items without replacement, via a partial Fisher-Yates; if n >= len(data), returns a shuffled copy of everything.
random_bootstrap(data, n)
n items with replacement — classic bootstrap resampling.
random_uniform_int(low, high)
A uniform integer in [low, high); returns low unchanged if low >= high.
random_permutation(n)
A random ordering of 0, 1, ..., n-1, via Fisher-Yates on an identity list.
stratified_sample(data, n_strata)
Splits data into n_strata equal-ish contiguous strata and draws one random element from each — data should be pre-sorted for this to mean anything, since the strata are just slices of the list as given.
tests/mojo/test_wave10.mojo pins the shape of every draw rather than a specific value, since the values are non-deterministic by construction: random_choice on two weights returns 0 or 1; random_permutation(5) has length 5; random_sample(data, 3) has length 3; random_bootstrap(data, 10) has length 10; random_uniform_int(10, 20) lands in [10, 20); stratified_sample(data, 3) has length 3.
serialization.msgpack: the standard wire format, picking the smallest tag per value
Every msgpack_encode_* function chooses the most compact tag the MessagePack spec allows for its value's magnitude; every msgpack_decode_* function reads a tag at pos and returns a {value, consumed} result struct so a caller can walk a buffer of concatenated values without tracking offsets by hand. tests/mojo/test_wave5.mojo round-trips each of the values below and pins the encoded bytes; the bytes are also independently reproducible from the tag ranges in msgpack.mojo itself:
msgpack_encode_int(v)
Encoded bytes
Format
42
[42]
positive fixint (0–127 encode as the byte itself)
0
[0]
positive fixint
-5
[251]
negative fixint (-32–-1 encode as v + 256)
200
[204, 200]
uint8 (0xcc + the byte, for 128–255)
1000
[205, 3, 232]
uint16 (0xcd + 2 big-endian bytes)
-100
[208, 156]
int8 (0xd0 + v + 256, for -128–-33)
msgpack_encode_float(3.14) always uses the 8-byte float64 tag (0xcb) — the module has no compact float32 path on the encode side, even for a value that would round-trip cleanly as one — so msgpack_decode_float reports consumed == 9 (1 tag byte + 8 data bytes) for every encoded float, exactly as test_wave5.mojo checks. msgpack_decode_float itself is more general than the encoder: it also accepts an incoming 0xca (float32) tag from some other encoder, consuming 5 bytes — a decode-side capability this module's own encoder never exercises. msgpack_encode_string("hello") produces a 1-byte fixstr header (0xa5) plus the 5 UTF-8 bytes, consumed == 6; msgpack_encode_bool(True)/(False) are the single bytes 0xc3/0xc2; msgpack_encode_nil() is 0xc0; msgpack_encode_array_header(3) is the single fixarray byte 0x93; msgpack_encode_map_header(2) is the single fixmap byte 0x82.
structs.containers: three real structs the dispatch table can't reach
Reading mojo/engine/structs/containers.mojo directly turns up a MinHeap (binary min-heap: push, pop, peek, size), a RingBuffer (fixed-capacity circular buffer: push, get, mean, is_full, size), and a SortedList (binary-search insert: insert, get, median, remove, size) — all three genuinely implemented, and all three exercised with real, pinned numbers in tests/mojo/test_wave7.mojo. None of the three appears in runtime_library_dispatch_generated.mojo's _dispatch_structs__containers — only counter and unique are registered there, matching the two entries in runtime_library_contract.json. This is the same shape of gap Config and data-parsing kernels documents for data.dataframe, whose thirty-odd DataFrame methods are real and tested but only df_from_columns is reachable through runtime.execute — here it is a heap, a ring buffer, and a sorted list playing the same role, real and tested but invisible to a caller going through the dispatch layer.
test_wave7.mojo's pinned numbers for the three structs, for reference (not reachable via runtime.execute, but real): a MinHeap pushed 5.0, 2.0, 8.0, 1.0 peeks 1.0 and pops 1.0 then 2.0, leaving size() == 2. A RingBuffer(3) pushed 1.0, 2.0, 3.0 is full with mean() == 2.0; pushing a fourth value 4.0 overwrites the oldest (1.0), leaving mean() == 3.0 and get(0) == 2.0 (now-oldest), get(2) == 4.0 (newest). A SortedList given 5.0, 1.0, 3.0, 2.0, 4.0 in that order reports get(0) == 1.0, get(4) == 5.0, median() == 3.0; removing index 2 (the middle value, 3.0) drops size() to 4 and leaves median() == 3.0 again, the average of the new middle pair [2.0, 4.0].
The two dispatchable functions, worked by hand on the same five-value fixture ([0.5, 0.6, 0.7, 0.4, 0.3]) every auto-generated smoke test in this codebase shares:
counter finds the data's own [min, max] range (here [0.3, 0.7], span 0.4) and divides it into bins equal-width buckets; a value exactly on the top edge is clamped into the last bucket rather than overflowing past it. unique sorts a copy (insertion sort) and then drops consecutive duplicates in one pass — order comes out ascending regardless of the input order, which is why an already-sorted, already-distinct input like the one above just comes back unchanged.
Verification
All six mojo/tests/libs/test_*.mojo files behind this page (test_env.mojo, test_filepath_pathlib.mojo, test_net_url.mojo, test_random_utils.mojo, test_serialization_msgpack.mojo, test_structs_containers.mojo) are auto-generated coverage smoke tests: each calls every function once against the same shared fixture values used across the whole tests/libs directory and checks only that the call completes and the result is finite, non-negative-length, or otherwise well-formed — none of them pins a specific numeric answer. The real, hand-written pinned coverage instead lives in tests/mojo/test_wave5.mojo (msgpack), test_wave6.mojo (pathlib), test_wave7.mojo (structs.containers and net.url), test_wave8.mojo (env), and test_wave10.mojo (random_utils) — every worked value on this page taken from a test is taken from one of those five files. The path_normalize relative-path trace, the mailto: url_parse trace, and the counter/unique three-bin example are not in any test file; they were hand-traced against the real bodies in pathlib.mojo, url.mojo, and containers.mojo and are reproducible by re-running the same steps.
Next: see Config and data-parsing kernels for the other family whose real Mojo source is larger than its dispatchable surface, or Exact numerics and graph kernels for the mutated_args calling convention random_shuffle shares with graph_add_edge.
Last updated
Was this helpful?