I'm trying to wrap my head around the proper way to think about Result.
I'm writing a client library that speaks to a server using a simple protocol. The client sends a command name (a simple string), followed by parameters (key/value pairs). The server processes the command and replies with a "Ok" or "Fail" followed by parameters (key/value pairs).
I represent both these "commands" and "replies" as:
struct MgmtCmd {
cmd: String,
params: HashMap<String, String>
}
I'm using async-std, and in order to be able to use the convenience operator ? together with async-std's IO functions the async functions returns io::Result.
I have a function send_mgmtcmd that performs a synchronous "send command and wait for and receive a reply" sequence.
What feels most natural to me is if a server failure occurs, then I return an Err with a custom error, but this is where it gets confusing to me. The io::Result is designed to return specifically library IO errors, no? I can't just return my own custom error enums from the same function, right?
It feels natural that my function that sends the command and receives the reply returns a Result<MgmtCmd>, but the way I understand it the typically-used io::Result is hard-coded to return an async-std io::Error type for it's Err(), no?
So let's say I'm writing a function that does mixed IO calles to a "std" library (whether it be actual std, async-std or tokio) and custom processing of data that may cause custom errors that are not "IO Errors" -- what should that function's return type be to be compatible with:
- library IO errors
- My own custom errors
- The
?operator
Just generally looking for good resources on how to properly use Result with a mix/blend of error types from different libraries.