1use std::{
2 cmp::{Ord, Ordering, PartialOrd},
3 fmt,
4};
5
6use vector_config::{configurable_component, ConfigurableString};
7
8#[configurable_component(no_deser, no_ser)]
10#[derive(::serde::Deserialize, ::serde::Serialize)]
11#[serde(from = "String", into = "String")]
12#[derive(Clone, Debug, Eq, Hash, PartialEq)]
13pub struct ComponentKey {
14 id: String,
16}
17
18impl ComponentKey {
19 #[must_use]
20 pub fn id(&self) -> &str {
21 &self.id
22 }
23
24 #[must_use]
25 pub fn join<D: fmt::Display>(&self, name: D) -> Self {
26 Self {
27 id: self.port(name),
29 }
30 }
31
32 pub fn port<D: fmt::Display>(&self, name: D) -> String {
33 format!("{}.{name}", self.id)
34 }
35
36 #[must_use]
37 pub fn into_id(self) -> String {
38 self.id
39 }
40}
41
42impl AsRef<ComponentKey> for ComponentKey {
43 fn as_ref(&self) -> &ComponentKey {
44 self
45 }
46}
47
48impl From<String> for ComponentKey {
49 fn from(id: String) -> Self {
50 Self { id }
51 }
52}
53
54impl From<&str> for ComponentKey {
55 fn from(value: &str) -> Self {
56 Self::from(value.to_owned())
57 }
58}
59
60impl From<ComponentKey> for String {
61 fn from(key: ComponentKey) -> Self {
62 key.into_id()
63 }
64}
65
66impl fmt::Display for ComponentKey {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 self.id.fmt(f)
69 }
70}
71
72impl Ord for ComponentKey {
73 fn cmp(&self, other: &Self) -> Ordering {
74 self.id.cmp(&other.id)
75 }
76}
77
78impl PartialOrd for ComponentKey {
79 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
80 Some(self.cmp(other))
81 }
82}
83
84impl ConfigurableString for ComponentKey {}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn deserialize_string() {
92 let result: ComponentKey = serde_json::from_str("\"foo\"").unwrap();
93 assert_eq!(result.id(), "foo");
94 }
95
96 #[test]
97 fn serialize_string() {
98 let item = ComponentKey::from("foo");
99 let result = serde_json::to_string(&item).unwrap();
100 assert_eq!(result, "\"foo\"");
101 }
102
103 #[test]
104 #[allow(clippy::similar_names)]
105 fn ordering() {
106 let global_baz = ComponentKey::from("baz");
107 let yolo_bar = ComponentKey::from("yolo.bar");
108 let foo_bar = ComponentKey::from("foo.bar");
109 let foo_baz = ComponentKey::from("foo.baz");
110 let mut list = vec![&foo_baz, &yolo_bar, &global_baz, &foo_bar];
111 list.sort();
112 assert_eq!(list, vec![&global_baz, &foo_bar, &foo_baz, &yolo_bar]);
113 }
114}