Reputation: 3401
I'm trying to use the snafu crate for error handling, but keep getting erros that my Error enum struct is missing the 'source' and that IntoError
is not implimented for Error
:
//main.rs
use snafu::{ResultExt, Snafu};
#[derive(Debug, Snafu)]
#[snafu(visibility = "pub(crate)")]
pub enum Error{
#[snafu(display("Could not load gallery JSON: {}: {}", json_path, source))]
LoadGallery {
source: std::io::Error,
json_path: String,
},
}
//gallery.rs
use snafu::{ResultExt};
use crate::Error::{LoadGallery};
pub struct Gallery{
name: String,
}
impl Gallery{
pub fn from_json(json_path: String)->Result<()>{
let configuration = std::fs::read_to_string(&json_path).context(LoadGallery { json_path })?;
Ok(())
}
}
results in:
let configuration = std::fs::read_to_string(&json_path).context(LoadGallery { json_path })?;
| ^^^^^^^^^^^ missing `source`
let configuration = std::fs::read_to_string(&json_path).context(LoadGallery { json_path })?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoError<_>` is not implemented for `Error`
Based on this example from the docs, I don't see what I'm doing wrong:
use snafu::{ResultExt, Snafu};
use std::{fs, io, path::PathBuf};
#[derive(Debug, Snafu)]
enum Error {
#[snafu(display("Unable to read configuration from {}: {}", path.display(), source))]
ReadConfiguration { source: io::Error, path: PathBuf },
#[snafu(display("Unable to write result to {}: {}", path.display(), source))]
WriteResult { source: io::Error, path: PathBuf },
}
type Result<T, E = Error> = std::result::Result<T, E>;
fn process_data() -> Result<()> {
let path = "config.toml";
let configuration = fs::read_to_string(path).context(ReadConfiguration { path })?;
let path = unpack_config(&configuration);
fs::write(&path, b"My complex calculation").context(WriteResult { path })?;
Ok(())
}
fn unpack_config(data: &str) -> &str {
"/some/path/that/does/not/exist"
}
Upvotes: 0
Views: 510
Reputation: 26157
It's because when you're constructing LoadGallery
, you're attempting to construct Error::LoadGallery
. You then get a compile error saying "missing source
", because the Error::LoadGallery
variant has a source
field. Fixing it is straight forward, you just need to change which LoadGallery
you import.
// Not this one:
// use crate::Error::LoadGallery;
// This one:
use crate::LoadGallery;
Why? Because snafu
generates a struct
for each of Error
's variants. So there's a struct LoadGallery
being generated. This struct doesn't contain the source
field, which is why you can construct it without source
and pass it to context()
, because it's not actually Error::LoadGallery
.
Your from_json()
also needs to return Result<(), Error>
instead of Result<()>
(you don't have the type alias, like in the example.)
use crate::{Error, LoadGallery};
use snafu::ResultExt;
pub struct Gallery {
name: String,
}
impl Gallery {
pub fn from_json(json_path: String) -> Result<(), Error> {
let configuration =
std::fs::read_to_string(&json_path).context(LoadGallery { json_path })?;
Ok(())
}
}
If you're curious you can use cargo expand
to inspect what macros expand to. You first need to install it by doing cargo install expand
. Then you can execute cargo expand
in any project.
Upvotes: 1