xmtp_proto/types/ids/
group_id.rs

1use std::{fmt, ops::Deref, str::FromStr};
2
3use bytes::Bytes;
4use hex::FromHexError;
5
6#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
7pub struct GroupId(bytes::Bytes);
8
9impl GroupId {
10    pub fn as_slice(&self) -> &[u8] {
11        self.0.as_ref()
12    }
13}
14
15impl fmt::Debug for GroupId {
16    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17        f.debug_tuple("GroupId")
18            .field(&xmtp_common::fmt::debug_hex(&self.0))
19            .finish()
20    }
21}
22
23impl FromStr for GroupId {
24    type Err = FromHexError;
25
26    fn from_str(s: &str) -> Result<Self, Self::Err> {
27        Ok(GroupId(Bytes::from(hex::decode(s)?)))
28    }
29}
30
31impl AsRef<[u8]> for GroupId {
32    fn as_ref(&self) -> &[u8] {
33        &self.0
34    }
35}
36
37impl fmt::Display for GroupId {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        write!(f, "{:x}", self.0)
40    }
41}
42
43impl Deref for GroupId {
44    type Target = bytes::Bytes;
45    fn deref(&self) -> &Self::Target {
46        &self.0
47    }
48}
49
50impl std::borrow::Borrow<[u8]> for GroupId {
51    fn borrow(&self) -> &[u8] {
52        self.0.as_ref()
53    }
54}
55
56impl From<Vec<u8>> for GroupId {
57    fn from(v: Vec<u8>) -> GroupId {
58        GroupId(v.into())
59    }
60}
61
62impl From<&[u8]> for GroupId {
63    fn from(v: &[u8]) -> GroupId {
64        GroupId(v.to_vec().into())
65    }
66}
67
68xmtp_common::if_test! {
69    impl xmtp_common::Generate for GroupId {
70        fn generate() -> Self {
71            GroupId(xmtp_common::rand_vec::<16>().into())
72        }
73    }
74}
75
76#[cfg(test)]
77mod test {
78    use rstest::rstest;
79
80    use super::*;
81
82    #[xmtp_common::test]
83    fn test_fromstr() {
84        let hex = hex::encode(xmtp_common::rand_vec::<16>());
85        let id: GroupId = hex.parse().unwrap();
86        assert_eq!(hex::encode(&id.0), hex);
87    }
88
89    #[rstest]
90    #[case(b"test_group".to_vec())]
91    #[case(vec![1, 2, 3, 4, 5])]
92    #[case(Vec::new())]
93    #[xmtp_common::test]
94    async fn test_group_id_from_vec(#[case] input: Vec<u8>) {
95        assert_eq!(GroupId::from(input.clone()).as_slice(), input.as_slice());
96        assert_eq!(GroupId::from(input.clone()).as_ref(), input.as_slice());
97    }
98
99    #[rstest]
100    #[case(b"test")]
101    #[case(b"")]
102    #[case(b"longer_test_data")]
103    #[xmtp_common::test]
104    async fn test_group_id_from_slice(#[case] input: &[u8]) {
105        assert_eq!(GroupId::from(input).as_slice(), input);
106    }
107
108    #[xmtp_common::test]
109    fn test_group_id_display_debug() {
110        let data = vec![0x12, 0x34, 0xab, 0xcd];
111        assert!(format!("{}", GroupId::from(data.clone())).contains("1234abcd"));
112        assert!(format!("{:?}", GroupId::from(data)).contains("GroupId"));
113    }
114}