xenclient/
devalloc.rs

1use bit_vec::BitVec;
2
3const DEVICE_COUNT: usize = 4096;
4const BYTE_COUNT: usize = DEVICE_COUNT / 8;
5
6pub struct DeviceIdAllocator {
7    states: BitVec,
8    cursor: u32,
9}
10
11impl Default for DeviceIdAllocator {
12    fn default() -> Self {
13        Self::new()
14    }
15}
16
17impl DeviceIdAllocator {
18    pub fn new() -> Self {
19        Self {
20            states: BitVec::from_elem(DEVICE_COUNT, false),
21            cursor: 0,
22        }
23    }
24
25    pub fn deserialize(bytes: &[u8]) -> Option<Self> {
26        if bytes.len() != BYTE_COUNT + 4 {
27            return None;
28        }
29
30        let cursor = bytes[0] as u32
31            | ((bytes[1] as u32) << 8)
32            | ((bytes[2] as u32) << 16)
33            | ((bytes[3] as u32) << 24);
34        let slice = &bytes[4..BYTE_COUNT + 4];
35        if slice.len() != BYTE_COUNT {
36            return None;
37        }
38        let states = BitVec::from_bytes(slice);
39
40        Some(Self { states, cursor })
41    }
42
43    pub fn allocate(&mut self) -> Option<u32> {
44        let start = self.cursor;
45        loop {
46            let id = self.cursor;
47            let value = self.states.get(self.cursor as usize)?;
48
49            self.cursor = (self.cursor + 1) % DEVICE_COUNT as u32;
50
51            if !value {
52                self.states.set(id as usize, true);
53                return Some(id);
54            }
55
56            if self.cursor == start {
57                return None;
58            }
59        }
60    }
61
62    pub fn release(&mut self, id: u32) {
63        self.states.set(id as usize, false);
64    }
65
66    pub fn count_free(&mut self) -> u32 {
67        self.states.count_zeros() as u32
68    }
69
70    pub fn serialize(&mut self) -> Vec<u8> {
71        let mut bytes = Vec::with_capacity(BYTE_COUNT + 4);
72        bytes.push((self.cursor & 0xff) as u8);
73        bytes.push(((self.cursor >> 8) & 0xff) as u8);
74        bytes.push(((self.cursor >> 16) & 0xff) as u8);
75        bytes.push(((self.cursor >> 24) & 0xff) as u8);
76        bytes.extend_from_slice(&self.states.to_bytes());
77        bytes
78    }
79}