1use std::fmt::{Display, Formatter};
4
5use crate::{Result, YugenDbError};
6
7const DEFAULT_NAME: &str = "default";
8
9fn validate_component(kind: &str, value: &str) -> Result<()> {
10 if value.is_empty() {
11 return Err(match kind {
12 "namespace" => YugenDbError::invalid_namespace("namespace must not be empty"),
13 "collection" => YugenDbError::invalid_collection("collection name must not be empty"),
14 "key" => YugenDbError::invalid_key("key must not be empty"),
15 _ => YugenDbError::internal_error("unknown key component kind"),
16 });
17 }
18
19 if value.chars().any(char::is_control) {
20 return Err(match kind {
21 "namespace" => {
22 YugenDbError::invalid_namespace("namespace must not contain control characters")
23 }
24 "collection" => YugenDbError::invalid_collection(
25 "collection name must not contain control characters",
26 ),
27 "key" => YugenDbError::invalid_key("key must not contain control characters"),
28 _ => YugenDbError::internal_error("unknown key component kind"),
29 });
30 }
31
32 Ok(())
33}
34
35#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
37pub struct Namespace(String);
38
39impl Namespace {
40 pub fn new(value: impl Into<String>) -> Result<Self> {
42 let value = value.into();
43 validate_component("namespace", &value)?;
44 Ok(Self(value))
45 }
46
47 #[must_use]
49 pub fn default_namespace() -> Self {
50 Self(DEFAULT_NAME.to_owned())
51 }
52
53 #[must_use]
55 pub fn as_str(&self) -> &str {
56 &self.0
57 }
58}
59
60impl Default for Namespace {
61 fn default() -> Self {
62 Self::default_namespace()
63 }
64}
65
66impl TryFrom<String> for Namespace {
67 type Error = YugenDbError;
68
69 fn try_from(value: String) -> Result<Self> {
70 Self::new(value)
71 }
72}
73
74impl TryFrom<&str> for Namespace {
75 type Error = YugenDbError;
76
77 fn try_from(value: &str) -> Result<Self> {
78 Self::new(value)
79 }
80}
81
82impl AsRef<str> for Namespace {
83 fn as_ref(&self) -> &str {
84 self.as_str()
85 }
86}
87
88impl Display for Namespace {
89 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
90 formatter.write_str(self.as_str())
91 }
92}
93
94#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
96pub struct CollectionName(String);
97
98impl CollectionName {
99 pub fn new(value: impl Into<String>) -> Result<Self> {
101 let value = value.into();
102 validate_component("collection", &value)?;
103 Ok(Self(value))
104 }
105
106 #[must_use]
108 pub fn default_collection() -> Self {
109 Self(DEFAULT_NAME.to_owned())
110 }
111
112 #[must_use]
114 pub fn as_str(&self) -> &str {
115 &self.0
116 }
117}
118
119impl Default for CollectionName {
120 fn default() -> Self {
121 Self::default_collection()
122 }
123}
124
125impl TryFrom<String> for CollectionName {
126 type Error = YugenDbError;
127
128 fn try_from(value: String) -> Result<Self> {
129 Self::new(value)
130 }
131}
132
133impl TryFrom<&str> for CollectionName {
134 type Error = YugenDbError;
135
136 fn try_from(value: &str) -> Result<Self> {
137 Self::new(value)
138 }
139}
140
141impl AsRef<str> for CollectionName {
142 fn as_ref(&self) -> &str {
143 self.as_str()
144 }
145}
146
147impl Display for CollectionName {
148 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
149 formatter.write_str(self.as_str())
150 }
151}
152
153#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
155pub struct Key(String);
156
157impl Key {
158 pub fn new(value: impl Into<String>) -> Result<Self> {
160 let value = value.into();
161 validate_component("key", &value)?;
162 Ok(Self(value))
163 }
164
165 #[must_use]
167 pub fn as_str(&self) -> &str {
168 &self.0
169 }
170}
171
172impl TryFrom<String> for Key {
173 type Error = YugenDbError;
174
175 fn try_from(value: String) -> Result<Self> {
176 Self::new(value)
177 }
178}
179
180impl TryFrom<&str> for Key {
181 type Error = YugenDbError;
182
183 fn try_from(value: &str) -> Result<Self> {
184 Self::new(value)
185 }
186}
187
188impl AsRef<str> for Key {
189 fn as_ref(&self) -> &str {
190 self.as_str()
191 }
192}
193
194impl Display for Key {
195 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
196 formatter.write_str(self.as_str())
197 }
198}