Last push of ditched initial design.
This is only getting pushed for reference' sake. I don't even know how functional this version is.
This commit is contained in:
Generated
+1382
-5
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -8,6 +8,8 @@ license = "MIT"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
num-traits = "0.2.19"
|
||||
ratatui = "0.30"
|
||||
ron = ">=0.8, <0.13"
|
||||
#rust-i18n = "3.1.3"
|
||||
|
||||
@@ -28,6 +30,6 @@ features = ["derive"]
|
||||
# with unsafe ffi disasters trying to solve problems.
|
||||
#
|
||||
# And yes, I spent time tracking down the first release with that constant.
|
||||
# v0.2.25 is almost 9 years old as of writing this comment
|
||||
# v0.2.25 is almost 9 years old as of writing this comment.
|
||||
[target.'cfg(all(unix, not(target_os = "macos")))'.dependencies]
|
||||
libc = "~0.2.25"
|
||||
|
||||
@@ -6,6 +6,7 @@ use clap::{ArgAction, Parser};
|
||||
pub static CONFIG: LazyLock<Args> = LazyLock::new(|| Args::parse());
|
||||
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
#[clap(author, version, about)]
|
||||
pub struct Args {
|
||||
/// Path to source file or block device
|
||||
#[arg(short, long, value_hint = clap::ValueHint::DirPath)]
|
||||
@@ -50,4 +51,8 @@ pub struct Args {
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
#[arg(short = 'd', long = "no-direct", action = ArgAction::SetFalse)]
|
||||
pub direct_io: bool,
|
||||
|
||||
/// Disable the TUI in favour of a classic CLI experience.
|
||||
#[arg(short = 't', long = "no-tui", action = ArgAction::SetFalse)]
|
||||
pub tui: bool,
|
||||
}
|
||||
|
||||
+33
@@ -3,8 +3,14 @@ mod io;
|
||||
mod mapping;
|
||||
mod path;
|
||||
mod recovery;
|
||||
mod tui;
|
||||
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
|
||||
use cli::CONFIG;
|
||||
use recovery::Recover;
|
||||
use tui::Tui;
|
||||
|
||||
use anyhow;
|
||||
|
||||
@@ -18,5 +24,32 @@ fn main() -> anyhow::Result<()> {
|
||||
let mut recover_tool = Recover::new()?;
|
||||
recover_tool.run()?;
|
||||
|
||||
if CONFIG.tui {
|
||||
run_tui()?;
|
||||
} else {
|
||||
run_cli();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_cli() {}
|
||||
|
||||
fn run_tui() -> std::io::Result<()> {
|
||||
let mut tui = Tui::new();
|
||||
|
||||
// Enter Raw terminal mode.
|
||||
let mut terminal = ratatui::init();
|
||||
|
||||
let (tx, rx) = mpsc::channel::<crate::tui::Event>();
|
||||
|
||||
let tx_input_fetcher = tx.clone();
|
||||
thread::spawn(move || tui::input_fetcher(tx_input_fetcher));
|
||||
|
||||
let tui_result = tui.run(&mut terminal, rx);
|
||||
|
||||
// Exit Raw terminal mode.
|
||||
ratatui::restore();
|
||||
|
||||
tui_result
|
||||
}
|
||||
|
||||
+4
-10
@@ -7,14 +7,14 @@ use serde::{Deserialize, Serialize};
|
||||
// Use `sort_by_key()` to be safe.
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Cluster {
|
||||
pub domain: Domain,
|
||||
domain: Domain<usize>,
|
||||
pub stage: Stage,
|
||||
}
|
||||
|
||||
impl Default for Cluster {
|
||||
fn default() -> Self {
|
||||
Cluster {
|
||||
domain: Domain::default(),
|
||||
domain: Domain::from(0..1),
|
||||
stage: Stage::default(),
|
||||
}
|
||||
}
|
||||
@@ -31,10 +31,7 @@ impl Cluster {
|
||||
|
||||
for _ in 0..(domain_len / cluster_len) {
|
||||
clusters.push(Cluster {
|
||||
domain: Domain {
|
||||
start,
|
||||
end: start + cluster_len,
|
||||
},
|
||||
domain: Domain::from(start..start + cluster_len),
|
||||
stage: self.stage,
|
||||
});
|
||||
|
||||
@@ -42,10 +39,7 @@ impl Cluster {
|
||||
}
|
||||
|
||||
clusters.push(Cluster {
|
||||
domain: Domain {
|
||||
start,
|
||||
end: self.domain.end,
|
||||
},
|
||||
domain: Domain::from(start..self.domain.end),
|
||||
stage: self.stage,
|
||||
});
|
||||
|
||||
|
||||
+31
-19
@@ -1,28 +1,20 @@
|
||||
use std::ops::{Deref, DerefMut, Range};
|
||||
|
||||
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, Eq, PartialOrd, Ord)]
|
||||
pub struct Domain {
|
||||
pub start: usize,
|
||||
pub end: usize,
|
||||
}
|
||||
|
||||
impl Default for Domain {
|
||||
fn default() -> Self {
|
||||
Domain { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Domain {
|
||||
/// Return length of domain in sectors.
|
||||
#[allow(dead_code)]
|
||||
pub fn len(self) -> usize {
|
||||
self.end - self.start
|
||||
}
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Domain<Idx>(Range<Idx>)
|
||||
where
|
||||
Idx: PartialEq + Eq + PartialOrd + Ord;
|
||||
|
||||
impl<Idx> Domain<Idx>
|
||||
where
|
||||
Idx: PartialEq + PartialOrd + Ord,
|
||||
{
|
||||
/// Returns the type of overlap between this domain and another.
|
||||
pub fn overlap(&self, other: Domain) -> DomainOverlap {
|
||||
pub fn overlap(&self, other: Self) -> DomainOverlap {
|
||||
if self.end <= other.start || other.end <= self.start {
|
||||
// Cases 7, 8, 12, and 13 of map::tests::test_update
|
||||
DomainOverlap::None
|
||||
@@ -42,6 +34,26 @@ impl Domain {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Idx> Deref for Domain<Idx> {
|
||||
type Target = Range<Idx>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<Idx> DerefMut for Domain<Idx> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<Idx> From<Range<Idx>> for Domain<Idx> {
|
||||
fn from(value: Range<Idx>) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum DomainOverlap {
|
||||
None,
|
||||
SelfEngulfsOther,
|
||||
|
||||
+75
-81
@@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize};
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct MapFile {
|
||||
pub sector_size: usize,
|
||||
pub domain: Domain,
|
||||
pub domain: Domain<usize>,
|
||||
pub map: Vec<Cluster>,
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ impl Default for MapFile {
|
||||
fn default() -> Self {
|
||||
MapFile {
|
||||
sector_size: crate::FB_SECTOR_SIZE,
|
||||
domain: Domain::default(),
|
||||
domain: Domain::from(0..1),
|
||||
map: vec![Cluster {
|
||||
domain: Domain::default(),
|
||||
domain: Domain::from(0..1),
|
||||
stage: Stage::Patchwork { depth: 0 },
|
||||
}],
|
||||
}
|
||||
@@ -136,7 +136,7 @@ impl MapFile {
|
||||
/// 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<usize> {
|
||||
pub fn extend(&mut self..usize) -> Option<usize> {
|
||||
if end <= self.domain.end {
|
||||
return None;
|
||||
}
|
||||
@@ -147,10 +147,7 @@ impl MapFile {
|
||||
|
||||
// Add new data as untested.
|
||||
self.update(Cluster {
|
||||
domain: Domain {
|
||||
start: old_end,
|
||||
end: self.domain.end,
|
||||
},
|
||||
domain: Domain::from(old_end..self.domain.end),
|
||||
..Default::default()
|
||||
});
|
||||
Some(delta)
|
||||
@@ -189,10 +186,7 @@ fn other_engulfs_self_update(new: Cluster, old: &mut Cluster, map: &mut Vec<Clus
|
||||
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,
|
||||
},
|
||||
domain: Domain::from(new.domain.end..old_end),
|
||||
stage: old.stage,
|
||||
})
|
||||
}
|
||||
@@ -217,14 +211,14 @@ mod tests {
|
||||
|
||||
let mut map = MapFile {
|
||||
map: vec![Cluster {
|
||||
domain: Domain { start: 1, end: 3 },
|
||||
domain: Domain::from(1..3),
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
map.update(Cluster {
|
||||
domain: Domain { start: 0, end: 2 },
|
||||
domain: Domain::from(0..2),
|
||||
..Default::default()
|
||||
});
|
||||
map.map.sort();
|
||||
@@ -233,11 +227,11 @@ mod tests {
|
||||
map.map,
|
||||
vec![
|
||||
Cluster {
|
||||
domain: Domain { start: 0, end: 2 },
|
||||
domain: Domain::from(0..2),
|
||||
..Default::default()
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 2, end: 3 },
|
||||
domain: Domain::from(2..3),
|
||||
..Default::default()
|
||||
}
|
||||
]
|
||||
@@ -256,14 +250,14 @@ mod tests {
|
||||
|
||||
let mut map = MapFile {
|
||||
map: vec![Cluster {
|
||||
domain: Domain { start: 0, end: 2 },
|
||||
domain: Domain::from(0..2),
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
map.update(Cluster {
|
||||
domain: Domain { start: 1, end: 3 },
|
||||
domain: Domain::from(1..3),
|
||||
..Default::default()
|
||||
});
|
||||
map.map.sort();
|
||||
@@ -272,11 +266,11 @@ mod tests {
|
||||
map.map,
|
||||
vec![
|
||||
Cluster {
|
||||
domain: Domain { start: 0, end: 1 },
|
||||
domain: Domain::from(0..1),
|
||||
..Default::default()
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 1, end: 3 },
|
||||
domain: Domain::from(1..3),
|
||||
..Default::default()
|
||||
}
|
||||
]
|
||||
@@ -294,14 +288,14 @@ mod tests {
|
||||
|
||||
let mut map = MapFile {
|
||||
map: vec![Cluster {
|
||||
domain: Domain { start: 1, end: 3 },
|
||||
domain: Domain::from(1..3),
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
map.update(Cluster {
|
||||
domain: Domain { start: 0, end: 3 },
|
||||
domain: Domain::from(0..3),
|
||||
..Default::default()
|
||||
});
|
||||
map.map.sort();
|
||||
@@ -309,7 +303,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
map.map,
|
||||
vec![Cluster {
|
||||
domain: Domain { start: 0, end: 3 },
|
||||
domain: Domain::from(0..3),
|
||||
..Default::default()
|
||||
}]
|
||||
);
|
||||
@@ -327,14 +321,14 @@ mod tests {
|
||||
|
||||
let mut map = MapFile {
|
||||
map: vec![Cluster {
|
||||
domain: Domain { start: 0, end: 3 },
|
||||
domain: Domain::from(0..3),
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
map.update(Cluster {
|
||||
domain: Domain { start: 1, end: 3 },
|
||||
domain: Domain::from(1..3),
|
||||
..Default::default()
|
||||
});
|
||||
map.map.sort();
|
||||
@@ -343,11 +337,11 @@ mod tests {
|
||||
map.map,
|
||||
vec![
|
||||
Cluster {
|
||||
domain: Domain { start: 0, end: 1 },
|
||||
domain: Domain::from(0..1),
|
||||
..Default::default()
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 1, end: 3 },
|
||||
domain: Domain::from(1..3),
|
||||
..Default::default()
|
||||
}
|
||||
]
|
||||
@@ -365,14 +359,14 @@ mod tests {
|
||||
|
||||
let mut map = MapFile {
|
||||
map: vec![Cluster {
|
||||
domain: Domain { start: 0, end: 2 },
|
||||
domain: Domain::from(0..2),
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
map.update(Cluster {
|
||||
domain: Domain { start: 0, end: 3 },
|
||||
domain: Domain::from(0..3),
|
||||
..Default::default()
|
||||
});
|
||||
map.map.sort();
|
||||
@@ -380,7 +374,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
map.map,
|
||||
vec![Cluster {
|
||||
domain: Domain { start: 0, end: 3 },
|
||||
domain: Domain::from(0..3),
|
||||
..Default::default()
|
||||
}]
|
||||
);
|
||||
@@ -398,14 +392,14 @@ mod tests {
|
||||
|
||||
let mut map = MapFile {
|
||||
map: vec![Cluster {
|
||||
domain: Domain { start: 0, end: 3 },
|
||||
domain: Domain::from(0..3),
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
map.update(Cluster {
|
||||
domain: Domain { start: 0, end: 2 },
|
||||
domain: Domain::from(0..2),
|
||||
..Default::default()
|
||||
});
|
||||
map.map.sort();
|
||||
@@ -414,11 +408,11 @@ mod tests {
|
||||
map.map,
|
||||
vec![
|
||||
Cluster {
|
||||
domain: Domain { start: 0, end: 2 },
|
||||
domain: Domain::from(0..2),
|
||||
..Default::default()
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 2, end: 3 },
|
||||
domain: Domain::from(2..3),
|
||||
..Default::default()
|
||||
}
|
||||
]
|
||||
@@ -436,14 +430,14 @@ mod tests {
|
||||
|
||||
let mut map = MapFile {
|
||||
map: vec![Cluster {
|
||||
domain: Domain { start: 2, end: 3 },
|
||||
domain: Domain::from(2..3),
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
map.update(Cluster {
|
||||
domain: Domain { start: 0, end: 2 },
|
||||
domain: Domain::from(0..2),
|
||||
..Default::default()
|
||||
});
|
||||
map.map.sort();
|
||||
@@ -452,11 +446,11 @@ mod tests {
|
||||
map.map,
|
||||
vec![
|
||||
Cluster {
|
||||
domain: Domain { start: 0, end: 2 },
|
||||
domain: Domain::from(0..2),
|
||||
..Default::default()
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 2, end: 3 },
|
||||
domain: Domain::from(2..3),
|
||||
..Default::default()
|
||||
}
|
||||
]
|
||||
@@ -473,14 +467,14 @@ mod tests {
|
||||
|
||||
let mut map = MapFile {
|
||||
map: vec![Cluster {
|
||||
domain: Domain { start: 0, end: 2 },
|
||||
domain: Domain::from(0..2),
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
map.update(Cluster {
|
||||
domain: Domain { start: 2, end: 3 },
|
||||
domain: Domain::from(2..3),
|
||||
..Default::default()
|
||||
});
|
||||
map.map.sort();
|
||||
@@ -489,11 +483,11 @@ mod tests {
|
||||
map.map,
|
||||
vec![
|
||||
Cluster {
|
||||
domain: Domain { start: 0, end: 2 },
|
||||
domain: Domain::from(0..2),
|
||||
..Default::default()
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 2, end: 3 },
|
||||
domain: Domain::from(2..3),
|
||||
..Default::default()
|
||||
}
|
||||
]
|
||||
@@ -511,14 +505,14 @@ mod tests {
|
||||
|
||||
let mut map = MapFile {
|
||||
map: vec![Cluster {
|
||||
domain: Domain { start: 1, end: 2 },
|
||||
domain: Domain::from(1..2),
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
map.update(Cluster {
|
||||
domain: Domain { start: 0, end: 3 },
|
||||
domain: Domain::from(0..3),
|
||||
..Default::default()
|
||||
});
|
||||
map.map.sort();
|
||||
@@ -526,7 +520,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
map.map,
|
||||
vec![Cluster {
|
||||
domain: Domain { start: 0, end: 3 },
|
||||
domain: Domain::from(0..3 ),
|
||||
..Default::default()
|
||||
}]
|
||||
);
|
||||
@@ -548,14 +542,14 @@ mod tests {
|
||||
|
||||
let mut map = MapFile {
|
||||
map: vec![Cluster {
|
||||
domain: Domain { start: 0, end: 3 },
|
||||
domain: Domain::from(0..3),
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
map.update(Cluster {
|
||||
domain: Domain { start: 1, end: 2 },
|
||||
domain: Domain::from(1..2 ),
|
||||
..Default::default()
|
||||
});
|
||||
map.map.sort();
|
||||
@@ -564,15 +558,15 @@ mod tests {
|
||||
map.map,
|
||||
vec![
|
||||
Cluster {
|
||||
domain: Domain { start: 0, end: 1 },
|
||||
domain: Domain::from(0..1 ),
|
||||
..Default::default()
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 1, end: 2 },
|
||||
domain: Domain::from(1..2 ),
|
||||
..Default::default()
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 2, end: 3 },
|
||||
domain: Domain::from(2..3 ),
|
||||
..Default::default()
|
||||
}
|
||||
]
|
||||
@@ -590,14 +584,14 @@ mod tests {
|
||||
|
||||
let mut map = MapFile {
|
||||
map: vec![Cluster {
|
||||
domain: Domain { start: 0, end: 3 },
|
||||
domain: Domain::from(0..3 ),
|
||||
stage: Stage::Patchwork { depth: 0 },
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
map.update(Cluster {
|
||||
domain: Domain { start: 0, end: 3 },
|
||||
domain: Domain::from(0..3 ),
|
||||
stage: Stage::Intact,
|
||||
});
|
||||
map.map.sort();
|
||||
@@ -605,7 +599,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
map.map,
|
||||
vec![Cluster {
|
||||
domain: Domain { start: 0, end: 3 },
|
||||
domain: Domain::from(0..3 ),
|
||||
stage: Stage::Intact
|
||||
}]
|
||||
);
|
||||
@@ -622,14 +616,14 @@ mod tests {
|
||||
|
||||
let mut map = MapFile {
|
||||
map: vec![Cluster {
|
||||
domain: Domain { start: 2, end: 3 },
|
||||
domain: Domain::from(2..3 ),
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
map.update(Cluster {
|
||||
domain: Domain { start: 0, end: 1 },
|
||||
domain: Domain::from(0..1 ),
|
||||
..Default::default()
|
||||
});
|
||||
map.map.sort();
|
||||
@@ -638,11 +632,11 @@ mod tests {
|
||||
map.map,
|
||||
vec![
|
||||
Cluster {
|
||||
domain: Domain { start: 0, end: 1 },
|
||||
domain: Domain::from(0..1 ),
|
||||
..Default::default()
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 2, end: 3 },
|
||||
domain: Domain::from(2..3 ),
|
||||
..Default::default()
|
||||
}
|
||||
]
|
||||
@@ -660,14 +654,14 @@ mod tests {
|
||||
|
||||
let mut map = MapFile {
|
||||
map: vec![Cluster {
|
||||
domain: Domain { start: 0, end: 1 },
|
||||
domain: Domain::from(0..1 ),
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
map.update(Cluster {
|
||||
domain: Domain { start: 2, end: 3 },
|
||||
domain: Domain::from(2..3 ),
|
||||
..Default::default()
|
||||
});
|
||||
map.map.sort();
|
||||
@@ -676,11 +670,11 @@ mod tests {
|
||||
map.map,
|
||||
vec![
|
||||
Cluster {
|
||||
domain: Domain { start: 0, end: 1 },
|
||||
domain: Domain::from(0..1 ),
|
||||
..Default::default()
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 2, end: 3 },
|
||||
domain: Domain::from(2..3 ),
|
||||
..Default::default()
|
||||
}
|
||||
]
|
||||
@@ -696,7 +690,7 @@ mod tests {
|
||||
// If this fails here, there's something SERIOUSLY wrong.
|
||||
assert!(
|
||||
mf_stage == Stage::Patchwork { depth: 0 },
|
||||
"Determined stage to be {:?}, when {:?} was expeccted.",
|
||||
"Determined stage to be {:?}, when {:?} was expected.",
|
||||
mf_stage,
|
||||
Stage::Patchwork { depth: 0 }
|
||||
);
|
||||
@@ -764,50 +758,50 @@ mod tests {
|
||||
fn defrag() {
|
||||
let mut mf = MapFile {
|
||||
sector_size: 1,
|
||||
domain: Domain { start: 0, end: 8 },
|
||||
domain: Domain::from(0..8 ),
|
||||
map: vec![
|
||||
Cluster {
|
||||
domain: Domain { start: 0, end: 1 },
|
||||
domain: Domain::from(0..1 ),
|
||||
stage: Stage::Patchwork { depth: 0 },
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 1, end: 2 },
|
||||
domain: Domain::from(1..1 ),
|
||||
stage: Stage::Patchwork { depth: 0 },
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 2, end: 3 },
|
||||
domain: Domain::from(2..3 ),
|
||||
stage: Stage::Patchwork { depth: 0 },
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 3, end: 4 },
|
||||
domain: Domain::from(3..4 ),
|
||||
stage: Stage::Isolate,
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 4, end: 5 },
|
||||
domain: Domain::from(4..5 ),
|
||||
stage: Stage::Isolate,
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 5, end: 6 },
|
||||
domain: Domain::from(5..6 ),
|
||||
stage: Stage::Patchwork { depth: 1 },
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 6, end: 7 },
|
||||
domain: Domain::from(6..7 ),
|
||||
stage: Stage::Patchwork { depth: 0 },
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 7, end: 8 },
|
||||
domain: Domain::from(7..8 ),
|
||||
stage: Stage::Damaged,
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 8, end: 10 },
|
||||
domain: Domain::from(8..10 ),
|
||||
stage: Stage::Intact,
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 10, end: 11 },
|
||||
domain: Domain::from(10..10 ),
|
||||
stage: Stage::BruteForceAndDesperation,
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 11, end: 12 },
|
||||
domain: Domain::from(11..12 ),
|
||||
stage: Stage::BruteForceAndDesperation,
|
||||
},
|
||||
],
|
||||
@@ -815,31 +809,31 @@ mod tests {
|
||||
|
||||
let expected = vec![
|
||||
Cluster {
|
||||
domain: Domain { start: 0, end: 3 },
|
||||
domain: Domain::from(0..3 ),
|
||||
stage: Stage::Patchwork { depth: 0 },
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 3, end: 5 },
|
||||
domain: Domain::from(3..5 ),
|
||||
stage: Stage::Isolate,
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 5, end: 6 },
|
||||
domain: Domain::from(5..6 ),
|
||||
stage: Stage::Patchwork { depth: 1 },
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 6, end: 7 },
|
||||
domain: Domain::from(6..7 ),
|
||||
stage: Stage::Patchwork { depth: 0 },
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 7, end: 8 },
|
||||
domain: Domain::from(7..8 ),
|
||||
stage: Stage::Damaged,
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 8, end: 10 },
|
||||
domain: Domain::from(8..10 ),
|
||||
stage: Stage::Intact,
|
||||
},
|
||||
Cluster {
|
||||
domain: Domain { start: 10, end: 12 },
|
||||
domain: Domain::from(10..12 ),
|
||||
stage: Stage::BruteForceAndDesperation,
|
||||
},
|
||||
];
|
||||
|
||||
+5
-2
@@ -91,12 +91,13 @@ impl Recover {
|
||||
|
||||
while self.map.get_stage() == (Stage::Patchwork { depth }) {
|
||||
// Order of these two expressions matters, stupid.
|
||||
buf_capacity /= depth;
|
||||
depth += 1;
|
||||
buf_capacity /= depth + 1;
|
||||
|
||||
for cluster in self.map.get_clusters(Stage::Patchwork { depth }) {
|
||||
self.read_domain(buf.as_mut(), cluster.domain, buf_capacity, Stage::Isolate)?;
|
||||
}
|
||||
|
||||
depth += 1;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -123,6 +124,8 @@ impl Recover {
|
||||
stage: Stage::Intact,
|
||||
};
|
||||
|
||||
dbg!(cluster.domain);
|
||||
|
||||
match self.read_sectors(buf.as_mut()) {
|
||||
Ok(bytes) => {
|
||||
self.output
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
use std::io;
|
||||
use std::sync::mpsc;
|
||||
|
||||
use ratatui::crossterm;
|
||||
use ratatui::layout::{Constraint, Layout};
|
||||
use ratatui::symbols::border;
|
||||
use ratatui::widgets::{Block, Widget};
|
||||
use ratatui::{DefaultTerminal, Frame};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Tui {
|
||||
// bool::default() -> false
|
||||
exit: bool,
|
||||
}
|
||||
|
||||
impl Tui {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn run(
|
||||
&mut self,
|
||||
terminal: &mut DefaultTerminal,
|
||||
rx: mpsc::Receiver<Event>,
|
||||
) -> io::Result<()> {
|
||||
while !self.exit {
|
||||
// Render frame.
|
||||
terminal.draw(|frame| self.draw(frame))?;
|
||||
|
||||
// Event handler
|
||||
// unwraps, bc what could go wrong?
|
||||
match rx.recv().unwrap() {
|
||||
Event::Input(key_event) => self.handle_key_event(key_event)?,
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn draw(&self, frame: &mut Frame) {
|
||||
frame.render_widget(self, frame.area());
|
||||
}
|
||||
|
||||
pub fn handle_key_event(&mut self, key_event: crossterm::event::KeyEvent) -> io::Result<()> {
|
||||
if key_event.kind == crossterm::event::KeyEventKind::Press
|
||||
&& key_event.code == crossterm::event::KeyCode::Char('q')
|
||||
{
|
||||
self.exit = true;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// impl on reference to avoid accidentally mutating.
|
||||
impl Widget for &Tui {
|
||||
fn render(self, area: ratatui::prelude::Rect, buf: &mut ratatui::prelude::Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let [main_area, _info_area] =
|
||||
Layout::vertical([Constraint::Percentage(75), Constraint::Fill(1)]).areas(area);
|
||||
|
||||
let main_block = Block::bordered()
|
||||
.title(" Viewer ")
|
||||
.border_set(border::THICK);
|
||||
main_block.render(main_area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Event {
|
||||
Input(crossterm::event::KeyEvent),
|
||||
}
|
||||
|
||||
pub fn input_fetcher(tx: mpsc::Sender<Event>) {
|
||||
loop {
|
||||
// unwraps, bc what could go wrong?
|
||||
match crossterm::event::read().unwrap() {
|
||||
crossterm::event::Event::Key(key_event) => tx.send(Event::Input(key_event)).unwrap(),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user