1use std::fmt;
12use std::str::FromStr;
13
14use serde::Deserialize;
15use serde::Serialize;
16use typeuri::ACTOR_PORT_BIT;
17use typeuri::Named;
18
19#[derive(
21 Clone,
22 Copy,
23 PartialEq,
24 Eq,
25 Hash,
26 PartialOrd,
27 Ord,
28 Serialize,
29 Deserialize
30)]
31pub struct Port(u64);
32
33impl Port {
34 pub fn handler<M: Named>() -> Self {
36 Port(M::port())
37 }
38
39 pub fn is_handler(&self) -> bool {
41 self.0 & ACTOR_PORT_BIT != 0
42 }
43
44 pub fn as_u64(&self) -> u64 {
46 self.0
47 }
48}
49
50impl From<u64> for Port {
51 fn from(v: u64) -> Self {
52 Port(v)
53 }
54}
55
56impl fmt::Display for Port {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 write!(f, "{}", self.0)
59 }
60}
61
62impl fmt::Debug for Port {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 write!(f, "Port({})", self.0)
65 }
66}
67
68impl FromStr for Port {
69 type Err = std::num::ParseIntError;
70
71 fn from_str(s: &str) -> Result<Self, Self::Err> {
72 let v: u64 = s.parse()?;
73 Ok(Port(v))
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 struct TestMsg;
82
83 impl Named for TestMsg {
84 fn typename() -> &'static str {
85 "test::TestMsg"
86 }
87 }
88
89 #[test]
90 fn test_handler_port() {
91 let port = Port::handler::<TestMsg>();
92 assert!(
93 port.is_handler(),
94 "handler ports should have ACTOR_PORT_BIT set"
95 );
96 assert_eq!(port.as_u64(), TestMsg::port());
97 }
98
99 #[test]
100 fn test_non_handler_port() {
101 let port = Port::from(42);
102 assert!(
103 !port.is_handler(),
104 "plain ports should not have ACTOR_PORT_BIT set"
105 );
106 assert_eq!(port.as_u64(), 42);
107 }
108
109 #[test]
110 fn test_display_fromstr_roundtrip() {
111 let port = Port::from(12345);
112 assert_eq!(port.to_string(), "12345");
113 let parsed: Port = port.to_string().parse().unwrap();
114 assert_eq!(port, parsed);
115 }
116
117 #[test]
118 fn test_display_fromstr_roundtrip_handler() {
119 let port = Port::handler::<TestMsg>();
120 let s = port.to_string();
121 let parsed: Port = s.parse().unwrap();
122 assert_eq!(port, parsed);
123 }
124
125 #[test]
126 fn test_debug() {
127 let port = Port::from(42);
128 assert_eq!(format!("{:?}", port), "Port(42)");
129 }
130}