Rewrite kothic in Rust - #38
Conversation
|
PTAL @biodranik |
|
What is the motivation for the rewrite? Only the speed? Is speed now the main issue with Kothic? Python code is easier to maintain/validate by humans. I like Rust, but we don't have enough experts at the moment to maintain/review these changes efficiently. How good is your experience with Rust and this Kothic code? |
|
My motivation with the rewrite was to mostly improve the architecture, but the speed improvement doesn't hurt at all. I find this Rust version way easier to understand and review, and we can also split into more modules as needed. I think for a tool like this, it makes more sense to use a fast and compiled language that produces a single binary. |
|
Rebased on top of, and integrated the changes from master. |
|
@biodranik It would be great to merge this PR (I will make a subsequent PR on the main repo to integrate the new version), as I want to pursue the open style issues and the Rust version is so much more easier to understand and work with, which is also the case for LLMs and agentic coding tools as well. |
Signed-off-by: Kuzey Bilgin <kuzeybilgin@proton.me>
|
I have doubts, because we don't have other contributors to do quality code reviews for vibecoded rust. Blindly trusting LLMs is not a great idea. Which model/efforts did you use to port btw? |
|
Well, I don't think converting to Rust suddenly makes the code more complicated. And it can be a learning opportunity as well :) I tried to keep the old structure as much as possible and didn't use too much idiomatic Rust. I used the Codex cli fyi. |
Rust rewrite of kothic
This PR replaces the Python kothic MapCSS parser/processor and drules generator
with a complete Rust implementation. The behavior and output are byte-identical
to the Python reference; the native drawing-rules wire format is unchanged.
What changed
kothic(single style),gen_all(all 6 styles),
merge_variantsandmerge_styles(family/merged files).self-contained (LTO release builds, ~3 MB each).
idiomatic
snake_case(updateStyles→update_styles,testChains→test_chains,parseZoom→parse_zoom,addZoom/addCondition/addStyles→
add_*, …),whatever_to_rgb/hex/cairo→parse_color_*, Python-flavoredhelpers (
Number()→number(),py_list_repr→list_repr,komap_mapswithme→generate_drules), dead code dropped (emptynewGroup(),unused
TOKEN_SUBPART, the unusedParser._srcfield), and the#![allow(non_snake_case)]banners are gone.Speed
On my personal machine, generating all 6 Organic Maps styles (
gen_all):≈ 6× faster than Python, and peak memory usage is less than half of before.
Verified byte-identical output
Rust and Python were both run against the real Organic Maps
data/tree:*.binand*.txtdrules files: identical.types.txt,classificator.txt,visibility.txt,colors.txt,patterns.txt: identical.generate_drules.shflow (single-style →merge_variants→merge_styles) reproduces the committeddrules_default/outdoors/vehicle.{bin,txt},drules_design.binanddrules_merged.{bin,txt}byte-for-byte.Tests / lint
cargo buildclean,cargo test: all 65 tests pass.cargo clippy --all-targetsonly produces 3 warnings.