This is the permalink for the full archive of #Rust tips: https://octodon.social/@rust
You can easily pass ownership of #Rustlang objects to C. There's no need to use `Box::into_raw()` or any unsafe trickery. Box is FFI-safe, and can be used as a return type directly:
Did you know crates.io has added new categories? Make your #Rustlang crate easier to find. Add categories to your Cargo.toml:
categories = ["insert category slugs here"]
#TIL that you can disallow certain types in your #Rust code with #Clippy (since 1.55):
https://nnethercote.github.io/perf-book/linting.html#disallowing-types
This is useful, if you e.g. want to use a faster HashMap (e.g. from ahash) and not the std HashMap.
Official docs:
https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type
Compare the uncomparable! #Rust enum variants can be compared with `==` only if they implement the `PartialEq` trait, but that isn't always available or convenient for enums with complex data.
However, the `match` expression always works, and there's a handy `matches!()` macro for one-off comparisons.
if value == SomeEnum::Variant(data) { /* maybe */ }
if matches!(value, SomeEnum::Variant(_)) { /* ok */ }
More examples:
https://play.rust-lang.org/?gist=359076b8145247b6d6b0295b46794a8a
If you're developing #Mac or #iOS applications, you can add #Rust dependencies to your projects using https://lib.rs/cargo-xcode
Common Rust Lifetime Misconceptions — very helpful resource that helps avoid fighting the borrow checker:
https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md
Use the following to include your README in your `doctest`s (so that your examples in your README are also executed).
#[doc = include_str!("../README.md")]
#[cfg(doctest)]
pub struct ReadmeDoctests;
See here:
https://doc.rust-lang.org/rustdoc/documentation-tests.html
You can convert a slice (or a `Vec`) to a fixed-length array using the `TryInto` trait:
let arr: [_; 4] = slice[..4].try_into().unwrap();
It's a bit verbose, but the `.try_into().unwrap()` part will be optimized out entirely whenever the compiler can see the slice is long enough.
"Unfortunately" this doesn't generalize to all attributes, so you can't have a cursed syntax like that:
struct Lol {
#![derive(Copy, Clone, Debug)]
}
fn nope() {
#![test]
}
#Rust has meta attributes that can apply to entire modules, like #[cfg(…)], #[allow(…)] and #[deny(…)].
The #[…] attribute syntax used outside of a module is equivalent to #![…] syntax inside it:
#[cfg(windows)]
mod win {
}
mod win {
#![cfg(windows)]
}
You have to use #![…] attribute syntax at the top of the lib.rs file, because there's no outer file that has the `mod` declaration for lib.rs.
The `.get()` method on a `Vec` or `HashMap` will only temporarily borrow an item, and you won't be allowed to move it or use it outside of the scope of the `.get()` call.
If you want to get an _owned_, freely movable value, use `.remove()` instead.
If you need to have an owned value without removing elements from the collection, you're going to have to clone. Clone can be fast if items are wrapped in `Rc` or `Arc`.
https://play.rust-lang.org/?gist=a7ccfd499aaafc4a3cb35d6e4dd16e03 #rustlang
Do you want io::Read::read_exact(), but read into a Vec instead?
let bytes_read = reader
.by_ref() // optional: avoids consuming the reader
.take(length_to_read) // limits number of bytes
.read_to_end(&mut vec)?; // reads up to the limit
// the file could have ended sooner, so needs a check
if bytes_read != length_to_read { return Err("EOF") }
https://play.rust-lang.org/?gist=05ac9c2145aa61b3442359921dd0607d
Cargo crate stats: https://lib.rs/stats
Number of #Rust users is growing exponentially. Downloads are more than doubling each year.
A quick way to update all your #Rust dependencies to their latest versions:
cargo install cargo-edit
cargo upgrade
It's worth bumping all versions to the latest regularly, because your code may be accidentally depending on newly-added features.
Cargo usually picks latest available versions, but not always. If you don't explicitly test with older versions of your dependencies, you can't promise they still work.
Try and weep:
cargo +nightly -Z minimal-versions generate-lockfile
Version numbers in #Rustlang Cargo mean this version *or later* that is semver-compatible.
[dependencies]
nom = "6.0.0"
will actually use nom 6.1.2 (or any later version lower than 7.0.0).
Forcing an exact version requires a "=" prefix, but don't pin dependencies like that unless necessary: it can cause dependency conflicts.
Cargo may pick a less-than-latest verison to satisfy other dependencies or Cargo.lock, so make sure your project actually works with the versions you specify.
If you're implementing an Iterator for a complex custom collection in #rustlang, implement optimized `try_fold`.
https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.try_fold
This method allows keeping state during iteration more efficiently than `.next()` allows, and may optimize better.
https://medium.com/@veedrac/rust-is-slow-and-i-am-the-cure-32facc0fdcb
`#[deny(warnings)]` will sooner or later break your code.
#Rust keeps adding new warnings and refining behavior of existing ones. If you're not prepared to deal with potential new compilation errors every 6 weeks, don't use #[deny(warnings)].
Rustc has a cap-lints feature to disable this footgun in dependencies, but it doesn't help macro-generated code and top-level crates.