I think I noticed in this article that Rust Future is basically a state machine, which is propagated through its states via appropriate runtime (and parked when not ready to move to a next state). But I did not appreciate this fact fully until recently I was making a small utility (here is new version for new futures and tokio) for creating tar archive asynchronously – it should be a Stream that produces chunks of data – first file header and then pieces of it’s content. When file is done move to next file, until all required files are sent to stream, then finally send two empty blocks, each of 512 bytes of binary zeros. I needed this Stream for my audioserve project, where I wanted to download content of whole directory as a tar archive. Stream is a kind of Future (which produces many values instead of just one), so it’s also a state machine. And when I started to think about it this way, implementation was obvious. Rust algebraic type system is of great help here as we can represent state with one complex enum type ( called TarState in this case) and it’s variants represent states of this state machine and also contain necessary internal variables for each state. So lets see state diagram for our TarStream:
With this vision in mind it was then fairly easy to implement the TarStream (although the manual implementation of state machine is not usually much exciting, but Rust types at least make it nice and clean).