zenoh_protocol_core/
endpoints.rs1use zenoh_core::bail;
15
16use crate::{
17 locators::{ArcProperties, Locator},
18 split_once,
19};
20
21use super::locators::{CONFIG_SEPARATOR, FIELD_SEPARATOR, LIST_SEPARATOR, METADATA_SEPARATOR};
22
23use std::{
24 convert::{TryFrom, TryInto},
25 iter::FromIterator,
26 str::FromStr,
27};
28
29#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
31#[serde(into = "String")]
32#[serde(try_from = "String")]
33pub struct EndPoint {
34 pub locator: Locator,
35 pub config: Option<ArcProperties>,
36}
37impl core::fmt::Display for EndPoint {
38 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> std::fmt::Result {
39 write!(f, "{}", &self.locator)?;
40 if let Some(meta) = &self.config {
41 let mut iter = meta.iter();
42 if let Some((k, v)) = iter.next() {
43 write!(f, "{}{}{}{}", CONFIG_SEPARATOR, k, FIELD_SEPARATOR, v)?;
44 }
45 for (k, v) in iter {
46 write!(f, "{}{}{}{}", LIST_SEPARATOR, k, FIELD_SEPARATOR, v)?;
47 }
48 }
49 Ok(())
50 }
51}
52impl From<EndPoint> for String {
53 fn from(v: EndPoint) -> String {
54 v.to_string()
55 }
56}
57
58impl EndPoint {
59 #[must_use = "returns true on success"]
60 pub fn set_addr(&mut self, addr: &str) -> bool {
61 self.locator.set_addr(addr)
62 }
63
64 pub fn extend_configuration(&mut self, extension: impl IntoIterator<Item = (String, String)>) {
65 match self.config.is_some() {
66 true => match &mut self.config {
67 Some(config) => config.extend(extension),
68 None => unsafe { std::hint::unreachable_unchecked() },
69 },
70 false => {
71 self.config =
72 Some(std::collections::HashMap::from_iter(extension.into_iter()).into())
73 }
74 }
75 }
76}
77impl From<EndPoint> for Locator {
78 fn from(val: EndPoint) -> Self {
79 val.locator
80 }
81}
82impl From<Locator> for EndPoint {
83 fn from(val: Locator) -> Self {
84 EndPoint {
85 locator: val,
86 config: None,
87 }
88 }
89}
90
91impl TryFrom<String> for EndPoint {
92 type Error = zenoh_core::Error;
93 fn try_from(mut value: String) -> Result<Self, Self::Error> {
94 let (l, r) = split_once(&value, CONFIG_SEPARATOR);
95 if r.contains(METADATA_SEPARATOR) {
96 bail!(
97 "{} is a forbidden character in endpoint metadata",
98 METADATA_SEPARATOR
99 );
100 }
101 let config = r.parse().ok();
102 let locator_len = l.len();
103 value.truncate(locator_len);
104 Ok(EndPoint {
105 locator: value.try_into()?,
106 config,
107 })
108 }
109}
110impl FromStr for EndPoint {
111 type Err = zenoh_core::Error;
112 fn from_str(s: &str) -> Result<Self, Self::Err> {
113 let (l, r) = split_once(s, CONFIG_SEPARATOR);
114 if r.contains(METADATA_SEPARATOR) {
115 bail!(
116 "{} is a forbidden character in endpoint metadata",
117 METADATA_SEPARATOR
118 );
119 }
120 Ok(EndPoint {
121 locator: l.parse()?,
122 config: r.parse().ok(),
123 })
124 }
125}