Just to be clear, a custom error type would not break try!, provided you have impl From<ReadExactError> for io::Error somewhere. You could also make using the combinators relatively painless by having a shorthand into_io_error method. Both of these could just turn Partial into UnexpectedEof.
I’d personally be leery of having read_exact return “success”, despite not actually reading anything. read_exact should be a convenience method; if you have to wrap it in yet another wrapper to get the “obvious” behaviour, it’s not doing its job.
Also, for those wondering: RFC #980, and it contains the following:
In the same way, if this method fails, there is no way to determine how many bytes were read before it determined it couldn’t completely fill the buffer.
Situations that require lower level control can still use read directly.