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
//! The Bridge design pattern example module
//!
//! In this example, the Bridge pattern is used to allow a program to offer
//! multiple ways to perform logging without changing how the logging is used
//! throughout the program.
//!
//! Take note of how the calls into the logger are the same regardless of the
//! logger used.
//!
//! Accessed through the bridge_exercise() function.

pub mod bridge_ilogger_trait;
pub mod bridge_logger;
pub mod bridge_nulllogger;
pub mod bridge_filelogger;
pub mod bridge_consolelogger;
pub mod bridge_loghelper;

use bridge_ilogger_trait::ILogger;
use bridge_logger::{create_logger, LoggerType};

//-----------------------------------------------------------------------------

/// Helper function to show an example of writing to a logger.
/// 
/// This is called for all types of loggers, showing how the ILogger interface
/// hides the details of the underlying implementation.
///
/// # Parameters
/// - logger
///
///   A struct that implements the ILogger trait to which to log to.
/// - logger_type
///
///   The type of the underlying logging implementation.
fn _bridge_exercise_demonstrate_logging(logger: &mut Box<dyn ILogger>, logger_type: &str) {
    let mut message = format!("Starting log to {logger_type} example");

    logger.log_trace(&message);
    logger.log_info("An example of an informational line");
    logger.log_error("An example of an error log entry");

    message = format!("Done with log to {logger_type} example");
    logger.log_trace(&message);
}


//-----------------------------------------------------------------------------


/// Example of using the "Bridge" pattern.
/// 
/// In this example, the Bridge pattern is used to allow a program to offer
/// multiple ways to perform logging without changing how the logging is
/// used throughout the program.
///
/// In this exercise, note how the calls into the logger are the
/// same regardless of the logger used.

// ! [Using Bridge in Rust]
pub fn bridge_exercise() -> Result<(), String> {
    println!("");
    println!("Bridge Exercise");

    {
        let mut logger = create_logger(LoggerType::ToFile, "bridge.log");
        println!("  Example of writing to a log file...");
        _bridge_exercise_demonstrate_logging(&mut logger, "file");
    }

    {
        let mut logger = create_logger(LoggerType::ToConsole, "");
        println!("  Example of writing to the console...");
        _bridge_exercise_demonstrate_logging(&mut logger, "console");
    }

    {
        let mut logger = create_logger(LoggerType::ToNull, "");
        println!("  Example of writing to a Null object (no output)...");
        _bridge_exercise_demonstrate_logging(&mut logger, "null");
    }

    println!("  Done.");

    Ok(())
}
// ! [Using Bridge in Rust]