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