This is consistent with the other pieces of tor-proto, which do not
handle timeouts on their own. It also lets us remove tor-rtcompat
as a dependency from tor-proto, and simplify some of the test cases
to use async_test.
This commit unindents a lot of test code; use git's "-b" flag to
read the parts that matter.
Now other crates don't need any 'ifdef tokio' code, since there
are wrappers that implement 'futures' right.
Technically, the 'futures' traits are in some ways less good than
the tokio ones, but we need a consistent API if we want to support
WASM someday and keep support for async_std. I'd rather hold out
hope for a future version of futures::io working like tokio than to
fix ourselves into the tokioverse forever.
At this point I'm going to pause writing tor-proto tests for a
little while and think about refactoring that could make these tests
simpler. I'm doing way too much copy-paste here.
dalek-crypto is stuck on rand_core 0.5.1, so we've been stuck too.
This commit introduces a compatibility module so that we can wrap
new rand_core instances to make them backward compatible.
Previously we'd flush after every write. Now we only flush when the
reader has nothing more to tell us. This way we can be sure that we're
sending out the data as soon as we can, without leaving any cells
partially filled unnecessarily.
The tricks I needed here turned out to be:
* I needed to store the future returned by read_cell() while it is
returning Poll::Pending.
* Since the type of that future is secret, I needed to put it in a
Box<dyn Future>.
* But since that future holds a reference to the DataReader, that
would create a self-referential structure if we tried to store
the DataReader and the future at the same time. So instead, I
had to make an enum() that either holds a DataReader directly,
or holds the future that will give us back the DataReader when
it's done. (I also had to change the read_cell() function so
that it takes ownership of the DataReader, and returns it when
it's finished.) (Daniel Franke explained how to do this.)
* Finally, I couldn't figure out how to change the enum's type
in-place, so I had to wrap it in an Option<>. (Daniel Franke
says this isn't actually necessary.)
I've noted a couple of places in the read code where I want to
handle errors and closes more carefully.
These new (internal so far) APIs correspond more closely to what
we'll need for AsyncRead and AsyncWrite.
We also make write methods take a mutable reference to self, since
that seems to be (closer to) what the AsyncRead/AsyncWrite code
expects.