mirror of
https://git.pumpin.online/funkpower/typikon.git
synced 2026-10-22 18:57:13 +00:00
Python was never the house language here: the mw-* desktop surface it came
from is 39 bash scripts and was exactly one Python script, the one this was
extracted from. What it cost was distribution, a widget dependency that
needed pipx and a Python floor, and 24ms of interpreter startup before a line
of the program ran.
The port is verified rather than asserted. Both implementations were run over
199,446 day-records, 26 jurisdictions across 21 years, with every field of
every record required to match; the JSON, the iCalendar and 480 renderings of
the text output are identical too. examples/dump.rs is the harness.
What the type system actually buys, which is less than the usual claim and
more than nothing:
- Level is an ordered enum, strictest first, so reads as 'a is
stricter' and relaxed_to() is the one place a feast can lift a fast. No
rule can get the direction backwards.
- Date is a newtype over the Julian Day Number and JulianDate is a separate
type, so a civil date and an ecclesiastical one cannot be mixed up. That
confusion is the single most common way calendar code goes wrong.
- Octets is a newtype in the iCalendar folder, because the bug it replaced
counted characters against a limit RFC 5545 states in octets.
- Movables is a struct, not a map, so a mistyped key is a compile error
rather than a None at the far end of the program.
Of the six defects an adversarial review found in the Python, exactly one had
a shape a type system would have caught. The rest were logic, and the tests
came with them.
The menologion is compiled in with include_str!, so the binary answers on its
own: 930KB, no runtime, 1.2ms to start against Python's 36ms.
20 lines
769 B
Rust
20 lines
769 B
Rust
// Dump every day of a range, every jurisdiction, as one JSON object per line,
|
|
// for differential testing against the Python implementation.
|
|
use typikon::calendars::Date;
|
|
use typikon::day::describe_with;
|
|
use typikon::jurisdictions::{CALENDARS, JURISDICTIONS};
|
|
use typikon::menologion;
|
|
|
|
fn main() {
|
|
let args: Vec<String> = std::env::args().collect();
|
|
let start = Date::parse_iso(&args[1]).expect("start date");
|
|
let days: i32 = args[2].parse().expect("days");
|
|
for jur in JURISDICTIONS.iter().chain(CALENDARS.iter()) {
|
|
let men = menologion::for_jurisdiction(jur.menaia);
|
|
for n in 0..days {
|
|
let d = describe_with(start + n, jur, &men);
|
|
println!("{}", serde_json::to_string(&d.to_json()).unwrap());
|
|
}
|
|
}
|
|
}
|