zenoh_protocol_core/
endpoints.rs

1//
2// Copyright (c) 2022 ZettaScale Technology
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7// which is available at https://www.apache.org/licenses/LICENSE-2.0.
8//
9// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10//
11// Contributors:
12//   ZettaScale Zenoh Team, <zenoh@zettascale.tech>
13//
14use 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/// A `String` that respects the [`EndPoint`] canon form: `<locator>#<config>`, such that `<locator>` is a valid [`Locator`] `<config>` is of the form `<key1>=<value1>;...;<keyN>=<valueN>` where keys are alphabetically sorted.
30#[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}