plabble_codec/codec/objects/
bucket_id.rs

1use rand::{thread_rng, RngCore};
2
3use crate::abstractions::{Serializable, SerializationInfo, ID_SIZE};
4
5/// Permissions for a bucket
6///
7/// # Fields
8///
9/// * `pub_read` - Whether the bucket can be read by everyone
10/// * `pub_write` - Whether the bucket can be written by everyone
11/// * `pub_append` - Whether the bucket can be appended by everyone
12/// * `priv_write` - Whether the bucket can be written by the owner
13/// * `priv_append` - Whether the bucket can be appended by the owner
14/// * `delete_bucket` - Whether the bucket can be deleted by the owner
15#[derive(Debug, PartialEq, Eq)]
16pub struct BucketPermissions {
17    pub pub_read: bool,      // bit 3 (4)
18    pub pub_write: bool,     // bit 4 (8)
19    pub pub_append: bool,    // bit 5 (16)
20    pub priv_write: bool,    // bit 6 (32)
21    pub priv_append: bool,   // bit 7 (64)
22    pub delete_bucket: bool, // bit 8 (128)
23}
24
25impl Default for BucketPermissions {
26    fn default() -> Self {
27        Self {
28            pub_read: true,
29            pub_write: false,
30            pub_append: false,
31            priv_write: true,
32            priv_append: false,
33            delete_bucket: false,
34        }
35    }
36}
37
38#[derive(Debug, PartialEq, Eq, Hash, Clone)]
39pub struct BucketId {
40    data: [u8; ID_SIZE],
41}
42
43/// Bucket Identifier
44impl BucketId {
45    /// Create a new bucket ID
46    ///
47    /// # Arguments
48    ///
49    /// * `lifetime` - The lifetime of the bucket in days. 0 for infinite
50    pub fn new(lifetime: u8) -> Self {
51        let mut bytes = [0u8; 16];
52        thread_rng().fill_bytes(&mut bytes);
53        let mut res = Self { data: bytes };
54        res.set_permissions(BucketPermissions::default());
55        res.set_lifetime(lifetime);
56        res
57    }
58
59    /// Get the lifetime of the bucket
60    pub fn lifetime(&self) -> u8 {
61        self.data[14]
62    }
63
64    /// Get the permissions of the bucket
65    pub fn permissions(&self) -> BucketPermissions {
66        BucketPermissions {
67            pub_read: self.data[15] & 4 != 0,
68            pub_write: self.data[15] & 8 != 0,
69            pub_append: self.data[15] & 16 != 0,
70            priv_write: self.data[15] & 32 != 0,
71            priv_append: self.data[15] & 64 != 0,
72            delete_bucket: self.data[15] & 128 != 0,
73        }
74    }
75
76    /// Set the lifetime of the bucket
77    pub fn set_lifetime(&mut self, lifetime: u8) {
78        self.data[14] = lifetime;
79    }
80
81    /// Set the permissions of the bucket
82    pub fn set_permissions(&mut self, permissions: BucketPermissions) {
83        let mut set_bits: u8 = 0b00000000;
84        let mut reset_bits: u8 = 0b11111111;
85        if permissions.pub_read {
86            set_bits += 4
87        } else {
88            reset_bits -= 4
89        };
90        if permissions.pub_write {
91            set_bits += 8
92        } else {
93            reset_bits -= 8
94        };
95        if permissions.pub_append {
96            set_bits += 16
97        } else {
98            reset_bits -= 16
99        };
100        if permissions.priv_write {
101            set_bits += 32
102        } else {
103            reset_bits -= 32
104        };
105        if permissions.priv_append {
106            set_bits += 64
107        } else {
108            reset_bits -= 64
109        };
110        if permissions.delete_bucket {
111            set_bits += 128
112        } else {
113            reset_bits -= 128
114        };
115
116        // Apply bit masks
117        let mut permissions = self.data[15];
118        permissions |= set_bits;
119        permissions &= reset_bits;
120        self.data[15] = permissions;
121    }
122}
123
124impl Serializable for BucketId {
125    fn size(&self) -> usize {
126        ID_SIZE
127    }
128
129    fn get_bytes(&self) -> Vec<u8> {
130        self.data.to_vec()
131    }
132
133    fn from_bytes(
134        data: &[u8],
135        _: Option<SerializationInfo>,
136    ) -> Result<Self, crate::abstractions::SerializationError>
137    where
138        Self: Sized,
139    {
140        Ok(BucketId {
141            data: data.try_into().unwrap(),
142        })
143    }
144}
145
146#[cfg(test)]
147mod test {
148    use super::*;
149
150    #[test]
151    fn can_create_bucket_id() {
152        let bucket_id = BucketId::new(0);
153        assert_eq!(0, bucket_id.lifetime());
154        assert_eq!(BucketPermissions::default(), bucket_id.permissions());
155    }
156
157    #[test]
158    fn can_set_bucket_permissions_and_lifetime() {
159        let bytes = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 255];
160        let mut id = BucketId::from_bytes(bytes, None).unwrap();
161        assert_eq!(
162            BucketPermissions {
163                pub_read: true,
164                pub_write: true,
165                pub_append: true,
166                priv_write: true,
167                priv_append: true,
168                delete_bucket: true
169            },
170            id.permissions()
171        );
172
173        assert_eq!(0b11111111, id.data[15]);
174        assert_eq!("10111111", &format!("{:08b}", 255 - 64));
175        assert_eq!("00111111", &format!("{:08b}", 255 - 64 - 128));
176
177        id.set_permissions(BucketPermissions {
178            pub_read: true,
179            pub_write: false,
180            pub_append: true,
181            priv_write: false,
182            priv_append: false,
183            delete_bucket: true,
184        });
185
186        assert_eq!(
187            BucketPermissions {
188                pub_read: true,
189                pub_write: false,
190                pub_append: true,
191                priv_write: false,
192                priv_append: false,
193                delete_bucket: true
194            },
195            id.permissions()
196        );
197
198        assert_eq!(0b10010111, id.data[15]);
199        assert_eq!(25, id.lifetime());
200        id.set_lifetime(253);
201        assert_eq!(253, id.lifetime());
202    }
203}