Also, consider using error-chain
, it makes defining custom errors wrapping other crates errors super easy.
Although, as a learning exercise it could pay to implement it yourself manually first, then see how much boilerplate error-chain
can let you drop from your library
error-chain
also defines a struct wrapping an enum, but unlike serde
the enum is public and intended to be used by consumers. The reason it uses a struct is so it can store extra data along with the actual error, including a (very useful) stacktrace when running in debug mode.