hyperactor/
port.rs

1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree.
7 */
8
9//! Port identifier newtype.
10
11use std::fmt;
12use std::str::FromStr;
13
14use serde::Deserialize;
15use serde::Serialize;
16use typeuri::ACTOR_PORT_BIT;
17use typeuri::Named;
18
19/// A port identifier within an actor.
20#[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    /// Create a port for handler message type `M`.
35    pub fn handler<M: Named>() -> Self {
36        Port(M::port())
37    }
38
39    /// Whether this is a handler port (actor port bit set).
40    pub fn is_handler(&self) -> bool {
41        self.0 & ACTOR_PORT_BIT != 0
42    }
43
44    /// The raw port index.
45    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}