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
//! Defines the `SET VARIABLE` AGI command.
//! See also the [official documentation](https://docs.asterisk.org/Asterisk_22_Documentation/API_Documentation/AGI_Commands/get_full_variable/)
use super::*;

/// The Set Variable command.
///
/// Use with
/// ```
/// use blazing_agi::command::SetVariable;
/// let cmd = SetVariable::new("TheVariable".to_owned(), "TheValue".to_owned());
/// // Will send:
/// assert_eq!(cmd.to_string(), "SET VARIABLE \"TheVariable\" \"TheValue\"\n")
/// ```
///
/// The associated [`InnerAGIResponse`] from [`send_command`](crate::connection::Connection::send_command) is
/// [`SetVariableResponse`].
#[derive(Debug)]
pub struct SetVariable {
    var_name: String,
    value: String,
}
impl SetVariable {
    /// Create [`SetVariable`]. When sent, this will set `var_name` to `value`.
    pub fn new(var_name: String, value: String) -> Self {
        Self { var_name, value }
    }
}
impl std::fmt::Display for SetVariable {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "SET VARIABLE \"{}\" \"{}\"\n", self.var_name, self.value)
    }
}
impl AGICommand for SetVariable {
    type Response = SetVariableResponse;
}

/// The responses we can get when sending [`SetVariableResponse`] that returned 200.
/// There is only one acceptable response: `200 result=1`, so this is the empty struct.
#[derive(Debug, PartialEq)]
pub struct SetVariableResponse {}
impl InnerAGIResponse for SetVariableResponse {}
/// Convert from a tuple `(result, operational_data)` to [`SetVariableResponse`]. This is used
/// internally when parsing AGI responses to sending a [`SetVariable`] command.
impl<'a> TryFrom<(&'a str, Option<&'a str>)> for SetVariableResponse {
    type Error = AGIStatusParseError;
    fn try_from((result, op_data): (&str, Option<&str>)) -> Result<Self, Self::Error> {
        let res_parsed = result.parse::<u16>();
        match res_parsed {
            Ok(1) => Ok(SetVariableResponse {}),
            _ => Err(AGIStatusParseError {
                result: result.to_owned(),
                op_data: op_data.map(|x| x.to_owned()),
                response_to_command: "SET VARIABLE",
            }),
        }
    }
}

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

    #[test]
    fn run_normal_set() {
        let cmd = SetVariable::new("TEST_VAR_NAME".to_owned(), "the-value".to_owned());
        assert_eq!(
            cmd.to_string(),
            "SET VARIABLE \"TEST_VAR_NAME\" \"the-value\"\n"
        );
    }

    #[test]
    fn parse_success() {
        assert_eq!(
            SetVariableResponse::try_from(("1", None)).unwrap(),
            SetVariableResponse {}
        );
    }

    #[test]
    fn parse_incorrect_result() {
        assert_eq!(
            SetVariableResponse::try_from(("0", Some("other stuff"))),
            Err(AGIStatusParseError {
                result: "0".to_owned(),
                op_data: Some("other stuff".to_owned()),
                response_to_command: "SET VARIABLE"
            })
        );
    }
}