1use crate::integrity::{adler32, EwfIntegrity, EwfIntegrityAnomaly, SECTION_DESCRIPTOR_SIZE};
2
3pub struct EwfRepair {
4 segments: Vec<Vec<u8>>,
5}
6
7pub struct RepairReport {
8 pub segments: Vec<Vec<u8>>,
9 pub repairs: Vec<Repaired>,
10 pub cannot_repair: Vec<CannotRepair>,
11}
12
13#[derive(Debug, Clone)]
14pub enum Repaired {
15 SectionDescriptorCrc { offset: u64, section_type: String },
16}
17
18#[derive(Debug, Clone)]
19pub enum CannotRepair {
20 HashMismatch {
21 computed: [u8; 16],
22 stored: [u8; 16],
23 },
24}
25
26impl EwfRepair {
27 pub fn new(data: Vec<u8>) -> Self {
28 Self { segments: vec![data] }
29 }
30
31 pub fn from_segments(segments: Vec<Vec<u8>>) -> Self {
32 Self { segments }
33 }
34
35 pub fn repair(mut self) -> RepairReport {
36 let mut repairs = Vec::new();
37 let mut cannot_repair = Vec::new();
38
39 let seg_refs: Vec<&[u8]> = self.segments.iter().map(|s| s.as_slice()).collect();
40 let anomalies = EwfIntegrity::from_segments(&seg_refs).analyse();
41
42 for anomaly in anomalies {
43 match anomaly {
44 EwfIntegrityAnomaly::SectionDescriptorCrcMismatch {
45 offset,
46 section_type,
47 ..
48 } => {
49 let mut abs = offset as usize;
51 for seg in &mut self.segments {
52 if abs < seg.len() {
53 let off = abs;
54 if off + SECTION_DESCRIPTOR_SIZE <= seg.len() {
55 let correct = adler32(&seg[off..off + 72]);
56 seg[off + 72..off + 76]
57 .copy_from_slice(&correct.to_le_bytes());
58 repairs.push(Repaired::SectionDescriptorCrc {
59 offset,
60 section_type,
61 });
62 }
63 break;
64 }
65 abs -= seg.len();
66 }
67 }
68 EwfIntegrityAnomaly::HashMismatch { computed, stored } => {
69 cannot_repair.push(CannotRepair::HashMismatch { computed, stored });
70 }
71 _ => {}
72 }
73 }
74
75 RepairReport {
76 segments: self.segments,
77 repairs,
78 cannot_repair,
79 }
80 }
81}