Chad Austin writes about systems programming, Rust, performance, terminals, and hardware tinkering, drawing on experience at Dropbox.
Commenters link his posts on performance, bitfields, CRTs and pixels, and unsafe Rust, and call his performance writing insightful.
Bitfields are hard! They are potentially unaligned, thus interact poorly with some language features, like pointers and references. And their size isn't a multiple of bytes, unlike any other value, which causes problems as well. They interact poorly with padding and the general idea of Rust ABIs that enables optimizations like reordering fields and using "niches" (invalid values) to find a more compact layout for structs and enums.
I agree Rust should eventually have some native support for bitfields, but only if it's a high quality spec that addresses the outstanding concerns - Rust should specifically avoid the C mess, which isn't usable for most projects.
But this doesn't mean bitfields can't be done in Rust; it's just not in the stdlib (yet). See this post[0] which contains a survey of various libraries (and their respective limitations), and this slightly older article [1]. Those articles somehow missed the modular-bitfield crate [2], which is perhaps the nicest to use, and is what I would recommend you.
If you don't care about the specifics you can get any crate discussed in the above articles and use them.
About interoperability with C (and C++), I really like bindgen, cbindgen and cxx. The bindgen book [3] is straighforward. This section of cxx documentation [4] also describes the tradeoffs between the different FFI approaches. I don't know Ada though, so I must ask: what does Ada do?
About this,
> I just don't see what Rust has to offer that Ada didn't already…
I do not have any non-Rust resources off the top of my head, but I can give you some quickly looked up resources and enough phrases to search for that should help you in this endeavor.
ADTs are Abstract Data Types[1][2][3]:
> ADT is implementation independent. For example, it only describes what a data type List consists (data) and what are the operations it can perform, but it has no information about how the List is actually implemented.
In the context of Rust it means that the traits, structs and enums are ADTs, while the impls are Data Structures.
Having structs and enums be the way they are in Rust (simplistic and with little extensibility beyond implementing traits) is that pattern matching[4][5] and destructuring is cheap and built in. Pattern matching becomes specially useful when combined with sum types/tagged unions/enums[6][7][8]. On the other corner you have Scala which lets you implement specific interfaces to allow structuring and destructuring for arbitrary types, but that has the same problems as overriding constructors in C++: the performance implications of pattern matching is impl dependent and hidden at the point of calling.
[1]: https://softwareengineering.stackexchange.com/questions/148747/abstract-data-type-and-data-structure
[2]: https://en.wikipedia.org/wiki/Abstract_data_type
[3]: https://abrickshort.wordpress.com/2005/03/06/abstract-data-types-vs-data-structures/
[4]: https://en.wikipedia.org/wiki/Pattern_matching
[5]:…
> The website prioritizes programs with 98% safe code over programs with 0% safe code.
Please explain this section of the Rustonomicon.
https://doc.rust-lang.org/nomicon/working-with-unsafe.html
> This code is 100% Safe Rust but it is also completely unsound. Changing the capacity violates the invariants of Vec (that cap reflects the allocated space in the Vec). This is not something the rest of Vec can guard against. It has to trust the capacity field because there's no way to verify it.
> Because it relies on invariants of a struct field, this unsafe code does more than pollute a whole function: it pollutes a whole module. Generally, the only bullet-proof way to limit the scope of unsafe code is at the module boundary with privacy.
If 2% code means that, wildly spitballing, 50% code has to be manually reviewed, it's not quite as impressive.
And it might be worse regarding memory safety than the "status quo" if one accepts the assumption that unsafe Rust is harder than C and C++, as many Rust developers do.
https://www.reddit.com/r/rust/comments/1amlfdj/comment/kpmb2b8/
> It may be even less safe because of the strong aliasing rules. That is, it may be harder to write correct unsafe {} Rust than correct C. Only use unsafe {} when absolutely needed.
https://chadaustin.me/2024/10/intrusive-linked-list-in-rust/
https://chadaustin.me/2024/10/intrusive-linked-list-in-rust/
https://news.ycombinator.com/item?id=41944121
The TLDR is that there’s all sorts of invariants that the Rust compiler internals assume about Rust code (eg pointers don’t alias). In C such assumptions can’t be made. Unsafe rust requires you to uphold all the same invariants that safe rust does without any guardrails and it has more such assumptions than C. C however is uniformly dangerous - there isn’t a safe subset to write your code in.
One example would be that you could have something like:
let x = 5; do_something(&x as *const _ as *mut _); Now do_something might dereference and write to the pointer. Now you have non-local safety to reason about because if the compiler realizes you’ve tried to dereference a mutable pointer to an immutable variable it’s free to declare that UB and do bad unsound things (the non-locality is because the unsafe is inside do_something but the problem is with the pointer cast in safe rust). There’s all sorts of subtle things like that.
> Choosing references as your default is insane, honestly. Safe Rust is akin to writing formally verified software in the mental and ergonomic overhead it incurs. That's not coincidental. I've come to the conclusion one of the biggest mistakes of the community is not pushing pointer-only Rust harder, given they want it to be taken seriously as a systems language.
That's an interesting perspective I hadn't heard before, but I think there are a couple problems. One, the culture is really against using unsafe unless it's impossible to write the code using safe Rust. This happened with the Actix web drama in 2020 [1]. And, there is the opinion that unsafe Rust is harder than C [2]. Not just that, but unsafe Rust is really ugly and annoying to use compared to safe Rust. I think that hinders the potential adoption of your idea, too.
[1]: https://steveklabnik.com/writing/a-sad-day-for-rust/
[2]: https://chadaustin.me/2024/10/intrusive-linked-list-in-rust/
That's not quite true. I had a look into the Bun port and it's not like c2rust where it literally will convert every pointer access into `unsafe` and 50% of your code will be `unsafe`. It's a lot safer than that. They claim only 4% of lines are unsafe, and 78% of those are from C/C++ interop. That's more than a typical Rust project but it's still a lot less than C/C++ or Zig.
> I could rewrite anything in unsafe Rust like right now, despite being a novice in the language.
I really doubt that. Unsafe Rust is actually significantly more difficult to get right than C or C++. See e.g. https://chadaustin.me/2024/10/intrusive-linked-list-in-rust/ or https://lucumr.pocoo.org/2022/1/30/unsafe-rust/
It's not too big of a deal because in idiomatic Rust you pretty much never write unsafe code (except for FFI), but it would be nice if it was not quite so hard (or poorly defined).