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

48 lines
2.6 KiB
Markdown
Raw Normal View History

2022-04-10 21:44:06 -05:00
---
title: A little type system trick in Rust
date: 2022-03-15
---
> This post is day 1 of me taking part in the
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
While working on a small project recently, I ended up writing this type in Rust.
```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](https://en.wikipedia.org/wiki/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](https://en.wikipedia.org/wiki/Linearizability#Primitive_atomic_instructions),
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](https://en.wikipedia.org/wiki/Lock_(computer_science))
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](https://en.wikipedia.org/wiki/Tagged_union),
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](https://docs.rs/image/latest/image/index.html).
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.