Skip to content

Commit 98513c1

Browse files
committed
Implement display with self clause (#8, #10, #6)
Author: Colin Kiegel <[email protected]>
1 parent 62e9f79 commit 98513c1

File tree

2 files changed

+67
-20
lines changed

2 files changed

+67
-20
lines changed

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ Here is the comprehensive example:
2828
}
2929
Other(descr: &'static str) {
3030
description(descr)
31-
display("Error: {}", descr)
31+
display("Errorr {}", descr)
3232
}
3333
IoAt(place: &'static str, err: io::Error) {
3434
cause(err)
35-
display("Error at {}: {}", place, err)
35+
display(me) -> ("{} {}: {}", me.description(), place, err)
3636
description("io error at")
3737
from(s: String) -> ("some string",
3838
io::Error::new(io::ErrorKind::Other, s))

src/lib.rs

Lines changed: 65 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,28 @@
113113
//! }
114114
//! ```
115115
//!
116+
//! If you need a reference to the error when `Display`ing, you can instead use
117+
//! `display(x) -> (pattern, ..args)`, where `x` sets the name of the reference.
118+
//!
119+
//! ```rust
120+
//! # #[macro_use] extern crate quick_error;
121+
//! # fn main() {}
122+
//! #
123+
//! use std::error::Error; // put methods like `description()` of this trait into scope
124+
//!
125+
//! quick_error! {
126+
//! #[derive(Debug)]
127+
//! pub enum SomeError {
128+
//! Io(err: std::io::Error) {
129+
//! display(x) -> ("{}: {}", x.description(), err)
130+
//! }
131+
//! Utf8(err: std::str::Utf8Error) {
132+
//! display(self_) -> ("{}, valid up to {}", self_.description(), err.valid_up_to())
133+
//! }
134+
//! }
135+
//! }
136+
//! ```
137+
//!
116138
//! To convert to the type from any other, use one of the three forms of
117139
//! `from` clause.
118140
//!
@@ -181,7 +203,6 @@
181203
//! Empty braces can be omitted as of quick_error 0.1.3.
182204
//!
183205
184-
185206
/// Main macro that does all the work
186207
#[macro_export]
187208
macro_rules! quick_error {
@@ -376,9 +397,11 @@ macro_rules! quick_error {
376397
match self {
377398
$(
378399
&$name::$item $( ( $(ref $var),* ) )* => {
379-
quick_error!(FIND_DISPLAY_IMPL
380-
$item self fmt [ $( ( $($var)* ) )* ]
381-
{ $($funcs)* })
400+
let display_fn = quick_error!(FIND_DISPLAY_IMPL
401+
$name $item
402+
{ $($funcs)* });
403+
404+
display_fn(self, fmt)
382405
}
383406
)*
384407
}
@@ -415,25 +438,34 @@ macro_rules! quick_error {
415438
{ $($funcs)* });
416439
)*
417440
};
418-
(FIND_DISPLAY_IMPL $item:ident $me:ident $fmt:ident
419-
[ $( ( $($var:ident)* ) )* ]
420-
{ display($($exprs:tt)*) $($tail:tt)* }
441+
(FIND_DISPLAY_IMPL $name:ident $item:ident
442+
{ display($self_:tt) -> ($($exprs:tt)*) $($tail:tt)* }
421443
) => {
422-
write!($fmt, $($exprs)*)
444+
|quick_error!(IDENT $self_): &$name, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) }
423445
};
424-
(FIND_DISPLAY_IMPL $item:ident $me:ident $fmt:ident
425-
[ $( ( $($var:ident)* ) )* ]
446+
(FIND_DISPLAY_IMPL $name:ident $item:ident
447+
{ display($pattern:expr) $($tail:tt)* }
448+
) => {
449+
|_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern) }
450+
};
451+
(FIND_DISPLAY_IMPL $name:ident $item:ident
452+
{ display($pattern:expr, $($exprs:tt)*) $($tail:tt)* }
453+
) => {
454+
|_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern, $($exprs)*) }
455+
};
456+
(FIND_DISPLAY_IMPL $name:ident $item:ident
426457
{ $t:tt $($tail:tt)* }
427458
) => {
428459
quick_error!(FIND_DISPLAY_IMPL
429-
$item $me $fmt [ $( ( $($var)* ) )* ]
460+
$name $item
430461
{ $($tail)* })
431462
};
432-
(FIND_DISPLAY_IMPL $item:ident $me:ident $fmt:ident
433-
[ $( ( $($var:ident)* ) )* ]
463+
(FIND_DISPLAY_IMPL $name:ident $item:ident
434464
{ }
435465
) => {
436-
write!($fmt, "{}", ::std::error::Error::description($me))
466+
|self_: &$name, f: &mut ::std::fmt::Formatter| {
467+
write!(f, "{}", ::std::error::Error::description(self_))
468+
}
437469
};
438470
(FIND_DESCRIPTION_IMPL $item:ident $me:ident $fmt:ident
439471
[ $( ( $($var:ident)* ) )* ]
@@ -533,7 +565,11 @@ macro_rules! quick_error {
533565
// anything else.
534566
// This is to contrast FIND_* clauses which just find stuff they need and
535567
// skip everything else completely
536-
(ERROR_CHECK display($($exprs:tt)*) $($tail:tt)*)
568+
(ERROR_CHECK display($self_:tt) -> ($($exprs:tt)*) $($tail:tt)*)
569+
=> { quick_error!(ERROR_CHECK $($tail)*); };
570+
(ERROR_CHECK display($pattern: expr) $($tail:tt)*)
571+
=> { quick_error!(ERROR_CHECK $($tail)*); };
572+
(ERROR_CHECK display($pattern: expr, $($exprs:tt)*) $($tail:tt)*)
537573
=> { quick_error!(ERROR_CHECK $($tail)*); };
538574
(ERROR_CHECK description($expr:expr) $($tail:tt)*)
539575
=> { quick_error!(ERROR_CHECK $($tail)*); };
@@ -546,6 +582,8 @@ macro_rules! quick_error {
546582
(ERROR_CHECK from($fvar:ident : $ftyp:ty) -> ($($e:expr),*) $($tail:tt)*)
547583
=> { quick_error!(ERROR_CHECK $($tail)*); };
548584
(ERROR_CHECK) => {};
585+
// Utility functions
586+
(IDENT $ident: ident) => { $ident }
549587
}
550588

551589
#[cfg(test)]
@@ -594,14 +632,17 @@ mod test {
594632
/// I/O error with some context
595633
IoAt(place: &'static str, err: io::Error) {
596634
cause(err)
597-
display("Error at {}: {}", place, err)
635+
display(self_) -> ("{} {}: {}", self_.description(), place, err)
598636
description("io error at")
599637
from(s: String) -> ("idea",
600638
io::Error::new(io::ErrorKind::Other, s))
601639
}
602640
Discard {
603641
from(&'static str)
604642
}
643+
Singleton {
644+
display("Just a string")
645+
}
605646
}
606647
}
607648

@@ -633,7 +674,7 @@ mod test {
633674
let err: &Error = &IoWrapper::IoAt("file",
634675
io::Error::new(io::ErrorKind::NotFound, io1));
635676
assert_eq!(format!("{}", err),
636-
"Error at file: I/O error: some error".to_string());
677+
"io error at file: I/O error: some error".to_string());
637678
assert_eq!(format!("{:?}", err), "IoAt(\"file\", Error { \
638679
repr: Custom(Custom { kind: NotFound, \
639680
error: Io(Error { repr: Custom(Custom { \
@@ -657,7 +698,7 @@ mod test {
657698
#[test]
658699
fn io_wrapper_custom_from() {
659700
let io1: IoWrapper = From::from("Stringy".to_string());
660-
assert_eq!(format!("{}", io1), "Error at idea: Stringy".to_string());
701+
assert_eq!(format!("{}", io1), "io error at idea: Stringy".to_string());
661702
assert_eq!(io1.cause().unwrap().description(), "Stringy");
662703
}
663704

@@ -668,4 +709,10 @@ mod test {
668709
assert!(io1.cause().is_none());
669710
}
670711

712+
#[test]
713+
fn io_wrapper_signleton() {
714+
let io1: IoWrapper = IoWrapper::Singleton;
715+
assert_eq!(format!("{}", io1), "Just a string".to_string());
716+
}
717+
671718
}

0 commit comments

Comments
 (0)