core_crypto/mls/client/
user_id.rs1use crate::{CryptoError, CryptoResult};
2
3#[derive(Debug, Clone, Copy, Eq, PartialEq, derive_more::Deref)]
11pub struct UserId<'a>(&'a [u8]);
12
13impl UserId<'_> {
14 const USER_ID_DELIMITER: u8 = 58; }
16
17impl<'a> TryFrom<&'a str> for UserId<'a> {
18 type Error = CryptoError;
19
20 fn try_from(client_id: &'a str) -> CryptoResult<Self> {
21 client_id.as_bytes().try_into()
22 }
23}
24
25impl<'a> TryFrom<&'a [u8]> for UserId<'a> {
26 type Error = CryptoError;
27
28 fn try_from(id: &'a [u8]) -> CryptoResult<Self> {
29 let found = id
30 .splitn(2, |&b| b == Self::USER_ID_DELIMITER)
31 .next()
32 .ok_or(CryptoError::InvalidClientId)?;
33 if found.len() == id.len() {
34 return Err(CryptoError::InvalidClientId);
35 }
36 Ok(Self(found))
37 }
38}
39
40impl TryFrom<UserId<'_>> for String {
41 type Error = CryptoError;
42
43 fn try_from(uid: UserId<'_>) -> CryptoResult<Self> {
44 Ok(std::str::from_utf8(&uid)?.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(), CryptoError::InvalidClientId));
69 }
70}