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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
mod compare;

pub use compare::compare;
pub use idx_file::{Avltriee, AvltrieeHolder, AvltrieeIter, FileMmap, Found, IdxFile};
pub use various_data_file::DataAddress;

use std::{
    cmp::Ordering,
    ops::{Deref, DerefMut},
    path::Path,
};

use various_data_file::VariousDataFile;

pub trait DataAddressHolder<T> {
    fn data_address(&self) -> &DataAddress;
    fn new(data_address: DataAddress, input: &[u8]) -> T;
}

pub struct IdxBinary<T> {
    index: IdxFile<T>,
    data_file: VariousDataFile,
}

impl<T> AsRef<Avltriee<T>> for IdxBinary<T> {
    fn as_ref(&self) -> &Avltriee<T> {
        self
    }
}
impl<T> AsMut<Avltriee<T>> for IdxBinary<T> {
    fn as_mut(&mut self) -> &mut Avltriee<T> {
        self
    }
}

impl<T> Deref for IdxBinary<T> {
    type Target = IdxFile<T>;
    fn deref(&self) -> &Self::Target {
        &self.index
    }
}
impl<T> DerefMut for IdxBinary<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.index
    }
}

impl<T: DataAddressHolder<T>> AvltrieeHolder<T, &[u8]> for IdxBinary<T> {
    fn cmp(&self, left: &T, right: &&[u8]) -> Ordering {
        self.cmp(left, right)
    }

    fn search_end(&self, input: &&[u8]) -> Found {
        self.index.search_end(|data| self.cmp(data, input))
    }

    fn value(&mut self, input: &[u8]) -> T {
        T::new(self.data_file.insert(input).address().clone(), input)
    }

    fn delete_before_update(&mut self, row: u32, delete_node: &T) {
        if !unsafe { self.index.has_same(row) } {
            self.data_file.delete(&delete_node.data_address());
        }
        self.index.delete(row);
        self.index.new_row(row);
    }
}

impl<T: DataAddressHolder<T>> IdxBinary<T> {
    pub fn new<P: AsRef<Path>>(path: P) -> Self {
        let path = path.as_ref();
        Self {
            index: IdxFile::new({
                let mut path = path.to_path_buf();
                path.push(".i");
                path
            }),
            data_file: VariousDataFile::new({
                let mut path = path.to_path_buf();
                path.push(".d");
                path
            }),
        }
    }
    pub fn bytes(&self, row: u32) -> Option<&'static [u8]> {
        self.index
            .value(row)
            .map(|value| unsafe { self.data_file.bytes(&value.data_address()) })
    }

    pub fn update(&mut self, row: u32, content: &[u8]) -> u32
    where
        T: Clone,
    {
        let row = self.index.new_row(row);
        unsafe {
            Avltriee::update_holder(self, row, content);
        }
        row
    }
    pub fn cmp(&self, data: &T, content: &[u8]) -> Ordering {
        let left = unsafe { self.data_file.bytes(data.data_address()) };
        if left == content {
            Ordering::Equal
        } else {
            compare(left, content)
        }
    }
}