Good job! Exposing state could make any async function 'pure'. All the user needs to do is push the state machine to the next state. I have tried to bind OpenSSL to async Rust before, its async API follows a similar design.
Is the similarity you are seeing that the work itself that gets scheduled via a job is agnostic over how it is executed?
From this example [0] it looks more like that async API is very similar to Rust's futures:
- Within a job you can access a "wait context"
- You can suspend on some condition
- You can trigger a wake-up to continue executing
[0]: https://www.openssl.org/docs/man1.1.1/man3/ASYNC_is_capable....
It is possible to do the same blocking IO but it feels a little less natural: You have to set the read-timeout on the socket to the time when you need to wake-up the state machine.
[0]: https://github.com/firezone/sans-io-blog-example/blob/99df77...