The online racing simulator
Rust - insim.rs - a suite of crates to help you work with LFS
insim.rs is a suite of crates to help you work with LFS in Rust.

The intention is to provide an ergonomic, strongly typed, native rust implementation of insim and various file formats, rather than a thin layer over a series of bytes and primitive types.

Both blocking (sync) and Tokio-based async are supported (through feature flags), depending on your needs.
  • The libraries are all published to crates.io.
  • All libraries are documented on docs.rs (this could be massively improved, but I needed to get this out the door).
  • You'll find examples in the git repo and simpler ones in the documentation.
Right now it works with the current version of Insim (at the time of writing). I have left in the ability for multiple versions of packets either through traits (if you delve through the git history you'll find the original implementation and why I removed this) or feature flags, down the line.

This was very much built for me and has become a passion project with no goal, or reason. But I hope that it can be useful for someone else.

The Future

I've got plans and ideas for the suite of crates, you can find them all here: https://github.com/theangryangel/insim.rs/issues. I do want to add Outsim, Outguage, MPR and SPR support.

However, my focus was to reach a stable API (v1.0.0) before the arrival of my 2 adopted daughters. I've just managed this, so I'll be giving them my complete focus for the next few months, at least.

Bugs and Pull Requests
  • If you have a bug, please log it against https://github.com/theangryangel/insim.rs/issues and I'll get to it when I can.
  • Pull requests are very welcome, but if it's not aligned with the goals of the project then be prepared for rejection. If you want to do something significant/radical maybe reach out first.
A Bit of History

Back in Feb 2021, I started work on this as an excuse to tinker with Rust after a Twitter conversation with Dygear. The original plan was just to bang out something quick and then build something fun with it.

Turns out that I enjoy a bit of yak shaving and didn't really get to the "build something" part.

There were a lot of long breaks, because of family life, and I spent an insane amount of time thinking about how to make it easy to use for people familiar with Rust and the original insim spec.

It turned out my original ideas weren't very sensible, and everything looks very different than what I had in mind originally.

Addressing that "Rewrite it in Rust" meme

I often use Insim as my "hello world" to a new language because it touches quite a number of areas.

I entered this saga thinking that I'd just bang out a library, as I've done before, and then move on. Mark Rust off the list of languages. I wouldn't publish it. I wouldn't do all the boring things like tests and documentation. I never set out to write the fastest, safest thing, in the new cool language.

I absolutely did not plan on spending a vast amount of time on this. It's completely insane. But somewhere along the way what I did find was a language which re-ignited my passion for programming, after spending years writing boring business software, for boring business people.

And I cannot explain it at all.
Damn, must accept an defeat... saw this code on some unnofficial repos but thought due to some design philospohy it won't be posted on crates.io, yet here we are, turning out I'm too late with my crate! Heheh. Congrats of finally pulling this one out to 1.0.0, thought, I myself gonna stick to my solution as it will allow me to iterate faster over next insim version updates.

Rust is for sure enjoyable langauge to discover, especially the 2021 edition, but to be happy to work with it in InSim is bit strange. The Cpp base in InSim protocol design is very prevelant and gotta say the Cpp + Rust worlds just collide too much, bringing huge pain in the ass to implement some structs, heheh. So bit shocked how this was your way of introduction into the language, yet you've still praised it.
Quote from CRAAACH :Damn, must accept an defeat...

No defeat necessary Smile There's plenty of room for lots of implementations Smile Maybe it's something we can cross-pollinate / borrow ideas from each other Smile

Quote from CRAAACH :I myself gonna stick to my solution as it will allow me to iterate faster over next insim version updates.

That's the main reason why it took me so long to publish the crates. Every time I thought that I had something workable I would do a little test to see how it felt working with it and every time I felt something was wrong and I needed to introduce a breaking change. There's absolutely real value in not releasing too early Smile I completely respect your decision because it's the right one imho Smile

Quote from CRAAACH :gotta say the Cpp + Rust worlds just collide too much, bringing huge pain in the ass to implement some structs, heheh.

I'll agree it's certainly been fun coming up with compromises or options Big grin Some stuff doesn't quite map nicely.

There are some areas of the code I think can be done better, but they'll have to wait. The IS_HCP is a good example where I think it needs to be closer to the IS_MAL, and there are a few fields that will need some incompatible changes down the line.

I initially went down the rust-bindgen route. Which was a mistake. I'm not even sure that made it into git history. After some experiments with manually writing parsers a significant amount of time the libraries used Deku. After a few compatibility and upgrade issues and realisation that it's compile time, I started work on some home-grown macros. I realised that I was just building a half-assed version of binrw, so eventually switched to that, and I'm very happy with it at the moment.

I probably wasted the most time on the parsing and writing of packets.
Love that it's on crates.io, congrats for getting it out the door. I've been a huge fan of Rust for a while now and I'm glad to see a real InSim implementation out there. I 100% agree that programming an InSim application in what ever programing language is a great introduction into the language it self. It touches so many areas and requires knowledge about various levels of the system. I didn't really "get" PHP until I built PRISM, even after years, and years, and years of working with PHP professionally.
All the credit really goes to you Dygear. I probably wouldn’t have pulled the trigger if not for you <3
2.0.0 for the suite just got released, it's a major version bump because technically it's got some breaking changes:
  • MSRV was raised
  • Game version is now parsed into it's own data type (see https://docs.rs/insim/latest/insim/insim/struct.Ver.html) which allows for version comparisons, etc.
  • I've removed some items from being exposed publicly, mostly to do with codepage decoding, colours and escaping. This likely won't affect anyone.
  • Adds support for 0.7F's new IPB packet https://github.com/theangryangel/insim.rs/pull/170
  • All enums are now marked non_exhaustive (as they should've been)

Full details at https://github.com/theangryangel/insim.rs/releases/tag/2.0.0

Most of the public API is exactly as it was.

My next task is probably going to be more on ergonomics. Eagerly looking at what Flame CZE is doing with node-insim at the moment Smile
Interesting read. I started playing with Rust in 2021 with some geospatial and public transit tools, actually rewriting them in Rust to check its speed. I'm worknig on a project in which the initial part started like 2 years ago, and also fall into yak shaving sometimes. Wish you energy to work on this!
2.1.0 release. Wasn't planning on doing another one so early, but as there is an unexpected panic and a missing codepage I figured I probably should get it out of the door relatively quickly.
  • fix: missing ^C codepage
  • fix: RaceLaps panic/overflow when parsing large numbers of laps
  • perf: improved performance of codepage and colour decoding
  • feat: Added convenience is_xxx methods on flags, i.e. `is_remote` on NcnFlags
  • feat: impl Into/From for relevant useful subtypes into Packet, meaning you can do `connection.write(TinyType::Ping).await?`
  • feat: Colourify trait to help build strings with colours. It's just a helper to build strings with colours by doing this `format!("{} {}", "Hello".dark_green(), "world".red())`
  • feat(strobe): A new example for client-side (aka Piran DD annoy-a-tron) showcasing impl Into/From for packet subtypes that flashes lights in a horrific sequence

FGED GREDG RDFGDR GSFDG