From 3e93cf233c4df5e4da85f7844b22796ad81e0477 Mon Sep 17 00:00:00 2001 From: bujnlc8 Date: Fri, 2 Aug 2024 23:41:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=98=BE=E7=A4=BA=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E8=BF=9B=E5=BA=A6=E6=9D=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 70 +++++++++++++++++++++++++++++++++++++++++++++++++---- Cargo.toml | 7 +++++- Makefile | 10 ++++---- README.md | 18 +++++++------- src/lib.rs | 50 +++++++++++++++++++++++++------------- src/main.rs | 20 +++++++++------ src/util.rs | 54 +++++++++++++++++++++++++++++++++++++++-- 7 files changed, 182 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 721845b..1c61adf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -119,9 +119,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca2be1d5c43812bae364ee3f30b3afcb7877cf59f4aeb94c66f313a41d2fac9" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" @@ -191,6 +191,25 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.52.0", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encoding_rs" version = "0.8.34" @@ -384,6 +403,28 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indicatif" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -472,6 +513,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "object" version = "0.36.2" @@ -518,11 +565,12 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phonerr" -version = "0.1.1" +version = "0.1.2" dependencies = [ "anyhow", "clap", "colored", + "indicatif", "reqwest", "tokio", ] @@ -559,6 +607,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "portable-atomic" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" + [[package]] name = "ppv-lite86" version = "0.2.18" @@ -816,9 +870,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.121" +version = "1.0.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" +checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" dependencies = [ "itoa", "memchr", @@ -1067,6 +1121,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 150c73a..0238a88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phonerr" -version = "0.1.1" +version = "0.1.2" edition = "2021" description = "A CLI to query mobile phone region." readme = "README.md" @@ -18,9 +18,14 @@ clap = { version = "4.5.13", features = ["derive"] } colored = "2.1.0" tokio = { version = "1.39.2", features = ["full"] } reqwest = { version = "0.12", features = ["rustls-tls", "charset", "json"], default-features=false} +indicatif = { version = "0.17.8", optional = true } [profile.release] lto = true opt-level = "z" panic = "abort" strip = true + +[features] +download-progress = ["indicatif"] +indicatif = ["dep:indicatif"] diff --git a/Makefile b/Makefile index a49bc6e..6b45544 100644 --- a/Makefile +++ b/Makefile @@ -3,23 +3,23 @@ test: PLATFORMS:=x86_64-apple-darwin x86_64-unknown-linux-gnu x86_64-unknown-linux-musl aarch64-apple-darwin -VERSION:=0.1.1 +VERSION:=0.1.2 CLI:=phoner HOST_TRIPLE := $(shell rustc -vV | grep 'host:' | awk '{print $$2}') all: $(PLATFORMS) x86_64-apple-darwin: - cargo build --release --locked + cargo build --release --locked --features download-progress x86_64-unknown-linux-musl: - TARGET_CC=x86_64-linux-musl-cc cargo build --release --target x86_64-unknown-linux-musl --locked + TARGET_CC=x86_64-linux-musl-cc cargo build --release --target x86_64-unknown-linux-musl --locked --features download-progress x86_64-unknown-linux-gnu: - TARGET_CC=x86_64-linux-gnu-cc cargo build --release --target x86_64-unknown-linux-gnu --locked + TARGET_CC=x86_64-linux-gnu-cc cargo build --release --target x86_64-unknown-linux-gnu --locked --features download-progress aarch64-apple-darwin: - cargo build --release --target aarch64-apple-darwin --locked + cargo build --release --target aarch64-apple-darwin --locked --features download-progress artifacts:all @mkdir -p artifacts/$(VERSION) diff --git a/README.md b/README.md index c1e0354..adbdc36 100644 --- a/README.md +++ b/README.md @@ -8,21 +8,21 @@ ## 下载 -- [⬇️ 点击下载 x86_64-apple-darwin](https://github.com/bujnlc8/phoner/releases/download/0.1.1/phoner_x86_64-apple-darwin.tar.gz) +- [⬇️ 点击下载 x86_64-apple-darwin](https://github.com/bujnlc8/phoner/releases/download/0.1.2/phoner_x86_64-apple-darwin.tar.gz) - > [phoner_x86_64-apple-darwin.tar.gz.md5](https://github.com/bujnlc8/phoner/releases/download/0.1.1/phoner_x86_64-apple-darwin.tar.gz.md5) + > [phoner_x86_64-apple-darwin.tar.gz.md5](https://github.com/bujnlc8/phoner/releases/download/0.1.2/phoner_x86_64-apple-darwin.tar.gz.md5) -- [⬇️ 点击下载 aarch64-apple-darwin](https://github.com/bujnlc8/phoner/releases/download/0.1.1/phoner_aarch64-apple-darwin.tar.gz) +- [⬇️ 点击下载 aarch64-apple-darwin](https://github.com/bujnlc8/phoner/releases/download/0.1.2/phoner_aarch64-apple-darwin.tar.gz) - > [phoner_aarch64-apple-darwin.tar.gz.md5](https://github.com/bujnlc8/phoner/releases/download/0.1.1/phoner_aarch64-apple-darwin.tar.gz.md5) + > [phoner_aarch64-apple-darwin.tar.gz.md5](https://github.com/bujnlc8/phoner/releases/download/0.1.2/phoner_aarch64-apple-darwin.tar.gz.md5) -- [⬇️ 点击下载 x86_64-unknown-linux-musl](https://github.com/bujnlc8/phoner/releases/download/0.1.1/phoner_x86_64-unknown-linux-musl.tar.gz) +- [⬇️ 点击下载 x86_64-unknown-linux-musl](https://github.com/bujnlc8/phoner/releases/download/0.1.2/phoner_x86_64-unknown-linux-musl.tar.gz) - > [phoner_x86_64-unknown-linux-musl.tar.gz.md5](https://github.com/bujnlc8/phoner/releases/download/0.1.1/phoner_x86_64-unknown-linux-musl.tar.gz.md5) + > [phoner_x86_64-unknown-linux-musl.tar.gz.md5](https://github.com/bujnlc8/phoner/releases/download/0.1.2/phoner_x86_64-unknown-linux-musl.tar.gz.md5) -- ~~[⬇️ 点击下载 x86_64-unknown-linux-gnu](https://github.com/bujnlc8/phoner/releases/download/0.1.1/phoner_x86_64-unknown-linux-gnu.tar.gz)~~ +- ~~[⬇️ 点击下载 x86_64-unknown-linux-gnu](https://github.com/bujnlc8/phoner/releases/download/0.1.2/phoner_x86_64-unknown-linux-gnu.tar.gz)~~ - > ~~[phoner_x86_64-unknown-linux-gnu.tar.gz.md5](https://github.com/bujnlc8/phoner/releases/download/0.1.1/phoner_x86_64-unknown-linux-gnu.tar.gz.md5)~~ + > ~~[phoner_x86_64-unknown-linux-gnu.tar.gz.md5](https://github.com/bujnlc8/phoner/releases/download/0.1.2/phoner_x86_64-unknown-linux-gnu.tar.gz.md5)~~ 请根据你的操作系统下载相应的版本,可对比 md5 hash 值确定是否下载了最新的版本 @@ -37,7 +37,7 @@ sudo spctl --master-disable ## 编译 ``` -cargo build --release --locked +cargo build --release --locked [--features download-progress] ``` **如果在使用过程中发现 bug,欢迎反馈 👏** diff --git a/src/lib.rs b/src/lib.rs index 0464e84..330140a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ pub mod util; -use std::{fmt::Debug, os::unix::fs::MetadataExt, path::PathBuf}; +use std::{cmp::Ordering, fmt::Debug, os::unix::fs::MetadataExt, path::PathBuf}; use anyhow::anyhow; use colored::Colorize; @@ -8,7 +8,7 @@ use tokio::{ fs::{self, File}, io::{AsyncReadExt, AsyncSeekExt}, }; -use util::{download_file, replace_home, u8_i32}; +use util::{download_file, download_file_silent, replace_home, u8_i32}; #[derive(Debug)] pub struct PhoneData { @@ -120,21 +120,33 @@ impl PhoneData { replace_home("~/.cache/phoner/phone.dat") } - pub async fn download_file(&self, download_url: Option) -> Result<(), anyhow::Error> { + pub async fn download_file( + &self, + download_url: Option, + silent: bool, + ) -> Result<(), anyhow::Error> { if !self.data_path.parent().unwrap().exists() { fs::create_dir_all(self.data_path.parent().unwrap()).await?; } - download_file( - download_url.unwrap_or(PHONE_DATA_URL.to_string()).as_str(), - &PathBuf::from(Self::get_data_path()), - ) - .await?; + if silent { + download_file_silent( + download_url.unwrap_or(PHONE_DATA_URL.to_string()).as_str(), + &PathBuf::from(Self::get_data_path()), + ) + .await?; + } else { + download_file( + download_url.unwrap_or(PHONE_DATA_URL.to_string()).as_str(), + &PathBuf::from(Self::get_data_path()), + ) + .await?; + } Ok(()) } async fn init(&mut self) -> Result<(), anyhow::Error> { if !self.data_path.exists() { - self.download_file(None).await?; + self.download_file(None, true).await?; } let mut file = File::open(self.data_path.clone()).await?; // 读取头部8个字节 版本号, 第一个索引的偏移 @@ -174,16 +186,20 @@ impl PhoneData { // 前4位为手机号 let prefix = &self.index[mid * 9..(mid * 9 + 4)]; let prefix = u8_i32(prefix); - if prefix > phone_prefix { - if mid == 0 { + match prefix.cmp(&phone_prefix) { + Ordering::Greater => { + if mid == 0 { + break; + } + end = mid - 1; + } + Ordering::Equal => { + position = Some(mid); break; } - end = mid - 1; - } else if prefix == phone_prefix { - position = Some(mid); - break; - } else { - start = mid + 1; + Ordering::Less => { + start = mid + 1; + } } if start > end { break; diff --git a/src/main.rs b/src/main.rs index 552f95a..a54ab08 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,15 +38,19 @@ async fn main() -> Result<(), anyhow::Error> { } let mut client = PhoneData::new(None); if cli.update { + #[cfg(not(feature = "download-progress"))] let wait = wait_blink("下载中,请稍候⏬...", 3); - client.download_file(cli.update_url).await?; - wait.sender.send(true).unwrap(); - wait.handle.await?; - println!( - "{} {}", - "下载完成 ✅".green(), - format!("{}ms elapsed.", start.elapsed().as_millis()).bright_black() - ); + client.download_file(cli.update_url, false).await?; + #[cfg(not(feature = "download-progress"))] + { + wait.sender.send(true).unwrap(); + wait.handle.await?; + println!( + "{} {}", + "下载完成 ✅".green(), + format!("{}ms elapsed.", start.elapsed().as_millis()).bright_black() + ); + } return Ok(()); } if cli.info { diff --git a/src/util.rs b/src/util.rs index 8b8e13b..3249afb 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,4 +1,5 @@ #![allow(deprecated)] +#![allow(unused_imports)] use colored::Colorize; @@ -67,8 +68,8 @@ pub fn wait_blink(msg: &str, blink_char_num: usize) -> WaitBlinker { WaitBlinker { sender: tx, handle } } -// 下载文件 -pub async fn download_file(download_url: &str, dest: &Path) -> Result<(), anyhow::Error> { +// 静默下载 +pub async fn download_file_silent(download_url: &str, dest: &Path) -> Result<(), anyhow::Error> { let response = reqwest::get(download_url).await?; let dest_dir = dest.parent().unwrap(); if !dest_dir.exists() { @@ -82,6 +83,12 @@ pub async fn download_file(download_url: &str, dest: &Path) -> Result<(), anyhow Ok(()) } +// 下载文件 +#[cfg(not(feature = "download-progress"))] +pub async fn download_file(download_url: &str, dest: &Path) -> Result<(), anyhow::Error> { + download_file_silent(download_url, dest).await +} + pub fn replace_home(p: &str) -> String { if p.starts_with('~') { let home = env::home_dir().unwrap(); @@ -89,3 +96,46 @@ pub fn replace_home(p: &str) -> String { } p.to_string() } + +#[cfg(feature = "download-progress")] +pub async fn download_file(download_url: &str, dest: &Path) -> Result<(), anyhow::Error> { + use std::time; + + use indicatif::{ProgressBar, ProgressStyle}; + use tokio::io::AsyncWriteExt; + let start = time::Instant::now(); + let mut response = reqwest::Client::new().get(download_url).send().await?; + let total_size = response.content_length().unwrap(); + let pb = ProgressBar::new(total_size); + pb.set_style(ProgressStyle::default_bar().template("{spinner:.green} [{elapsed_precise}] [{bar:50.cyan/blue}] {bytes}/{total_bytes} ({eta})").unwrap().progress_chars("#>-")); + pb.clone().with_elapsed(start.elapsed()); + let dest_dir = dest.parent().unwrap(); + if !dest_dir.exists() { + fs::create_dir_all(dest_dir).await?; + } + let mut file = fs::File::create(dest).await?; + while let Some(chunk) = response.chunk().await? { + pb.inc(chunk.len() as u64); + file.write(&chunk).await?; + } + pb.finish(); + Ok(()) +} + +#[cfg(test)] +mod tests { + + use std::path::Path; + + use super::download_file; + + #[tokio::test] + async fn download_file_with_progress_test() -> Result<(), anyhow::Error> { + download_file( + "https://raw.githubusercontent.com/ls0f/phone/master/phone/phone.dat", + Path::new("./phone.dat").as_ref(), + ) + .await?; + Ok(()) + } +}