bgenc.net/content/posts/rust-typesystem-tricks.md

2.6 KiB

title date
A little type system trick in Rust 2022-03-15

This post is day 1 of me taking part in the #100DaysToOffload challenge.

While working on a small project recently, I ended up writing this type in Rust.

type ImageData = Arc<Mutex<Option<ImageBuffer<Rgba<u8>, Vec<u8>>>>>;

Even though I wrote it myself, it actually took me a bit after writing it to figure out what this type was doing so I wanted to write about it.

Let me start from outside-in, the first type we have is Arc. Arc stands for "atomic reference counting". Reference counting is a method to handle ownership of the data, or in other words to figure out when the data needs to be freed. Garbage collected languages do this transparently in the background, but in Rust we explicitly need to state that we want it. Atomic means this is done using atomic operations, so it is thread safe. In my case, I needed this because this data was going to be shared between multiple threads, and I didn't know exactly when I would be "done" with the data.

The next type is Mutex, which means mutual exclusion or locking. Locks are used to restrict access to data to a single thread at a time. That means whatever type is inside of this is not thread safe, so I'm using the lock to protect it. Which is true!

The type after that is Option. This basically means "nullable", there may or may not be a thing inside this. The interesting thing here is that this is a sum type, so Rust helps remind us that this is nullable without introducing a nullability concept to the language. It's just part of the type system!

Then we have ImageBuffer, a type from the popular image crate. Not much to talk about with this, that's the data I wanted to store.

The next thing that is interesting is the Rgba<u8> and Vec<u8> inside the image buffer. What that means (and I'm speculating here because I'm lazy/too busy to check), is that Rgba is just a basic wrapper type (or a "newtype"). It makes the compiler enforce the type of the image data that's stored in this image buffer, so the user doesn't mix up different data types. Similar for Vec<u8>, (I think) it means that the data inside this buffer is stored in a vector.

Finally, u8 is probably self descriptive, the pixels and the vector are made out of 8-bit unsigned integers.