1use std::fmt;
4use std::sync::Arc;
5
6use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9pub struct IdentifierError {
10 pub kind: &'static str,
11 pub value: String,
12}
13
14impl fmt::Display for IdentifierError {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 write!(f, "invalid {} identifier: {}", self.kind, self.value)
17 }
18}
19
20impl std::error::Error for IdentifierError {}
21
22fn is_ident_start(ch: char) -> bool {
23 ch.is_ascii_alphabetic() || ch == '_'
24}
25
26fn is_ident_continue(ch: char) -> bool {
27 ch.is_ascii_alphanumeric() || ch == '_'
28}
29
30fn validate_ident(kind: &'static str, value: &str) -> Result<(), IdentifierError> {
31 let mut chars = value.chars();
32 let Some(first) = chars.next() else {
33 return Err(IdentifierError {
34 kind,
35 value: value.to_string(),
36 });
37 };
38 if !is_ident_start(first) {
39 return Err(IdentifierError {
40 kind,
41 value: value.to_string(),
42 });
43 }
44 if !chars.all(is_ident_continue) {
45 return Err(IdentifierError {
46 kind,
47 value: value.to_string(),
48 });
49 }
50 Ok(())
51}
52
53#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
54pub struct RoleName(Arc<str>);
55
56impl RoleName {
57 pub fn new(value: impl Into<String>) -> Result<Self, IdentifierError> {
58 let value = value.into();
59 validate_ident("role", &value)?;
60 Ok(Self(Arc::from(value)))
61 }
62
63 pub fn from_static(value: &'static str) -> Self {
64 debug_assert!(validate_ident("role", value).is_ok());
65 Self(Arc::from(value))
66 }
67
68 pub fn as_str(&self) -> &str {
69 &self.0
70 }
71}
72
73impl fmt::Debug for RoleName {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 write!(f, "RoleName({})", self.0)
76 }
77}
78
79impl fmt::Display for RoleName {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 f.write_str(&self.0)
82 }
83}
84
85impl Serialize for RoleName {
86 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
87 where
88 S: Serializer,
89 {
90 serializer.serialize_str(self.as_str())
91 }
92}
93
94impl<'de> Deserialize<'de> for RoleName {
95 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
96 where
97 D: Deserializer<'de>,
98 {
99 let value = String::deserialize(deserializer)?;
100 RoleName::new(value).map_err(de::Error::custom)
101 }
102}
103
104#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
105pub struct Namespace(Arc<str>);
106
107impl Namespace {
108 pub fn new(value: impl Into<String>) -> Result<Self, IdentifierError> {
109 let value = value.into();
110 validate_ident("namespace", &value)?;
111 Ok(Self(Arc::from(value)))
112 }
113
114 pub fn as_str(&self) -> &str {
115 &self.0
116 }
117}
118
119impl fmt::Debug for Namespace {
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 write!(f, "Namespace({})", self.0)
122 }
123}
124
125impl fmt::Display for Namespace {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 f.write_str(&self.0)
128 }
129}
130
131impl Serialize for Namespace {
132 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
133 where
134 S: Serializer,
135 {
136 serializer.serialize_str(self.as_str())
137 }
138}
139
140impl<'de> Deserialize<'de> for Namespace {
141 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
142 where
143 D: Deserializer<'de>,
144 {
145 let value = String::deserialize(deserializer)?;
146 Namespace::new(value).map_err(de::Error::custom)
147 }
148}
149
150#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
151pub struct Datacenter(Arc<str>);
152
153impl Datacenter {
154 pub fn new(value: impl Into<String>) -> Result<Self, IdentifierError> {
155 let value = value.into();
156 validate_ident("datacenter", &value)?;
157 Ok(Self(Arc::from(value)))
158 }
159
160 pub fn as_str(&self) -> &str {
161 &self.0
162 }
163}
164
165impl fmt::Debug for Datacenter {
166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167 write!(f, "Datacenter({})", self.0)
168 }
169}
170
171impl fmt::Display for Datacenter {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 f.write_str(&self.0)
174 }
175}
176
177impl Serialize for Datacenter {
178 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
179 where
180 S: Serializer,
181 {
182 serializer.serialize_str(self.as_str())
183 }
184}
185
186impl<'de> Deserialize<'de> for Datacenter {
187 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
188 where
189 D: Deserializer<'de>,
190 {
191 let value = String::deserialize(deserializer)?;
192 Datacenter::new(value).map_err(de::Error::custom)
193 }
194}
195
196#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
197pub struct Region(Arc<str>);
198
199impl Region {
200 pub fn new(value: impl Into<String>) -> Result<Self, IdentifierError> {
201 let value = value.into();
202 validate_ident("region", &value)?;
203 Ok(Self(Arc::from(value)))
204 }
205
206 pub fn as_str(&self) -> &str {
207 &self.0
208 }
209}
210
211impl fmt::Debug for Region {
212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213 write!(f, "Region({})", self.0)
214 }
215}
216
217impl fmt::Display for Region {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 f.write_str(&self.0)
220 }
221}
222
223impl Serialize for Region {
224 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
225 where
226 S: Serializer,
227 {
228 serializer.serialize_str(self.as_str())
229 }
230}
231
232impl<'de> Deserialize<'de> for Region {
233 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
234 where
235 D: Deserializer<'de>,
236 {
237 let value = String::deserialize(deserializer)?;
238 Region::new(value).map_err(de::Error::custom)
239 }
240}
241
242#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
243pub struct Endpoint(Arc<str>);
244
245impl Endpoint {
246 pub fn new(value: impl Into<String>) -> Result<Self, IdentifierError> {
247 let value = value.into();
248 if value.trim().is_empty() {
249 return Err(IdentifierError {
250 kind: "endpoint",
251 value,
252 });
253 }
254 Ok(Self(Arc::from(value)))
255 }
256
257 pub fn as_str(&self) -> &str {
258 &self.0
259 }
260}
261
262impl fmt::Debug for Endpoint {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 write!(f, "Endpoint({})", self.0)
265 }
266}
267
268impl fmt::Display for Endpoint {
269 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270 f.write_str(&self.0)
271 }
272}
273
274impl Serialize for Endpoint {
275 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
276 where
277 S: Serializer,
278 {
279 serializer.serialize_str(self.as_str())
280 }
281}
282
283impl<'de> Deserialize<'de> for Endpoint {
284 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
285 where
286 D: Deserializer<'de>,
287 {
288 let value = String::deserialize(deserializer)?;
289 Endpoint::new(value).map_err(de::Error::custom)
290 }
291}