1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use idx_binary::IdxFile;
use std::{num::NonZeroU32, path::PathBuf};

use crate::RowFragment;

pub(crate) struct SerialNumber {
    serial: IdxFile<u32>,
    fragment: RowFragment,
}
impl std::ops::Deref for SerialNumber {
    type Target = IdxFile<u32>;
    fn deref(&self) -> &Self::Target {
        &self.serial
    }
}
impl SerialNumber {
    pub fn new(path: PathBuf, reserve_unit: u32) -> Self {
        let file_name = path.file_name().map_or("".into(), |f| f.to_string_lossy());
        SerialNumber {
            serial: IdxFile::new(
                {
                    let mut path = path.clone();
                    path.set_file_name(&(file_name.to_string() + ".i"));
                    path
                },
                reserve_unit,
            ),
            fragment: RowFragment::new({
                let mut path = path.clone();
                path.set_file_name(&(file_name.into_owned() + ".f"));
                path
            }),
        }
    }

    #[inline(always)]
    pub fn delete(&mut self, row: NonZeroU32) {
        self.serial.delete(row);
        self.fragment.insert_blank(row);
    }

    pub async fn next_row(&mut self) -> NonZeroU32 {
        let row = if let Some(row) = self.fragment.pop() {
            self.serial.allocate(row);
            row
        } else {
            self.serial.create_row()
        };
        unsafe {
            self.serial
                .update(row, self.fragment.serial_increment().get())
        }
        .await;
        row
    }
}