1#[cfg(feature = "ser")]
2use serde::Serialize;
3use std::cmp;
4use std::hash::{Hash, Hasher};
5
6pub type KeyName = String;
7
8#[derive(Debug, Clone)]
9#[cfg_attr(feature = "ser", derive(Serialize))]
10pub struct Key {
11    pub(crate) name: KeyName,
12    pub(crate) tags: Vec<Tag>,
13}
14
15#[derive(PartialEq, Eq, Hash, Clone, Debug, PartialOrd, Ord)]
16#[cfg_attr(feature = "ser", derive(Serialize))]
17pub struct Tag {
18    key: String,
19    value: String,
20}
21
22impl Key {
23    pub fn from_name(name: &str) -> Self {
24        Key {
25            name: name.to_owned(),
26            tags: Vec::with_capacity(0),
27        }
28    }
29
30    pub fn from(name: &str, tags: Vec<Tag>) -> Self {
31        Key {
32            name: name.to_owned(),
33            tags,
34        }
35    }
36
37    pub fn key(&self) -> &str {
38        self.name.as_str()
39    }
40
41    pub fn tags(&self) -> &[Tag] {
42        self.tags.as_slice()
43    }
44}
45
46impl PartialEq for Key {
47    fn eq(&self, other: &Self) -> bool {
48        self.name == other.name && self.tags == other.tags
49    }
50}
51
52impl Eq for Key {}
53
54impl PartialOrd for Key {
55    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
56        Some(self.cmp(other))
57    }
58}
59
60impl Ord for Key {
61    fn cmp(&self, other: &Self) -> cmp::Ordering {
62        (&self.name, &self.tags).cmp(&(&other.name, &other.tags))
63    }
64}
65
66impl Hash for Key {
67    fn hash<H: Hasher>(&self, state: &mut H) {
68        key_hasher_impl(state, &self.name, &self.tags);
69    }
70}
71
72impl Tag {
73    pub fn new(key: &str, value: &str) -> Self {
74        Self {
75            key: key.to_owned(),
76            value: value.to_owned(),
77        }
78    }
79    pub fn key(&self) -> &str {
80        self.key.as_str()
81    }
82
83    pub fn value(&self) -> &str {
84        self.value.as_str()
85    }
86}
87
88fn key_hasher_impl<H: Hasher>(state: &mut H, name: &KeyName, tags: &[Tag]) {
89    name.hash(state);
90    tags.hash(state);
91}