mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2025-11-13 08:12:44 +10:00
* feat: add new template options, asahi support, and refactoring * feat: install dir scanning, validation fixes, progress fixes, download manager refactor This kind of ballooned out of scope, but I implemented some much needed fixes for the download manager. First off, I cleanup the Downloadable trait, there was some duplication of function. Second, I refactored the "validate" into the GameDownloadAgent, which calls a 'validate_chunk_logic' yada, same structure as downloading. Third, I fixed the progress and validation issues. Fourth, I added game scanning * feat: out of box support for Asahi Linux * fix: clippy * fix: don't break database
105 lines
2.6 KiB
Rust
105 lines
2.6 KiB
Rust
use std::{
|
|
fs::File,
|
|
io::{self, BufWriter, Read, Seek, SeekFrom, Write},
|
|
};
|
|
|
|
use log::debug;
|
|
use md5::Context;
|
|
|
|
use crate::{
|
|
download_manager::
|
|
util::{
|
|
download_thread_control_flag::{DownloadThreadControl, DownloadThreadControlFlag},
|
|
progress_object::ProgressHandle,
|
|
}
|
|
,
|
|
error::application_download_error::ApplicationDownloadError,
|
|
games::downloads::manifest::DropDownloadContext,
|
|
};
|
|
|
|
pub fn validate_game_chunk(
|
|
ctx: &DropDownloadContext,
|
|
control_flag: &DownloadThreadControl,
|
|
progress: ProgressHandle,
|
|
) -> Result<bool, ApplicationDownloadError> {
|
|
debug!(
|
|
"Starting chunk validation {}, {}, {} #{}",
|
|
ctx.file_name, ctx.index, ctx.offset, ctx.checksum
|
|
);
|
|
// If we're paused
|
|
if control_flag.get() == DownloadThreadControlFlag::Stop {
|
|
progress.set(0);
|
|
return Ok(false);
|
|
}
|
|
|
|
let Ok(mut source) = File::open(&ctx.path) else {
|
|
return Ok(false);
|
|
};
|
|
|
|
if ctx.offset != 0 {
|
|
source
|
|
.seek(SeekFrom::Start(ctx.offset))
|
|
.expect("Failed to seek to file offset");
|
|
}
|
|
|
|
let mut hasher = md5::Context::new();
|
|
|
|
let completed =
|
|
validate_copy(&mut source, &mut hasher, ctx.length, control_flag, progress).unwrap();
|
|
if !completed {
|
|
return Ok(false);
|
|
}
|
|
|
|
let res = hex::encode(hasher.compute().0);
|
|
if res != ctx.checksum {
|
|
return Ok(false);
|
|
}
|
|
|
|
debug!(
|
|
"Successfully finished verification #{}, copied {} bytes",
|
|
ctx.checksum, ctx.length
|
|
);
|
|
|
|
Ok(true)
|
|
}
|
|
|
|
fn validate_copy(
|
|
source: &mut File,
|
|
dest: &mut Context,
|
|
size: usize,
|
|
control_flag: &DownloadThreadControl,
|
|
progress: ProgressHandle,
|
|
) -> Result<bool, io::Error> {
|
|
let copy_buf_size = 512;
|
|
let mut copy_buf = vec![0; copy_buf_size];
|
|
let mut buf_writer = BufWriter::with_capacity(1024 * 1024, dest);
|
|
let mut total_bytes = 0;
|
|
|
|
loop {
|
|
if control_flag.get() == DownloadThreadControlFlag::Stop {
|
|
buf_writer.flush()?;
|
|
return Ok(false);
|
|
}
|
|
|
|
let mut bytes_read = source.read(&mut copy_buf)?;
|
|
total_bytes += bytes_read;
|
|
|
|
// If we read over (likely), truncate our read to
|
|
// the right size
|
|
if total_bytes > size {
|
|
let over = total_bytes - size;
|
|
bytes_read -= over;
|
|
total_bytes = size;
|
|
}
|
|
|
|
buf_writer.write_all(©_buf[0..bytes_read])?;
|
|
progress.add(bytes_read);
|
|
|
|
if total_bytes >= size {
|
|
break;
|
|
}
|
|
}
|
|
buf_writer.flush()?;
|
|
Ok(true)
|
|
}
|