core_crypto/mls/conversation/
id.rs

1use std::{
2    borrow::{Borrow, Cow},
3    ops::Deref,
4};
5
6/// A unique identifier for a group/conversation. The identifier must be unique within a client.
7#[derive(
8    core_crypto_macros::Debug,
9    derive_more::AsRef,
10    derive_more::From,
11    derive_more::Into,
12    PartialEq,
13    Eq,
14    PartialOrd,
15    Ord,
16    Hash,
17    Clone,
18)]
19#[sensitive]
20#[as_ref([u8])]
21#[from(&[u8], Vec<u8>)]
22pub struct ConversationId(Vec<u8>);
23
24impl Borrow<ConversationIdRef> for ConversationId {
25    fn borrow(&self) -> &ConversationIdRef {
26        ConversationIdRef::new(&self.0)
27    }
28}
29
30impl Deref for ConversationId {
31    type Target = ConversationIdRef;
32
33    fn deref(&self) -> &Self::Target {
34        ConversationIdRef::new(&self.0)
35    }
36}
37
38impl From<ConversationId> for Cow<'_, [u8]> {
39    fn from(value: ConversationId) -> Self {
40        Cow::Owned(value.0)
41    }
42}
43
44impl<'a> From<&'a ConversationId> for Cow<'a, [u8]> {
45    fn from(value: &'a ConversationId) -> Self {
46        Cow::Borrowed(value.as_ref())
47    }
48}
49
50/// Reference to a ConversationId.
51///
52/// This type is `!Sized` and is only ever seen as a reference, like `str` or `[u8]`.
53//
54// pattern from https://stackoverflow.com/a/64990850
55#[repr(transparent)]
56#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
57pub struct ConversationIdRef([u8]);
58
59impl ConversationIdRef {
60    /// Creates a `ConversationId` Ref, needed to implement `Borrow<ConversationIdRef>` for `T`
61    pub fn new<Bytes>(bytes: &Bytes) -> &ConversationIdRef
62    where
63        Bytes: AsRef<[u8]> + ?Sized,
64    {
65        // safety: because of `repr(transparent)` we know that `ConversationIdRef` has a memory layout
66        // identical to `[u8]`, so we can perform this cast
67        unsafe { &*(bytes.as_ref() as *const [u8] as *const ConversationIdRef) }
68    }
69}
70
71impl ConversationIdRef {
72    pub(crate) fn to_bytes(&self) -> Vec<u8> {
73        self.0.to_owned()
74    }
75}
76
77impl ToOwned for ConversationIdRef {
78    type Owned = ConversationId;
79
80    fn to_owned(&self) -> Self::Owned {
81        ConversationId(self.0.to_owned())
82    }
83}
84
85impl AsRef<[u8]> for ConversationIdRef {
86    fn as_ref(&self) -> &[u8] {
87        &self.0
88    }
89}
90
91impl<'a> From<&'a ConversationIdRef> for Cow<'a, [u8]> {
92    fn from(value: &'a ConversationIdRef) -> Self {
93        Cow::Borrowed(value.as_ref())
94    }
95}