hydro_lang/location/
member_id.rs

1use std::fmt::{Debug, Display};
2use std::hash::Hash;
3use std::marker::PhantomData;
4
5use serde::{Deserialize, Serialize};
6
7#[derive(Clone, Deserialize, Serialize, Debug)]
8pub enum TaglessMemberId {
9    Legacy { raw_id: u32 },
10    Docker { container_name: String },
11}
12
13impl TaglessMemberId {
14    pub fn from_raw_id(raw_id: u32) -> Self {
15        Self::Legacy { raw_id }
16    }
17
18    pub fn from_container_name(container_name: impl ToString) -> Self {
19        Self::Docker {
20            container_name: container_name.to_string(),
21        }
22    }
23
24    pub fn get_raw_id(&self) -> u32 {
25        match self {
26            TaglessMemberId::Legacy { raw_id } => *raw_id,
27            _ => panic!(),
28        }
29    }
30
31    pub fn get_container_name(&self) -> String {
32        match &self {
33            TaglessMemberId::Docker { container_name } => container_name.clone(),
34            _ => panic!(),
35        }
36    }
37}
38
39impl Hash for TaglessMemberId {
40    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
41        match self {
42            TaglessMemberId::Legacy { raw_id } => raw_id.hash(state),
43            TaglessMemberId::Docker { container_name } => container_name.hash(state),
44        }
45    }
46}
47
48impl PartialEq for TaglessMemberId {
49    fn eq(&self, other: &Self) -> bool {
50        match (self, other) {
51            (
52                TaglessMemberId::Legacy { raw_id },
53                TaglessMemberId::Legacy {
54                    raw_id: other_raw_id,
55                },
56            ) => raw_id == other_raw_id,
57            (
58                TaglessMemberId::Docker { container_name },
59                TaglessMemberId::Docker {
60                    container_name: other_container_name,
61                },
62            ) => container_name == other_container_name,
63            _ => unreachable!(),
64        }
65    }
66}
67
68impl Eq for TaglessMemberId {}
69
70impl PartialOrd for TaglessMemberId {
71    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
72        Some(self.cmp(other))
73    }
74}
75
76impl Ord for TaglessMemberId {
77    // Comparing tags of different deployment origins means something has gone very wrong and the best thing to do is just crash immediately.
78    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
79        match (self, other) {
80            (
81                TaglessMemberId::Legacy { raw_id },
82                TaglessMemberId::Legacy {
83                    raw_id: other_raw_id,
84                },
85            ) => raw_id.cmp(other_raw_id),
86            (
87                TaglessMemberId::Docker { container_name },
88                TaglessMemberId::Docker {
89                    container_name: other_container_name,
90                },
91            ) => container_name.cmp(other_container_name),
92            _ => unreachable!(),
93        }
94    }
95}
96
97#[repr(transparent)]
98pub struct MemberId<Tag> {
99    inner: TaglessMemberId,
100    _phantom: PhantomData<Tag>,
101}
102
103impl<Tag> MemberId<Tag> {
104    pub fn into_tagless(self) -> TaglessMemberId {
105        self.inner
106    }
107
108    pub fn from_tagless(inner: TaglessMemberId) -> Self {
109        Self {
110            inner,
111            _phantom: Default::default(),
112        }
113    }
114
115    pub fn from_raw_id(raw_id: u32) -> Self {
116        Self {
117            inner: TaglessMemberId::from_raw_id(raw_id),
118            _phantom: Default::default(),
119        }
120    }
121
122    pub fn get_raw_id(&self) -> u32 {
123        self.inner.get_raw_id()
124    }
125}
126
127impl<Tag> Debug for MemberId<Tag> {
128    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129        Display::fmt(self, f)
130    }
131}
132
133impl<Tag> Display for MemberId<Tag> {
134    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135        match &self.inner {
136            TaglessMemberId::Legacy { raw_id, .. } => {
137                write!(
138                    f,
139                    "MemberId::<{}>({})",
140                    std::any::type_name::<Tag>(),
141                    raw_id
142                )
143            }
144            TaglessMemberId::Docker { container_name, .. } => {
145                write!(
146                    f,
147                    "MemberId::<{}>(\"{}\")",
148                    std::any::type_name::<Tag>(),
149                    container_name
150                )
151            }
152        }
153    }
154}
155
156impl<Tag> Clone for MemberId<Tag> {
157    fn clone(&self) -> Self {
158        Self {
159            inner: self.inner.clone(),
160            _phantom: Default::default(),
161        }
162    }
163}
164
165impl<Tag> Serialize for MemberId<Tag> {
166    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
167    where
168        S: serde::Serializer,
169    {
170        self.inner.serialize(serializer)
171    }
172}
173
174impl<'a, Tag> Deserialize<'a> for MemberId<Tag> {
175    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
176    where
177        D: serde::Deserializer<'a>,
178    {
179        Ok(Self::from_tagless(TaglessMemberId::deserialize(
180            deserializer,
181        )?))
182    }
183}
184
185impl<Tag> PartialOrd for MemberId<Tag> {
186    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
187        Some(self.cmp(other))
188    }
189}
190
191impl<Tag> Ord for MemberId<Tag> {
192    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
193        self.inner.cmp(&other.inner)
194    }
195}
196
197impl<Tag> PartialEq for MemberId<Tag> {
198    fn eq(&self, other: &Self) -> bool {
199        self.inner == other.inner
200    }
201}
202
203impl<Tag> Eq for MemberId<Tag> {}
204
205impl<Tag> Hash for MemberId<Tag> {
206    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
207        self.inner.hash(state);
208        std::any::type_name::<Tag>().hash(state); // This seems like the a good thing to do. This will ensure that two member ids that come from different clusters but the same underlying host receive different hashes.
209    }
210}