error_annotation/
annotate.rs

1use crate::ErrorAnnotation;
2
3/// Capture diagnostic information in a closure that extends a source error type into a wrapping
4/// [`ErrorAnnotation`].
5///
6/// `annotate` captures a `label` and a diagnostic `info` construction closure, `mkinfo`, returning
7/// a closure that creates an [`ErrorAnnotation`] given a source error of type `S`. This API design
8/// makes it ergonomic to use as the parameter to `Result::map_err` to transform a source error
9/// by extending it with diagnostic information.
10///
11/// `mkinfo` is a closure which allows deferring the construction of the diagnostic `info` until
12/// the error case is encountered, similar to the design of `Option::ok_or_else`.
13///
14/// # Example
15///
16/// ```
17/// use std::path::Path;
18/// use std::fs::Metadata;
19/// use error_annotation::{ErrorAnnotation, annotate};
20///
21/// type IoErrorWithPath<'a> = ErrorAnnotation<std::io::Error, std::path::Display<'a>>;
22///
23/// fn metadata(p: &Path) -> Result<Metadata, IoErrorWithPath> {
24///   std::fs::metadata(p).map_err(annotate("path", || p.display()))
25/// }
26/// ```
27pub fn annotate<S, F, I>(label: &'static str, mkinfo: F) -> impl FnOnce(S) -> ErrorAnnotation<S, I>
28where
29    F: FnOnce() -> I,
30{
31    move |source| ErrorAnnotation {
32        source,
33        label,
34        info: mkinfo(),
35    }
36}