ouisync/network/
peer_state.rs

1use std::time::SystemTime;
2
3use ouisync_macros::api;
4use serde::{Deserialize, Serialize};
5
6use super::runtime_id::PublicRuntimeId;
7
8#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)]
9#[api]
10pub enum PeerState {
11    Known,
12    Connecting,
13    Handshaking,
14    Active {
15        id: PublicRuntimeId,
16        #[serde(with = "system_time")]
17        since: SystemTime,
18    },
19}
20
21mod system_time {
22    use serde::{ser, Deserialize, Deserializer, Serialize, Serializer};
23
24    use crate::time::{from_millis_since_epoch, to_millis_since_epoch};
25    use std::time::SystemTime;
26
27    pub(super) fn serialize<S: Serializer>(time: &SystemTime, s: S) -> Result<S::Ok, S::Error> {
28        to_millis_since_epoch(*time)
29            .map_err(ser::Error::custom)?
30            .serialize(s)
31    }
32
33    pub(super) fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<SystemTime, D::Error> {
34        Ok(from_millis_since_epoch(u64::deserialize(d)?))
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use crate::time::{from_millis_since_epoch, to_millis_since_epoch};
41
42    use super::*;
43    use crate::network::runtime_id::SecretRuntimeId;
44    use serde_json::json;
45
46    #[test]
47    fn serialize_deserialize_json() {
48        let id = SecretRuntimeId::random().public();
49        let now = SystemTime::now();
50
51        let test_vectors = [
52            (PeerState::Known, json!("Known")),
53            (PeerState::Connecting, json!("Connecting")),
54            (PeerState::Handshaking, json!("Handshaking")),
55            (
56                PeerState::Active {
57                    id,
58                    // The timestamp is serialized as the number of milliseconds since the epoch so we
59                    // need to round it to whole milliseconds otherwise the deserialized value would
60                    // not be exactly equal to the original one.
61                    since: round_to_millis(now),
62                },
63                json!({
64                    "Active": {
65                        "id": id.as_ref(),
66                        "since": to_millis_since_epoch(now).unwrap(),
67                    }
68                }),
69            ),
70        ];
71
72        for (input, expected) in test_vectors {
73            let s = serde_json::to_string(&input).unwrap();
74            let v: serde_json::Value = serde_json::from_str(&s).unwrap();
75
76            assert_eq!(v, expected);
77
78            let d: PeerState = serde_json::from_str(&s).unwrap();
79            assert_eq!(d, input);
80        }
81    }
82
83    #[test]
84    fn serialize_deserialize_msgpack() {
85        let id = SecretRuntimeId::random().public();
86        let now = SystemTime::now();
87
88        let test_vectors = [
89            (PeerState::Known, {
90                let mut out = Vec::new();
91                rmp::encode::write_str(&mut out, "Known").unwrap();
92                out
93            }),
94            (PeerState::Connecting, {
95                let mut out = Vec::new();
96                rmp::encode::write_str(&mut out, "Connecting").unwrap();
97                out
98            }),
99            (PeerState::Handshaking, {
100                let mut out = Vec::new();
101                rmp::encode::write_str(&mut out, "Handshaking").unwrap();
102                out
103            }),
104            (
105                PeerState::Active {
106                    id,
107                    since: round_to_millis(now),
108                },
109                {
110                    let mut out = Vec::new();
111                    rmp::encode::write_map_len(&mut out, 1).unwrap();
112                    rmp::encode::write_str(&mut out, "Active").unwrap();
113                    rmp::encode::write_array_len(&mut out, 2).unwrap();
114                    rmp::encode::write_bin(&mut out, id.as_ref()).unwrap();
115                    rmp::encode::write_u64(&mut out, to_millis_since_epoch(now).unwrap()).unwrap();
116                    out
117                },
118            ),
119        ];
120
121        for (input, expected) in test_vectors {
122            let s = rmp_serde::to_vec(&input).unwrap();
123            assert_eq!(s, expected);
124
125            let d: PeerState = rmp_serde::from_slice(&s).unwrap();
126            assert_eq!(d, input);
127        }
128    }
129
130    fn round_to_millis(time: SystemTime) -> SystemTime {
131        from_millis_since_epoch(to_millis_since_epoch(time).unwrap())
132    }
133}