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
//! The State design pattern example module
//! 
//! The State pattern alters the behavior of an object hierarchy based on some
//! state.  This is the basis of a Finite State Machine.
//! 
//! In this exercise, the State struct is a filter that parses text to remove
//! Rust-style line and block comments.  It needs to be smart enough to ignore
//! comment characters inside quotes.
//! 
//! The filtering process starts with creating the context that drives
//! the state machine.  Internal structs are provided for each state.
//!
//! Accessed through the state_exercise() function.

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

pub mod state_context;
pub mod state_istatebehavior_trait;
pub mod state_istatecontext_trait;

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

use state_context::StateContext;

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

/// Helper function to display text from the State exercise.  Text is displayed
/// with line numbers.
///
/// # Parameters
/// - text
///
///   Text to display
fn state_display_text(text: &str) {
    let local_text = text.to_string();
    let lines = local_text.split("\n");
    let mut line_number = 1;
    for line in lines {
        println!("    {0:2}) {1}", line_number, line);
        line_number += 1;
    }
}


/// Example of using the "State" design pattern.
/// 
/// The State pattern alters the behavior of an object hierarchy based on some
/// state.  This is the basis of a Finite State Machine.
/// 
/// In this exercise, the State struct is a filter that parses text to remove
/// Rust-style line and block comments.  It needs to be smart enough to ignore
/// comment characters inside quotes.
/// 
/// The filtering process starts with creating the context that drives
/// the state machine.  Internal structs are provided for each state.
// ! [Using State in Rust]
pub fn state_exercise() -> Result<(), String> {
    println!("");
    println!("State Exercise");

    let mut context = StateContext::new();

    let text_to_filter =
r#"/*####################  Block Comment  #################################*/
//####################  Line Comment  ####################################
// A comment.  /* A nested comment */

fn state_exercise() { // An exercise in state machines
    let character = '\"';
    println!("");
    println!("\"State\" /*Exercise*/");

    let mut context = StateContext::new();

    println!("\t\tDone. //(No, really)//");
}"#;

    println!("  Text to filter:");
    state_display_text(text_to_filter);

    println!("  Filtering text...");
    let filtered_text = context.remove_comments(text_to_filter);

    println!("  Filtered text:");
    state_display_text(&filtered_text);

    println!("  Done.");

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