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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//! Representation of a KFF index

/* std use */

/* crate use */

/* project use */
use crate::error;

/// Struct to Read and Write Index section
#[derive(
    getset::Getters, getset::Setters, getset::MutGetters, std::default::Default, std::fmt::Debug,
)]
#[getset(get = "pub", set = "pub", get_mut = "pub")]
pub struct Index {
    /// Vector of block type and relative position
    pair: Vec<(u8, i64)>,
    /// Position of the next index
    next_index: u64,
}

impl Index {
    /// Skip index section
    pub fn skip<R>(inner: &mut R) -> error::Result<Self>
    where
        R: std::io::Read + crate::KffRead,
    {
        let nb_block = inner.read_u64()?;

        let _ = inner.read_n_bytes_dyn((8 * nb_block + nb_block + 8) as usize)?;

        Ok(Self {
            pair: Vec::default(),
            next_index: 0,
        })
    }
}

impl Index {
    /// Create an index
    pub fn new(pair: Vec<(u8, i64)>, next_index: u64) -> Self {
        Self { pair, next_index }
    }

    /// Read an Index section, section flag must be already read
    pub fn read<R>(inner: &mut R) -> error::Result<Self>
    where
        R: std::io::Read + crate::KffRead,
    {
        let mut pair = Vec::new();

        let nb_block = inner.read_u64()?;

        for _ in 0..nb_block {
            let section_type = inner.read_u8()?;
            let delta = inner.read_i64()?;

            pair.push((section_type, delta));
        }

        let next_index = inner.read_u64()?;
        Ok(Self { pair, next_index })
    }

    /// Write an Index section, section flag isn't write
    pub fn write<W>(&self, outer: &mut W) -> error::Result<()>
    where
        W: std::io::Write + crate::KffWrite,
    {
        outer.write_u64(&(self.pair.len() as u64))?;

        for (section_type, delta) in &self.pair {
            outer.write_u8(section_type)?;
            outer.write_i64(delta)?;
        }

        outer.write_u64(&self.next_index)?;

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn read() -> error::Result<()> {
        let mut data: &[u8] = &[
            0, 0, 0, 0, 0, 0, 0, 3, // number of pair
            b'r', 0, 0, 0, 0, 0, 0, 55, 255, // Raw section
            b't', 255, 0, 0, 0, 0, 0, 0, 255, // a T section with value in past
            b'm', 0, 0, 0, 0, 0, 255, 0, 255, // Minimizer section
            0, 0, 0, 0, 0, 45, 33, 0, // Next index section
        ];

        let index = Index::read(&mut data)?;

        assert_eq!(
            index.pair(),
            &[(b'r', 14335), (b't', -72057594037927681), (b'm', 16711935)]
        );
        assert_eq!(index.next_index(), &2957568);

        Ok(())
    }

    #[test]
    fn write() -> error::Result<()> {
        let mut data: &[u8] = &[
            0, 0, 0, 0, 0, 0, 0, 3, // number of pair
            b'r', 0, 0, 0, 0, 0, 0, 55, 255, // Raw section
            b't', 255, 0, 0, 0, 0, 0, 0, 255, // a T section with value in past
            b'm', 0, 0, 0, 0, 0, 255, 0, 255, // Minimizer section
            0, 0, 0, 0, 0, 45, 33, 0, // Next index section
        ];

        let index = Index::read(&mut data)?;

        let mut output = Vec::new();
        index.write(&mut output)?;

        assert_eq!(
            output,
            &[
                0, 0, 0, 0, 0, 0, 0, 3, // number of pair
                b'r', 0, 0, 0, 0, 0, 0, 55, 255, // Raw section
                b't', 255, 0, 0, 0, 0, 0, 0, 255, // a T section with value in past
                b'm', 0, 0, 0, 0, 0, 255, 0, 255, // Minimizer section
                0, 0, 0, 0, 0, 45, 33, 0, // Next index section
            ]
        );

        Ok(())
    }

    #[test]
    fn skip() -> error::Result<()> {
        let mut data: &[u8] = &[
            0, 0, 0, 0, 0, 0, 0, 3, // number of pair
            b'r', 0, 0, 0, 0, 0, 0, 55, 255, // Raw section
            b't', 255, 0, 0, 0, 0, 0, 0, 255, // a T section with value in past
            b'm', 0, 0, 0, 0, 0, 255, 0, 255, // Minimizer section
            0, 0, 0, 0, 0, 45, 33, 0, // Next index section
        ];

        let index = Index::skip(&mut data)?;

        assert_eq!(index.pair(), &[]);
        assert_eq!(index.next_index(), &0);

        Ok(())
    }
}