48 lines
2.6 KiB
Markdown
48 lines
2.6 KiB
Markdown
|
---
|
||
|
title: A little type system trick in Rust
|
||
|
date: 2022-03-15
|
||
|
---
|
||
|
|
||
|
> This post day 1 of me taking a 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.
|
||
|
|