1use crate::{atomics::AtomicU64, cow::Cow, IntoLabels, KeyHasher, Label, SharedString};
2use std::{
3 borrow::Borrow,
4 cmp, fmt,
5 hash::{Hash, Hasher},
6 slice::Iter,
7 sync::atomic::{AtomicBool, Ordering},
8};
9
10const NO_LABELS: [Label; 0] = [];
11
12#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
14pub struct KeyName(SharedString);
15
16impl KeyName {
17 pub const fn from_const_str(name: &'static str) -> Self {
19 KeyName(SharedString::const_str(name))
20 }
21
22 pub fn as_str(&self) -> &str {
24 &self.0
25 }
26
27 pub fn into_inner(self) -> SharedString {
29 self.0
30 }
31}
32
33impl<T> From<T> for KeyName
34where
35 T: Into<SharedString>,
36{
37 fn from(name: T) -> Self {
38 KeyName(name.into())
39 }
40}
41
42impl Borrow<str> for KeyName {
43 fn borrow(&self) -> &str {
44 self.0.borrow()
45 }
46}
47
48impl From<KeyName> for std::borrow::Cow<'static, str> {
49 fn from(name: KeyName) -> Self {
50 name.0.into()
51 }
52}
53
54#[derive(Debug)]
71pub struct Key {
72 name: KeyName,
73 labels: Cow<'static, [Label]>,
74 hashed: AtomicBool,
75 hash: AtomicU64,
76}
77
78impl Key {
79 pub fn from_name<N>(name: N) -> Self
81 where
82 N: Into<KeyName>,
83 {
84 let name = name.into();
85 let labels = Cow::from_owned(Vec::new());
86
87 Self::builder(name, labels)
88 }
89
90 pub fn from_parts<N, L>(name: N, labels: L) -> Self
92 where
93 N: Into<KeyName>,
94 L: IntoLabels,
95 {
96 let name = name.into();
97 let labels = Cow::from_owned(labels.into_labels());
98
99 Self::builder(name, labels)
100 }
101
102 pub fn from_static_labels<N>(name: N, labels: &'static [Label]) -> Self
104 where
105 N: Into<KeyName>,
106 {
107 Self {
108 name: name.into(),
109 labels: Cow::const_slice(labels),
110 hashed: AtomicBool::new(false),
111 hash: AtomicU64::new(0),
112 }
113 }
114
115 pub const fn from_static_name(name: &'static str) -> Self {
119 Self::from_static_parts(name, &NO_LABELS)
120 }
121
122 pub const fn from_static_parts(name: &'static str, labels: &'static [Label]) -> Self {
126 Self {
127 name: KeyName::from_const_str(name),
128 labels: Cow::const_slice(labels),
129 hashed: AtomicBool::new(false),
130 hash: AtomicU64::new(0),
131 }
132 }
133
134 fn builder(name: KeyName, labels: Cow<'static, [Label]>) -> Self {
135 let hash = generate_key_hash(&name, &labels);
136
137 Self { name, labels, hashed: AtomicBool::new(true), hash: AtomicU64::new(hash) }
138 }
139
140 pub fn name(&self) -> &str {
142 self.name.0.as_ref()
143 }
144
145 pub fn name_shared(&self) -> KeyName {
147 self.name.clone()
148 }
149
150 pub fn labels(&self) -> Iter<'_, Label> {
152 self.labels.iter()
153 }
154
155 pub fn into_parts(self) -> (KeyName, Vec<Label>) {
157 (self.name, self.labels.into_owned())
158 }
159
160 pub fn with_extra_labels(&self, extra_labels: Vec<Label>) -> Self {
162 if extra_labels.is_empty() {
163 return self.clone();
164 }
165
166 let name = self.name.clone();
167 let mut labels = self.labels.clone().into_owned();
168 labels.extend(extra_labels);
169
170 Self::builder(name, labels.into())
171 }
172
173 pub fn get_hash(&self) -> u64 {
175 if self.hashed.load(Ordering::Acquire) {
176 self.hash.load(Ordering::Acquire)
177 } else {
178 let hash = generate_key_hash(&self.name, &self.labels);
179 self.hash.store(hash, Ordering::Release);
180 self.hashed.store(true, Ordering::Release);
181 hash
182 }
183 }
184}
185
186fn generate_key_hash(name: &KeyName, labels: &Cow<'static, [Label]>) -> u64 {
187 let mut hasher = KeyHasher::default();
188 key_hasher_impl(&mut hasher, name, labels);
189 hasher.finish()
190}
191
192fn key_hasher_impl<H: Hasher>(state: &mut H, name: &KeyName, labels: &Cow<'static, [Label]>) {
193 name.0.hash(state);
194 labels.len().hash(state);
195 match labels.len() {
196 0 => {}
197 1 => labels[0].hash(state),
198 2 => {
199 if labels[0] < labels[1] {
200 labels[0].hash(state);
201 labels[1].hash(state);
202 } else {
203 labels[1].hash(state);
204 labels[0].hash(state);
205 }
206 }
207 n if n < 8 => {
208 let mut labels_sort_map: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
209 labels_sort_map[..n].sort_by_key(|i| labels[*i as usize].key());
210 for i in 0..n {
211 labels[labels_sort_map[i] as usize].hash(state)
212 }
213 }
214 n => {
215 let mut labels_sort_map: Vec<usize> = (0..n).collect();
216 labels_sort_map.sort_by_key(|i| labels[*i].key());
217 for i in 0..n {
218 labels[labels_sort_map[i]].hash(state)
219 }
220 }
221 }
222}
223
224impl Clone for Key {
225 fn clone(&self) -> Self {
226 Self {
227 name: self.name.clone(),
228 labels: self.labels.clone(),
229 hashed: AtomicBool::new(self.hashed.load(Ordering::Acquire)),
230 hash: AtomicU64::new(self.hash.load(Ordering::Acquire)),
231 }
232 }
233}
234
235impl PartialEq for Key {
236 fn eq(&self, other: &Self) -> bool {
237 if self.name != other.name {
238 return false;
239 }
240 if self.labels.len() != other.labels.len() {
241 return false;
242 }
243 match self.labels.len() {
244 0 => true,
245 1 => self.labels[0] == other.labels[0],
246 2 => {
247 if self.labels[0] == other.labels[0] {
248 self.labels[1] == other.labels[1]
249 } else if self.labels[0] == other.labels[1] {
250 self.labels[1] == other.labels[0]
251 } else {
252 false
253 }
254 }
255 n if n < 8 => {
256 let mut labels_sort_map: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
257 labels_sort_map[..n].sort_by_key(|i| self.labels[*i as usize].key());
258 let mut his_labels_sort_map: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
259 his_labels_sort_map[..n].sort_by_key(|i| other.labels[*i as usize].key());
260 for i in 0..n {
261 if self.labels[labels_sort_map[i] as usize]
262 != other.labels[his_labels_sort_map[i] as usize]
263 {
264 return false;
265 }
266 }
267 true
268 }
269 n => {
270 let mut labels_sort_map: Vec<usize> = (0..n).collect();
271 labels_sort_map.sort_by_key(|i| self.labels[*i].key());
272 let mut his_labels_sort_map: Vec<usize> = (0..n).collect();
273 his_labels_sort_map.sort_by_key(|i| other.labels[*i].key());
274 for i in 0..n {
275 if self.labels[labels_sort_map[i]] != other.labels[his_labels_sort_map[i]] {
276 return false;
277 }
278 }
279 true
280 }
281 }
282 }
283}
284
285impl Eq for Key {}
286
287impl PartialOrd for Key {
288 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
289 Some(self.cmp(other))
290 }
291}
292
293impl Ord for Key {
294 fn cmp(&self, other: &Self) -> cmp::Ordering {
295 match (&self.name, self.labels.len()).cmp(&(&other.name, other.labels.len())) {
296 cmp::Ordering::Less => return cmp::Ordering::Less,
297 cmp::Ordering::Equal => {}
298 cmp::Ordering::Greater => return cmp::Ordering::Greater,
299 }
300 match self.labels.len() {
301 0 => cmp::Ordering::Equal,
302 1 => self.labels[0].cmp(&other.labels[0]),
303 n if n < 8 => {
304 let mut labels_sort_map: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
305 labels_sort_map[..n].sort_by_key(|i| self.labels[*i as usize].key());
306 let mut his_labels_sort_map: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
307 his_labels_sort_map[..n].sort_by_key(|i| other.labels[*i as usize].key());
308 for i in 0..n {
309 match self.labels[labels_sort_map[i] as usize]
310 .cmp(&other.labels[his_labels_sort_map[i] as usize])
311 {
312 cmp::Ordering::Less => return cmp::Ordering::Less,
313 cmp::Ordering::Equal => {}
314 cmp::Ordering::Greater => return cmp::Ordering::Greater,
315 }
316 }
317 cmp::Ordering::Equal
318 }
319 n => {
320 let mut labels_sort_map: Vec<usize> = (0..n).collect();
321 labels_sort_map.sort_by_key(|i| self.labels[*i].key());
322 let mut his_labels_sort_map: Vec<usize> = (0..n).collect();
323 his_labels_sort_map.sort_by_key(|i| other.labels[*i].key());
324 for i in 0..n {
325 match self.labels[labels_sort_map[i]].cmp(&other.labels[his_labels_sort_map[i]])
326 {
327 cmp::Ordering::Less => return cmp::Ordering::Less,
328 cmp::Ordering::Equal => {}
329 cmp::Ordering::Greater => return cmp::Ordering::Greater,
330 }
331 }
332 cmp::Ordering::Equal
333 }
334 }
335 }
336}
337
338impl Hash for Key {
339 fn hash<H: Hasher>(&self, state: &mut H) {
340 key_hasher_impl(state, &self.name, &self.labels);
341 }
342}
343
344impl fmt::Display for Key {
345 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
346 if self.labels.is_empty() {
347 write!(f, "Key({})", self.name.as_str())
348 } else {
349 write!(f, "Key({}, [", self.name.as_str())?;
350 let mut first = true;
351 for label in self.labels.as_ref() {
352 if first {
353 write!(f, "{} = {}", label.0, label.1)?;
354 first = false;
355 } else {
356 write!(f, ", {} = {}", label.0, label.1)?;
357 }
358 }
359 write!(f, "])")
360 }
361 }
362}
363
364impl<T> From<T> for Key
365where
366 T: Into<KeyName>,
367{
368 fn from(name: T) -> Self {
369 Self::from_name(name)
370 }
371}
372
373impl<N, L> From<(N, L)> for Key
374where
375 N: Into<KeyName>,
376 L: IntoLabels,
377{
378 fn from(parts: (N, L)) -> Self {
379 Self::from_parts(parts.0, parts.1)
380 }
381}
382
383#[cfg(test)]
384mod tests {
385 use super::Key;
386 use crate::{KeyName, Label};
387 use std::{cmp, collections::HashMap, ops::Deref, sync::Arc};
388
389 static BORROWED_NAME: &str = "name";
390 static FOOBAR_NAME: &str = "foobar";
391 static BORROWED_BASIC: Key = Key::from_static_name(BORROWED_NAME);
392 static LABELS: [Label; 1] = [Label::from_static_parts("key", "value")];
393 static BORROWED_LABELS: Key = Key::from_static_parts(BORROWED_NAME, &LABELS);
394
395 #[test]
396 fn test_key_ord_and_partialord() {
397 let keys_expected: Vec<Key> =
398 vec![Key::from_name("aaaa"), Key::from_name("bbbb"), Key::from_name("cccc")];
399
400 let keys_unsorted: Vec<Key> =
401 vec![Key::from_name("bbbb"), Key::from_name("cccc"), Key::from_name("aaaa")];
402
403 let keys = {
404 let mut keys = keys_unsorted.clone();
405 keys.sort();
406 keys
407 };
408 assert_eq!(keys, keys_expected);
409
410 let keys = {
411 let mut keys = keys_unsorted.clone();
412 keys.sort_by(|a, b| a.partial_cmp(b).unwrap());
413 keys
414 };
415 assert_eq!(keys, keys_expected);
416 }
417
418 #[test]
419 fn test_key_ord_total() {
420 let mut keys: Vec<_> = (1..16)
421 .flat_map(|i| {
422 let names: Vec<Label> =
423 (0..i).map(|s| Label::new(format!("{}", s), format!("{}", s))).collect();
424 let key1 = Key::from_parts("key", names.clone());
425
426 let mut names_alt = names.clone();
428 names_alt.rotate_left(1);
429 let key2 = Key::from_parts("key", names_alt);
430 assert_eq!(key1, key2);
431
432 names_alt = names.clone();
434 names_alt[0] = Label::new("x".to_string(), "0".to_string());
435 let key3 = Key::from_parts("key", names_alt);
436 assert_ne!(key1, key3);
437
438 names_alt = names.clone();
440 names_alt[i - 1] = Label::new("x".to_string(), "0".to_string());
441 let key4 = Key::from_parts("key", names_alt);
442 assert_ne!(key1, key4);
443
444 [key1, key2, key3, key4]
445 })
446 .collect();
447 keys.push(Key::from_parts("key", vec![]));
448 keys.sort();
449 for i in 0..keys.len() {
450 for j in 0..keys.len() {
451 match (keys[i] == keys[j], keys[i].cmp(&keys[j])) {
453 (true, cmp::Ordering::Equal) => {}
454 (true, cmp::Ordering::Less) => panic!("at {} {} equal keys compared lt", i, j),
455 (true, cmp::Ordering::Greater) => {
456 panic!("at {} {} equal keys compared gt", i, j)
457 }
458 (false, cmp::Ordering::Equal) => {
459 panic!("at {} {} unequal keys compared equal", i, j)
460 }
461 (false, cmp::Ordering::Less) => assert!(i < j),
462 (false, cmp::Ordering::Greater) => assert!(i > j),
463 }
464 }
465 }
466 }
467
468 #[test]
469 fn test_key_eq_and_hash() {
470 let mut keys = HashMap::new();
471
472 let owned_basic: Key = Key::from_name("name");
473 assert_eq!(&owned_basic, &BORROWED_BASIC);
474
475 let previous = keys.insert(owned_basic, 42);
476 assert!(previous.is_none());
477
478 let previous = keys.get(&BORROWED_BASIC);
479 assert_eq!(previous, Some(&42));
480
481 let labels = LABELS.to_vec();
482 let owned_labels = Key::from_parts(BORROWED_NAME, labels);
483 assert_eq!(&owned_labels, &BORROWED_LABELS);
484
485 let previous = keys.insert(owned_labels, 43);
486 assert!(previous.is_none());
487
488 let previous = keys.get(&BORROWED_LABELS);
489 assert_eq!(previous, Some(&43));
490
491 let basic: Key = "constant_key".into();
492 let cloned_basic = basic.clone();
493 assert_eq!(basic, cloned_basic);
494
495 for i in 1..16 {
496 let names: Vec<Label> =
497 (0..i).map(|s| Label::new(format!("{}", s), format!("{}", s))).collect();
498 let key1 = Key::from_parts("key", names.clone());
499 let mut names_alt = names.clone();
500
501 names_alt.rotate_left(1);
503 let key2 = Key::from_parts("key", names_alt);
504 assert_eq!(key1, key2);
505 assert_eq!(key1.get_hash(), key2.get_hash());
506
507 names_alt = names.clone();
509 names_alt[0] = Label::new("x".to_string(), "0".to_string());
510 let key2 = Key::from_parts("key", names_alt);
511 assert_ne!(key1, key2);
512 assert_ne!(key1.get_hash(), key2.get_hash());
513
514 names_alt = names.clone();
516 names_alt[i - 1] = Label::new("x".to_string(), "0".to_string());
517 let key2 = Key::from_parts("key", names_alt);
518 assert_ne!(key1, key2);
519 assert_ne!(key1.get_hash(), key2.get_hash());
520
521 let key2 = Key::from_parts("key", vec![]);
523 assert_ne!(key1, key2);
524 assert_ne!(key1.get_hash(), key2.get_hash());
525 }
526 }
527
528 #[test]
529 fn test_key_data_proper_display() {
530 let key1 = Key::from_name("foobar");
531 let result1 = key1.to_string();
532 assert_eq!(result1, "Key(foobar)");
533
534 let key2 = Key::from_parts(FOOBAR_NAME, vec![Label::new("system", "http")]);
535 let result2 = key2.to_string();
536 assert_eq!(result2, "Key(foobar, [system = http])");
537
538 let key3 = Key::from_parts(
539 FOOBAR_NAME,
540 vec![Label::new("system", "http"), Label::new("user", "joe")],
541 );
542 let result3 = key3.to_string();
543 assert_eq!(result3, "Key(foobar, [system = http, user = joe])");
544
545 let key4 = Key::from_parts(
546 FOOBAR_NAME,
547 vec![
548 Label::new("black", "black"),
549 Label::new("lives", "lives"),
550 Label::new("matter", "matter"),
551 ],
552 );
553 let result4 = key4.to_string();
554 assert_eq!(result4, "Key(foobar, [black = black, lives = lives, matter = matter])");
555 }
556
557 #[test]
558 fn test_key_name_equality() {
559 static KEY_NAME: &str = "key_name";
560
561 let borrowed_const = KeyName::from_const_str(KEY_NAME);
562 let borrowed_nonconst = KeyName::from(KEY_NAME);
563 let owned = KeyName::from(KEY_NAME.to_owned());
564
565 let shared_arc = Arc::from(KEY_NAME);
566 let shared = KeyName::from(Arc::clone(&shared_arc));
567
568 assert_eq!(borrowed_const, borrowed_nonconst);
569 assert_eq!(borrowed_const.as_str(), borrowed_nonconst.as_str());
570 assert_eq!(borrowed_const, owned);
571 assert_eq!(borrowed_const.as_str(), owned.as_str());
572 assert_eq!(borrowed_const, shared);
573 assert_eq!(borrowed_const.as_str(), shared.as_str());
574 }
575
576 #[test]
577 fn test_shared_key_name_drop_logic() {
578 let shared_arc = Arc::from("foo");
579 let shared = KeyName::from(Arc::clone(&shared_arc));
580
581 assert_eq!(shared_arc.deref(), shared.as_str());
582
583 assert_eq!(Arc::strong_count(&shared_arc), 2);
584 drop(shared);
585 assert_eq!(Arc::strong_count(&shared_arc), 1);
586
587 let shared_weak = Arc::downgrade(&shared_arc);
588 assert_eq!(Arc::strong_count(&shared_arc), 1);
589
590 let shared = KeyName::from(Arc::clone(&shared_arc));
591 assert_eq!(shared_arc.deref(), shared.as_str());
592 assert_eq!(Arc::strong_count(&shared_arc), 2);
593
594 drop(shared_arc);
595 assert_eq!(shared_weak.strong_count(), 1);
596
597 drop(shared);
598 assert_eq!(shared_weak.strong_count(), 0);
599 }
600}