ouisync/network/
peer_state.rs1use 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 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}