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)]
16pub struct NamespaceImpl {
17 pub delimiter: &'static str,
18 pub parts: Vec<&'static str>,
19}
20
21impl NamespaceImpl {
22 pub fn into_arc(self) -> Arc<NamespaceImpl> {
24 Arc::new(self)
25 }
26}
27
28impl Namespace for NamespaceImpl {
29 fn path(&self) -> String {
30 self.parts.join(self.delimiter)
31 }
32
33 fn with_suffix(&self, suffix: Vec<&str>) -> String {
34 let parts_with_suffix: Vec<&str> = self.parts.clone().into_iter().chain(suffix).collect();
35
36 parts_with_suffix.join(self.delimiter)
37 }
38}
39
40impl fmt::Display for NamespaceImpl {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 write!(f, "{}", self.path())
43 }
44}
45
46#[derive(Debug, Clone)]
48pub struct DynamicNamespace {
49 pub delimiter: String,
50 pub parts: Vec<String>,
51}
52
53impl DynamicNamespace {
54 pub fn from_str(path: &str, delimiter: &str) -> Self {
56 Self {
57 delimiter: delimiter.to_string(),
58 parts: path.split(delimiter).map(|s| s.to_string()).collect(),
59 }
60 }
61
62 pub fn new_arc(path: &str, delimiter: &str) -> Arc<Self> {
64 Arc::new(Self::from_str(path, delimiter))
65 }
66}
67
68impl Namespace for DynamicNamespace {
69 fn path(&self) -> String {
70 self.parts.join(&self.delimiter)
71 }
72
73 fn with_suffix(&self, suffix: Vec<&str>) -> String {
74 let mut p = self.parts.clone();
75 p.extend(suffix.iter().map(|s| s.to_string()));
76 p.join(&self.delimiter)
77 }
78}
79
80impl fmt::Display for DynamicNamespace {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 write!(f, "{}", self.path())
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use crate::test_utils::test_namespace;
90
91 #[test]
92 fn test_namespace_path() {
93 let ns = test_namespace();
94 assert_eq!("dev.plexo", ns.path());
95 }
96
97 #[test]
98 fn test_namespace_with_suffix() {
99 let ns = test_namespace();
100 assert_eq!(
101 "dev.plexo.test.foobar",
102 ns.with_suffix(vec!["test", "foobar"])
103 );
104 }
105
106 #[test]
107 fn test_namespace_display() {
108 let ns = NamespaceImpl {
109 delimiter: ".",
110 parts: vec!["dev", "plexo"],
111 };
112 assert_eq!("dev.plexo", format!("{ns}"));
113 }
114}