1
|
|
use crate::io::{read_u16, write_u16};
|
2
|
|
use crc::crc16::checksum_usb;
|
3
|
|
|
4
|
1
|
pub fn double_buffer_check(buffer_0: &[u8], buffer_1: &[u8]) -> (u8, bool) {
|
5
|
1
|
assert!(buffer_0.len() == buffer_1.len());
|
6
|
1
|
let checksum_pos = buffer_0.len() - 2;
|
7
|
1
|
let valid_0 = checksum_usb(&buffer_0[0..checksum_pos]) == read_u16(&buffer_0[checksum_pos..checksum_pos + 2]);
|
8
|
1
|
let valid_1 = checksum_usb(&buffer_1[0..checksum_pos]) == read_u16(&buffer_1[checksum_pos..checksum_pos + 2]);
|
9
|
1
|
let flush_number_0 = buffer_0[buffer_0.len() - 3];
|
10
|
1
|
let flush_number_1 = buffer_1[buffer_1.len() - 3];
|
11
|
1
|
if valid_0 && valid_1 {
|
12
|
1
|
if (flush_number_0 == 2 && flush_number_1 == 1) || (flush_number_0 == 0 && flush_number_1 == 3) {
|
13
|
1
|
(flush_number_0, true)
|
14
|
|
} else {
|
15
|
1
|
(flush_number_1, false)
|
16
|
|
}
|
17
|
1
|
} else if valid_0 {
|
18
|
1
|
(flush_number_0, true)
|
19
|
1
|
} else if valid_1 {
|
20
|
1
|
(flush_number_1, false)
|
21
|
|
} else {
|
22
|
0
|
panic!("cannot open this persy archive seems to have a corrupted journal");
|
23
|
|
}
|
24
|
1
|
}
|
25
|
|
|
26
|
1
|
pub fn prepare_buffer_flush(buffer: &mut [u8], mut last_flush: u8) -> (u8, u32) {
|
27
|
1
|
last_flush += 1;
|
28
|
1
|
if last_flush == 4 {
|
29
|
1
|
last_flush = 0;
|
30
|
|
}
|
31
|
1
|
let checksum_pos = buffer.len() - 2;
|
32
|
1
|
buffer[buffer.len() - 3] = last_flush;
|
33
|
1
|
let crc = checksum_usb(&buffer[0..checksum_pos]);
|
34
|
1
|
write_u16(&mut buffer[checksum_pos..checksum_pos + 2], crc);
|
35
|
1
|
let offset = if last_flush % 2 == 0 { 0 } else { buffer.len() as u32 };
|
36
|
1
|
(last_flush, offset)
|
37
|
1
|
}
|
38
|
|
|
39
|
|
#[cfg(test)]
|
40
|
|
mod tests {
|
41
|
|
use super::{double_buffer_check, prepare_buffer_flush};
|
42
|
|
use crate::io::write_u64;
|
43
|
|
|
44
|
|
#[test]
|
45
|
1
|
fn first_valid() {
|
46
|
1
|
let mut buffer_0 = [0; 11];
|
47
|
1
|
let buffer_1 = [0; 11];
|
48
|
1
|
write_u64(&mut buffer_0, 10);
|
49
|
1
|
prepare_buffer_flush(&mut buffer_0, 0);
|
50
|
1
|
let (flush, first) = double_buffer_check(&buffer_0, &buffer_1);
|
51
|
1
|
assert!(first);
|
52
|
1
|
assert_eq!(flush, 1);
|
53
|
|
|
54
|
1
|
let mut buffer_0 = [0; 11];
|
55
|
1
|
let mut buffer_1 = [0; 11];
|
56
|
1
|
write_u64(&mut buffer_0, 10);
|
57
|
1
|
prepare_buffer_flush(&mut buffer_0, 0);
|
58
|
1
|
write_u64(&mut buffer_1, 10);
|
59
|
1
|
prepare_buffer_flush(&mut buffer_1, 1);
|
60
|
1
|
buffer_1[10] = 2;
|
61
|
1
|
let (flush, first) = double_buffer_check(&buffer_0, &buffer_1);
|
62
|
1
|
assert!(first);
|
63
|
1
|
assert_eq!(flush, 1);
|
64
|
|
|
65
|
1
|
let mut buffer_0 = [0; 11];
|
66
|
1
|
let mut buffer_1 = [0; 11];
|
67
|
1
|
write_u64(&mut buffer_0, 10);
|
68
|
1
|
prepare_buffer_flush(&mut buffer_0, 3);
|
69
|
1
|
write_u64(&mut buffer_1, 10);
|
70
|
1
|
prepare_buffer_flush(&mut buffer_1, 2);
|
71
|
1
|
buffer_1[10] = 2;
|
72
|
1
|
let (flush, first) = double_buffer_check(&buffer_0, &buffer_1);
|
73
|
1
|
assert!(first);
|
74
|
1
|
assert_eq!(flush, 0);
|
75
|
1
|
}
|
76
|
|
|
77
|
|
#[test]
|
78
|
1
|
fn second_valid() {
|
79
|
1
|
let mut buffer_0 = [0; 11];
|
80
|
1
|
let mut buffer_1 = [0; 11];
|
81
|
1
|
write_u64(&mut buffer_0, 10);
|
82
|
1
|
prepare_buffer_flush(&mut buffer_0, 0);
|
83
|
1
|
write_u64(&mut buffer_1, 10);
|
84
|
1
|
prepare_buffer_flush(&mut buffer_1, 1);
|
85
|
1
|
let (flush, first) = double_buffer_check(&buffer_0, &buffer_1);
|
86
|
1
|
assert!(!first);
|
87
|
1
|
assert_eq!(flush, 2);
|
88
|
|
|
89
|
1
|
let mut buffer_0 = [0; 11];
|
90
|
1
|
let mut buffer_1 = [0; 11];
|
91
|
1
|
write_u64(&mut buffer_0, 10);
|
92
|
1
|
prepare_buffer_flush(&mut buffer_0, 2);
|
93
|
1
|
buffer_0[10] = 4;
|
94
|
1
|
write_u64(&mut buffer_1, 10);
|
95
|
1
|
prepare_buffer_flush(&mut buffer_1, 1);
|
96
|
1
|
let (flush, first) = double_buffer_check(&buffer_0, &buffer_1);
|
97
|
1
|
assert!(!first);
|
98
|
1
|
assert_eq!(flush, 2);
|
99
|
1
|
}
|
100
|
|
}
|