Skip to content

Instantly share code, notes, and snippets.

Created June 10, 2016 21:40
Show Gist options
  • Save anonymous/a6652bb9fc5cd2409551be5dec533a04 to your computer and use it in GitHub Desktop.
Save anonymous/a6652bb9fc5cd2409551be5dec533a04 to your computer and use it in GitHub Desktop.
Shared via Rust Playground
#![feature(specialization)]
macro_rules! debug_or {
($e:expr, $s:expr, $($a:expr),*) => {
$e.debug_or_else(|f| write!(f, $s, $($a),*))
};
($e:expr, $s:expr) => {
debug_or!($e, $s,)
}
}
fn main() {
struct X;
#[derive(Debug)] struct Y;
println!("{:?}", X.debug_or("-"));
println!("{:?}", X.debug_or(&1234));
println!("{:?}", X.debug_or_else(|f| write!(f, "{}", "-")));
println!("{:?}", X.debug_or_else(|f| write!(f, "{}", 1234)));
println!("{:?}", debug_or!(X, "-"));
println!("{:?}", debug_or!(X, "{:?}", "-"));
println!("{:?}", debug_or!(X, "{}", 1234));
println!("{:?}", Y.debug_or("-"));
println!("{:?}", Y.debug_or(&1234));
println!("{:?}", Y.debug_or_else(|f| write!(f, "{}", "-")));
println!("{:?}", Y.debug_or_else(|f| write!(f, "{}", 1234)));
println!("{:?}", debug_or!(Y, "-"));
println!("{:?}", debug_or!(Y, "{:?}", "-"));
println!("{:?}", debug_or!(Y, "{}", 1234));
}
use std::fmt::Debug;
use std::fmt;
enum DebugOr<'a, A: 'a + ?Sized, Fallback: 'a + ?Sized + Debug> {
A(&'a A),
Fallback(&'a Fallback),
}
enum DebugOrElse<'a, A: 'a + ?Sized, Fallback> {
A(&'a A),
Fallback(Fallback),
}
trait MaybeDebug {
fn debug_or<'a, U: ?Sized + Debug>(&'a self, u: &'a U) -> DebugOr<'a, Self, U>;
fn debug_or_else<'a, F: Fn(&mut fmt::Formatter) -> fmt::Result>(&'a self, f: F) -> DebugOrElse<'a, Self, F>;
}
impl<T: ?Sized> MaybeDebug for T {
default fn debug_or<'a, U: ?Sized + Debug>(&'a self, u: &'a U) -> DebugOr<'a, Self, U> {
DebugOr::Fallback(u)
}
default fn debug_or_else<'a, F: Fn(&mut fmt::Formatter) -> fmt::Result>(&'a self, f: F) -> DebugOrElse<'a, Self, F> {
DebugOrElse::Fallback(f)
}
}
impl<T: ?Sized + Debug> MaybeDebug for T {
fn debug_or<'a, U: ?Sized + Debug>(&'a self, _: &'a U) -> DebugOr<'a, Self, U> {
DebugOr::A(self)
}
fn debug_or_else<'a, F: Fn(&mut fmt::Formatter) -> fmt::Result>(&'a self, _: F) -> DebugOrElse<'a, Self, F> {
DebugOrElse::A(self)
}
}
impl<'a, T: ?Sized, U: ?Sized + Debug> Debug for DebugOr<'a, T, U> {
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DebugOr::A(_) => unreachable!(),
DebugOr::Fallback(ref a) => a.fmt(f),
}
}
}
impl<'a, T: ?Sized + Debug, U: ?Sized + Debug> Debug for DebugOr<'a, T, U> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DebugOr::A(ref a) => a.fmt(f),
DebugOr::Fallback(_) => unreachable!(),
}
}
}
impl<'a, T: ?Sized, F: Fn(&mut fmt::Formatter) -> fmt::Result> Debug for DebugOrElse<'a, T, F> {
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DebugOrElse::A(_) => unreachable!(),
DebugOrElse::Fallback(ref a) => a(f),
}
}
}
impl<'a, T: ?Sized + Debug, F: Fn(&mut fmt::Formatter) -> fmt::Result> Debug for DebugOrElse<'a, T, F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DebugOrElse::A(ref a) => a.fmt(f),
DebugOrElse::Fallback(_) => unreachable!(),
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment