use crate::progress::{check_cancel, OperationPhase, OperationProgress};
use anyhow::Result;
use std::sync::atomic::AtomicBool;
use std::thread;
use std::time::Duration;
const SIMULATED_TOTAL_BYTES: u64 = 1_024 * 1_024 * 512; const SIMULATED_STEPS: u64 = 20;
pub fn simulate_flash<F>(
image: &str,
device: &str,
block_size: usize,
silent: bool,
verify: bool,
mut progress: Option<F>,
cancel: Option<&AtomicBool>,
) -> Result<()>
where
F: FnMut(OperationProgress),
{
emit(
silent,
&mut progress,
OperationProgress::new(OperationPhase::Preparing)
.with_message(format!("Opening image {image} (simulated)")),
);
check_cancel(cancel)?;
thread::sleep(Duration::from_millis(80));
check_cancel(cancel)?;
for step in 1..=SIMULATED_STEPS {
check_cancel(cancel)?;
let bytes = SIMULATED_TOTAL_BYTES * step / SIMULATED_STEPS;
let pct = if verify {
(bytes as f64 / SIMULATED_TOTAL_BYTES as f64) * 85.0
} else {
(bytes as f64 / SIMULATED_TOTAL_BYTES as f64) * 90.0
};
emit(
silent,
&mut progress,
OperationProgress::new(OperationPhase::Writing)
.with_bytes(bytes, Some(SIMULATED_TOTAL_BYTES))
.with_percentage(pct),
);
thread::sleep(Duration::from_millis(40));
}
let (sync_start, sync_end) = if verify { (85.0, 95.0) } else { (90.0, 100.0) };
for step in 1..=5 {
check_cancel(cancel)?;
let synced = SIMULATED_TOTAL_BYTES * step / 5;
let fraction = synced as f64 / SIMULATED_TOTAL_BYTES as f64;
let pct = sync_start + fraction * (sync_end - sync_start);
emit(
silent,
&mut progress,
OperationProgress::new(OperationPhase::Syncing)
.with_bytes(synced, Some(SIMULATED_TOTAL_BYTES))
.with_percentage(pct)
.with_message("Syncing data to device (simulated)"),
);
thread::sleep(Duration::from_millis(40));
}
if verify {
check_cancel(cancel)?;
emit(
silent,
&mut progress,
OperationProgress::new(OperationPhase::Verifying)
.with_percentage(95.0)
.with_message("Verifying checksum (simulated)"),
);
for step in 1..=5 {
check_cancel(cancel)?;
let verified = SIMULATED_TOTAL_BYTES * step / 5;
let pct = 95.0 + (verified as f64 / SIMULATED_TOTAL_BYTES as f64) * 5.0;
emit(
silent,
&mut progress,
OperationProgress::new(OperationPhase::Verifying)
.with_bytes(verified, Some(SIMULATED_TOTAL_BYTES))
.with_percentage(pct.min(99.9)),
);
thread::sleep(Duration::from_millis(40));
}
}
check_cancel(cancel)?;
emit(
silent,
&mut progress,
OperationProgress::new(OperationPhase::Complete)
.with_bytes(SIMULATED_TOTAL_BYTES, Some(SIMULATED_TOTAL_BYTES))
.with_percentage(100.0)
.with_message(format!(
"Simulated flash of {image} to {device} (block_size={block_size}, verify={verify})"
)),
);
Ok(())
}
pub fn simulate_clone<F>(
device: &str,
file: &str,
block_size: usize,
silent: bool,
mut progress: Option<F>,
cancel: Option<&AtomicBool>,
) -> Result<()>
where
F: FnMut(OperationProgress),
{
emit(
silent,
&mut progress,
OperationProgress::new(OperationPhase::Preparing)
.with_message(format!("Opening {device} (simulated)")),
);
check_cancel(cancel)?;
thread::sleep(Duration::from_millis(80));
check_cancel(cancel)?;
for step in 1..=SIMULATED_STEPS {
check_cancel(cancel)?;
let bytes = SIMULATED_TOTAL_BYTES * step / SIMULATED_STEPS;
let pct = (bytes as f64 / SIMULATED_TOTAL_BYTES as f64) * 100.0;
emit(
silent,
&mut progress,
OperationProgress::new(OperationPhase::Writing)
.with_bytes(bytes, Some(SIMULATED_TOTAL_BYTES))
.with_percentage(pct),
);
thread::sleep(Duration::from_millis(40));
}
check_cancel(cancel)?;
emit(
silent,
&mut progress,
OperationProgress::new(OperationPhase::Complete)
.with_bytes(SIMULATED_TOTAL_BYTES, Some(SIMULATED_TOTAL_BYTES))
.with_percentage(100.0)
.with_message(format!(
"Simulated clone of {device} to {file} (block_size={block_size})"
)),
);
Ok(())
}
fn emit<F>(silent: bool, progress: &mut Option<F>, event: OperationProgress)
where
F: FnMut(OperationProgress),
{
if silent {
return;
}
if let Some(callback) = progress {
callback(event);
}
}