rust - How can I wrap any impl of std::error::Error to ease error propagation? -
i'm trying simplify error flow in webapp i'm working on, , plan make struct implements std::error::error
, forwards result of description()
whatever kind of error it's wrapped around. i've implemented from
types of errors want wrap, struct makes easy use try!
uniform error result. here's have far struct:
#![feature(convert)] use std::error::{error}; use std::fmt::{self,display,formatter}; use std::io::{self,read}; use std::ops::deref; use std::fs::{file}; #[derive(debug)] pub struct strerr{ desc:string, c: option<box<error>> } impl strerr{ pub fn new(msg:string) ->self{ strerr{desc:msg, c:none} } } impl error strerr{ fn description(&self) -> &str{ self.desc.as_str() } fn cause(& self) -> option<& error> { self.c.map(|e| e.deref()) } } impl display strerr { fn fmt(&self, f:&mut formatter) -> result<(),fmt::error> { f.write_str(self.desc.as_str()) } } impl from<io::error> strerr { fn from(o:io::error) -> self { strerr{desc: string::from(o.description()),c:some(box::new(o))} } } fn main(){ let contrived = some("foo.txt") .ok_or_else(|| strerr::new(string::from("error message"))) .and_then(|filename| ok(try!(file::open(filename)))) .and_then(|mut file| { let mut content = string::new(); try!(file.read_to_string(&mut content)); ok(content) }); if let ok(content) = contrived { println!("got content: {}", content); } else { println!("got error"); } }
the problem cause()
method - can't return reference inner error
instance because e
doesn't live long enough. there different way can structure can keep generic reference implements error
(which putting in box) can still implement error
trait (which expecting ref parent error
)?
i've worked around punting on cause()
, having return none
, i'd rather conform intent of trait.
rustc 1.2.0-nightly (613e57b44 2015-06-01) (built 2015-06-02)
this 1 way can convert option<box<trait>>
option<&trait>
. i'm avoiding of trait implementation show interesting code:
use std::error::error; pub struct strerr { c: option<box<error>> } impl strerr { fn cause(&self) -> option<&error> { self.c.as_ref().map(|e| &**e) } } fn main() {}
we use option::as_ref
avoid consuming self.c
item. map
closure provided &box<trait>
, dereference twice trait
, , reference once &trait
.
Comments
Post a Comment