core_crypto/mls/session/
id.rs1use std::{
2 borrow::{Borrow, Cow},
3 fmt,
4 ops::Deref,
5};
6
7use super::error::Error;
8
9#[derive(
15 core_crypto_macros::Debug,
16 Clone,
17 Eq,
18 PartialOrd,
19 Ord,
20 Hash,
21 derive_more::From,
22 derive_more::Into,
23 serde::Serialize,
24 serde::Deserialize,
25)]
26#[sensitive]
27pub struct ClientId(pub(crate) Vec<u8>);
28
29impl ClientId {
30 pub(crate) fn into_inner(self) -> Vec<u8> {
31 self.0
32 }
33}
34
35impl From<Box<[u8]>> for ClientId {
36 fn from(value: Box<[u8]>) -> Self {
37 Self(value.into())
38 }
39}
40
41impl<const N: usize> From<[u8; N]> for ClientId {
42 fn from(value: [u8; N]) -> Self {
43 Self(value.into())
44 }
45}
46
47impl<'a> From<&'a [u8]> for ClientId {
48 fn from(value: &'a [u8]) -> Self {
49 Self(value.into())
50 }
51}
52
53impl From<ClientId> for Box<[u8]> {
54 fn from(value: ClientId) -> Self {
55 value.0.into_boxed_slice()
56 }
57}
58
59impl Deref for ClientId {
60 type Target = ClientIdRef;
61
62 fn deref(&self) -> &Self::Target {
63 ClientIdRef::new(&self.0)
64 }
65}
66
67impl AsRef<[u8]> for ClientId {
68 fn as_ref(&self) -> &[u8] {
69 &self.0
70 }
71}
72
73impl AsRef<ClientIdRef> for ClientId {
74 fn as_ref(&self) -> &ClientIdRef {
75 ClientIdRef::new(&self.0)
76 }
77}
78
79impl From<ClientId> for Cow<'_, [u8]> {
80 fn from(value: ClientId) -> Self {
81 Cow::Owned(value.0)
82 }
83}
84
85impl std::fmt::Display for ClientId {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 write!(f, "{}", hex::encode(self.0.as_slice()))
88 }
89}
90
91impl std::str::FromStr for ClientId {
92 type Err = Error;
93
94 fn from_str(s: &str) -> Result<Self, Self::Err> {
95 Ok(Self(
96 hex::decode(s).map_or_else(|_| s.as_bytes().to_vec(), std::convert::identity),
97 ))
98 }
99}
100
101impl<T> PartialEq<T> for ClientId
102where
103 ClientIdRef: PartialEq<T>,
104{
105 fn eq(&self, other: &T) -> bool {
106 (**self).eq(other)
107 }
108}
109
110#[cfg(test)]
111impl From<&str> for ClientId {
112 fn from(value: &str) -> Self {
113 Self(value.as_bytes().into())
114 }
115}
116
117#[repr(transparent)]
123#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, derive_more::Deref)]
124pub struct ClientIdRef([u8]);
125
126impl ClientIdRef {
127 pub fn new<Bytes>(bytes: &Bytes) -> &ClientIdRef
129 where
130 Bytes: AsRef<[u8]> + ?Sized,
131 {
132 unsafe { &*(bytes.as_ref() as *const [u8] as *const ClientIdRef) }
135 }
136
137 pub fn as_slice(&self) -> &[u8] {
139 self.as_ref()
140 }
141}
142
143impl<'a> From<&'a [u8]> for &'a ClientIdRef {
144 fn from(value: &'a [u8]) -> Self {
145 ClientIdRef::new(value)
146 }
147}
148
149impl<'a> From<&'a Vec<u8>> for &'a ClientIdRef {
150 fn from(value: &'a Vec<u8>) -> Self {
151 ClientIdRef::new(value.as_slice())
152 }
153}
154
155impl Borrow<ClientIdRef> for ClientId {
156 fn borrow(&self) -> &ClientIdRef {
157 ClientIdRef::new(&self.0)
158 }
159}
160
161impl Borrow<ClientIdRef> for &'_ ClientId {
162 fn borrow(&self) -> &ClientIdRef {
163 ClientIdRef::new(&*self.0)
164 }
165}
166
167impl ToOwned for ClientIdRef {
168 type Owned = ClientId;
169
170 fn to_owned(&self) -> Self::Owned {
171 ClientId(self.0.to_owned())
172 }
173}
174
175impl AsRef<[u8]> for ClientIdRef {
176 fn as_ref(&self) -> &[u8] {
177 &self.0
178 }
179}
180
181impl<'a> From<&'a ClientIdRef> for Cow<'a, [u8]> {
182 fn from(value: &'a ClientIdRef) -> Self {
183 Cow::Borrowed(value.as_ref())
184 }
185}
186
187impl PartialEq<ClientId> for ClientIdRef {
188 fn eq(&self, other: &ClientId) -> bool {
189 &self.0 == other.as_slice()
190 }
191}
192
193impl PartialEq<[u8]> for ClientIdRef {
194 fn eq(&self, other: &[u8]) -> bool {
195 &self.0 == other
196 }
197}
198
199impl PartialEq<&'_ [u8]> for ClientIdRef {
200 fn eq(&self, other: &&'_ [u8]) -> bool {
201 &self.0 == *other
202 }
203}
204
205impl std::fmt::Display for ClientIdRef {
206 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
207 write!(f, "{}", hex::encode(&self.0))
208 }
209}
210
211macro_rules! impl_eq {
212 ($( $t:ty => |$self:ident, $other:ident| $impl:expr ; )+) => {
213 $(
214 impl PartialEq<$t> for ClientIdRef {
215 fn eq(&self, other: &$t) -> bool {
216 let $self = self;
217 let $other = other;
218 $impl
219 }
220 }
221
222 impl PartialEq<ClientIdRef> for $t {
223 fn eq(&self, other: &ClientIdRef) -> bool {
224 other.eq(self)
225 }
226 }
227
228 impl PartialEq<$t> for &'_ ClientIdRef {
229 fn eq(&self, other: &$t) -> bool {
230 let $self = self;
231 let $other = other;
232 $impl
233 }
234 }
235
236 impl PartialEq<&'_ ClientIdRef> for $t {
237 fn eq(&self, other: &&'_ ClientIdRef) -> bool {
238 other.eq(self)
239 }
240 }
241 )+
242 };
243}
244
245impl_eq!(
246 Vec<u8> => |me, other| me.0.eq(other.as_slice());
247 Cow<'_, ClientIdRef> => |me, other| me.eq(&other.as_slice());
248);
249
250impl fmt::Debug for ClientIdRef {
257 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
258 f.debug_tuple("ClientIdRef")
259 .field(&obfuscate::Obfuscated::from(&self.0))
260 .finish()
261 }
262}
263
264#[cfg(test)]
265impl ClientId {
266 pub(crate) fn to_user_id(&self) -> String {
267 let self_bytes: &[u8] = &self.0;
268 crate::e2e_identity::id::WireQualifiedClientId::try_from(self_bytes)
269 .unwrap()
270 .get_user_id()
271 }
272
273 pub(crate) fn to_string_triple(&self) -> [String; 3] {
274 let qualified_id = crate::e2e_identity::id::QualifiedE2eiClientId::from(self.clone());
275 let id_string: String = qualified_id.try_into().unwrap();
276 [id_string, "".into(), self.to_user_id()]
277 }
278}