1use std::fmt;
8use std::sync::Arc;
9
10pub trait Namespace: fmt::Display + Send + Sync + 'static {
11 fn path(&self) -> String;
12 fn with_suffix(&self, suffix: Vec<&str>) -> String;
13}
14
15#[derive(Debug, Clone)]
27pub struct NamespaceImpl {
28 pub delimiter: &'static str,
29 pub parts: Vec<&'static str>,
30}
31
32impl NamespaceImpl {
33 pub fn into_arc(self) -> Arc<NamespaceImpl> {
35 Arc::new(self)
36 }
37}
38
39impl Namespace for NamespaceImpl {
40 fn path(&self) -> String {
41 self.parts.join(self.delimiter)
42 }
43
44 fn with_suffix(&self, suffix: Vec<&str>) -> String {
45 let parts_with_suffix: Vec<&str> = self.parts.clone().into_iter().chain(suffix).collect();
46
47 parts_with_suffix.join(self.delimiter)
48 }
49}
50
51impl fmt::Display for NamespaceImpl {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(f, "{}", self.path())
54 }
55}
56
57#[derive(Debug, Clone)]
59pub struct DynamicNamespace {
60 pub delimiter: String,
61 pub parts: Vec<String>,
62}
63
64impl DynamicNamespace {
65 pub fn from_str(path: &str, delimiter: &str) -> Self {
77 Self {
78 delimiter: delimiter.to_string(),
79 parts: path.split(delimiter).map(|s| s.to_string()).collect(),
80 }
81 }
82
83 pub fn new_arc(path: &str, delimiter: &str) -> Arc<Self> {
85 Arc::new(Self::from_str(path, delimiter))
86 }
87}
88
89impl Namespace for DynamicNamespace {
90 fn path(&self) -> String {
91 self.parts.join(&self.delimiter)
92 }
93
94 fn with_suffix(&self, suffix: Vec<&str>) -> String {
95 let mut p = self.parts.clone();
96 p.extend(suffix.iter().map(|s| s.to_string()));
97 p.join(&self.delimiter)
98 }
99}
100
101impl fmt::Display for DynamicNamespace {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 write!(f, "{}", self.path())
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110 use crate::test_utils::test_namespace;
111
112 #[test]
113 fn test_namespace_path() {
114 let ns = test_namespace();
115 assert_eq!("dev.plexo", ns.path());
116 }
117
118 #[test]
119 fn test_namespace_with_suffix() {
120 let ns = test_namespace();
121 assert_eq!(
122 "dev.plexo.test.foobar",
123 ns.with_suffix(vec!["test", "foobar"])
124 );
125 }
126
127 #[test]
128 fn test_namespace_display() {
129 let ns = NamespaceImpl {
130 delimiter: ".",
131 parts: vec!["dev", "plexo"],
132 };
133 assert_eq!("dev.plexo", format!("{ns}"));
134 }
135}