1
use crate::{
2
    discref::{Page, PageOps},
3
    io::{read_u16, write_u16, InfallibleWrite, InfallibleWriteFormat},
4
    PRes,
5
};
6
use crc::crc16::checksum_usb;
7

8 1
pub fn double_buffer_check(buffer_0: &[u8], buffer_1: &[u8]) -> (u8, bool) {
9 1
    assert!(buffer_0.len() == buffer_1.len());
10 1
    let checksum_pos = buffer_0.len() - 2;
11 1
    let valid_0 = checksum_usb(&buffer_0[0..checksum_pos]) == read_u16(&buffer_0[checksum_pos..checksum_pos + 2]);
12 1
    let valid_1 = checksum_usb(&buffer_1[0..checksum_pos]) == read_u16(&buffer_1[checksum_pos..checksum_pos + 2]);
13 1
    let flush_number_0 = buffer_0[buffer_0.len() - 3];
14 1
    let flush_number_1 = buffer_1[buffer_1.len() - 3];
15 1
    if valid_0 && valid_1 {
16 1
        if (flush_number_0 == 2 && flush_number_1 == 1) || (flush_number_0 == 0 && flush_number_1 == 3) {
17 1
            (flush_number_0, true)
18
        } else {
19 1
            (flush_number_1, false)
20
        }
21 1
    } else if valid_0 {
22 1
        (flush_number_0, true)
23 1
    } else if valid_1 {
24 1
        (flush_number_1, false)
25
    } else {
26 0
        panic!("cannot open this persy archive seems to have a corrupted journal");
27
    }
28 1
}
29

30 1
pub fn prepare_buffer_flush(buffer: &mut [u8], mut last_flush: u8) -> (u8, u32) {
31 1
    last_flush += 1;
32 1
    if last_flush == 4 {
33 1
        last_flush = 0;
34
    }
35 1
    let checksum_pos = buffer.len() - 2;
36 1
    buffer[buffer.len() - 3] = last_flush;
37 1
    let crc = checksum_usb(&buffer[0..checksum_pos]);
38 1
    write_u16(&mut buffer[checksum_pos..checksum_pos + 2], crc);
39 1
    let offset = if last_flush % 2 == 0 { 0 } else { buffer.len() as u32 };
40 1
    (last_flush, offset)
41 1
}
42

43 1
pub fn write_root_page(root: &mut Page, buffer: &mut [u8], version: u8, last_flush: u8) -> PRes<u8> {
44 1
    let (last_flush, offset) = prepare_buffer_flush(buffer, last_flush);
45 1
    root.write_u8(version);
46 1
    root.seek(offset + 1);
47 1
    root.write_all(&buffer);
48 1
    Ok(last_flush)
49 1
}
50

51
#[cfg(test)]
52
mod tests {
53
    use super::{double_buffer_check, prepare_buffer_flush};
54
    use crate::io::write_u64;
55

56
    #[test]
57 1
    fn first_valid() {
58 1
        let mut buffer_0 = [0; 11];
59 1
        let buffer_1 = [0; 11];
60 1
        write_u64(&mut buffer_0, 10);
61 1
        prepare_buffer_flush(&mut buffer_0, 0);
62 1
        let (flush, first) = double_buffer_check(&buffer_0, &buffer_1);
63 1
        assert!(first);
64 1
        assert_eq!(flush, 1);
65

66 1
        let mut buffer_0 = [0; 11];
67 1
        let mut buffer_1 = [0; 11];
68 1
        write_u64(&mut buffer_0, 10);
69 1
        prepare_buffer_flush(&mut buffer_0, 0);
70 1
        write_u64(&mut buffer_1, 10);
71 1
        prepare_buffer_flush(&mut buffer_1, 1);
72 1
        buffer_1[10] = 2;
73 1
        let (flush, first) = double_buffer_check(&buffer_0, &buffer_1);
74 1
        assert!(first);
75 1
        assert_eq!(flush, 1);
76

77 1
        let mut buffer_0 = [0; 11];
78 1
        let mut buffer_1 = [0; 11];
79 1
        write_u64(&mut buffer_0, 10);
80 1
        prepare_buffer_flush(&mut buffer_0, 3);
81 1
        write_u64(&mut buffer_1, 10);
82 1
        prepare_buffer_flush(&mut buffer_1, 2);
83 1
        buffer_1[10] = 2;
84 1
        let (flush, first) = double_buffer_check(&buffer_0, &buffer_1);
85 1
        assert!(first);
86 1
        assert_eq!(flush, 0);
87 1
    }
88

89
    #[test]
90 1
    fn second_valid() {
91 1
        let mut buffer_0 = [0; 11];
92 1
        let mut buffer_1 = [0; 11];
93 1
        write_u64(&mut buffer_0, 10);
94 1
        prepare_buffer_flush(&mut buffer_0, 0);
95 1
        write_u64(&mut buffer_1, 10);
96 1
        prepare_buffer_flush(&mut buffer_1, 1);
97 1
        let (flush, first) = double_buffer_check(&buffer_0, &buffer_1);
98 1
        assert!(!first);
99 1
        assert_eq!(flush, 2);
100

101 1
        let mut buffer_0 = [0; 11];
102 1
        let mut buffer_1 = [0; 11];
103 1
        write_u64(&mut buffer_0, 10);
104 1
        prepare_buffer_flush(&mut buffer_0, 2);
105 1
        buffer_0[10] = 4;
106 1
        write_u64(&mut buffer_1, 10);
107 1
        prepare_buffer_flush(&mut buffer_1, 1);
108 1
        let (flush, first) = double_buffer_check(&buffer_0, &buffer_1);
109 1
        assert!(!first);
110 1
        assert_eq!(flush, 2);
111 1
    }
112
}

Read our documentation on viewing source code .

Loading