I am trying to use generics to deserialize structs from file for use with a Swagger generated API. So I have hacked together this which almost works, but I am unable to unpack t
When you use a type parameter like T here:
fn readfile(filename: String) -> Result, Box>;
The concrete type of T is determined by the caller. The compiler doesn't just look at all available type and make a guess at what makes sense.
First of all, you need to tell the compiler that any T passed here will actually work. That means constraining T to be something that is deserializable, within compatible lifetimes:
// filename should be &str here
fn readfile<'a, T: ?Sized>(filename: &str) -> Result>, Box>
where
for<'de> T: Deserialize<'de> + 'a
{
let f = std::fs::File::open(filename)?;
let config_data: Outer = serde_yaml::from_reader(f)?;
Ok(Box::new(config_data))
}
// filename should be &str here
fn readconfig<'a, T: ?Sized>(filename: &str) -> Result>, &'static str>
where
for<'de> T: Deserialize<'de> + 'a
{
// read the config file
let config_data = readfile(filename);
match config_data {
Ok(e) => {
Ok(Box::new(*e)) // need to deref the Box before reboxing
},
Err(_) => {
Err("nadda")
}
}
}
Next, when you call this, you need to tell it a concrete type:
let result: Box> = readconfig("config.yaml")?;
This will fail if the input cannot be parsed into a Box, in which case you can try parsing it to Box, perhaps using Result::or_else.