atm0s_sdn_identity/
conn_id.rs1use serde::{Deserialize, Serialize};
2use std::fmt::{Debug, Formatter};
3use std::hash::{Hash, Hasher};
4
5#[derive(Deserialize, Serialize, Copy, Clone)]
6pub struct ConnId {
7 protocol: u8,
8 direction: ConnDirection,
9 session: u64,
10}
11
12#[derive(Deserialize, Serialize, Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
13#[repr(u8)]
14pub enum ConnDirection {
15 Outgoing = 0,
16 Incoming = 1,
17}
18
19impl ConnId {
20 pub fn from_raw(protocol: u8, direction: ConnDirection, session: u64) -> ConnId {
32 ConnId { protocol, direction, session }
33 }
34
35 pub fn from_out(protocol: u8, session: u64) -> ConnId {
46 Self::from_raw(protocol, ConnDirection::Outgoing, session)
47 }
48
49 pub fn from_in(protocol: u8, session: u64) -> ConnId {
68 Self::from_raw(protocol, ConnDirection::Incoming, session)
69 }
70
71 pub fn protocol(&self) -> u8 {
73 self.protocol
74 }
75
76 pub fn direction(&self) -> ConnDirection {
78 self.direction
79 }
80 pub fn is_outgoing(&self) -> bool {
82 self.direction() == ConnDirection::Outgoing
83 }
84
85 pub fn session(&self) -> u64 {
87 self.session
88 }
89}
90
91impl std::fmt::Display for ConnId {
92 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
93 let str = format!("Conn({:?},{},0x{:x})", self.direction(), self.protocol(), self.session());
94 std::fmt::Display::fmt(&str, f)
95 }
96}
97
98impl Debug for ConnId {
99 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
100 let str = format!("Conn({:?},{},0x{:x})", self.direction(), self.protocol(), self.session());
101 Debug::fmt(&str, f)
102 }
103}
104
105impl PartialEq<Self> for ConnId {
106 fn eq(&self, other: &Self) -> bool {
107 self.session == other.session && self.direction == other.direction
109 }
110}
111
112impl Eq for ConnId {}
113
114impl Hash for ConnId {
115 fn hash<H: Hasher>(&self, state: &mut H) {
116 state.write_u8(self.direction as u8);
117 state.write_u64(self.session);
118 }
119}
120
121impl PartialOrd<Self> for ConnId {
122 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
123 Some(self.cmp(other))
125 }
126}
127
128impl Ord for ConnId {
129 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
130 if self.session == other.session {
132 self.direction.cmp(&other.direction)
133 } else {
134 self.session.cmp(&other.session)
135 }
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn test_conn_id_from_out() {
145 let conn_id = ConnId::from_out(1, 123);
146 assert_eq!(conn_id.protocol(), 1);
147 assert_eq!(conn_id.direction(), ConnDirection::Outgoing);
148 assert_eq!(conn_id.session(), 123);
149 }
150
151 #[test]
152 fn test_conn_id_from_in() {
153 let conn_id = ConnId::from_in(2, 456);
154 assert_eq!(conn_id.protocol(), 2);
155 assert_eq!(conn_id.direction(), ConnDirection::Incoming);
156 assert_eq!(conn_id.session(), 456);
157 }
158
159 #[test]
160 fn test_conn_id_display() {
161 let conn_id = ConnId::from_out(3, 0x789);
162 assert_eq!(format!("{}", conn_id), "Conn(Outgoing,3,0x789)");
163 }
164
165 #[test]
166 fn test_conn_id_debug() {
167 let conn_id = ConnId::from_in(4, 0x101112);
168 assert_eq!(format!("{:?}", conn_id), "\"Conn(Incoming,4,0x101112)\"");
169 }
170
171 #[test]
172 fn test_conn_id_eq() {
173 let conn_id1 = ConnId::from_out(5, 131415);
174 let conn_id2 = ConnId::from_out(5, 131415);
175 let conn_id3 = ConnId::from_in(5, 131415);
176 assert_eq!(conn_id1, conn_id2);
177 assert_ne!(conn_id1, conn_id3);
178 }
179
180 #[test]
181 fn test_conn_id_hash() {
182 let conn_id1 = ConnId::from_out(6, 161718);
183 let conn_id2 = ConnId::from_out(6, 161718);
184 let conn_id3 = ConnId::from_in(6, 161718);
185 let mut set = std::collections::HashSet::new();
186 set.insert(conn_id1);
187 assert!(set.contains(&conn_id1));
188 assert!(set.contains(&conn_id2));
189 assert!(!set.contains(&conn_id3));
190 }
191}