From c28fee9f82df161d709232ec6528928852fff2a7 Mon Sep 17 00:00:00 2001 From: Cutieguwu Date: Wed, 31 Dec 2025 11:07:24 -0500 Subject: [PATCH] CLeanup, and get domain overlap and mapping adjustment working. --- src/io.rs | 20 +- src/main.rs | 44 +-- src/mapping/cluster.rs | 2 +- src/mapping/domain.rs | 30 +- src/mapping/map.rs | 626 ++++++++++++++++++++++++++++++++++++----- src/mapping/mod.rs | 2 +- src/mapping/prelude.rs | 2 +- src/mapping/stage.rs | 4 +- src/recovery.rs | 72 +++-- 9 files changed, 662 insertions(+), 140 deletions(-) diff --git a/src/io.rs b/src/io.rs index a69e402..8b51ece 100644 --- a/src/io.rs +++ b/src/io.rs @@ -1,6 +1,8 @@ use std::io::{self, Seek, SeekFrom}; use std::path::{Path, PathBuf}; +use anyhow::Context; + /// Get length of data stream. /// Physical length of data stream in bytes /// (multiple of sector_size, rather than actual). @@ -17,20 +19,26 @@ pub fn get_stream_length(stream: &mut S) -> io::Result { /// Generates a file path if one not provided. /// source_name for fallback name. -pub fn get_path

(file_path: &Option

, source_name: &P, extension: &str) -> Option +pub fn get_path

( + file_path: &Option

, + source_name: &P, + extension: &str, +) -> anyhow::Result where P: AsRef, { if let Some(f) = file_path { - return f.as_ref().to_path_buf().into(); + return Ok(f.as_ref().to_path_buf()); } - PathBuf::from(format!( + Ok(PathBuf::from(format!( "{:?}.{}", - source_name.as_ref().to_str()?, + source_name + .as_ref() + .to_str() + .context("source_name path was not UTF-8 valid.")?, extension )) .as_path() - .to_owned() - .into() + .to_owned()) } diff --git a/src/main.rs b/src/main.rs index 299cb69..6f3368d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,10 +18,6 @@ const FB_PAD_VALUE: u8 = 0; fn main() -> anyhow::Result<()> { let config = Args::parse(); - // Live with it, prefer to use expect() here. - // I'm lazy and don't want to mess around with comparing error types. - // Thus, any error in I/O here should be treated as fatal. - let mut input: File = { let input_path = &config.input.as_path(); @@ -44,37 +40,23 @@ fn main() -> anyhow::Result<()> { .with_context(|| format!("Failed to open/create output file at: {}", path.display()))? }; - /* let map: MapFile = { - let path = get_path( - &config.output, - &config - .input - .to_str() - .expect("Input path is not UTF-8 valid"), - "map", - ); + let path = crate::io::get_path(&config.output, &config.input, "map") + .context("Failed to generate map path.")?; - let file = OpenOptions::new() - .read(true) - .create(true) - .open(path) - .expect("Failed to open/create mapping file"); - - if let Ok(map) = MapFile::try_from(file) { - map - } else { - MapFile::new(config.sector_size) - } + MapFile::try_from( + OpenOptions::new() + .read(true) + .create(true) + .open(&path) + .with_context(|| { + format!("Failed to open/create mapping file at: {}", path.display()) + })?, + ) + .unwrap_or(MapFile::new(config.sector_size)) }; - */ - let mut recover_tool = { - let buf_capacity = crate::io::get_stream_length(&mut input) - .context("Failed to get buffer capacity from input")?; - - Recover::new(&config, input, output, MapFile::default(), buf_capacity) - }; + let mut recover_tool = Recover::new(&config, &mut input, output, map)?; recover_tool.run(); diff --git a/src/mapping/cluster.rs b/src/mapping/cluster.rs index 46a9562..1e66537 100644 --- a/src/mapping/cluster.rs +++ b/src/mapping/cluster.rs @@ -3,7 +3,7 @@ use super::{Domain, Stage}; use serde::{Deserialize, Serialize}; /// A map for data stored in memory for processing and saving to disk. -#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct Cluster { pub domain: Domain, pub stage: Stage, diff --git a/src/mapping/domain.rs b/src/mapping/domain.rs index 778520e..b6b1b71 100644 --- a/src/mapping/domain.rs +++ b/src/mapping/domain.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; /// Domain, in sectors. /// Requires sector_size to be provided elsewhere for conversion to bytes. -#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct Domain { pub start: usize, pub end: usize, @@ -19,6 +19,34 @@ impl Domain { pub fn len(self) -> usize { self.end - self.start } + + /// Returns the type of overlap between this domain and another. + pub fn overlap(&self, other: Domain) -> DomainOverlap { + if self.end <= other.start || other.end <= self.start { + // Cases 7, 8, 12, and 13 of map::tests::test_update + DomainOverlap::None + } else if other.start >= self.start && other.end <= self.end { + // Cases 3, 5, 9, and 11 of map::tests::test_update + DomainOverlap::SelfEngulfsOther + } else if other.start <= self.start && other.end >= self.end { + // Cases 4, 6, and 10 of map::tests::test_update + DomainOverlap::OtherEngulfsSelf + } else if self.start < other.start { + // Case 1 of map::tests::test_update + DomainOverlap::OtherOverlapsEnd + } else { + // Case 2 of map::tests::test_update + DomainOverlap::OtherOverlapsStart + } + } +} + +pub enum DomainOverlap { + None, + SelfEngulfsOther, + OtherEngulfsSelf, + OtherOverlapsStart, + OtherOverlapsEnd, } #[cfg(test)] diff --git a/src/mapping/map.rs b/src/mapping/map.rs index 3b821f6..2457d5c 100644 --- a/src/mapping/map.rs +++ b/src/mapping/map.rs @@ -1,7 +1,7 @@ use std::fs::File; use std::io::Write; -use super::{Cluster, Domain, Stage}; +use super::{Cluster, Domain, DomainOverlap, Stage}; use anyhow; use ron::de::from_reader; @@ -47,66 +47,32 @@ impl MapFile { } /// Recalculate cluster mappings. - pub fn update(&mut self, new_cluster: Cluster) -> &mut Self { - let mut new_map: Vec = vec![Cluster::from(new_cluster.to_owned())]; + pub fn update(&mut self, new: Cluster) -> &mut Self { + let mut map: Vec = vec![Cluster::from(new.clone())]; - for map_cluster in self.map.iter() { - let mut map_cluster = *map_cluster; + for old in self.map.iter() { + let mut old = *old; - // If new_cluster doesn't start ahead and ends short, map_cluster is forgotten. - if new_cluster.domain.start < map_cluster.domain.start - && new_cluster.domain.end < map_cluster.domain.end - { - /* - new_cluster overlaps the start of map_cluster, - but ends short of map_cluster end. - - ACTION: Crop map_cluster to start at end of new_cluster. - */ - - map_cluster.domain.start = new_cluster.domain.end; - new_map.push(map_cluster); - } else if new_cluster.domain.end < map_cluster.domain.end { - /* - new_cluster starts within map_cluster domain. - - ACTION: Crop - */ - - let domain_end = map_cluster.domain.end; - - // Crop current object. - map_cluster.domain.end = new_cluster.domain.start; - new_map.push(map_cluster); - - if new_cluster.domain.end < map_cluster.domain.end { - /* - new_cluster is within map_cluster. - - ACTION: Crop & Fracture map_cluster - NOTE: Crop completed above. - */ - - new_map.push(Cluster { - domain: Domain { - start: new_cluster.domain.end, - end: domain_end, - }, - stage: map_cluster.stage.to_owned(), - }); + match new.domain.overlap(old.domain) { + DomainOverlap::None => map.push(old), + DomainOverlap::SelfEngulfsOther => (), + DomainOverlap::OtherEngulfsSelf => { + other_engulfs_self_update(new, &mut old, &mut map) } - } else { - /* - No overlap. - - ACTION: Transfer - */ - - new_map.push(map_cluster); - } + DomainOverlap::OtherOverlapsEnd => { + // Case 1 + old.domain.start = new.domain.end; + map.push(old); + } + DomainOverlap::OtherOverlapsStart => { + // Case 2 + old.domain.end = new.domain.start; + map.push(old); + } + }; } - self.map = new_map; + self.map = map; self } @@ -126,7 +92,7 @@ impl MapFile { } } Stage::Damaged => (), - Stage::Intact => unreachable!(), + Stage::Intact => (), } } @@ -197,6 +163,29 @@ impl MapFile { self.map = new_map; self } + + /// Extend the domain of the MapFile. + /// Returns None if the domain cannot be changed or is unchanged. + /// Returns the delta of the previous domain end and the new end. + pub fn extend(&mut self, end: usize) -> Option { + if end <= self.domain.end { + return None; + } + + let old_end = self.domain.end; + let delta = end - old_end; + self.domain.end = end; + + // Add new data as untested. + self.update(Cluster { + domain: Domain { + start: old_end, + end: self.domain.end, + }, + ..Default::default() + }); + Some(delta) + } } pub fn write_map_to_file(file: &mut File, map: &MapFile) -> anyhow::Result { @@ -213,17 +202,522 @@ pub fn write_map_to_file(file: &mut File, map: &MapFile) -> anyhow::Result) { + if new.domain.start == old.domain.start { + // Case 6 of map::tests::test_update + old.domain.start = new.domain.end; + } else { + // Case 4 and part of 10 + + let old_end = old.domain.end; + old.domain.end = new.domain.start; + + if new.domain.end != old_end { + // Case 10 of map::tests::test_update + map.push(Cluster { + domain: Domain { + start: new.domain.end, + end: old_end, + }, + stage: old.stage, + }) + } + } + + map.push(old.to_owned()) +} + #[cfg(test)] mod tests { + use std::collections::HashSet; + use super::*; - // Test for MapFile::update() - - // Test for MapFile::get_stage() + /// Test for MapFile::update() #[test] - fn test_get_stage() { - use std::vec; + fn update_1_new_overlaps_start() { + // Case 1: + // |----new----| + // |----old----| + // + // | --> |-old-| + // Solution: old.start = new.end + let mut map = MapFile { + map: vec![Cluster { + domain: Domain { start: 1, end: 3 }, + ..Default::default() + }], + ..Default::default() + }; + + map.update(Cluster { + domain: Domain { start: 0, end: 2 }, + ..Default::default() + }); + map.map.sort(); + + assert_eq!( + map.map, + vec![ + Cluster { + domain: Domain { start: 0, end: 2 }, + ..Default::default() + }, + Cluster { + domain: Domain { start: 2, end: 3 }, + ..Default::default() + } + ] + ); + } + + /// Test for MapFile::update() + #[test] + fn update_2_new_overlaps_end() { + // Case 2: + // |----new----| + // |----old----| + // + // |-old-| <-- | + // Solution: old.end = new.start + + let mut map = MapFile { + map: vec![Cluster { + domain: Domain { start: 0, end: 2 }, + ..Default::default() + }], + ..Default::default() + }; + + map.update(Cluster { + domain: Domain { start: 1, end: 3 }, + ..Default::default() + }); + map.map.sort(); + + assert_eq!( + map.map, + vec![ + Cluster { + domain: Domain { start: 0, end: 1 }, + ..Default::default() + }, + Cluster { + domain: Domain { start: 1, end: 3 }, + ..Default::default() + } + ] + ); + } + + /// Test for MapFile::update() + #[test] + fn update_3_new_engulfs_common_end() { + // Case 3: + // |----new----| + // |--old--| + // + // Solution: Remove old. + + let mut map = MapFile { + map: vec![Cluster { + domain: Domain { start: 1, end: 3 }, + ..Default::default() + }], + ..Default::default() + }; + + map.update(Cluster { + domain: Domain { start: 0, end: 3 }, + ..Default::default() + }); + map.map.sort(); + + assert_eq!( + map.map, + vec![Cluster { + domain: Domain { start: 0, end: 3 }, + ..Default::default() + }] + ); + } + + /// Test for MapFile::update() + #[test] + fn update_4_old_engulfs_common_end() { + // Case 4: + // |--new--| + // |-----old-----| + // + // |-old-| <---- | + // Solution: old.end = new.start + + let mut map = MapFile { + map: vec![Cluster { + domain: Domain { start: 0, end: 3 }, + ..Default::default() + }], + ..Default::default() + }; + + map.update(Cluster { + domain: Domain { start: 1, end: 3 }, + ..Default::default() + }); + map.map.sort(); + + assert_eq!( + map.map, + vec![ + Cluster { + domain: Domain { start: 0, end: 1 }, + ..Default::default() + }, + Cluster { + domain: Domain { start: 1, end: 3 }, + ..Default::default() + } + ] + ); + } + + /// Test for MapFile::update() + #[test] + fn update_5_new_engulfs_common_start() { + // Case 5: + // |-----new----| + // |--old--| + // + // Solution: Remove old. + + let mut map = MapFile { + map: vec![Cluster { + domain: Domain { start: 0, end: 2 }, + ..Default::default() + }], + ..Default::default() + }; + + map.update(Cluster { + domain: Domain { start: 0, end: 3 }, + ..Default::default() + }); + map.map.sort(); + + assert_eq!( + map.map, + vec![Cluster { + domain: Domain { start: 0, end: 3 }, + ..Default::default() + }] + ); + } + + /// Test for MapFile::update() + #[test] + fn update_6_old_engulfs_common_start() { + // Case 6: + // |--new--| + // |-----old-----| + // + // | ----> |-old-| + // Solution: old.start = new.end + + let mut map = MapFile { + map: vec![Cluster { + domain: Domain { start: 0, end: 3 }, + ..Default::default() + }], + ..Default::default() + }; + + map.update(Cluster { + domain: Domain { start: 0, end: 2 }, + ..Default::default() + }); + map.map.sort(); + + assert_eq!( + map.map, + vec![ + Cluster { + domain: Domain { start: 0, end: 2 }, + ..Default::default() + }, + Cluster { + domain: Domain { start: 2, end: 3 }, + ..Default::default() + } + ] + ); + } + + /// Test for MapFile::update() + #[test] + fn update_7_new_precedes() { + // Case 7: + // |--new--| + // |--old--| + // + // Solution: Leave unchanged. + + let mut map = MapFile { + map: vec![Cluster { + domain: Domain { start: 2, end: 3 }, + ..Default::default() + }], + ..Default::default() + }; + + map.update(Cluster { + domain: Domain { start: 0, end: 2 }, + ..Default::default() + }); + map.map.sort(); + + assert_eq!( + map.map, + vec![ + Cluster { + domain: Domain { start: 0, end: 2 }, + ..Default::default() + }, + Cluster { + domain: Domain { start: 2, end: 3 }, + ..Default::default() + } + ] + ); + } + + /// Test for MapFile::update() + #[test] + fn update_8_new_trails() { + // Case 8: + // |--new--| + // |--old--| + // Solution: Leave unchanged. + + let mut map = MapFile { + map: vec![Cluster { + domain: Domain { start: 0, end: 2 }, + ..Default::default() + }], + ..Default::default() + }; + + map.update(Cluster { + domain: Domain { start: 2, end: 3 }, + ..Default::default() + }); + map.map.sort(); + + assert_eq!( + map.map, + vec![ + Cluster { + domain: Domain { start: 0, end: 2 }, + ..Default::default() + }, + Cluster { + domain: Domain { start: 2, end: 3 }, + ..Default::default() + } + ] + ); + } + + /// Test for MapFile::update() + #[test] + fn update_9_new_engulfs() { + // Case 9: + // |-----new-----| + // |--old--| + // + // Solution: Remove old. + + let mut map = MapFile { + map: vec![Cluster { + domain: Domain { start: 1, end: 2 }, + ..Default::default() + }], + ..Default::default() + }; + + map.update(Cluster { + domain: Domain { start: 0, end: 3 }, + ..Default::default() + }); + map.map.sort(); + + assert_eq!( + map.map, + vec![Cluster { + domain: Domain { start: 0, end: 3 }, + ..Default::default() + }] + ); + } + + /// Test for MapFile::update() + #[test] + fn update_10_old_engulfs() { + // Case 10: + // |--new--| + // |--------------old--------------| + // + // |----old----| <---- | + // + |--fracture-| + // Solution: old.end = new.start + // && fracture: + // with fracture.start = new.end + // && fracture.end = old.original_end + + let mut map = MapFile { + map: vec![Cluster { + domain: Domain { start: 0, end: 3 }, + ..Default::default() + }], + ..Default::default() + }; + + map.update(Cluster { + domain: Domain { start: 1, end: 2 }, + ..Default::default() + }); + map.map.sort(); + + assert_eq!( + map.map, + vec![ + Cluster { + domain: Domain { start: 0, end: 1 }, + ..Default::default() + }, + Cluster { + domain: Domain { start: 1, end: 2 }, + ..Default::default() + }, + Cluster { + domain: Domain { start: 2, end: 3 }, + ..Default::default() + } + ] + ); + } + + /// Test for MapFile::update() + #[test] + fn update_11_common_start_and_end() { + // Case 11: + // |--new--| + // |--old--| + // + // Solution: Remove old. + + let mut map = MapFile { + map: vec![Cluster { + domain: Domain { start: 0, end: 3 }, + stage: Stage::Untested, + }], + ..Default::default() + }; + + map.update(Cluster { + domain: Domain { start: 0, end: 3 }, + stage: Stage::Intact, + }); + map.map.sort(); + + assert_eq!( + map.map, + vec![Cluster { + domain: Domain { start: 0, end: 3 }, + stage: Stage::Intact + }] + ); + } + + /// Test for MapFile::update() + #[test] + fn update_12_new_out_of_range_preceding() { + // Case 12: + // |--new--| + // |--old--| + // + // Solution: Leave Unchanged. + + let mut map = MapFile { + map: vec![Cluster { + domain: Domain { start: 2, end: 3 }, + ..Default::default() + }], + ..Default::default() + }; + + map.update(Cluster { + domain: Domain { start: 0, end: 1 }, + ..Default::default() + }); + map.map.sort(); + + assert_eq!( + map.map, + vec![ + Cluster { + domain: Domain { start: 0, end: 1 }, + ..Default::default() + }, + Cluster { + domain: Domain { start: 2, end: 3 }, + ..Default::default() + } + ] + ); + } + + /// Test for MapFile::update() + #[test] + fn update_13_new_out_of_range_trailing() { + // Case 13: + // |--new--| + // |--old--| + // + // Solution: Leave Unchanged. + + let mut map = MapFile { + map: vec![Cluster { + domain: Domain { start: 0, end: 1 }, + ..Default::default() + }], + ..Default::default() + }; + + map.update(Cluster { + domain: Domain { start: 2, end: 3 }, + ..Default::default() + }); + map.map.sort(); + + assert_eq!( + map.map, + vec![ + Cluster { + domain: Domain { start: 0, end: 1 }, + ..Default::default() + }, + Cluster { + domain: Domain { start: 2, end: 3 }, + ..Default::default() + } + ] + ); + } + + /// Test for MapFile::get_stage() + #[test] + fn get_stage() { let mut mf = MapFile::default(); let mut mf_stage = mf.get_stage(); @@ -258,9 +752,9 @@ mod tests { } } - // Test for MapFile::get_clusters() + /// Test for MapFile::get_clusters() #[test] - fn test_get_clusters() { + fn get_clusters() { let mut mf = MapFile::default(); mf.map = vec![ @@ -297,9 +791,9 @@ mod tests { } } - // Test for MapFile::defrag() + /// Test for MapFile::defrag() #[test] - fn test_defrag() { + fn defrag() { let mut mf = MapFile { sector_size: 1, domain: Domain { start: 0, end: 8 }, diff --git a/src/mapping/mod.rs b/src/mapping/mod.rs index 48ef000..df836b0 100644 --- a/src/mapping/mod.rs +++ b/src/mapping/mod.rs @@ -7,6 +7,6 @@ pub mod prelude; pub mod stage; pub use cluster::Cluster; -pub use domain::Domain; +pub use domain::{Domain, DomainOverlap}; pub use map::MapFile; pub use stage::Stage; diff --git a/src/mapping/prelude.rs b/src/mapping/prelude.rs index 8dc3f40..2f746eb 100644 --- a/src/mapping/prelude.rs +++ b/src/mapping/prelude.rs @@ -1,6 +1,6 @@ #![allow(unused_imports)] pub use super::cluster::Cluster; -pub use super::domain::Domain; +pub use super::domain::{Domain, DomainOverlap}; pub use super::map::{write_map_to_file, MapFile}; pub use super::stage::Stage; diff --git a/src/mapping/stage.rs b/src/mapping/stage.rs index 9c874c3..cb5acd9 100644 --- a/src/mapping/stage.rs +++ b/src/mapping/stage.rs @@ -1,11 +1,11 @@ use serde::{Deserialize, Serialize}; -#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub enum Stage { - Intact, Untested, ForIsolation(u8), Damaged, + Intact, } impl Default for Stage { diff --git a/src/recovery.rs b/src/recovery.rs index 0380b6e..41ca273 100644 --- a/src/recovery.rs +++ b/src/recovery.rs @@ -9,42 +9,47 @@ use crate::mapping::prelude::*; #[derive(Debug)] #[allow(dead_code)] pub struct Recover<'a> { - /// Buffer capacity in bytes. - buf_capacity: u64, config: &'a Args, + stream_len: u64, - input: File, + buf: Vec, + + input: &'a mut File, output: BufWriter, map: MapFile, - stage: Stage, } impl<'a> Recover<'a> { pub fn new( config: &'a Args, - input: File, + input: &'a mut File, output: File, map: MapFile, - buf_capacity: u64, - ) -> Self { - let stage = map.get_stage(); + ) -> anyhow::Result { + let stream_len = + crate::io::get_stream_length(input).context("Failed to get input stream length.")?; let mut r = Recover { - buf_capacity, config, - input: input, - output: BufWriter::with_capacity(buf_capacity as usize, output), + stream_len, + buf: vec![], + input, + output: BufWriter::with_capacity(stream_len as usize, output), map, - stage: stage, }; - // Ensure that buffer capacity is adjusted based on progress. - r.set_buf_capacity(); - r + r.restore(); + + Ok(r) } /// Recover media. pub fn run(&mut self) -> () { + // From start, read to end or error. + // + // If all data recovered, return early. + // Else, read from end to error. + self.copy_untested(); /* @@ -70,40 +75,47 @@ impl<'a> Recover<'a> { // return recovered_bytes } + /// Restore current progress based on MapFile. + /// Also updates MapFile if needed, such as to extend the MapFile domain. + pub fn restore(&mut self) { + self.map.extend(self.stream_len as usize); + } + /// Attempt to copy all untested blocks. fn copy_untested(&mut self) -> anyhow::Result<()> { - let mut buf = vec![crate::FB_PAD_VALUE; self.buf_capacity as usize]; + // Caching. + let buf_capacity = self.get_buf_capacity(); - // Purely caching. + self.buf = vec![crate::FB_PAD_VALUE; buf_capacity as usize]; + + // Yet more caching. let mut read_position = 0_u64; - let last_read_position = crate::io::get_stream_length(&mut self.input) - .context("Failed to get length of input stream")? - - self.buf_capacity; + let final_read_position = self.stream_len - buf_capacity; - while read_position < last_read_position { - if let Err(err) = self.input.read_exact(&mut buf) { + while read_position < final_read_position { + if let Err(err) = self.input.read_exact(&mut self.buf) { println!("Hit error: {:?}", err); self.input - .seek_relative(self.buf_capacity as i64) + .seek_relative(buf_capacity as i64) .context("Failed to seek input by buf_capacity to skip previous error")?; } else { self.output - .write_all(buf.as_slice()) + .write_all(self.buf.as_slice()) .context("Failed to write data to output file")?; self.map.update(Cluster { domain: Domain { start: read_position as usize, - end: (read_position + self.buf_capacity) as usize, + end: (read_position + buf_capacity) as usize, }, stage: Stage::Intact, }); } - read_position += self.buf_capacity; + read_position += buf_capacity; } - crate::mapping::map::write_map_to_file( + write_map_to_file( { let map_path = crate::io::get_path(&self.config.map, &self.config.input, "map") .context("Failed to generate map path.")?; @@ -125,10 +137,8 @@ impl<'a> Recover<'a> { /// Set buffer capacity as cluster length in bytes. /// Varies depending on the recovery stage. - fn set_buf_capacity(&mut self) -> &mut Self { - self.buf_capacity = self.config.sector_size as u64 * self.config.cluster_length as u64; - - self + fn get_buf_capacity(&mut self) -> u64 { + self.config.sector_size as u64 * self.config.cluster_length as u64 } }