Struct error_stack::fmt::HookContext
source · #[repr(transparent)]pub struct HookContext<T> { /* private fields */ }
std
only.Expand description
Carrier for contextual information used across hook invocations.
HookContext
has two fundamental use-cases:
- Adding body entries and appendix entries
- Storage
Adding body entries and appendix entries
A Debug
backtrace consists of two different sections, a rendered tree of objects (the
body) and additional text/information that is too large to fit into the tree (the
appendix).
Entries for the body can be attached to the rendered tree of objects via
HookContext::push_body
. An appendix entry can be attached via
HookContext::push_appendix
.
Example
use std::io::{Error, ErrorKind};
use error_stack::Report;
struct Warning(&'static str);
struct HttpResponseStatusCode(u64);
struct Suggestion(&'static str);
struct Secret(&'static str);
Report::install_debug_hook::<HttpResponseStatusCode>(|HttpResponseStatusCode(value), context| {
// Create a new appendix, which is going to be displayed when someone requests the alternate
// version (`:#?`) of the report.
if context.alternate() {
context.push_appendix(format!("error {value}: {} error", if *value < 500 {"client"} else {"server"}))
}
// This will push a new entry onto the body with the specified value
context.push_body(format!("error code: {value}"));
});
Report::install_debug_hook::<Suggestion>(|Suggestion(value), context| {
let idx = context.increment_counter();
// Create a new appendix, which is going to be displayed when someone requests the alternate
// version (`:#?`) of the report.
if context.alternate() {
context.push_body(format!("suggestion {idx}:\n {value}"));
}
// This will push a new entry onto the body with the specified value
context.push_body(format!("suggestion ({idx})"));
});
Report::install_debug_hook::<Warning>(|Warning(value), context| {
// You can add multiples entries to the body (and appendix) in the same hook.
context.push_body("abnormal program execution detected");
context.push_body(format!("warning: {value}"));
});
// By not adding anything you are able to hide an attachment
// (it will still be counted towards opaque attachments)
Report::install_debug_hook::<Secret>(|_, _| {});
let report = Report::new(Error::from(ErrorKind::InvalidInput))
.attach(HttpResponseStatusCode(404))
.attach(Suggestion("do you have a connection to the internet?"))
.attach(HttpResponseStatusCode(405))
.attach(Warning("unable to determine environment"))
.attach(Secret("pssst, don't tell anyone else c;"))
.attach(Suggestion("execute the program from the fish shell"))
.attach(HttpResponseStatusCode(501))
.attach(Suggestion("try better next time!"));
println!("{report:?}");
println!("{report:#?}");
The output of println!("{report:?}")
:
invalid input parameter ├╴ src/fmt/hook.rs:49:14 ├╴ backtrace (1) ├╴ error code: 404 ├╴ suggestion (0) ├╴ error code: 405 ├╴ abnormal program execution detected ├╴ warning: unable to determine environment ├╴ suggestion (1) ├╴ error code: 501 ╰╴ suggestion (2) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ backtrace no. 1 [redacted]
The output of println!("{report:#?}")
:
invalid input parameter ├╴ src/fmt/hook.rs:49:14 ├╴ backtrace (1) ├╴ error code: 404 ├╴ suggestion 0: │ do you have a connection to the internet? ├╴ suggestion (0) ├╴ error code: 405 ├╴ abnormal program execution detected ├╴ warning: unable to determine environment ├╴ suggestion 1: │ execute the program from the fish shell ├╴ suggestion (1) ├╴ error code: 501 ├╴ suggestion 2: │ try better next time! ╰╴ suggestion (2) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ backtrace no. 1 [redacted] error 404: client error error 405: client error error 501: server error
Storage
HookContext
can be used to store and retrieve values that are going to be used on multiple
hook invocations in a single Debug
call.
Every hook can request their corresponding HookContext
.
This is especially useful for incrementing/decrementing values, but can also be used to store
any arbitrary value for the duration of the Debug
invocation.
All data stored in HookContext
is completely separated from all other hooks and can store
any arbitrary data of any type, and even data of multiple types at the same time.
Example
use std::io::ErrorKind;
use error_stack::Report;
struct Computation(u64);
Report::install_debug_hook::<Computation>(|Computation(value), context| {
// Get a value of type `u64`, if we didn't insert one yet, default to 0
let mut acc = context.get::<u64>().copied().unwrap_or(0);
acc += *value;
// Get a value of type `f64`, if we didn't insert one yet, default to 1.0
let mut div = context.get::<f32>().copied().unwrap_or(1.0);
div /= *value as f32;
// Insert the calculated `u64` and `f32` back into storage, so that we can use them
// in the invocations following this one (for the same `Debug` call)
context.insert(acc);
context.insert(div);
context.push_body(format!(
"computation for {value} (acc = {acc}, div = {div})"
));
});
let report = Report::new(std::io::Error::from(ErrorKind::InvalidInput))
.attach(Computation(2))
.attach(Computation(3));
println!("{report:?}");
invalid input parameter ├╴ src/fmt/hook.rs:31:14 ├╴ backtrace (1) ├╴ computation for 2 (acc = 2, div = 0.5) ╰╴ computation for 3 (acc = 5, div = 0.16666667) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ backtrace no. 1 [redacted]
Implementations
sourceimpl<T> HookContext<T>
impl<T> HookContext<T>
sourcepub fn push_appendix(&mut self, content: impl Into<String>)
pub fn push_appendix(&mut self, content: impl Into<String>)
The contents of the appendix are going to be displayed after the body in the order they have
been pushed into the HookContext
.
This is useful for dense information like backtraces, or span traces.
Example
use std::io::ErrorKind;
use error_stack::Report;
struct Error {
code: usize,
reason: &'static str,
}
Report::install_debug_hook::<Error>(|Error { code, reason }, context| {
if context.alternate() {
// Add an entry to the appendix
context.push_appendix(format!("error {code}:\n {reason}"));
}
context.push_body(format!("error {code}"));
});
let report = Report::new(std::io::Error::from(ErrorKind::InvalidInput))
.attach(Error {
code: 404,
reason: "not found - server cannot find requested resource",
})
.attach(Error {
code: 405,
reason: "bad request - server cannot or will not process request",
});
println!("{report:#?}");
invalid input parameter ├╴ src/fmt/hook.rs:24:14 ├╴ backtrace (1) ├╴ error 404 ╰╴ error 405 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ backtrace no. 1 [redacted] error 404: not found - server cannot find requested resource error 405: bad request - server cannot or will not process request
sourcepub fn push_body(&mut self, content: impl Into<String>)
pub fn push_body(&mut self, content: impl Into<String>)
Add a new entry to the body.
Example
use std::io;
use error_stack::Report;
struct Suggestion(&'static str);
Report::install_debug_hook::<Suggestion>(|Suggestion(value), context| {
context.push_body(format!("suggestion: {value}"));
// We can push multiples entries in a single hook, these lines will be added one after
// another.
context.push_body("sorry for the inconvenience!");
});
let report = Report::new(io::Error::from(io::ErrorKind::InvalidInput))
.attach(Suggestion("try better next time"));
println!("{report:?}");
invalid input parameter ├╴ src/fmt/hook.rs:19:14 ├╴ backtrace (1) ├╴ suggestion: try better next time ╰╴ sorry for the inconvenience! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ backtrace no. 1 [redacted]
sourcepub fn cast<U>(&mut self) -> &mut HookContext<U>
pub fn cast<U>(&mut self) -> &mut HookContext<U>
Cast the HookContext
to a new type U
.
The storage of HookContext
is partitioned, meaning that if T
and U
are different
types the values stored in HookContext<T>
will be separated from values in
HookContext<U>
.
In most situations this functions isn’t needed, as it transparently casts between different partitions of the storage. Only hooks that share storage with hooks of different types should need to use this function.
Example
use std::io::ErrorKind;
use error_stack::Report;
struct Warning(&'static str);
struct Error(&'static str);
Report::install_debug_hook::<Error>(|Error(frame), context| {
let idx = context.increment_counter() + 1;
context.push_body(format!("[{idx}] [ERROR] {frame}"));
});
Report::install_debug_hook::<Warning>(|Warning(frame), context| {
// We want to share the same counter with `Error`, so that we're able to have
// a global counter to keep track of all errors and warnings in order, this means
// we need to access the storage of `Error` using `cast()`.
let context = context.cast::<Error>();
let idx = context.increment_counter() + 1;
context.push_body(format!("[{idx}] [WARN] {frame}"))
});
let report = Report::new(std::io::Error::from(ErrorKind::InvalidInput))
.attach(Error("unable to reach remote host"))
.attach(Warning("disk nearly full"))
.attach(Error("cannot resolve example.com: unknown host"));
println!("{report:?}");
invalid input parameter ├╴ src/fmt/hook.rs:27:14 ├╴ backtrace (1) ├╴ [1] [ERROR] unable to reach remote host ├╴ [2] [WARN] disk nearly full ╰╴ [3] [ERROR] cannot resolve example.com: unknown host ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ backtrace no. 1 [redacted]
sourcepub const fn alternate(&self) -> bool
pub const fn alternate(&self) -> bool
Returns if the currently requested format should render the alternate representation.
This corresponds to the output of std::fmt::Formatter::alternate
.
sourceimpl<T: 'static> HookContext<T>
impl<T: 'static> HookContext<T>
sourcepub fn get<U: 'static>(&self) -> Option<&U>
pub fn get<U: 'static>(&self) -> Option<&U>
Return a reference to a value of type U
, if a value of that type exists.
Values returned are isolated and “bound” to T
, this means that HookContext<Warning>
and HookContext<Error>
do not share the same values. Values are only retained during the
invocation of Debug
.
sourcepub fn get_mut<U: 'static>(&mut self) -> Option<&mut U>
pub fn get_mut<U: 'static>(&mut self) -> Option<&mut U>
Return a mutable reference to a value of type U
, if a value of that type exists.
Values returned are isolated and “bound” to T
, this means that HookContext<Warning>
and HookContext<Error>
do not share the same values. Values are only retained during the
invocation of Debug
.
sourcepub fn insert<U: 'static>(&mut self, value: U) -> Option<U>
pub fn insert<U: 'static>(&mut self, value: U) -> Option<U>
Insert a new value of type U
into the storage of HookContext
.
The returned value will the previously stored value of the same type U
scoped over type
T
, if it existed, did no such value exist it will return None
.
sourcepub fn remove<U: 'static>(&mut self) -> Option<U>
pub fn remove<U: 'static>(&mut self) -> Option<U>
Remove the value of type U
from the storage of HookContext
if it existed.
The returned value will be the previously stored value of the same type U
if it existed in
the scope of T
, did no such value exist, it will return None
.
sourcepub fn increment_counter(&mut self) -> isize
pub fn increment_counter(&mut self) -> isize
One of the most common interactions with HookContext
is a counter to reference previous
frames in an entry to the appendix that was added using HookContext::push_appendix
.
This is a utility method, which uses the other primitive methods provided to automatically
increment a counter, if the counter wasn’t initialized this method will return 0
.
use std::io::ErrorKind;
use error_stack::Report;
struct Suggestion(&'static str);
Report::install_debug_hook::<Suggestion>(|Suggestion(value), context| {
let idx = context.increment_counter();
context.push_body(format!("suggestion {idx}: {value}"));
});
let report = Report::new(std::io::Error::from(ErrorKind::InvalidInput))
.attach(Suggestion("use a file you can read next time!"))
.attach(Suggestion("don't press any random keys!"));
println!("{report:?}");
invalid input parameter ├╴ src/fmt/hook.rs:17:14 ├╴ backtrace (1) ├╴ suggestion 0: use a file you can read next time! ╰╴ suggestion 1: don't press any random keys! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ backtrace no. 1 [redacted]
sourcepub fn decrement_counter(&mut self) -> isize
pub fn decrement_counter(&mut self) -> isize
One of the most common interactions with HookContext
is a counter to reference previous
frames in an entry to the appendix that was added using HookContext::push_appendix
.
This is a utility method, which uses the other primitive method provided to automatically
decrement a counter, if the counter wasn’t initialized this method will return -1
to stay
consistent with HookContext::increment_counter
.
use std::io::ErrorKind;
use error_stack::Report;
struct Suggestion(&'static str);
Report::install_debug_hook::<Suggestion>(|Suggestion(value), context| {
let idx = context.decrement_counter();
context.push_body(format!("suggestion {idx}: {value}"));
});
let report = Report::new(std::io::Error::from(ErrorKind::InvalidInput))
.attach(Suggestion("use a file you can read next time!"))
.attach(Suggestion("don't press any random keys!"));
println!("{report:?}");
invalid input parameter ├╴ src/fmt/hook.rs:17:14 ├╴ backtrace (1) ├╴ suggestion -1: use a file you can read next time! ╰╴ suggestion -2: don't press any random keys! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ backtrace no. 1 [redacted]
Auto Trait Implementations
impl<T> !RefUnwindSafe for HookContext<T>
impl<T> !Send for HookContext<T>
impl<T> !Sync for HookContext<T>
impl<T> Unpin for HookContext<T>
impl<T> !UnwindSafe for HookContext<T>
Blanket Implementations
sourceimpl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
sourceimpl<T> Instrument for T
impl<T> Instrument for T
sourcefn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
sourcefn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
sourceimpl<D> OwoColorize for D
impl<D> OwoColorize for D
sourcefn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
sourcefn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
sourcefn black(&'a self) -> FgColorDisplay<'a, Black, Self>
fn black(&'a self) -> FgColorDisplay<'a, Black, Self>
sourcefn on_black(&'a self) -> BgColorDisplay<'a, Black, Self>
fn on_black(&'a self) -> BgColorDisplay<'a, Black, Self>
sourcefn red(&'a self) -> FgColorDisplay<'a, Red, Self>
fn red(&'a self) -> FgColorDisplay<'a, Red, Self>
sourcefn on_red(&'a self) -> BgColorDisplay<'a, Red, Self>
fn on_red(&'a self) -> BgColorDisplay<'a, Red, Self>
sourcefn green(&'a self) -> FgColorDisplay<'a, Green, Self>
fn green(&'a self) -> FgColorDisplay<'a, Green, Self>
sourcefn on_green(&'a self) -> BgColorDisplay<'a, Green, Self>
fn on_green(&'a self) -> BgColorDisplay<'a, Green, Self>
sourcefn yellow(&'a self) -> FgColorDisplay<'a, Yellow, Self>
fn yellow(&'a self) -> FgColorDisplay<'a, Yellow, Self>
sourcefn on_yellow(&'a self) -> BgColorDisplay<'a, Yellow, Self>
fn on_yellow(&'a self) -> BgColorDisplay<'a, Yellow, Self>
sourcefn blue(&'a self) -> FgColorDisplay<'a, Blue, Self>
fn blue(&'a self) -> FgColorDisplay<'a, Blue, Self>
sourcefn on_blue(&'a self) -> BgColorDisplay<'a, Blue, Self>
fn on_blue(&'a self) -> BgColorDisplay<'a, Blue, Self>
sourcefn magenta(&'a self) -> FgColorDisplay<'a, Magenta, Self>
fn magenta(&'a self) -> FgColorDisplay<'a, Magenta, Self>
sourcefn on_magenta(&'a self) -> BgColorDisplay<'a, Magenta, Self>
fn on_magenta(&'a self) -> BgColorDisplay<'a, Magenta, Self>
sourcefn purple(&'a self) -> FgColorDisplay<'a, Magenta, Self>
fn purple(&'a self) -> FgColorDisplay<'a, Magenta, Self>
sourcefn on_purple(&'a self) -> BgColorDisplay<'a, Magenta, Self>
fn on_purple(&'a self) -> BgColorDisplay<'a, Magenta, Self>
sourcefn cyan(&'a self) -> FgColorDisplay<'a, Cyan, Self>
fn cyan(&'a self) -> FgColorDisplay<'a, Cyan, Self>
sourcefn on_cyan(&'a self) -> BgColorDisplay<'a, Cyan, Self>
fn on_cyan(&'a self) -> BgColorDisplay<'a, Cyan, Self>
sourcefn white(&'a self) -> FgColorDisplay<'a, White, Self>
fn white(&'a self) -> FgColorDisplay<'a, White, Self>
sourcefn on_white(&'a self) -> BgColorDisplay<'a, White, Self>
fn on_white(&'a self) -> BgColorDisplay<'a, White, Self>
sourcefn default_color(&'a self) -> FgColorDisplay<'a, Default, Self>
fn default_color(&'a self) -> FgColorDisplay<'a, Default, Self>
sourcefn on_default_color(&'a self) -> BgColorDisplay<'a, Default, Self>
fn on_default_color(&'a self) -> BgColorDisplay<'a, Default, Self>
sourcefn bright_black(&'a self) -> FgColorDisplay<'a, BrightBlack, Self>
fn bright_black(&'a self) -> FgColorDisplay<'a, BrightBlack, Self>
sourcefn on_bright_black(&'a self) -> BgColorDisplay<'a, BrightBlack, Self>
fn on_bright_black(&'a self) -> BgColorDisplay<'a, BrightBlack, Self>
sourcefn bright_red(&'a self) -> FgColorDisplay<'a, BrightRed, Self>
fn bright_red(&'a self) -> FgColorDisplay<'a, BrightRed, Self>
sourcefn on_bright_red(&'a self) -> BgColorDisplay<'a, BrightRed, Self>
fn on_bright_red(&'a self) -> BgColorDisplay<'a, BrightRed, Self>
sourcefn bright_green(&'a self) -> FgColorDisplay<'a, BrightGreen, Self>
fn bright_green(&'a self) -> FgColorDisplay<'a, BrightGreen, Self>
sourcefn on_bright_green(&'a self) -> BgColorDisplay<'a, BrightGreen, Self>
fn on_bright_green(&'a self) -> BgColorDisplay<'a, BrightGreen, Self>
sourcefn bright_yellow(&'a self) -> FgColorDisplay<'a, BrightYellow, Self>
fn bright_yellow(&'a self) -> FgColorDisplay<'a, BrightYellow, Self>
sourcefn on_bright_yellow(&'a self) -> BgColorDisplay<'a, BrightYellow, Self>
fn on_bright_yellow(&'a self) -> BgColorDisplay<'a, BrightYellow, Self>
sourcefn bright_blue(&'a self) -> FgColorDisplay<'a, BrightBlue, Self>
fn bright_blue(&'a self) -> FgColorDisplay<'a, BrightBlue, Self>
sourcefn on_bright_blue(&'a self) -> BgColorDisplay<'a, BrightBlue, Self>
fn on_bright_blue(&'a self) -> BgColorDisplay<'a, BrightBlue, Self>
sourcefn bright_magenta(&'a self) -> FgColorDisplay<'a, BrightMagenta, Self>
fn bright_magenta(&'a self) -> FgColorDisplay<'a, BrightMagenta, Self>
sourcefn on_bright_magenta(&'a self) -> BgColorDisplay<'a, BrightMagenta, Self>
fn on_bright_magenta(&'a self) -> BgColorDisplay<'a, BrightMagenta, Self>
sourcefn bright_purple(&'a self) -> FgColorDisplay<'a, BrightMagenta, Self>
fn bright_purple(&'a self) -> FgColorDisplay<'a, BrightMagenta, Self>
sourcefn on_bright_purple(&'a self) -> BgColorDisplay<'a, BrightMagenta, Self>
fn on_bright_purple(&'a self) -> BgColorDisplay<'a, BrightMagenta, Self>
sourcefn bright_cyan(&'a self) -> FgColorDisplay<'a, BrightCyan, Self>
fn bright_cyan(&'a self) -> FgColorDisplay<'a, BrightCyan, Self>
sourcefn on_bright_cyan(&'a self) -> BgColorDisplay<'a, BrightCyan, Self>
fn on_bright_cyan(&'a self) -> BgColorDisplay<'a, BrightCyan, Self>
sourcefn bright_white(&'a self) -> FgColorDisplay<'a, BrightWhite, Self>
fn bright_white(&'a self) -> FgColorDisplay<'a, BrightWhite, Self>
sourcefn on_bright_white(&'a self) -> BgColorDisplay<'a, BrightWhite, Self>
fn on_bright_white(&'a self) -> BgColorDisplay<'a, BrightWhite, Self>
sourcefn bold(&'a self) -> BoldDisplay<'a, Self>
fn bold(&'a self) -> BoldDisplay<'a, Self>
sourcefn dimmed(&'a self) -> DimDisplay<'a, Self>
fn dimmed(&'a self) -> DimDisplay<'a, Self>
sourcefn italic(&'a self) -> ItalicDisplay<'a, Self>
fn italic(&'a self) -> ItalicDisplay<'a, Self>
sourcefn underline(&'a self) -> UnderlineDisplay<'a, Self>
fn underline(&'a self) -> UnderlineDisplay<'a, Self>
sourcefn blink(&'a self) -> BlinkDisplay<'a, Self>
fn blink(&'a self) -> BlinkDisplay<'a, Self>
sourcefn blink_fast(&'a self) -> BlinkFastDisplay<'a, Self>
fn blink_fast(&'a self) -> BlinkFastDisplay<'a, Self>
sourcefn reversed(&'a self) -> ReversedDisplay<'a, Self>
fn reversed(&'a self) -> ReversedDisplay<'a, Self>
sourcefn strikethrough(&'a self) -> StrikeThroughDisplay<'a, Self>
fn strikethrough(&'a self) -> StrikeThroughDisplay<'a, Self>
sourcefn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::fg
or
a color-specific method, such as OwoColorize::green
, Read moresourcefn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::bg
or
a color-specific method, such as OwoColorize::on_yellow
, Read moresourcefn fg_rgb<const R: u8, const G: u8, const B: u8>(
&self
) -> FgColorDisplay<'_, CustomColor<R, G, B>, Self>
fn fg_rgb<const R: u8, const G: u8, const B: u8>(
&self
) -> FgColorDisplay<'_, CustomColor<R, G, B>, Self>
sourcefn bg_rgb<const R: u8, const G: u8, const B: u8>(
&self
) -> BgColorDisplay<'_, CustomColor<R, G, B>, Self>
fn bg_rgb<const R: u8, const G: u8, const B: u8>(
&self
) -> BgColorDisplay<'_, CustomColor<R, G, B>, Self>
sourcefn truecolor(&self, r: u8, g: u8, b: u8) -> FgDynColorDisplay<'_, Rgb, Self>
fn truecolor(&self, r: u8, g: u8, b: u8) -> FgDynColorDisplay<'_, Rgb, Self>
sourcefn on_truecolor(&self, r: u8, g: u8, b: u8) -> BgDynColorDisplay<'_, Rgb, Self>
fn on_truecolor(&self, r: u8, g: u8, b: u8) -> BgDynColorDisplay<'_, Rgb, Self>
sourcefn if_supports_color<'a, Out, ApplyFn>(
&'a self,
stream: Stream,
apply: ApplyFn
) -> SupportsColorsDisplay<'a, Self, Out, ApplyFn>where
ApplyFn: Fn(&'a Self) -> Out,
fn if_supports_color<'a, Out, ApplyFn>(
&'a self,
stream: Stream,
apply: ApplyFn
) -> SupportsColorsDisplay<'a, Self, Out, ApplyFn>where
ApplyFn: Fn(&'a Self) -> Out,
supports-colors
only.