I’m working on a parser for a packet-based file format. The different packets are processed by different functions To get at the actual data, I pass in a std::io:Error
. I’ve considered three different approaches, but each has issues.
Currently, I’m passing around a &mut std::io::read
, i.e., something like:
fn foo_process(reader: &mut T) -> Result<Foo, std::io::Error>
But, this apprears to be incompatible with flate2’s expectations, which appears to want to own the std::io::Read
. (Or, I can’t figure out how to get it to work. Example code here: https://play.rust-lang.org/?gist=217ad42f5aac811a4ea4d4113ff40ee0&version=stable ).
Moving the std::io::Read
obect into the function solves that problem, but, then I have to worry about returning it and the deserialized packet, i.e., something like:
fn foo_process(reader: T) -> Result<(Foo, T), std::io::Error>
Which is ugly.
I’ve also played with boxed trait objects:
fn foo_process(reader: Boxstd::io::Read) -> Result<Foo, std::io::Error);
But this approach clutters the code with lots of boxing and unboxing, has a few Sized
issues, which require some acrobatics, and has a small performance cost, which I don’t think is significant for this code. Although, I’ve come furthest with this approach, I suspect it is less idomatic.
So, my question is: should I be passing around references, moving objects, or using boxes?
Thanks!