depo_api/request/
update_recovery.rs

1use bc_envelope::prelude::*;
2
3use crate::{
4    Error, RECOVERY_METHOD_PARAM, RECOVERY_METHOD_PARAM_NAME, Result,
5    UPDATE_RECOVERY_FUNCTION,
6    util::{Abbrev, FlankedFunction},
7};
8
9//
10// Request
11//
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct UpdateRecovery(Option<String>);
15
16impl UpdateRecovery {
17    pub fn new(recovery: Option<String>) -> Self { Self(recovery) }
18
19    pub fn recovery(&self) -> Option<&String> { self.0.as_ref() }
20}
21
22impl From<UpdateRecovery> for Expression {
23    fn from(value: UpdateRecovery) -> Self {
24        let method = if let Some(recovery) = value.0.clone() {
25            recovery.to_envelope()
26        } else {
27            Envelope::null()
28        };
29        Expression::new(UPDATE_RECOVERY_FUNCTION)
30            .with_parameter(RECOVERY_METHOD_PARAM, method)
31    }
32}
33
34impl TryFrom<Expression> for UpdateRecovery {
35    type Error = Error;
36
37    fn try_from(expression: Expression) -> Result<Self> {
38        let recovery_object = expression
39            .object_for_parameter(RECOVERY_METHOD_PARAM)
40            .map_err(|_e| Error::MissingParameter {
41                parameter: RECOVERY_METHOD_PARAM_NAME.to_string(),
42            })?;
43        let recovery = if recovery_object.is_null() {
44            None
45        } else {
46            Some(recovery_object.extract_subject().map_err(|e| {
47                Error::InvalidEnvelope {
48                    message: format!(
49                        "failed to extract recovery method: {}",
50                        e
51                    ),
52                }
53            })?)
54        };
55        Ok(Self::new(recovery))
56    }
57}
58
59impl std::fmt::Display for UpdateRecovery {
60    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61        f.write_fmt(format_args!(
62            "{} to {}",
63            "updateRecovery".flanked_function(),
64            self.recovery().abbrev()
65        ))
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use indoc::indoc;
72
73    use super::*;
74
75    #[test]
76    fn test_request() {
77        bc_envelope::register_tags();
78
79        let recovery = "recovery".to_string();
80
81        let request = UpdateRecovery::new(Some(recovery));
82        let expression: Expression = request.clone().into();
83        let request_envelope = expression.to_envelope();
84        // println!("{}", request_envelope.format());
85        #[rustfmt::skip]
86        assert_eq!(request_envelope.format(), indoc! {r#"
87            «"updateRecovery"» [
88                ❰"recoveryMethod"❱: "recovery"
89            ]
90        "#}.trim());
91        let decoded_expression =
92            Expression::try_from(request_envelope).unwrap();
93        let decoded = UpdateRecovery::try_from(decoded_expression).unwrap();
94        assert_eq!(request, decoded);
95    }
96}