1
use serde::{Deserialize, Serialize};
2

            
3
#[derive(Debug, zvariant::Type, PartialEq, Eq, Copy, Clone)]
4
#[zvariant(signature = "s")]
5
/// Algorithm used to start a new session.
6
///
7
/// The communication between the Secret Service and the application can either
8
/// be encrypted or the items can be sent in plain text.
9
pub enum Algorithm {
10
    /// Plain text, per <https://specifications.freedesktop.org/secret-service-spec/latest/ch07s02.html>.
11
    Plain,
12
    /// Encrypted, per <https://specifications.freedesktop.org/secret-service-spec/latest/ch07s03.html>.
13
    Encrypted,
14
}
15

            
16
const PLAIN_ALGORITHM: &str = "plain";
17
const ENCRYPTED_ALGORITHM: &str = "dh-ietf1024-sha256-aes128-cbc-pkcs7";
18

            
19
impl Serialize for Algorithm {
20
18
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
21
    where
22
        S: serde::Serializer,
23
    {
24
17
        match self {
25
18
            Self::Plain => str::serialize(PLAIN_ALGORITHM, serializer),
26
10
            Self::Encrypted => str::serialize(ENCRYPTED_ALGORITHM, serializer),
27
        }
28
    }
29
}
30

            
31
impl<'de> Deserialize<'de> for Algorithm {
32
8
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
33
    where
34
        D: serde::Deserializer<'de>,
35
    {
36
16
        match String::deserialize(deserializer)?.as_str() {
37
16
            PLAIN_ALGORITHM => Ok(Self::Plain),
38
12
            ENCRYPTED_ALGORITHM => Ok(Self::Encrypted),
39
4
            e => Err(serde::de::Error::custom(format!("Invalid algorithm {e}"))),
40
        }
41
    }
42
}
43

            
44
#[cfg(test)]
45
mod tests {
46
    use zvariant::{Endian, serialized::Context, to_bytes};
47

            
48
    use super::*;
49

            
50
    #[test]
51
    fn serialization() {
52
        let ctxt = Context::new_dbus(Endian::Little, 0);
53

            
54
        // Test serializing Plain
55
        let encoded = to_bytes(ctxt, &Algorithm::Plain).unwrap();
56
        let value: String = encoded.deserialize().unwrap().0;
57
        assert_eq!(value, "plain");
58

            
59
        // Test serializing Encrypted
60
        let encoded = to_bytes(ctxt, &Algorithm::Encrypted).unwrap();
61
        let value: String = encoded.deserialize().unwrap().0;
62
        assert_eq!(value, "dh-ietf1024-sha256-aes128-cbc-pkcs7");
63

            
64
        // Test deserializing plain
65
        let encoded = to_bytes(ctxt, &PLAIN_ALGORITHM).unwrap();
66
        let algo: Algorithm = encoded.deserialize().unwrap().0;
67
        assert_eq!(algo, Algorithm::Plain);
68

            
69
        // Test deserializing encrypted
70
        let encoded = to_bytes(ctxt, &ENCRYPTED_ALGORITHM).unwrap();
71
        let algo: Algorithm = encoded.deserialize().unwrap().0;
72
        assert_eq!(algo, Algorithm::Encrypted);
73

            
74
        // Test deserializing invalid algorithm
75
        let encoded = to_bytes(ctxt, &"invalid-algorithm").unwrap();
76
        let result: Result<(Algorithm, _), _> = encoded.deserialize();
77
        assert!(result.is_err());
78
        assert!(
79
            result
80
                .unwrap_err()
81
                .to_string()
82
                .contains("Invalid algorithm")
83
        );
84

            
85
        // Test roundtrip for Plain
86
        let original = Algorithm::Plain;
87
        let encoded = to_bytes(ctxt, &original).unwrap();
88
        let decoded: Algorithm = encoded.deserialize().unwrap().0;
89
        assert_eq!(original, decoded);
90

            
91
        // Test roundtrip for Encrypted
92
        let original = Algorithm::Encrypted;
93
        let encoded = to_bytes(ctxt, &original).unwrap();
94
        let decoded: Algorithm = encoded.deserialize().unwrap().0;
95
        assert_eq!(original, decoded);
96
    }
97
}