# fast-pull
[](https://github.com/fast-down/core/commits/stable)
[](https://github.com/fast-down/core/actions)
[](https://crates.io/crates/fast-pull)
[](https://docs.rs/fast-pull)
[](https://github.com/fast-down/core/blob/stable/crates/fast-pull/LICENSE)
`fast-pull` **Fastest** concurrent downloader!
**[Official Website (Simplified Chinese)](https://fast.s121.top/)**
## Features
1. **⚡️ Fastest Download**
We created [fast-steal](https://github.com/fast-down/fast-steal) With optimized Work Stealing, **1.43 x faster** than
NDM.
2. **🔄 File consistency**
Switching Wi-Fi, Turn Off Wi-Fi, Switch proxies. **We guarantee the consistency**.
3. **⛓️💥 Resuming Downloads**
You can **interrupt** at any time, and **resume downloading** after.
4. **⛓️💥 Incremental Downloads**
1000 more lines server logs? Don't worry, we **only download new lines**.
5. **💰 Free and open-source**
The code stays free and open-source. Thanks to [share121](https://github.com/share121), [Cyan](https://github.com/CyanChanges) and other fast-down contributors.
6. **No std support**
## Usage
```rust
use core::{num::NonZeroUsize, time::Duration};
use fast_pull::{
Event, MergeProgress, ProgressEntry,
file::RandFilePusherMmap,
multi::{self, download_multi},
reqwest::{Prefetch, ReqwestPuller},
};
use reqwest::Client;
use tokio::fs::OpenOptions;
#[tokio::main]
async fn main() {
let url = "https://example.com/file.txt";
let client = Client::new();
let info = client.prefetch(url).await.unwrap();
let file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.truncate(false)
.open(info.name)
.await
.unwrap();
let puller = ReqwestPuller::new(url.parse().unwrap(), client);
let pusher = RandFilePusherMmap::new(file, info.size, 8 * 1024)
.await
.unwrap();
let download_chunks = vec![0..info.size as u64];
let result = download_multi(
puller,
pusher,
multi::DownloadOptions {
concurrent: NonZero::new(32).unwrap(),
retry_gap: Duration::from_secs(1),
push_queue_cap: 1024,
download_chunks: download_chunks.clone(),
},
)
.await;
let mut pull_progress: Vec<ProgressEntry> = Vec::new();
let mut push_progress: Vec<ProgressEntry> = Vec::new();
while let Ok(e) = result.event_chain.recv().await {
match e {
Event::PullProgress(_, p) => {
pull_progress.merge_progress(p);
}
Event::PushProgress(_, p) => {
push_progress.merge_progress(p);
}
_ => {}
}
}
result.join().await.unwrap();
}
```