mirror of
https://github.com/lifegpc/pixiv_downloader.git
synced 2026-07-08 01:32:41 +08:00
Add set_len
This commit is contained in:
@@ -54,9 +54,20 @@ pub trait GetTargetFileName {
|
||||
}
|
||||
}
|
||||
|
||||
/// Truncates or extends the underlying file, updating the size of this file.
|
||||
pub trait SetLen {
|
||||
/// Truncates or extends the underlying file, updating the size of this file to become `size`.
|
||||
///
|
||||
/// If the `size` is less than the current file’s size, then the file will be shrunk.
|
||||
/// If it is greater than the current file’s size, then the file will be extended to `size` and have all of the intermediate data filled in with 0s.
|
||||
fn set_len(&mut self, size: u64) -> Result<(), DownloaderError>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// A file downloader
|
||||
pub struct DownloaderInternal<T: Write + Seek + Send + Sync + ClearFile + GetTargetFileName> {
|
||||
pub struct DownloaderInternal<
|
||||
T: Write + Seek + Send + Sync + ClearFile + GetTargetFileName + SetLen,
|
||||
> {
|
||||
/// The webclient
|
||||
pub client: Arc<WebClient>,
|
||||
/// The download status
|
||||
@@ -185,7 +196,7 @@ impl DownloaderInternal<LocalFile> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Write + Seek + Send + Sync + ClearFile + GetTargetFileName> DownloaderInternal<T> {
|
||||
impl<T: Write + Seek + Send + Sync + ClearFile + GetTargetFileName + SetLen> DownloaderInternal<T> {
|
||||
/// Add a new task to tasks
|
||||
/// * `task` - Task
|
||||
pub fn add_task(&self, task: JoinHandle<Result<(), DownloaderError>>) {
|
||||
@@ -395,6 +406,19 @@ impl<T: Write + Seek + Send + Sync + ClearFile + GetTargetFileName> DownloaderIn
|
||||
self.dropped.qstore(true);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Truncates or extends the underlying file, updating the size of this file to become `size`.
|
||||
///
|
||||
/// If the `size` is less than the current file’s size, then the file will be shrunk.
|
||||
/// If it is greater than the current file’s size, then the file will be extended to `size` and have all of the intermediate data filled in with 0s.
|
||||
pub fn set_len(&self, size: u64) -> Result<(), DownloaderError> {
|
||||
match self.file.get_mut().deref_mut() {
|
||||
Some(f) => f.set_len(size)?,
|
||||
None => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Set the downloader is panic and set the error.
|
||||
/// * `err` - Error
|
||||
@@ -491,7 +515,7 @@ impl<T: Write + Seek + Send + Sync + ClearFile + GetTargetFileName> DownloaderIn
|
||||
///
|
||||
/// When dropping downloader, the downloader need some times to let all threads exited.
|
||||
/// This process is handled after [Drop].
|
||||
pub struct Downloader<T: Write + Seek + Send + Sync + ClearFile + GetTargetFileName> {
|
||||
pub struct Downloader<T: Write + Seek + Send + Sync + ClearFile + GetTargetFileName + SetLen> {
|
||||
/// internal type
|
||||
downloader: Arc<DownloaderInternal<T>>,
|
||||
}
|
||||
@@ -553,7 +577,9 @@ macro_rules! define_downloader_fn {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Write + Seek + Send + Sync + ClearFile + GetTargetFileName + 'static> Downloader<T> {
|
||||
impl<T: Write + Seek + Send + Sync + ClearFile + GetTargetFileName + SetLen + 'static>
|
||||
Downloader<T>
|
||||
{
|
||||
/// Start download if download not started.
|
||||
///
|
||||
/// Returns the status of the Downloader
|
||||
@@ -703,7 +729,9 @@ impl<T: Write + Seek + Send + Sync + ClearFile + GetTargetFileName + 'static> Do
|
||||
define_downloader_fn!(is_panic, bool, "Returns true if the downloader is panic.");
|
||||
}
|
||||
|
||||
impl<T: Write + Seek + Send + Sync + ClearFile + GetTargetFileName> Drop for Downloader<T> {
|
||||
impl<T: Write + Seek + Send + Sync + ClearFile + GetTargetFileName + SetLen> Drop
|
||||
for Downloader<T>
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.downloader.set_dropped();
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use super::downloader::GetTargetFileName;
|
||||
use super::downloader::SetLen;
|
||||
use crate::ext::io::ClearFile;
|
||||
use std::fs::remove_file;
|
||||
use std::fs::File;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Seek;
|
||||
use std::io::Write;
|
||||
use std::ops::Deref;
|
||||
@@ -22,7 +24,12 @@ impl LocalFile {
|
||||
/// This function will create a file if it does not exist, and will truncate it if it does.
|
||||
pub fn create<P: AsRef<Path>>(path: P) -> std::io::Result<Self> {
|
||||
let p = path.as_ref().to_owned();
|
||||
let f = File::create(&p)?;
|
||||
let f = OpenOptions::new()
|
||||
.create(true)
|
||||
.read(true)
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.open(&p)?;
|
||||
Ok(Self {
|
||||
file: Some(f),
|
||||
path: p,
|
||||
@@ -32,7 +39,11 @@ impl LocalFile {
|
||||
/// Attempts to open a file in read-only mode.
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> std::io::Result<Self> {
|
||||
let p = path.as_ref().to_owned();
|
||||
let f = File::open(&p)?;
|
||||
let f = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.open(&p)?;
|
||||
Ok(Self {
|
||||
file: Some(f),
|
||||
path: p,
|
||||
@@ -72,6 +83,13 @@ impl Seek for LocalFile {
|
||||
}
|
||||
}
|
||||
|
||||
impl SetLen for LocalFile {
|
||||
fn set_len(&mut self, size: u64) -> Result<(), super::DownloaderError> {
|
||||
self.file.as_ref().unwrap().set_len(size)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for LocalFile {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
self.file.as_ref().unwrap().write(buf)
|
||||
|
||||
@@ -21,6 +21,7 @@ use std::fs::create_dir;
|
||||
use std::fs::metadata;
|
||||
use std::fs::remove_file;
|
||||
use std::fs::File;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Read;
|
||||
use std::io::Seek;
|
||||
use std::io::SeekFrom;
|
||||
@@ -392,7 +393,11 @@ impl PdFile {
|
||||
/// Returns errors or a new instance.
|
||||
pub fn read_from_file<P: AsRef<Path> + ?Sized>(path: &P) -> Result<Self, PdFileError> {
|
||||
let p = path.as_ref();
|
||||
let mut f = File::open(p)?;
|
||||
let mut f = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.open(p)?;
|
||||
f.seek(SeekFrom::Start(0))?;
|
||||
let mut buf = [0u8, 0, 0, 0];
|
||||
f.read_exact(&mut buf)?;
|
||||
@@ -446,7 +451,12 @@ impl PdFile {
|
||||
if p.exists() {
|
||||
remove_file(p)?;
|
||||
}
|
||||
let f = File::create(p)?;
|
||||
let f = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.create(true)
|
||||
.open(p)?;
|
||||
self.file.get_mut().replace(f);
|
||||
self.file_path.get_mut().replace(PathBuf::from(p));
|
||||
self.mem_only.qstore(false);
|
||||
@@ -485,7 +495,14 @@ impl PdFile {
|
||||
}
|
||||
remove_file(self.file_path.get_ref().as_ref().unwrap())?;
|
||||
f.take();
|
||||
f.replace(File::create(self.file_path.get_ref().as_ref().unwrap())?);
|
||||
f.replace(
|
||||
OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.create(true)
|
||||
.open(self.file_path.get_ref().as_ref().unwrap())?,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use super::downloader::DownloaderInternal;
|
||||
use super::downloader::GetTargetFileName;
|
||||
use super::downloader::SetLen;
|
||||
use super::error::DownloaderError;
|
||||
use super::pd_file::PdFilePartStatus;
|
||||
use crate::concat_error;
|
||||
@@ -43,7 +44,7 @@ macro_rules! check_dropped {
|
||||
|
||||
/// Create a download tasks in simple thread mode.
|
||||
pub async fn create_download_tasks_simple<
|
||||
T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName,
|
||||
T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName + SetLen,
|
||||
>(
|
||||
d: Arc<DownloaderInternal<T>>,
|
||||
) -> Result<(), DownloaderError> {
|
||||
@@ -133,6 +134,7 @@ pub async fn create_download_tasks_simple<
|
||||
if d.enabled_progress_bar() {
|
||||
d.set_progress_bar_length(len);
|
||||
}
|
||||
d.set_len(len)?;
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
@@ -147,7 +149,7 @@ pub async fn create_download_tasks_simple<
|
||||
|
||||
/// Do first job when download in multiple mode.
|
||||
pub async fn create_download_tasks_multi_first<
|
||||
T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName,
|
||||
T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName + SetLen,
|
||||
>(
|
||||
d: Arc<DownloaderInternal<T>>,
|
||||
) -> Result<(), DownloaderError> {
|
||||
@@ -185,6 +187,7 @@ pub async fn create_download_tasks_multi_first<
|
||||
if d.enabled_progress_bar() {
|
||||
d.set_progress_bar_length(len);
|
||||
}
|
||||
d.set_len(len)?;
|
||||
}
|
||||
None => {
|
||||
d.fallback_to_simp();
|
||||
@@ -209,7 +212,7 @@ pub async fn create_download_tasks_multi_first<
|
||||
|
||||
/// Create a new download task in multiple thread mode.
|
||||
pub async fn create_download_tasks_multi<
|
||||
T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName,
|
||||
T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName + SetLen,
|
||||
>(
|
||||
d: Arc<DownloaderInternal<T>>,
|
||||
pd: Arc<PdFilePartStatus>,
|
||||
@@ -224,7 +227,7 @@ pub async fn create_download_tasks_multi<
|
||||
|
||||
/// Create a new download task in multiple thread mode.
|
||||
pub async fn create_download_tasks_multi_internal<
|
||||
T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName,
|
||||
T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName + SetLen,
|
||||
>(
|
||||
d: Arc<DownloaderInternal<T>>,
|
||||
pd: Arc<PdFilePartStatus>,
|
||||
@@ -260,7 +263,9 @@ pub async fn create_download_tasks_multi_internal<
|
||||
}
|
||||
|
||||
/// Handle download process
|
||||
pub async fn handle_download<T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName>(
|
||||
pub async fn handle_download<
|
||||
T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName + SetLen,
|
||||
>(
|
||||
d: Arc<DownloaderInternal<T>>,
|
||||
re: Response,
|
||||
pd: Option<Arc<PdFilePartStatus>>,
|
||||
@@ -365,7 +370,7 @@ pub async fn handle_download<T: Seek + Write + Send + Sync + ClearFile + GetTarg
|
||||
}
|
||||
|
||||
pub async fn add_new_multi_tasks<
|
||||
T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName + 'static,
|
||||
T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName + SetLen + 'static,
|
||||
>(
|
||||
d: &Arc<DownloaderInternal<T>>,
|
||||
) -> Result<(), DownloaderError> {
|
||||
@@ -395,7 +400,7 @@ pub async fn add_new_multi_tasks<
|
||||
|
||||
/// Check tasks are completed or not. And create new tasks if needed.
|
||||
pub async fn check_tasks<
|
||||
T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName + 'static,
|
||||
T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName + SetLen + 'static,
|
||||
>(
|
||||
d: Arc<DownloaderInternal<T>>,
|
||||
) -> Result<(), DownloaderError> {
|
||||
|
||||
Reference in New Issue
Block a user