distant_protocol/common/
version.rs

1use serde::{Deserialize, Serialize};
2
3use crate::semver;
4
5/// Represents version information.
6#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
7pub struct Version {
8    /// Server version.
9    pub server_version: semver::Version,
10
11    /// Protocol version.
12    pub protocol_version: semver::Version,
13
14    /// Additional features available.
15    #[serde(default, skip_serializing_if = "Vec::is_empty")]
16    pub capabilities: Vec<String>,
17}
18
19impl Version {
20    /// Supports executing processes.
21    pub const CAP_EXEC: &'static str = "exec";
22
23    /// Supports reading and writing via filesystem IO.
24    pub const CAP_FS_IO: &'static str = "fs_io";
25
26    /// Supports modifying permissions of filesystem.
27    pub const CAP_FS_PERM: &'static str = "fs_perm";
28
29    /// Supports searching filesystem.
30    pub const CAP_FS_SEARCH: &'static str = "fs_search";
31
32    /// Supports watching filesystem for changes.
33    pub const CAP_FS_WATCH: &'static str = "fs_watch";
34
35    /// Supports TCP tunneling.
36    // pub const CAP_TCP_TUNNEL: &'static str = "tcp_tunnel";
37
38    /// Supports TCP reverse tunneling.
39    // pub const CAP_TCP_REV_TUNNEL: &'static str = "tcp_rev_tunnel";
40
41    /// Supports retrieving system information.
42    pub const CAP_SYS_INFO: &'static str = "sys_info";
43
44    pub const fn capabilities() -> &'static [&'static str] {
45        &[
46            Self::CAP_EXEC,
47            Self::CAP_FS_IO,
48            Self::CAP_FS_PERM,
49            Self::CAP_FS_SEARCH,
50            Self::CAP_FS_WATCH,
51            /* Self::CAP_TCP_TUNNEL,
52            Self::CAP_TCP_REV_TUNNEL, */
53            Self::CAP_SYS_INFO,
54        ]
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61    use semver::Version as SemVer;
62
63    #[test]
64    fn should_be_able_to_serialize_to_json() {
65        let version = Version {
66            server_version: "123.456.789-rc+build".parse().unwrap(),
67            protocol_version: SemVer::new(1, 2, 3),
68            capabilities: vec![String::from("cap")],
69        };
70
71        let value = serde_json::to_value(version).unwrap();
72        assert_eq!(
73            value,
74            serde_json::json!({
75                "server_version": "123.456.789-rc+build",
76                "protocol_version": "1.2.3",
77                "capabilities": ["cap"]
78            })
79        );
80    }
81
82    #[test]
83    fn should_be_able_to_deserialize_from_json() {
84        let value = serde_json::json!({
85            "server_version": "123.456.789-rc+build",
86            "protocol_version": "1.2.3",
87            "capabilities": ["cap"]
88        });
89
90        let version: Version = serde_json::from_value(value).unwrap();
91        assert_eq!(
92            version,
93            Version {
94                server_version: "123.456.789-rc+build".parse().unwrap(),
95                protocol_version: SemVer::new(1, 2, 3),
96                capabilities: vec![String::from("cap")],
97            }
98        );
99    }
100
101    #[test]
102    fn should_be_able_to_serialize_to_msgpack() {
103        let version = Version {
104            server_version: "123.456.789-rc+build".parse().unwrap(),
105            protocol_version: SemVer::new(1, 2, 3),
106            capabilities: vec![String::from("cap")],
107        };
108
109        // NOTE: We don't actually check the output here because it's an implementation detail
110        // and could change as we change how serialization is done. This is merely to verify
111        // that we can serialize since there are times when serde fails to serialize at
112        // runtime.
113        let _ = rmp_serde::encode::to_vec_named(&version).unwrap();
114    }
115
116    #[test]
117    fn should_be_able_to_deserialize_from_msgpack() {
118        // NOTE: It may seem odd that we are serializing just to deserialize, but this is to
119        // verify that we are not corrupting or causing issues when serializing on a
120        // client/server and then trying to deserialize on the other side. This has happened
121        // enough times with minor changes that we need tests to verify.
122        let buf = rmp_serde::encode::to_vec_named(&Version {
123            server_version: "123.456.789-rc+build".parse().unwrap(),
124            protocol_version: SemVer::new(1, 2, 3),
125            capabilities: vec![String::from("cap")],
126        })
127        .unwrap();
128
129        let version: Version = rmp_serde::decode::from_slice(&buf).unwrap();
130        assert_eq!(
131            version,
132            Version {
133                server_version: "123.456.789-rc+build".parse().unwrap(),
134                protocol_version: SemVer::new(1, 2, 3),
135                capabilities: vec![String::from("cap")],
136            }
137        );
138    }
139}