Skip to content

Commit d3571f2

Browse files
committed
WIP: Add preliminary support for contexts
1 parent cb7a954 commit d3571f2

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed

examples/context.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#[macro_use(quick_error)] extern crate quick_error;
2+
3+
use std::io::{self, stderr, Read, Write};
4+
use std::fs::File;
5+
use std::env;
6+
use std::num::ParseIntError;
7+
use std::path::{Path, PathBuf};
8+
9+
use quick_error::{Context, ResultExt};
10+
11+
quick_error! {
12+
#[derive(Debug)]
13+
pub enum Error {
14+
NoFileName {
15+
description("no file name specified")
16+
}
17+
Io(err: io::Error, path: PathBuf) {
18+
display("could not read file {:?}: {}", path, err)
19+
context(path: &'a Path, err: io::Error)
20+
-> (err, path.to_path_buf())
21+
}
22+
Parse(err: ParseIntError, path: PathBuf) {
23+
display("could not parse file {:?}: {}", path, err)
24+
context(path: &'a Path, err: ParseIntError)
25+
-> (err, path.to_path_buf())
26+
}
27+
}
28+
}
29+
30+
fn parse_file() -> Result<u64, Error> {
31+
let fname = try!(env::args().skip(1).next().ok_or(Error::NoFileName));
32+
let fname = Path::new(&fname);
33+
let mut file = try!(File::open(fname).context(fname));
34+
let mut buf = String::new();
35+
try!(file.read_to_string(&mut buf).context(fname));
36+
Ok(try!(buf.parse().context(fname)))
37+
}
38+
39+
fn main() {
40+
match parse_file() {
41+
Ok(val) => {
42+
println!("Read: {}", val);
43+
}
44+
Err(e) => {
45+
writeln!(&mut stderr(), "Error: {}", e).ok();
46+
}
47+
}
48+
}

src/lib.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,11 @@ macro_rules! quick_error {
516516
$name $item: $imode [$( $var:$typ ),*]
517517
{$( $funcs )*});
518518
)*
519+
$(
520+
quick_error!(FIND_CONTEXT_IMPL
521+
$name $item: $imode [$( $var:$typ ),*]
522+
{$( $funcs )*});
523+
)*
519524
};
520525
(FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
521526
{ display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*}
@@ -586,6 +591,7 @@ macro_rules! quick_error {
586591
) => {
587592
None
588593
};
594+
// ----------------------------- FROM IMPL --------------------------
589595
(FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
590596
[$( $var:ident: $typ:ty ),*]
591597
{ from() $( $tail:tt )*}
@@ -656,6 +662,53 @@ macro_rules! quick_error {
656662
{ }
657663
) => {
658664
};
665+
// ----------------------------- CONTEXT IMPL --------------------------
666+
(FIND_CONTEXT_IMPL $name:ident $item:ident: TUPLE
667+
[$( $var:ident: $typ:ty ),*]
668+
{ context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
669+
-> ($( $texpr:expr ),*) $( $tail:tt )*}
670+
) => {
671+
impl<'a> From<Context<$ctyp, $ftyp>> for $name {
672+
fn from(Context($cvar, $fvar): Context<$ctyp, $ftyp>) -> $name {
673+
$name::$item($( $texpr ),*)
674+
}
675+
}
676+
quick_error!(FIND_CONTEXT_IMPL
677+
$name $item: TUPLE [$( $var:$typ ),*]
678+
{ $($tail)* });
679+
};
680+
/*
681+
(FIND_CONTEXT_IMPL $name:ident $item:ident: STRUCT
682+
[$( $var:ident: $typ:ty ),*]
683+
{ from($fvar:ident: $ftyp:ty) -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )*}
684+
) => {
685+
impl From<$ftyp> for $name {
686+
fn from($fvar: $ftyp) -> $name {
687+
$name::$item {
688+
$( $tvar: $texpr ),*
689+
}
690+
}
691+
}
692+
quick_error!(FIND_CONTEXT_IMPL
693+
$name $item: STRUCT [$( $var:$typ ),*]
694+
{ $($tail)* });
695+
};
696+
*/
697+
(FIND_CONTEXT_IMPL $name:ident $item:ident: $imode:tt
698+
[$( $var:ident: $typ:ty ),*]
699+
{ $t:tt $( $tail:tt )*}
700+
) => {
701+
quick_error!(FIND_CONTEXT_IMPL
702+
$name $item: $imode [$( $var:$typ ),*]
703+
{$( $tail )*}
704+
);
705+
};
706+
(FIND_CONTEXT_IMPL $name:ident $item:ident: $imode:tt
707+
[$( $var:ident: $typ:ty ),*]
708+
{ }
709+
) => {
710+
};
711+
// ----------------------------- ITEM IMPL --------------------------
659712
(ITEM_BODY $(#[$imeta:meta])* $item:ident: UNIT
660713
) => { };
661714
(ITEM_BODY $(#[$imeta:meta])* $item:ident: TUPLE
@@ -704,12 +757,34 @@ macro_rules! quick_error {
704757
=> { quick_error!(ERROR_CHECK TUPLE $($tail)*); };
705758
(ERROR_CHECK STRUCT from($fvar:ident: $ftyp:ty) -> {$( $v:ident: $e:expr ),*} $( $tail:tt )*)
706759
=> { quick_error!(ERROR_CHECK STRUCT $($tail)*); };
760+
761+
(ERROR_CHECK TUPLE context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
762+
-> ($( $e:expr ),*) $( $tail:tt )*)
763+
=> { quick_error!(ERROR_CHECK TUPLE $($tail)*); };
764+
(ERROR_CHECK STRUCT context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
765+
-> {$( $v:ident: $e:expr ),*} $( $tail:tt )*)
766+
=> { quick_error!(ERROR_CHECK STRUCT $($tail)*); };
767+
707768
(ERROR_CHECK $imode:tt ) => {};
708769
// Utility functions
709770
(IDENT $ident:ident) => { $ident }
710771
}
711772

712773

774+
pub struct Context<X, E>(pub X, pub E);
775+
776+
pub trait ResultExt<T, E> {
777+
fn context<X>(self, x: X) -> Result<T, Context<X, E>>;
778+
}
779+
780+
impl<T, E> ResultExt<T, E> for Result<T, E> {
781+
fn context<X>(self, x: X) -> Result<T, Context<X, E>> {
782+
self.map_err(|e| Context(x, e))
783+
}
784+
}
785+
786+
787+
713788
#[cfg(test)]
714789
mod test {
715790
use std::num::ParseFloatError;

0 commit comments

Comments
 (0)