Blessed.rs – An unofficial guide to the Rust ecosystem
blessed.rs
blessed.rs
I consider quite incomplete at this point (but hopefully already useful). There are several categories of crate that just aren't covered yet (suggestions very welcome, either here or on the github repo https://github.com/nicoburns/blessed-rs).
I'd also like to add more hand curated content such as:
- Installation and developer environment setup - Link to learning resources (books, projects, etc) - Explanations of the community (reddit, TWIR, discourse, github, zulip, etc) - Themed guides (backend web development, CLI tools, game development, etc)
I want to put together more guidance on how to contribute, and gradually transition this into more of a community maintained model over time, but I haven't had a chance to do this yet.
- askama
- tera
- liquid
And more importantly logging, due to this being a common usecase:
- log
- ... and companions
- (maybe even advanced things, like opentelemetry)
Some other ideas:
* Config: dotenvy
* Database: sqlx (async), diesel (sync, ORM)
* gRPC: prost (protobuf library)
[1] https://www.sqlite.org/stricttables.html
[2] https://docs.rs/rusqlite/latest/rusqlite/functions/index.htm...
There is also `slotmap` which isn't really an arena, but can be used for some of the same use cases.
This site says about the time crate: "The original datetime crate which was split out of std pre-rust-1.0" but as far as I can tell the time crate as it is now is not the original crate and is maintained. The book zero2prod uses chrono.
What's the recommended crate to use for time today ?
I've made some PRs recently to chrono, the new maintainer is very good
I think we're starting to do better again with Chrono, hopefully it won't take us too long to get out a solid 0.5 release.
(I'm one of the current Chrono maintainers -- the previous maintainer burnt out on the project earlier this year, at which point the project sorely needed some TLC.)
Personally I still prefer chrono's API; chrono is also much more conservative about the MSRV (currently at 1.38) whereas time consistently bumps to N - 3, which seems like a meaningful difference.
time depends on the libc timezone parsing with some fairly involved workarounds to avoid hitting undefined behavior, while we incorporated time zone parsing in Rust with some caching for chrono.
So I think these are meaningful differences -- feels unlikely that these projects will merge.
The more challenging part is working in niche areas, https://lib.rs definitely helps as well.
Something else I'd like to see is a tad more clarity on how the recommended channel implementations relate to std::mpsc::channel and tokio::mpsc::channel - the recommended options seem to claim to be better than their respective std/tokio counterparts, but blessed.rs itself doesn't explicitly make that claim. Should it? (I've only ever used std::mpsc and tokio::mpsc, and not in a production context.)
Tokio vs crossbeam/std::sync is a bit of a different question. Using the tokio implementations let you await (i.e., asynchronously block) on a channel, whereas the others will block the thread. So within async code, use tokio for use cases where you may have a blocking operation (writing to a bounded queue or waiting for a message). Otherwise, use crossbeam.
I'm all for "batteries not included", but every time I dip my toes into languages like that, it can take a bit of work to find out common libraries that the majority is using. Not trying to re-ivent the wheel. It's nice to see opinionated takes on things in one central location.
There also the various awesome lists on GitHub, but they are not always well curated
I've been looking for a list of semi-blessed crates like this for a long time. Before finding this and the OP's site I looked at the dependencies of rustc and cargo and considered those to be mostly trusted.
https://github.com/rust-unofficial/awesome-rust
This list is currently far more comprehensive, and it's filled with a lot of high-quality crates for a wide variety of common tasks.
I would like to see this list transformed into a navigable website. It'd also be nice to include code samples (eg. I recently had to investigate each test mocking library directly, and a high level summary or comparison would have helped).
An "Awesome" list can help you find 6 different very interesting libraries for each of those problems, but that's not solving the big problem, because everyone will pick a different library; without a consensus pick, some of those libraries can lose momentum, which is a problem 2 years down the road when the maintainer packs up shop.
What you'd want, if you're the audience for this page, is just a list of straight-up "use this library" picks, in the hopes that those libraries will be stable and maintained indefinitely, and will develop supportive communities.
Github search is much better for finding quality libraries as you can filter by star count, age, recency, last commit, and see fork numbers. It's not perfect, but generally cuts the work down significantly and then you can finish evaluation the projects by clicking through to read the stats of each one.
The Wayland list comes to mind, while I don't have any specific examples
I recently found out that ByteDance has a competitor library which supposedly has better performance:
One of the advantages of Go imho is it's solid stdlib, which includes production-ready HTTP server/client, JSON, XML, crypto libraries and more.
• One size does not fit all. Rust targets many different environments, including embedded and WASM. A big stdlib makes porting Rust harder. It's already problematic, e.g. `std::fs` makes no sense in a browser context, and std's out-of-memory handling strategy was unacceptable for the Linux kernel.
• Rust is judged by the size of its "Hello World!" executable, which already looks pretty fat due having stdlib linked statically.
• Rust has a strong backwards-compatibility guarantee, which means that anything stabilized in stdlib has to stay, forever, and can't evolve. Not many features can be nailed on the first try, and not nailing them means people will forever debate whether to use the worse-but-standard version or a 3rd party version.
• Rust has already dodged some bullets, because 3rd party `serde` turned out better than Rust's old built-in `rustc-serialize`, `syn` won over Rust's `syntex`, `criterion` is better than built-in `bencher`, `rand` had 8 major revisions, `time` broke compat 3 times, etc.
• Rust is stuck with `std::mpsc` which turned out to be slower and less flexible than `crossbeam-channel`.
• Rust team is not an infinite resource.
• The Rust language is designed to be extensible via libraries, unlike Go where e.g. maps, channels, range iteration are special built-ins you can't replace.
If libraries are initially kept outside of the standard library they can compete, gain and lose support, and a clear winner will eventually surface. Old patterns can continue to exist and be support without breaking changes while new, better APIs can incubate. In time, after they've proved themselves, then they can be pulled into the stdlib.
When it isn't included in the stdlib then a new developer needs to always ask "is this the recommended library?" In some of my projects I'm still using a few libraries that might not be the preferred community solution anymore, they are still very well supported. When a winner becomes more clear then I can migrate.
It comes down to two different approaches. Both are valid, both have their advantages. I prefer rust's conservative approach to the stdlib but I understand why someone would rather less reliance on shifting 3rd party libraries.
Compare it with Java's logging framework hell. java.util.Logging used to be near-unusable, and the resulting cambrian explosion of logger frameworks continues to this day. Using a library will make you depend on some logging framework. So it is today normal for a Java program to contain 4-5 different logging frameworks, passing messages to each other.
"Not enough" or "too much" is relative to your use-case. Go is almost purpose-built for web servers, whereas Rust is much more general and lower-level. It's got excellent built-ins for core data structures, async primitives, etc (which makes it much more batteries-included than C), but many (most?) of Rust's users don't need an HTTP server or JSON parsing
It's a judgement call. I think they struck a pretty good balance, especially considering the vibrant ecosystem and breezy package management that can help fill in the gaps, but it's never going to be perfect for everybody's usecase
https://docs.python.org/3/library/csv.html#csv.Sniffer
This feature runs some heuristics and invents a new dialect of CSV based on a sample of the file. That should send chills down your spine, there is literally no safe way to use this thing. Using it in production is a bug in and of itself and will likely lead to security issues.
How many Rust packages work on IBM i?
IBM i was a random example, there are plenty of platforms out there.
But if you're working in an environment where Rust support is poor and Python support is rich, then yeah it totally makes sense to choose Python over Rust, I'm not any sort of absolutist.
Have you had a different experience that's leading you to these views?
Channels appear to be trickier, but it might be possible to upstream crossbeam's version of those as well (it's certainly been proposed and discussed for years).
Why would you say that? Do a cycle of deprecate + remove every few major releases, provide a migration path, and you're good.
Editions currently don't allow existence of multiple standard libraries, because code from different editions can be mixed.
Neither of these things have ever been done, though they have been proposed, and it's just up to the library team to determine if they ever think it would be worth it to do so.
Seems like this would be a great way to deal with deprecated stdlib functionality. Especially in the case that there is a better replacement available. Ranges and channels would be obvious candidates for this.
> crypto does change
A nearby comment mentioned Python, which did have that problem. The ssl module on its standard library didn't verify certificates by default, and since that's no longer considered good cryptographic practice (to put it mildly), that behavior had to change, even though it could break existing code. See for instance https://access.redhat.com/articles/2039753 and the several PEPs it links to, in particular https://peps.python.org/pep-0466/ which is about the backporting of the Python 3.x version of that module to a patch release of Python 2.7.
Designing Cargo was outsourced for a similar reason AFAIK.
As for cargo, what we have today is literally Rust's third package manager, after the experience with using the first two led people to conclude that they just needed to hire domain experts to design and implement it (the bundler folks).
Rust's language design decisions are more of a cathedral; the language feels cohesive and carefully put together, like a delicate puzzle. They're slow to adopt language design decisions, leaving them in an unstabilized purgatory until a very high degree of confidence is developed that it's the right decision. Rust's approach to dependencies is more of a bizarre; you're expected to go to crates.io and work out what dependencies to adopt for just about everything.
https://lib.rs has some basic features to make it faster to sniff test various crates. Eg, I like being able to see a summary of the authors, and things like "maintained by RustCrypto team" just looking at the summary. My suspicion is that some concept of graph centrality (perhaps via authors?), and perhaps counting applications which aren't usually distributed via cargo (this contributing to crates.io downloads), could both yield a better popularity metric. But the trend stuff is pretty reasonable already.
Some related efforts at documenting pseudo-official crates (in contrast to gigantic "awesome" lists) are the "areweX yet" pages (https://www.arewewebyet.org/), the Rust Cookbook (https://rust-lang-nursery.github.io/rust-cookbook/), and the Rust Lang Nursery (https://github.com/rust-lang-nursery). Here is an ancient github issue from way back in 2014 discussing the idea of "official" crates: https://github.com/rust-lang/cargo/issues/934
What is windows-rs missing that's in winapi? So far I've found everything I need in windows-rs, including some pretty obscure corners of the massive Windows API.
But I can't help thinking this could or (should even) be under the auspices of crates.io. Provide a way to categorise crates and highlight commonly-used or trusted crates.
I do like this website though!
It also seems to be more actively maintained than `chrono`; i would recommend preferring `time` for new projects.
I wish this existed when i was starting out with Rust ;)
> You might consider using tracing instead. It's been a while since slog was created and it served Rust community well all this time. It remains a stable, featureful and battle-tested library, used in many important projects.
> In last few years, another ecosystem for Rust was created with similar features and a very good support for debugging async code and already larger dev team and community.
> Please check tracing and see if it is more suitable for your use-case. It seems that it is already a go-to logging/tracing solution for Rust.
> Reasons you might want to stick with slog anyway:
> async support doesn't benefit you
> you consider mature, stable code & API a plus
> it has some features that tracing is missing
> great performance (I have NOT done any comparison, but slog's performance is very good).
Thanks for it btw!
- slotmap
- memchr
- bytecount
- rouille
- csv
bytecount is faster than memchr for counting occurrences for bytes. It doesn't have to stop and report offsets. It can just zip through and count.
Does anybody else have a similar background that can share their opinion/love level of rust?
Rust people: do you use Rust for (nearly) everything? i.e. does it feel very general purpose, or if you are doing something that will be entirely network I/O bound anyway do you reach for something else?
I've used Rust for *nix based IOT programs to ingest data from different sources (network I/O, serial, CAN, files, etc), as well as for bare-metal embedded development. I've also made some dinky webservers as an exercise and various random tooling.
It's a very, very flexible language, once you get over its quirks. I found myself using it to make tools that I would usually turn to Python for. I'm quite impressed with how "high level" the language feels despite being able to work with low-level concepts. Simple stuff like mapping iterators and the Option<T> type while working without an OS is a fantastic feeling.
As most people will likely say, take Rust for a test drive with a basic project to decide for yourself. I would say to keep it simple and not go down the async route as your first foray, though.
As far as things I typically make, database-backed HTTP APIs are probably the most common, and influxdb collectors second most common.
Not Elixir but I spend 10 years in Erlang before moving to Rust and prefer to never go back.
A statically typed language is just better. No matter how easy Erlang/Elixir makes some things. I do not at all miss needing to refactor my code and being scared of all the crashes that inevitably result. I do not at all miss seeing crashes that only show up under production load.
How long did it take you to get to the point with Rust where you wouldn't want to back?
Do you use any sort of actor implementation in Rust?
I do not use an actor framework. It is best to use whatever is standard for the language. For Rust this is Tokio async ecosystem.
I come from higher level language(s). But I find hard to program without functional composition as well.
> Rust people: do you use Rust for (nearly) everything? i.e. does it feel very general purpose, or if you are doing something that will be entirely network I/O bound anyway do you reach for something else?
General purpose language != efficient for all the use cases. I do a considerable amount of hobby programming in Rust, but I think it's a niche language. I think it's vastly most efficient to use other language in the very large majority of the use cases - there are plenty of modern languages the are good enough and don't have such a high overhead (ie. manual memory management). Nonetheless I've found that with a couple of years of experience (likely less than half, if programming professionally), developing with Rust is considerably simpler than one would imagine.
Haskell and the ML family are fine but they just don't have the same number of high-quality libraries with the well thought out modern stdlib of Rust as a base. Elixir/Erlang/Lisps are fine but I'd really like strong, static types. Gleam/Pony are too niche. I'd like to like Scala but every time I try I run into something inscrutable and demonic, and the Java ecosystem is comprehensive but (in my opinion) super annoying.
I love the functional style of Elixir, it's elegant to write and read, but feels unsafe. The lack of a type system is hard for me and has been a nightmare when trying to find the origin of a particular error tuple and refactoring code, running the app to see if it works. Running it in production feels like a ticking time bomb, even if it does handle fault tolerance gracefully.
I've reached for Rust for the occasional project and have never regretted it, I couldn't justify its use for everything though. Very high-quality ecosystem, rock solid and predictable performance and tiny footprint. I've made a VPN supervisor process that fits in a few MB Docker image (without OS), uses a few MB of RAM, no idle CPU and wonderful latency.
Perhaps Erlang can manage tail latencies better under load, pre-emptive scheduling is awesome, but my personal experience has been that Rust is just much more efficient at doing the same task, giving you more free CPU time, predictable memory freeing that rivals Erlang's per-process GC. You finish that blocking computation before it even becomes noticeable. Erlang’s fault tolerance is matched by Rust’s type system and memory safety guarantees. It's hard to compare C++/Rust to Erlang/Python/Ruby, they're just different.
It's slower and more frustrating to write, but the language server gives you so much feedback and useful comments. I find the linter amazing, it finds some pretty obscure and neat improvements with the additional type information it has, and Option<T> and Result<T,E> have an almost functional-like chaining pattern.
For a small hobby project, Rust 100% of the time. No painful dependency management, no complex build process. For a more serious project, or for a client, not always justifiable. I always miss Rust’s language features and libraries when coding in another language that has the upper hand in their respective dominant fields, although I like that a lot of tooling (ESBuild, swc, Tailwind's compiler, fnm, Rome, ...) is being remade in Go/Rust, it benefits far more people than it inconveniences.
Nearly. There are still some things easier to do in Python or JS, but the gap is closing quickly and I'm fine with spending small amount of convenience to get quality of Rust code. I am looking now into having nearly 100% Rust frontend + Rust backend for some simple project and it does look promising.
[0] https://news.ycombinator.com/item?id=12177002
[1] https://internals.rust-lang.org/t/follow-up-the-rust-platfor...