rust-imap
rust-imap copied to clipboard
Does rust-imap parse things twice?
It seems like a common pattern in the codebase is to use
run_command_and_read_response
, and then parse its output. However,read_response
already fully parses the response, its just that the results of the parsing seems to be discarded https://github.com/mattnenterprise/rust-imap/blob/master/src/client.rs#L521.Assuming my reading of the code is correct, is there a reason it's laid out like this, as opposed to read_response returning a Vec of the parsed responses or similar?
See the original issue here: https://github.com/mattnenterprise/rust-imap/issues/78
This seems like an interesting thing to look into, but first what are we looking into?
We can see every time run_command_and_read_response
is called we are generally executing another parsing function on the returned response.
rg -i -A3 run_command_and_read_response
https://github.com/jonhoo/rust-imap/blob/5d0d2f9723b626770ffeab7e334ded67ae94fd7e/src/client.rs#L353-L358
read_response
parses the response once to assess if there were any errors (all the way to the end), and then Capabilities::parse
parses the entire response again to identify the capabilities therein. (I believe)
The ideal situation would be able to compose different parsers together and iterate over the stream just once. That's just my current understanding, but I haven't written too much Rust yet so still getting my bearings.
read_response_onto
being the one responsible for reading through the whole response once. After which subsequent parsers will iterate through the whole response again.
https://github.com/jonhoo/rust-imap/blob/5d0d2f9723b626770ffeab7e334ded67ae94fd7e/src/client.rs#L1521-L1525
imap-proto
makes heavy use of nom
and streaming
parsing to handle parsing the streams.
It's likely that we can get rid of readline
by building on nom
as well:
https://github.com/jonhoo/rust-imap/blob/5d0d2f9723b626770ffeab7e334ded67ae94fd7e/src/client.rs#L1606-L1621
Theoretically there's a part of the stream that is "general control", some that's "specific control for the request", and then finally the data we want to parse. We would want to be able to compose these parsers as so: general_control(specific_control(data))
and that should do parsing in one pass.