Introduction to using Rust Libraries (cargo and crates)
So perhaps you’re thinking it’s time to use Rust on your next project. You’ll find plenty of primers on how to get your feet wet in the language (and if you somehow made it this far without that much, The Book is that starting point), but maybe you’re feeling a bit lost amidst the seas of opportunity. While still growing, the Rust ecosystem has many great existing options to pull from, and you’re now asking “How do I even?”
If you’re wondering how to make sense of your third-party library ecosystem, I hope to get you thinking like a Rustacean.
If you’re stuck on trying to find the right library for you, jump down to the section on crates for a primer on discoverability. Otherwise, if you already know what you’re working with and are looking to understand it, keep reading to see how I do it.
Documentation
Great, so you found a crate you’re interested in and want to start using it. Generally, an idiomatic Rustacean will provide “official” documentation within the Docs.rs platform, which is a companion to Crates.io; as with most things Rust, there is a Book for this purpose.
Note in the crate landing pages that many provide Documentation links (not always true). This documentation is programmatically generated by the cargo doc
command, and members of a codebase are collated into HTML documentation. Using Arrow as an illustration, let’s take a quick look at its corresponding Docs.rs landing page:
Not all libraries are created equal, but Apache represents one of the better groups of authors in the Rust community. As you’ll see if you get curious and click the source link shown above, you’ll find that the documentation is in fact the source code in disguise, with fancy-formatted comments as the headliners. These embedded documents are one of the principal ways in which Rust library developers communicate information to their consumers.
…And that brings us to one of the most important facets of Rust development – the source code is the documentation. Yes, there are comments, official human-readable documentation, maybe even fancy standalone websites walking you through the codebase, but at the end of the day you as a Rust developer are expected to consult the source code at some point. There are multiple points of consideration at play:
- The emphasis on idiomatic Rust is in large part because of this situation. Knowing you’ll be reading others’ code, the language idioms try to steer you into styles and best-practices that produce consistently formatted and structured code.
- The source code also functions as a teaching tool. This language inherently depends on communicating ideas through code, and one of the fastest ways to learn the language is to study what others are doing.
- Developers that follow the conventions get to benefit from a baked-in ecosystem of tools that make life easier.
Note, too, that everything you see in the documentation generated using cargo doc
is a 1:1 analog for what the LSP exposes in your IDE/editor. For instance, consider the hint popover in Helix when compared to the corresponding information in Docs.rs:
Examples
Well, the repo’s documentation might be enough to get you started, but in practice there’s only so much you can accomplish in one comment block. By convention, Rust accounts for the need for example code by allowing code authors to create example programs in /examples
under the project’s root, which can then be executed using the cargo run --example <example name goes here>
command.
In practice, an example program offers high-level and self-contained illustrations for how to accomplish a task. For instance, the examples in the parquet library include an illustration of how to read a parquet file. Examples like this tend to be accompanied by any necessary dependencies (e.g. mock data) so that they run out-of-the-box.
Personally, though I’ve put this point pretty far into the article, this is actually the first tool I’d reach for when trying to learn a new framework or library. In fact, some fast-moving libraries, such as Bevy, are highly dependent on examples to communicate its most important features or behaviors; this is reinforced in its official Book:
Bevy is still in the early stages of development … Documentation is sparse.
Practically speaking, you should be able to trust the examples more than the documentation, since the former will cause a compiler failure if they’re not well-formed, whereas the latter is dependent on having a developer that focuses on keeping descriptive text in sync with its backing codebase.
Tests
By convention, Rust developers are encouraged to package tests alongside the code that they target. Consider this excerpt from Rust By Example:
Most unit tests go into a
tests
mod with the#[cfg(test)]
attribute. Test functions are marked with the#[test]
attribute.
If you clicked the link above and continued reading, you’d note that tests
mod it refers to is located immediately below the functions they’re testing. By convention, a tests module tends to live at the bottom of a source file. Of course, this isn’t a mandate, and in fact it’s not uncommon to see other projects keep tests in their own folder (e.g. Rhai).
Arguing the merits and nuances of unit testing is a great way to start a war, right alongside debating whether vim is in fact superior to emacs. For the purposes of this discussion, just know that many authors use tests as a way to express how to consume an API.
Want to know how read nullable data in CSV using Arrow? There’s a test for that.
Wondering how to tell whether an Arrow schema contains a field? See the test.
In general, the line between examples and tests gets blurry; the former is purpose-built for illustrating ideas, while the tests are a tool that can be used different ways but often accomplishes the same objective as examples do. If you find that you need some illustrative code and didn’t get what you were after with examples, this is the next best place to check.
Community
One of Rust’s most glaring issues at the moment is that it’s hard to find other people in your environment writing it. It’s not hard to walk down the hall and find a person who knows Java or SQL, but finding a Rustacean in the wild is a bit of a challenge. By necessity, you’ll inevitably need to seek out strangers on the internet to get any kind of interactive help.
Thankfully, the online community for Rust is flourishing, and generally full of supportive people eager to see others’ interest in learning the language or finding uses for it. A typical Rustacean is self-aware enough to know that other languages exist and that their own isn’t necessarily the easiest to pick up on your own, so they’re often primed to be a bit more accommodating when someone asks for help.
Where the community lives depends heavily on the project in question. However, there are some common places to check:
Whatever your opinions of Reddit in general might be, you should know that the r/rust subreddit is a thriving forum for all things Rust. For language beginners, there’s a pinned “Got a question” thread that refreshes every week and has many eyes on it, and it’s very likely that you’ll get constructive feedback through this method. For broader questions, or things of a project-specific nature, firing up a new post will often get you some eager responses as well.
While you’re here, note that the sub’s header menu has a dropdown for Discussion Platforms that can take you in other directions as well, such as the official language forum or assorted Discord links.
GitHub (and the like)
This one is very project-dependent, but many projects (e.g. nalgebra) offer the Discussions feature. My own observation is that these forums don’t often offer immediate feedback, but when it’s offered is the preferred place to go with general Q&A. Absent that (or sometimes, in spite of it), the best way to get answers is to pose your question as an Issue (using another nalgebra example).
I’d also encourage looking at Issues as a means of gauging the project’s overall health. You can find library utilization stats on Crates.io by looking at the bottom of any crate’s landing page, but popularity doesn’t always equate to quality. Looking at both the open and closed issues’ histories, you can get a feel for how responsive authors are to user concerns as well as how volatile or dependable a codebase might be.
Discord
For whatever reason, Discord is popular for Rust projects, and is often the fastest way to get topical help. If this is the case, you’ll find that the project authors will make this information readily available.
Crates
So you know you are looking for something, but haven’t yet figured out what that something is? With rare exceptions, if it exists it can be found at Crates.io. You’d be hard-pressed to have gone through The Book (you did that, right?) and not know about Crates.io at this point. Support for this de facto package registry is baked into the Cargo distributables, and in this context the packages are referred to as “crates.”
For illustration purposes, I’ll walk you through how I wrapped my head around Arrow, which was showcased in a previous blog article. Various editors/IDEs may have some baked-in support for Crates.io cataloging, but for now we’ll use their web-based search function to track down the library in question (see the search box prominently displayed at the top of every page on the site).
Drilling into the first hit, you’ll see what is most likely the backing repository’s README.md file:
In this example, we knew the name of the library we were looking for and searched by name to find it; that was pretty easy, but what if we didn’t have that level of information? Thinking back to that article, we started with the premise that we were dealing with Parquet files. Searching for “parquet” instead, we see the following item at the top of our list:
This time, we get a different library name, eponymously named “parquet.” As it happens, though, under the hood both projects are in fact rooted in the same codebase (you’ll note the version, and if you verify the Repository link you’ll see both crates go to the same place).
Of course, you shouldn’t expect every project to be named for what it is. The search function in Crates.io is, as you surely expected, a full-text search that will match on keywords, though expect that you’ll probably need to page through the results to get what you need more often than not; stopping on the first page of hits would be a mistake if you’re not seeing the thing you’re looking for right away.
The landing page for a given project should serve as a launching point for any further needs you have. In particular, this page should feature the following (in addition to the aforementioned readme):
- License
- Installation instructions for the current version
- Link to documentation
- Link to source repository