core_crypto/mls/session/
user_id.rs

1use super::{Error, Result};
2
3/// Unique identifier of a User (human person holding some devices).
4/// This contradicts the initial design requirements of this project since it was supposed to be
5/// agnostic from Wire.
6/// End-to-end Identity re-shuffled that... But we still want to keep this isolated from the rest
7/// of the crate that's why this should remain here and be used cautiously, having the context quoted
8/// above in mind.
9/// For example in `wireapp://LcksJb74Tm6N12cDjFy7lQ!8e6424430d3b28be@wire.com` the [UserId] is `LcksJb74Tm6N12cDjFy7lQ`
10#[derive(Debug, Clone, Copy, Eq, PartialEq, derive_more::Deref)]
11pub struct UserId<'a>(&'a [u8]);
12
13impl UserId<'_> {
14    const USER_ID_DELIMITER: u8 = b':';
15}
16
17impl<'a> TryFrom<&'a str> for UserId<'a> {
18    type Error = Error;
19
20    fn try_from(client_id: &'a str) -> Result<Self> {
21        client_id.as_bytes().try_into()
22    }
23}
24
25impl<'a> TryFrom<&'a [u8]> for UserId<'a> {
26    type Error = Error;
27
28    fn try_from(id: &'a [u8]) -> Result<Self> {
29        let found = id
30            .splitn(2, |&b| b == Self::USER_ID_DELIMITER)
31            .next()
32            .ok_or(Error::InvalidUserId)?;
33        if found.len() == id.len() {
34            return Err(Error::InvalidUserId);
35        }
36        Ok(Self(found))
37    }
38}
39
40impl TryFrom<UserId<'_>> for String {
41    type Error = Error;
42
43    fn try_from(uid: UserId<'_>) -> Result<Self> {
44        Ok(std::str::from_utf8(&uid).map_err(|_| Error::InvalidUserId)?.to_string())
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51    use wasm_bindgen_test::*;
52
53    wasm_bindgen_test_configure!(run_in_browser);
54
55    #[async_std::test]
56    #[wasm_bindgen_test]
57    async fn should_parse_client_id() {
58        let user_id = "LcksJb74Tm6N12cDjFy7lQ:8e6424430d3b28be@world.com";
59        let user_id = UserId::try_from(user_id).unwrap();
60        assert_eq!(user_id, UserId("LcksJb74Tm6N12cDjFy7lQ".as_bytes()));
61    }
62
63    #[async_std::test]
64    #[wasm_bindgen_test]
65    async fn should_fail_when_invalid() {
66        let user_id = "LcksJb74Tm6N12cDjFy7lQ/8e6424430d3b28be@world.com";
67        let user_id = UserId::try_from(user_id);
68        assert!(matches!(user_id.unwrap_err(), Error::InvalidUserId));
69    }
70}