Composing errors of different types

I have the following code, where msg is a websocket message that may be convertible to a string:

let str_result = msg.to_str();
let result = str_result.map_or(Err(XXX), serde_json::from_str::<TargetType>);

The problem with this code is that to_str returns a Result<&str, ()> while serde_json::from_str returns a Result<TargetType, serde_json::error::Error>. Is there an elegant way that I can convert the error from to_str into a serde_json::error::Error, e.g., an EOF error?

Is there a better approach to solving this problem in general that I am missing?

I guess this problem could be solved if I was able to create a serde_json error like in the following pseudo code:

let str_result = msg.to_str();
use serde_json::error::{Category, Error};
str_result.map_or(Error::new(Category::Eof), serde_json::from_str::<TargetType>);

However, the API doesn't seem to provide this functionality, which makes me think that I am trying to solve this problem incorrectly...

What I would do, and have done, in this situation is create a module-private or crate-wide error enum type, and add variants to the enum that represent all possible errors that could occur there. That way, you can just have your own code return a Result<T, MyError> and just use question marks in there.

There is one tricky aspect to this though, and that is if your own error needs to derive certain trait impls eg Debug or PartialEq/PartialOrd/Eq/Ord, and the encapsulated errors do not provide a trait impl for that.
In that case it might be more useful to simply convert the encapsulated errors to some kind of string, and encapsulate that instead of the originally encapsulated error. That way you can still do pattern matching (one of the main reasons to go for enums over traits).

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.