summaryrefslogtreecommitdiffstats
path: root/CLI/rust/src/game_of_life/opts/validators.rs
blob: 4abcc1962ada0be112462a7aa359d9c0035f5f8f (plain) (blame)
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! Clap validators module
//!
//! Used for validating different CLI args (like width, height and delay)
//! Ref: https://docs.rs/clap/3.0.0-beta.2/clap/struct.Arg.html#method.validator

use terminal_size::{Height, Width};
use super::terminal_size_wrapper;

/// Validator to check if width configuration can be used
///
/// The maximum width allowed is the current terminal window width
pub(crate) fn is_fitting_term_width(val: &str) -> Result<(), String> {
    let (Width(term_width), Height(_)) = terminal_size_wrapper();
    match val.parse::<u16>() {
        Ok(n) if n > 0 && n <= term_width => Ok(()),
        Ok(_) => Err(format!(
            "must be between 1 and {} (current terminal width)",
            term_width
        )),
        Err(e) => Err(e.to_string()),
    }
}

#[cfg(test)]
mod is_fitting_term_width {
    use super::*;
    use mocktopus::mocking::*;

    #[test]
    fn positive_value() {
        terminal_size_wrapper.mock_safe(|| MockResult::Return((Width(42), Height(42))));
        assert!(is_fitting_term_width("13").is_ok());
    }

    #[test]
    fn value_too_large() {
        terminal_size_wrapper.mock_safe(|| MockResult::Return((Width(42), Height(42))));
        assert!(is_fitting_term_width("1337").is_err());
    }

    #[test]
    fn negative_value() {
        terminal_size_wrapper.mock_safe(|| MockResult::Return((Width(42), Height(42))));
        assert!(is_fitting_term_width("-13").is_err());
    }

    #[test]
    fn string_value() {
        terminal_size_wrapper.mock_safe(|| MockResult::Return((Width(42), Height(42))));
        assert!(is_fitting_term_width("not a number").is_err());
    }
}

/// Validator to check if height configuration can be used
///
/// The maximum height allowed is the current terminal window height - 2
/// The last 2 lines are used for status reporting (seed/input) and space
/// for ease of use
pub(crate) fn is_fitting_term_height(val: &str) -> Result<(), String> {
    let (Width(_), Height(term_height)) = terminal_size_wrapper();
    let term_height = term_height - 2;
    match val.parse::<u16>() {
        Ok(n) if n > 0 && n <= term_height => Ok(()),
        Ok(_) => Err(format!(
            "must be between 1 and {} (current terminal height)",
            term_height
        )),
        Err(e) => Err(e.to_string()),
    }
}

#[cfg(test)]
mod is_fitting_term_height {
    use super::*;
    use mocktopus::mocking::*;

    #[test]
    fn positive_value() {
        terminal_size_wrapper.mock_safe(|| MockResult::Return((Width(42), Height(42))));
        assert!(is_fitting_term_height("13").is_ok());
    }

    #[test]
    fn value_too_large() {
        terminal_size_wrapper.mock_safe(|| MockResult::Return((Width(42), Height(42))));
        assert!(is_fitting_term_height("1337").is_err());
    }

    #[test]
    fn negative_value() {
        terminal_size_wrapper.mock_safe(|| MockResult::Return((Width(42), Height(42))));
        assert!(is_fitting_term_height("-13").is_err());
    }

    #[test]
    fn string_value() {
        terminal_size_wrapper.mock_safe(|| MockResult::Return((Width(42), Height(42))));
        assert!(is_fitting_term_height("not a number").is_err());
    }
}

/// Validator to check if delay value is positive
pub(crate) fn is_positive(val: &str) -> Result<(), String> {
    match val.parse::<i16>() {
        Ok(n) if n.is_positive() => Ok(()),
        Ok(_) => Err(String::from("must be postive value (so far)")),
        Err(e) => Err(e.to_string()),
    }
}

#[cfg(test)]
mod is_positive {
    use super::*;

    #[test]
    fn positive_value() {
        assert!(is_positive("1337").is_ok());
    }

    #[test]
    fn negative_value() {
        assert!(is_positive("-1337").is_err());
    }

    #[test]
    fn string_value() {
        assert!(is_positive("not a number").is_err());
    }
}