1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#![warn(missing_docs)]
//! Provide a .diag() function for diagnostic output if requested.
//!
//! The [`ConfigDiag`] trait may be used to decorate an object that
//! stores some kind of configuration information. It adds
//! a [`diag`][`ConfigDiag::diag`] method that checks whether
//! verbose output has been requested and,
//! if so, displays a message to the standard error stream.
//! If the [`diag_to_stderr`][`ConfigDiag::diag_to_stderr`] method is
//! overridden and it returns false, any diagnostic messages selected for
//! display are sent to the standard output stream instead.
//!
//! Example:
//!
//! ```rust
//! # use std::error;
//! #
//! use config_diag::ConfigDiag;
//!
//! struct Config {
//!     verbose: bool,
//! }
//!
//! impl ConfigDiag for Config {
//!     fn diag_is_verbose(&self) -> bool {
//!         self.verbose
//!     }
//! }
//!
//! # pub fn main() -> Result<(), Box<dyn error::Error>> {
//! let config = Config { verbose: true };
//! # let event = 42;
//! config.diag(|| format!("Something happened: {}", event));
//! config.diag_("Got here!");
//! # Ok(())
//! # }
#![doc(html_root_url = "https://docs.rs/config-diag/1.0.2")]
/*
 * Copyright (c) 2021, 2022  Peter Pentchev <roam@ringlet.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/// Provide a `.diag()` function for verbose output if requested.
/// Useful for decorating configuration-like classes.
pub trait ConfigDiag {
    /// Has verbose output been requested?
    fn diag_is_verbose(&self) -> bool;

    /// Should diagnostic messages go to the standard error stream?
    /// If overridden to return false, the messages are sent to
    /// the standard output stream instead.
    #[inline]
    fn diag_to_stderr(&self) -> bool {
        true
    }

    /// Output a message to the standard error stream if requested.
    /// If the [`Self::diag_is_verbose`] method returns true,
    /// call the specified function to build a diagnostic message and
    /// write the latter to the stream selected by
    /// [`Self::diag_to_stderr`].
    #[inline]
    #[allow(clippy::print_stderr)]
    #[allow(clippy::print_stdout)]
    fn diag<F>(&self, f: F)
    where
        F: FnOnce() -> String,
    {
        if self.diag_is_verbose() {
            let msg = f();
            if self.diag_to_stderr() {
                eprintln!("{}", msg);
            } else {
                println!("{}", msg);
            }
        }
    }

    /// Output a constant message to the standard error stream if requested.
    /// If the [`Self::diag_is_verbose`] method returns true,
    /// write the specified message to the stream selected by
    /// [`Self::diag_to_stderr`].
    #[inline]
    fn diag_(&self, msg: &str) {
        self.diag(|| msg.to_owned());
    }
}

#[cfg(test)]
pub mod tests;