core_crypto/mls/session/
id.rs

1use super::error::Error;
2
3/// A Client identifier
4///
5/// A unique identifier for clients. A client is an identifier for each App a user is using, such as desktop,
6/// mobile, etc. Users can have multiple clients.
7/// More information [here](https://messaginglayersecurity.rocks/mls-architecture/draft-ietf-mls-architecture.html#name-group-members-and-clients)
8#[derive(
9    core_crypto_macros::Debug, Clone, PartialEq, Eq, Hash, derive_more::Deref, serde::Serialize, serde::Deserialize,
10)]
11#[sensitive]
12pub struct ClientId(pub(crate) Vec<u8>);
13
14impl From<&[u8]> for ClientId {
15    fn from(value: &[u8]) -> Self {
16        Self(value.into())
17    }
18}
19
20impl From<Vec<u8>> for ClientId {
21    fn from(value: Vec<u8>) -> Self {
22        Self(value)
23    }
24}
25
26impl From<Box<[u8]>> for ClientId {
27    fn from(value: Box<[u8]>) -> Self {
28        Self(value.into())
29    }
30}
31
32impl From<ClientId> for Box<[u8]> {
33    fn from(value: ClientId) -> Self {
34        value.0.into_boxed_slice()
35    }
36}
37
38#[cfg(test)]
39impl From<&str> for ClientId {
40    fn from(value: &str) -> Self {
41        Self(value.as_bytes().into())
42    }
43}
44
45#[allow(clippy::from_over_into)]
46impl Into<Vec<u8>> for ClientId {
47    fn into(self) -> Vec<u8> {
48        self.0
49    }
50}
51
52impl std::fmt::Display for ClientId {
53    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54        write!(f, "{}", hex::encode(self.0.as_slice()))
55    }
56}
57
58impl std::str::FromStr for ClientId {
59    type Err = Error;
60
61    fn from_str(s: &str) -> Result<Self, Self::Err> {
62        Ok(Self(
63            hex::decode(s).map_or_else(|_| s.as_bytes().to_vec(), std::convert::identity),
64        ))
65    }
66}
67
68#[cfg(test)]
69impl ClientId {
70    pub(crate) fn to_user_id(&self) -> String {
71        let self_bytes: &[u8] = &self.0;
72        crate::e2e_identity::id::WireQualifiedClientId::try_from(self_bytes)
73            .unwrap()
74            .get_user_id()
75    }
76
77    pub(crate) fn to_string_triple(&self) -> [String; 3] {
78        let qualified_id = crate::e2e_identity::id::QualifiedE2eiClientId::from(self.clone());
79        let id_string: String = qualified_id.try_into().unwrap();
80        [id_string, "".into(), self.to_user_id()]
81    }
82}