Repository navigation
v0.1.0 — the first coordinated release
Every runtime already has TryParse. What it hands back is a bool and a shrug — no reason, no location, and none of the notations untrusted sources actually send. HyperCast returns a verdict instead: the value, or Empty / Malformed / OutOfRange plus the exact byte span that offended. One allocation-free engine written in Rust, called directly from C#, Java, Go, Swift, Ruby, PHP and Python — and as of this tag, every one of those eight is real: published, verified by an actual external install rather than a green CI run, and returning bit-for-bit identical verdicts from the same input on every platform.
This is the first coordinated release. Nothing here is a placeholder or a "coming soon" — see The doors for the full grammar each door accepts, and Receipts for exactly what has been proven on which platform, and how.
Install
| Language | ||
|---|---|---|
| Rust | cargo add hypercast |
crates.io |
| C# | dotnet add package HyperCast |
nuget.org |
| Java | io.github.skunkwerkx:hypercast:0.1.0 |
Maven Central |
| Python | pip install hypercast |
PyPI |
| Ruby | gem install hypercast |
RubyGems |
| PHP | composer require skunkwerkx/hypercast |
Packagist |
| Swift | .package(url: "https://github.com/SkunkWerkx/HyperCast", from: "0.1.0") |
git tag |
| Go | go get github.com/SkunkWerkx/HyperCast/go@go/v0.1.0 |
git tag |
Go's module path is versioned under its own go/vX.Y.Z tag (a Go modules requirement for a subdirectory module) rather than the bare tag every other binding uses — that's already pushed alongside this release, not a separate step.
The doors
Twenty cast_* exports over a plain C ABI: boolean (twenty lexemes — true/false, yes/no, on/off, enabled/disabled, in/out, …), the full integer family (i8–i64, u8–u64), reals (f32/f64), UUID (all five .NET Guid text forms plus urn:uuid: prefixes), RFC 3339 timestamp, Unix epoch at a declared precision, date and time, local date-time (the AM/PM world, with no zone read and none invented), declared-order separated dates, Excel serial dates, and duration (ISO 8601, invariant colon form, protobuf JSON seconds).
Culture never lives in the core. Numeric doors take a caller-declared NumFormat — separators plus individually declarable leniences — and separated dates take a caller-declared DateOrder, because 1/7/2026 is January 7th or July 1st only if you say which. NumFormat.DETECT resolves ./, roles structurally per input, and reports the genuinely ambiguous (12.185, 1,000) as Malformed at the separator rather than guessing.
The scoreboard
Real numbers, not adjusted for story. The RFC 3339 timestamp door against each platform's own parser, linux-arm64, with the FFI crossing and transcode included in every HyperCast figure. Full receipts and methodology in the root README and each binding's own.
| Language | HyperCast | Platform parser | |
|---|---|---|---|
| Java | 62.9 ns | 561 ns Instant.parse |
8.9x faster |
| C# | 71 ns | 286 ns DateTimeOffset.TryParse |
4.0x faster |
| Ruby | 713 ns | 2.88 µs Time.iso8601 |
4.0x faster |
| Swift | 278 ns | 837 ns Date.ISO8601FormatStyle |
3.0x faster |
| PHP | 487 ns | 1.3 µs DateTimeImmutable |
2.7x faster |
| Python | 201 ns | 163 ns fromisoformat (C-accelerated) |
near-parity |
| Go | 175 ns | 67 ns time.Parse(RFC3339Nano) |
slower — on purpose, and printed |
The gap is widest on the messy-feed doors, where most platforms have no parser for the input at all and strptime is the only thing that accepts it: 1/7/2026 3:04 PM under a declared order is 12.7x faster than datetime.strptime in Python, 4.1x than a Java DateTimeFormatter, 3.6x than DateTime.TryParse on .NET.
Go stays in the roster losing per call on purpose: its stdlib RFC 3339 path is genuinely excellent and there is no FFI boundary to beat, and the honest result is what makes the other wins credible rather than a foregone conclusion. Individual losses elsewhere are reported the same way — Boolean.parseBoolean and UUID.fromString on the JVM, int.TryParse with AllowThousands on .NET, Ruby's civil-date door.
What's proven, and how
- The corpus is the contract. 380 vectors across twelve files replay through the Rust core's suite and every binding's, so all eight agree byte for byte on values and fault spans. Ruby replays it twice, once per backend.
- Allocation-free is asserted by a counting allocator, not a doc comment — 1000 calls to every door, success and failure paths, zero allocations demanded. A fault is a span into your buffer; nothing is captured or formatted on the error path.
- The Rust core is
#![no_std]and links no allocator. A bare-metal consumer supplies a#[panic_handler]and stops there. Both halves are CI-guarded, not asserted. - Fuzzed, and it found real bugs. A
cargo-fuzztarget drives all 20 doors under six format profiles and every declared order/precision/epoch. It caught two real classes within a minute — truncation faults pointing one byte past the input, and spans overrunning on text ending mid-UTF-8-character — both fixed structurally and pinned as ordinary tests. The following 550M-execution session found nothing. - AOT on both managed platforms, proven against the published artifacts rather than the working tree: C# under
PublishAotinto a real native binary, Java through a real GraalVM Native Image build that inherits the FFM signatures and resources glob from the shippedreachability-metadata.jsonwith zero configuration. - Exhaustiveness is a compile error where the language can enforce it — a native
[Union]with CS8509-as-error in C#, asealed interfacein Java, a compiler-mandatory-exhaustiveenumin Swift.
What's known and out of scope, on purpose
- The tabular layer is not in this release. CSV/TSV/XLSX ingestion — and the JSON layer behind it — is the endgame, and it's the reason the doors are shaped the way they are: zero allocation per cast and verdict-as-span exist so a batch layer can cross the FFI boundary once per chunk instead of once per cell. A million-row, 20-column file is 20M scalar casts. See docs/roadmap.md.
- WebAssembly is proven for the Rust core — the full suite (66 tests) passes under
wasmtimeonwasm32-wasip1. The Blazor browser-wasm story is proven as far as packaging and linking go; it has not yet been run in a real browser session, and isn't claimed as such until it has. Python's Pyodide path left deliberately with the retired ctypes backend. - Per-language floors are each driven by a feature the verdict type actually needs: .NET 11, JDK 22, Python 3.10, Ruby 3.2, PHP 8.1, Swift tools 5.9 / macOS 13, Go 1.26.
Verification
Every binding in this release was pulled from its real, live registry — or resolved via its real git tag — into a fresh scratch project and run, because "the publish succeeded" and "a consumer can use it" are different claims. Three of the four bugs this project has shipped were found exactly in that gap, and none of them could have failed a build in this repository.
Thanks
If you're reading this because you care about honest performance work rather than marketing claims — that's exactly the audience this project was built for.