Skip to main content

atomr_core/actor/
address.rs

1//! An `Address` locates an actor system on the network.
2
3use std::fmt;
4
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
8pub struct Address {
9    pub protocol: String,
10    pub system: String,
11    pub host: Option<String>,
12    pub port: Option<u16>,
13}
14
15impl Address {
16    pub fn local(system: impl Into<String>) -> Self {
17        Self { protocol: "akka".into(), system: system.into(), host: None, port: None }
18    }
19
20    pub fn remote(
21        protocol: impl Into<String>,
22        system: impl Into<String>,
23        host: impl Into<String>,
24        port: u16,
25    ) -> Self {
26        Self { protocol: protocol.into(), system: system.into(), host: Some(host.into()), port: Some(port) }
27    }
28
29    pub fn has_local_scope(&self) -> bool {
30        self.host.is_none()
31    }
32
33    pub fn has_global_scope(&self) -> bool {
34        self.host.is_some()
35    }
36
37    /// Parses strings like `akka://sys` or `akka.tcp://sys@host:1234`.
38    pub fn parse(s: &str) -> Option<Self> {
39        let (protocol, rest) = s.split_once("://")?;
40        if let Some((sys, host_port)) = rest.split_once('@') {
41            let (host, port) = host_port.split_once(':')?;
42            Some(Self::remote(protocol, sys, host, port.parse().ok()?))
43        } else {
44            Some(Self::local(rest).with_protocol(protocol))
45        }
46    }
47
48    fn with_protocol(mut self, p: impl Into<String>) -> Self {
49        self.protocol = p.into();
50        self
51    }
52}
53
54impl fmt::Display for Address {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        match (&self.host, self.port) {
57            (Some(h), Some(p)) => write!(f, "{}://{}@{}:{}", self.protocol, self.system, h, p),
58            _ => write!(f, "{}://{}", self.protocol, self.system),
59        }
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn local_has_no_host() {
69        let a = Address::local("Sys");
70        assert!(a.has_local_scope());
71        assert_eq!(a.to_string(), "akka://Sys");
72    }
73
74    #[test]
75    fn remote_roundtrips() {
76        let a = Address::remote("akka.tcp", "Sys", "host", 1234);
77        assert!(a.has_global_scope());
78        assert_eq!(Address::parse(&a.to_string()).unwrap(), a);
79    }
80
81    #[test]
82    fn parses_local_form() {
83        assert_eq!(Address::parse("akka://Sys").unwrap(), Address::local("Sys"));
84    }
85}