diff --git a/proc_macros/proc_macros.rs b/proc_macros/proc_macros.rs index 713ee25..4fae577 100644 --- a/proc_macros/proc_macros.rs +++ b/proc_macros/proc_macros.rs @@ -3,8 +3,8 @@ extern crate syn; use proc_macro::TokenStream; use quote::quote; -use syn::Ident; use syn::parse_macro_input; +use syn::Ident; #[proc_macro] pub fn define_struct_reader_fn(item: TokenStream) -> TokenStream { diff --git a/src/author_name_filter.rs b/src/author_name_filter.rs index 0d2e4b1..8ea0e7d 100644 --- a/src/author_name_filter.rs +++ b/src/author_name_filter.rs @@ -1,6 +1,6 @@ use crate::ext::json::ToJson; -use crate::gettext; use crate::ext::try_err::TryErr; +use crate::gettext; use json::JsonValue; use regex::Regex; use std::cmp::PartialEq; @@ -17,15 +17,17 @@ pub enum AuthorNameFilterError { impl Display for AuthorNameFilterError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::String(s) => { f.write_str(s) } - Self::Regex(r) => { f.write_fmt(format_args!("{} {}", gettext("Failed to parse regex:"), r)) } + Self::String(s) => f.write_str(s), + Self::Regex(r) => { + f.write_fmt(format_args!("{} {}", gettext("Failed to parse regex:"), r)) + } } } } impl From<&str> for AuthorNameFilterError { fn from(s: &str) -> Self { - Self::String(String::from(s)) + Self::String(String::from(s)) } } @@ -58,15 +60,11 @@ impl AuthorNameFilter { impl AuthorFiler for AuthorNameFilter { fn filter(&self, author: &str) -> String { match self { - Self::Simple(s) => { - match author.rfind(s) { - Some(i) => { String::from(&author[..i]) } - None => { String::from(author) } - } - } - Self::Regex(r) => { - r.replace_all(author, "").to_owned().to_string() - } + Self::Simple(s) => match author.rfind(s) { + Some(i) => String::from(&author[..i]), + None => String::from(author), + }, + Self::Regex(r) => r.replace_all(author, "").to_owned().to_string(), } } } @@ -93,20 +91,14 @@ impl From<&str> for AuthorNameFilter { impl PartialEq for AuthorNameFilter { fn eq(&self, other: &Self) -> bool { match self { - Self::Simple(s) => { - match other { - Self::Regex(_) => { false } - Self::Simple(t) => { s == t } - } - } - Self::Regex(r) => { - match other { - Self::Simple(_) => { false } - Self::Regex(s) => { - r.as_str() == s.as_str() - } - } - } + Self::Simple(s) => match other { + Self::Regex(_) => false, + Self::Simple(t) => s == t, + }, + Self::Regex(r) => match other { + Self::Simple(_) => false, + Self::Regex(s) => r.as_str() == s.as_str(), + }, } } } @@ -117,14 +109,23 @@ impl TryFrom<&JsonValue> for AuthorNameFilter { if j.is_string() { return Ok(Self::from(j.as_str().unwrap())); } else if j.is_object() { - let t = (&j["type"]).as_str().try_err(gettext("Failed to get filter's type."))?.to_lowercase(); - let rule = (&j["rule"]).as_str().try_err(gettext("Failed to get filter's rule."))?; + let t = (&j["type"]) + .as_str() + .try_err(gettext("Failed to get filter's type."))? + .to_lowercase(); + let rule = (&j["rule"]) + .as_str() + .try_err(gettext("Failed to get filter's rule."))?; if t == "simple" { return Ok(Self::from(rule)); } else if t == "regex" { return Ok(Self::from(Regex::new(rule)?)); } else { - Err(format!("{} {}", gettext("Unknown filter's type:"), t.as_str()))?; + Err(format!( + "{} {}", + gettext("Unknown filter's type:"), + t.as_str() + ))?; } } else { Err(gettext("Unsupported JSON type."))?; @@ -136,7 +137,11 @@ impl TryFrom<&JsonValue> for AuthorNameFilter { pub fn check_author_name_filters(v: &JsonValue) -> bool { let r = AuthorNameFilter::from_json(v); if r.is_err() { - println!("{} {}", gettext("Failed parse author name filters:"), r.as_ref().unwrap_err()); + println!( + "{} {}", + gettext("Failed parse author name filters:"), + r.as_ref().unwrap_err() + ); } r.is_ok() } @@ -144,15 +149,27 @@ pub fn check_author_name_filters(v: &JsonValue) -> bool { #[test] fn test_author_name_filter() { assert!(AuthorNameFilter::from("s") == AuthorNameFilter::from("s")); - assert!(AuthorNameFilter::from(Regex::new("s").unwrap()) == AuthorNameFilter::from(Regex::new("s").unwrap())); + assert!( + AuthorNameFilter::from(Regex::new("s").unwrap()) + == AuthorNameFilter::from(Regex::new("s").unwrap()) + ); let l = AuthorNameFilter::from_json(json::array!["🌸"]).unwrap(); assert_eq!(l, vec![AuthorNameFilter::from("🌸")]); assert_eq!(l[0].filter("moco🌸お仕事募集中"), String::from("moco")); let r = AuthorNameFilter::from(Regex::new(".?お仕事募集中").unwrap()); assert_eq!(r.filter("moco🌸お仕事募集中"), String::from("moco")); - let l = AuthorNameFilter::from_json(json::array![{"type": "simple", "rule": "🌸"}, {"type": "regex", "rule": ".?お仕事募集中"}]).unwrap(); - assert_eq!(l, vec![AuthorNameFilter::from("🌸"), AuthorNameFilter::from(r)]); - assert_eq!(l.filter("moco<お仕事募集中🌸お仕事募集中"), String::from("moco<お仕事募集中")); + let l = AuthorNameFilter::from_json( + json::array![{"type": "simple", "rule": "🌸"}, {"type": "regex", "rule": ".?お仕事募集中"}], + ) + .unwrap(); + assert_eq!( + l, + vec![AuthorNameFilter::from("🌸"), AuthorNameFilter::from(r)] + ); + assert_eq!( + l.filter("moco<お仕事募集中🌸お仕事募集中"), + String::from("moco<お仕事募集中") + ); assert_eq!(l.filter("sss@ss@お仕事募集中"), "sss@ss"); assert_eq!(l.filter("sss🌸ss🌸お仕事募集中"), "sss🌸ss"); } diff --git a/src/avdict.rs b/src/avdict.rs index 19267bc..5bb99f5 100644 --- a/src/avdict.rs +++ b/src/avdict.rs @@ -27,12 +27,12 @@ pub enum AVDictError { /// The error code from ffmpeg CodeError(AVDictCodeError), /// The error occured when convert data to the string in C. - ToCstr(ToCStrError) + ToCstr(ToCStrError), } impl From<&str> for AVDictError { fn from(s: &str) -> Self { - Self::String(String::from(s)) + Self::String(String::from(s)) } } @@ -45,10 +45,14 @@ impl From for AVDictError { impl Display for AVDictError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::String(s) => { f.write_str(s) } - Self::Utf8Error(s) => { f.write_fmt(format_args!("{} {}", gettext("Failed to decode string with UTF-8:"), s)) } - Self::CodeError(s) => { f.write_fmt(format_args!("{}", s)) } - Self::ToCstr(s) => { f.write_fmt(format_args!("{}", s)) } + Self::String(s) => f.write_str(s), + Self::Utf8Error(s) => f.write_fmt(format_args!( + "{} {}", + gettext("Failed to decode string with UTF-8:"), + s + )), + Self::CodeError(s) => f.write_fmt(format_args!("{}", s)), + Self::ToCstr(s) => f.write_fmt(format_args!("{}", s)), } } } @@ -78,21 +82,19 @@ impl AVDictCodeError { impl Display for AVDictCodeError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.to_str() { - Ok(s) => { - f.write_str(s.as_str()) - } - Err(e) => { - f.write_fmt(format_args!("{} {}", gettext("Failed to get error message:"), e)) - } + Ok(s) => f.write_str(s.as_str()), + Err(e) => f.write_fmt(format_args!( + "{} {}", + gettext("Failed to get error message:"), + e + )), } } } impl From for AVDictCodeError { fn from(i: c_int) -> Self { - Self { - err: i, - } + Self { err: i } } } @@ -143,15 +145,17 @@ impl AVDict { if re != 0 { Err(re)?; } - Ok(Self { - m, - }) + Ok(Self { m }) } /// Set all entries in the map to the dictionary /// * `maps` - The map which contains entries /// * `flags` - The flags to use when setting entries. - pub fn from_map>(&mut self, maps: &HashMap, flags: F) -> Result<(), AVDictError> { + pub fn from_map>( + &mut self, + maps: &HashMap, + flags: F, + ) -> Result<(), AVDictError> { let flags = flags.to_flag_set(); for (k, v) in maps { self.set(k, v, flags)?; @@ -162,12 +166,23 @@ impl AVDict { /// Get a dictionary value with matching key. /// * `key` - The matching key /// * `flags` - The flags to control how entry is retrieved. - pub fn get>(&self, key: K, flags: F) -> Result, AVDictError> { + pub fn get>( + &self, + key: K, + flags: F, + ) -> Result, AVDictError> { if self.m.is_null() { return Ok(None); } let k = key.to_cstr()?; - let re = unsafe { _avdict::avdict_get(self.m, k.as_ptr(), 0 as *mut _avdict::AVDictEntry, flags.to_bits()) }; + let re = unsafe { + _avdict::avdict_get( + self.m, + k.as_ptr(), + 0 as *mut _avdict::AVDictEntry, + flags.to_bits(), + ) + }; if !re.is_null() && unsafe { !(*re).value.is_null() } { let s = unsafe { CStr::from_ptr((*re).value) }; let s = s.to_owned(); @@ -176,12 +191,23 @@ impl AVDict { Ok(None) } - pub fn get_all>(&self, key: K, flags: F) -> Result>, AVDictError> { + pub fn get_all>( + &self, + key: K, + flags: F, + ) -> Result>, AVDictError> { if self.m.is_null() { return Ok(None); } let k = key.to_cstr()?; - let mut re = unsafe { _avdict::avdict_get(self.m, k.as_ptr(), 0 as *mut _avdict::AVDictEntry, flags.to_bits()) }; + let mut re = unsafe { + _avdict::avdict_get( + self.m, + k.as_ptr(), + 0 as *mut _avdict::AVDictEntry, + flags.to_bits(), + ) + }; let mut l = Vec::new(); while !re.is_null() { if unsafe { (*re).value.is_null() } { @@ -210,7 +236,9 @@ impl AVDict { pub fn get_string(&self, key_val_sep: char, pairs_sep: char) -> Result { let mut buf = 0 as *mut c_char; let pbuf: *mut *mut c_char = &mut buf; - let re = unsafe { _avdict::avdict_get_string(self.m, pbuf, key_val_sep as c_char, pairs_sep as c_char) }; + let re = unsafe { + _avdict::avdict_get_string(self.m, pbuf, key_val_sep as c_char, pairs_sep as c_char) + }; if re != 0 { Err(re)?; } @@ -237,26 +265,39 @@ impl AVDict { } /// Parse the key/value pairs list and add the parsed entries to a dictionary. - /// + /// /// In case of failure, all the successfully set entries are stored. /// * `s` - string /// * `key_val_sep` - a list of characters used to separate key from value /// * `pairs_sep` - a list of characters used to separate two pairs from each other /// * `flags` - flags to use when adding to dictionary. /// StrdupKey and StrdipValue are ignored since the key/value tokens will always be duplicated. - pub fn parse_string>(&mut self, s: K, key_val_sep: V, pairs_sep: S, flags: F) -> Result<(), AVDictError> { + pub fn parse_string>( + &mut self, + s: K, + key_val_sep: V, + pairs_sep: S, + flags: F, + ) -> Result<(), AVDictError> { let pm: *mut *mut _avdict::AVDict = &mut self.m; let s = s.to_cstr()?; let k = key_val_sep.to_cstr()?; let p = pairs_sep.to_cstr()?; - let re = unsafe { _avdict::avdict_parse_string(pm, s.as_ptr(), k.as_ptr(), p.as_ptr(), flags.to_bits()) }; + let re = unsafe { + _avdict::avdict_parse_string(pm, s.as_ptr(), k.as_ptr(), p.as_ptr(), flags.to_bits()) + }; if re != 0 { Err(re)?; } Ok(()) } - pub fn set>(&mut self, key: K, value: V, flags: F) -> Result<(), AVDictError> { + pub fn set>( + &mut self, + key: K, + value: V, + flags: F, + ) -> Result<(), AVDictError> { let pm: *mut *mut _avdict::AVDict = &mut self.m; let k = key.to_cstr()?; let v = value.to_cstr()?; @@ -267,7 +308,12 @@ impl AVDict { Ok(()) } - pub fn set_int>(&mut self, key: K, value: i64, flags: F) -> Result<(), AVDictError> { + pub fn set_int>( + &mut self, + key: K, + value: i64, + flags: F, + ) -> Result<(), AVDictError> { let pm: *mut *mut _avdict::AVDict = &mut self.m; let k = key.to_cstr()?; let re = unsafe { _avdict::avdict_set_int(pm, k.as_ptr(), value, flags.to_bits()) }; @@ -306,14 +352,14 @@ impl Drop for AVDict { } } -impl TryFrom> for AVDict { +impl TryFrom> for AVDict { type Error = AVDictError; fn try_from(value: HashMap) -> Result { Self::try_from(&value) } } -impl TryFrom<&HashMap> for AVDict { +impl TryFrom<&HashMap> for AVDict { type Error = AVDictError; fn try_from(value: &HashMap) -> Result { let mut d = Self::new(); @@ -349,7 +395,14 @@ impl<'a> Iterator for AVDictItor<'a> { } self.started = true; let m = unsafe { self.d.to_raw_handle() }; - let re = unsafe { _avdict::avdict_get(m, NULLSTR.as_ptr(), self.cur as *const _avdict::AVDictEntry, AVDictFlags::IgnoreSuffix.to_bits()) }; + let re = unsafe { + _avdict::avdict_get( + m, + NULLSTR.as_ptr(), + self.cur as *const _avdict::AVDictEntry, + AVDictFlags::IgnoreSuffix.to_bits(), + ) + }; self.cur = re; if re.is_null() { return None; @@ -380,15 +433,21 @@ fn test_avdict() { d2.set("b", "ok", AVDictFlags::Multikey).unwrap(); d2.set("b", "test", AVDictFlags::Multikey).unwrap(); assert_eq!(Ok(Some(CString::new("ok").unwrap())), d2.get("b", None)); - assert_eq!(Ok(Some(vec![ - CString::new("ok").unwrap(), - CString::new("test").unwrap(), - ])), d2.get_all("b", None)); + assert_eq!( + Ok(Some(vec![ + CString::new("ok").unwrap(), + CString::new("test").unwrap(), + ])), + d2.get_all("b", None) + ); d.set_int("i", 17, None).unwrap(); assert_eq!(Ok(Some(CString::new("17").unwrap())), d.get("i", None)); d.set("c", "test", AVDictFlags::Append).unwrap(); d.set("c", "test2", AVDictFlags::Append).unwrap(); - assert_eq!(Ok(Some(CString::new("testtest2").unwrap())), d.get("c", None)); + assert_eq!( + Ok(Some(CString::new("testtest2").unwrap())), + d.get("c", None) + ); assert_eq!(3, d.len()); assert_eq!(3, d2.len()); let mut m = HashMap::new(); @@ -402,7 +461,13 @@ fn test_avdict() { let mut d4 = AVDict::new(); d4.parse_string("a=b b=c", "=", " ", None).unwrap(); assert_eq!(2, d4.len()); - assert_eq!(Ok(CString::new("a=b b=c").unwrap()), d4.get_string('=', ' ')); + assert_eq!( + Ok(CString::new("a=b b=c").unwrap()), + d4.get_string('=', ' ') + ); let mut it = d4.iter(); - assert_eq!(Some((CString::new("a").unwrap(), CString::new("b").unwrap())), it.next()); + assert_eq!( + Some((CString::new("a").unwrap(), CString::new("b").unwrap())), + it.next() + ); } diff --git a/src/data/data.rs b/src/data/data.rs index 6cc55d8..40654d3 100644 --- a/src/data/data.rs +++ b/src/data/data.rs @@ -1,8 +1,8 @@ use crate::author_name_filter::AuthorFiler; use crate::gettext; use crate::opthelper::get_helper; -use crate::pixiv_link::ToPixivID; use crate::pixiv_link::PixivID; +use crate::pixiv_link::ToPixivID; use json::JsonValue; use std::convert::TryInto; use xml::unescape; @@ -58,8 +58,10 @@ impl PixivData { if author.is_some() { let au = author.unwrap(); match get_helper().author_name_filters() { - Some(l) => { self.author = Some(l.filter(au)) } - None => { self.author = Some(String::from(author.unwrap())); } + Some(l) => self.author = Some(l.filter(au)), + None => { + self.author = Some(String::from(author.unwrap())); + } } } } @@ -71,7 +73,9 @@ impl PixivData { if description.is_some() { let re = unescape(description.unwrap()); match re { - Ok(s) => { self.description = Some(s); } + Ok(s) => { + self.description = Some(s); + } Err(s) => { println!("{} {}", gettext("Failed to unescape string:"), s.as_str()); } diff --git a/src/data/exif.rs b/src/data/exif.rs index fed4022..cab22d9 100644 --- a/src/data/exif.rs +++ b/src/data/exif.rs @@ -80,7 +80,11 @@ fn add_image_page(data: &mut ExifData, page: u16) -> Result<(), ()> { Ok(()) } -pub fn add_exifdata_to_image + ?Sized>(file_name: &S, data: &PixivData, page: u16) -> Result<(), ()> { +pub fn add_exifdata_to_image + ?Sized>( + file_name: &S, + data: &PixivData, + page: u16, +) -> Result<(), ()> { let mut f = ExifImage::new(file_name)?; let mut d = ExifData::new()?; add_image_id(&mut d, data)?; diff --git a/src/data/json.rs b/src/data/json.rs index 455d953..38312e3 100644 --- a/src/data/json.rs +++ b/src/data/json.rs @@ -8,8 +8,8 @@ use json::JsonValue; use std::collections::HashMap; use std::convert::From; use std::ffi::OsStr; -use std::fs::File; use std::fs::remove_file; +use std::fs::File; use std::io::Write; use std::path::Path; use std::sync::Arc; @@ -97,7 +97,8 @@ impl From<&PixivData> for JSONDataFile { f.add("author", p.author.as_ref().unwrap()).unwrap(); } if p.description.is_some() { - f.add("description", p.description.as_ref().unwrap()).unwrap(); + f.add("description", p.description.as_ref().unwrap()) + .unwrap(); let pd = parse_description(p.description.as_ref().unwrap()); if pd.is_some() { f.add("parsed_description", pd.unwrap()).unwrap(); diff --git a/src/data/video.rs b/src/data/video.rs index 07b46ef..e656630 100644 --- a/src/data/video.rs +++ b/src/data/video.rs @@ -17,8 +17,8 @@ pub fn get_video_metadata(data: &PixivData) -> Result { let odesc = data.description.as_ref().unwrap(); let desc = parse_description(odesc); let des = match &desc { - Some(d) => { d } - None => { odesc } + Some(d) => d, + None => odesc, }; d.set("comment", des, None)?; } diff --git a/src/download.rs b/src/download.rs index 60ec4bf..6837d56 100644 --- a/src/download.rs +++ b/src/download.rs @@ -1,5 +1,6 @@ #[cfg(feature = "avdict")] use crate::avdict::AVDict; +use crate::concat_pixiv_downloader_error; use crate::data::data::PixivData; #[cfg(feature = "exif")] use crate::data::exif::add_exifdata_to_image; @@ -10,14 +11,13 @@ use crate::downloader::Downloader; use crate::downloader::DownloaderResult; use crate::downloader::LocalFile; use crate::error::PixivDownloaderError; -use crate::concat_pixiv_downloader_error; use crate::ext::try_err::TryErr; use crate::gettext; use crate::opthelper::get_helper; use crate::pixiv_link::PixivID; use crate::pixiv_web::PixivWebClient; #[cfg(feature = "ugoira")] -use crate::ugoira::{UgoiraFrames, convert_ugoira_to_mp4}; +use crate::ugoira::{convert_ugoira_to_mp4, UgoiraFrames}; use crate::utils::ask_need_overwrite; use crate::utils::get_file_name_from_url; use crate::webclient::WebClient; @@ -51,7 +51,11 @@ impl Main { let r = if r.is_ok() { 0 } else { - println!("{} {}", gettext("Failed to download artwork:"), r.unwrap_err()); + println!( + "{} {}", + gettext("Failed to download artwork:"), + r.unwrap_err() + ); 1 }; if r != 0 { @@ -69,11 +73,26 @@ impl Main { /// * `progress_bars` - Multiple progress bars /// * `datas` - The artwork's data /// * `base` - The directory of the target - pub async fn download_artwork_link(link: L, np: u16, progress_bars: Option>, datas: Arc, base: Arc) -> Result<(), PixivDownloaderError> { - let file_name = get_file_name_from_url(link.clone()).try_err(format!("{} {}", gettext("Failed to get file name from url:"), link.as_str()))?; + pub async fn download_artwork_link( + link: L, + np: u16, + progress_bars: Option>, + datas: Arc, + base: Arc, + ) -> Result<(), PixivDownloaderError> { + let file_name = get_file_name_from_url(link.clone()).try_err(format!( + "{} {}", + gettext("Failed to get file name from url:"), + link.as_str() + ))?; let file_name = base.join(file_name); let helper = get_helper(); - let downloader = Downloader::::new(link, json::object!{"referer": "https://www.pixiv.net/"}, Some(&file_name), helper.overwrite())?; + let downloader = Downloader::::new( + link, + json::object! {"referer": "https://www.pixiv.net/"}, + Some(&file_name), + helper.overwrite(), + )?; match downloader { DownloaderResult::Ok(d) => { d.handle_options(&helper, progress_bars); @@ -110,7 +129,11 @@ impl Main { Ok(()) } - pub async fn download_artwork(&self, pw: Arc, id: u64) -> Result<(), PixivDownloaderError> { + pub async fn download_artwork( + &self, + pw: Arc, + id: u64, + ) -> Result<(), PixivDownloaderError> { let mut re = None; let pages; let mut ajax_ver = true; @@ -136,7 +159,9 @@ impl Main { pages_data = pw.get_illust_pages(id).await; } if pages > 1 && pages_data.is_none() { - return Err(PixivDownloaderError::from(gettext("Failed to get pages' data."))); + return Err(PixivDownloaderError::from(gettext( + "Failed to get pages' data.", + ))); } let base = Arc::new(PathBuf::from(".")); let json_file = base.join(format!("{}.json", id)); @@ -149,7 +174,9 @@ impl Main { let datas = Arc::new(datas); let json_data = JSONDataFile::from(Arc::clone(&datas)); if !json_data.save(&json_file) { - return Err(PixivDownloaderError::from(gettext("Failed to save metadata to JSON file."))); + return Err(PixivDownloaderError::from(gettext( + "Failed to save metadata to JSON file.", + ))); } let illust_type = if ajax_ver { (&re["illustType"]).as_i64() @@ -159,23 +186,40 @@ impl Main { if illust_type.is_some() { let illust_type = illust_type.unwrap(); match illust_type { - 0 => { } + 0 => {} 2 => { - let ugoira_data = pw.get_ugoira(id).await.try_err(gettext("Failed to get ugoira's data."))?; - let src = (&ugoira_data["originalSrc"]).as_str().try_err(gettext("Can not find source link for ugoira."))?; - let file_name = get_file_name_from_url(src).try_err(format!("{} {}", gettext("Failed to get file name from url:"), src))?; + let ugoira_data = pw + .get_ugoira(id) + .await + .try_err(gettext("Failed to get ugoira's data."))?; + let src = (&ugoira_data["originalSrc"]) + .as_str() + .try_err(gettext("Can not find source link for ugoira."))?; + let file_name = get_file_name_from_url(src).try_err(format!( + "{} {}", + gettext("Failed to get file name from url:"), + src + ))?; let file_name = base.join(file_name); let dw = if file_name.exists() { match helper.overwrite() { - Some(overwrite) => { overwrite } - None => { ask_need_overwrite(file_name.to_str().unwrap()) } + Some(overwrite) => overwrite, + None => ask_need_overwrite(file_name.to_str().unwrap()), } } else { true }; if dw { - let r = pw.download_image(src).await.try_err(format!("{} {}", gettext("Failed to download ugoira:"), src))?; - WebClient::download_stream(&file_name, r).try_err(format!("{} {}", gettext("Failed to download ugoira:"), src))?; + let r = pw.download_image(src).await.try_err(format!( + "{} {}", + gettext("Failed to download ugoira:"), + src + ))?; + WebClient::download_stream(&file_name, r).try_err(format!( + "{} {}", + gettext("Failed to download ugoira:"), + src + ))?; println!( "{} {} -> {}", gettext("Downloaded ugoira:"), @@ -186,21 +230,44 @@ impl Main { #[cfg(feature = "ugoira")] { let metadata = match get_video_metadata(Arc::clone(&datas).as_ref()) { - Ok(m) => { m } + Ok(m) => m, Err(e) => { - println!("{} {}", gettext("Warning: Failed to generate video's metadata:"), e); + println!( + "{} {}", + gettext("Warning: Failed to generate video's metadata:"), + e + ); AVDict::new() } }; let options = AVDict::new(); - let frames = UgoiraFrames::from_json(&ugoira_data["frames"])?; + let frames = UgoiraFrames::from_json(&ugoira_data["frames"])?; let output_file_name = base.join(format!("{}.mp4", id)); - convert_ugoira_to_mp4(&file_name, &output_file_name, &frames, 60f32, &options, &metadata)?; - println!("{}", gettext("Converted -> ").replace("", file_name.to_str().unwrap_or("(null)")).replace("", output_file_name.to_str().unwrap_or("(null)")).as_str()); + convert_ugoira_to_mp4( + &file_name, + &output_file_name, + &frames, + 60f32, + &options, + &metadata, + )?; + println!( + "{}", + gettext("Converted -> ") + .replace("", file_name.to_str().unwrap_or("(null)")) + .replace("", output_file_name.to_str().unwrap_or("(null)")) + .as_str() + ); } return Ok(()); } - _ => { println!("{} {}", gettext("Warning: Unknown illust type:"), illust_type) } + _ => { + println!( + "{} {}", + gettext("Warning: Unknown illust type:"), + illust_type + ) + } } } else { println!("{}", gettext("Warning: Failed to get illust's type.")); @@ -214,32 +281,44 @@ impl Main { for page in pages_data.members() { let url = page["urls"]["original"].as_str(); if url.is_none() { - concat_pixiv_downloader_error!(re, Err::<(), &str>(gettext("Failed to get original picture's link."))); + concat_pixiv_downloader_error!( + re, + Err::<(), &str>(gettext("Failed to get original picture's link.")) + ); continue; } - let f = tokio::spawn(Self::download_artwork_link(url.unwrap().to_owned(), np, Some(Arc::clone(&progress_bars)), Arc::clone(&datas), Arc::clone(&base))); + let f = tokio::spawn(Self::download_artwork_link( + url.unwrap().to_owned(), + np, + Some(Arc::clone(&progress_bars)), + Arc::clone(&datas), + Arc::clone(&base), + )); tasks.push(f); np += 1; } for task in tasks { let r = task.await; let r = match r { - Ok(r) => { r } - Err(e) => { - Err(PixivDownloaderError::from(e)) - } + Ok(r) => r, + Err(e) => Err(PixivDownloaderError::from(e)), }; concat_pixiv_downloader_error!(re, r); } return re; - } - else if pages_data.is_some() { + } else if pages_data.is_some() { #[cfg(feature = "exif")] let mut np = 0u16; let pages_data = pages_data.as_ref().unwrap(); for page in pages_data.members() { - let link = page["urls"]["original"].as_str().try_err(gettext("Failed to get original picture's link."))?; - let file_name = get_file_name_from_url(link).try_err(format!("{} {}", gettext("Failed to get file name from url:"), link))?; + let link = page["urls"]["original"] + .as_str() + .try_err(gettext("Failed to get original picture's link."))?; + let file_name = get_file_name_from_url(link).try_err(format!( + "{} {}", + gettext("Failed to get file name from url:"), + link + ))?; let file_name = base.join(file_name); if file_name.exists() { match helper.overwrite() { @@ -268,8 +347,16 @@ impl Main { } } } - let r = pw.download_image(link).await.try_err(format!("{} {}", gettext("Failed to download image:"), link))?; - WebClient::download_stream(&file_name, r).try_err(format!("{} {}", gettext("Failed to download image:"), link))?; + let r = pw.download_image(link).await.try_err(format!( + "{} {}", + gettext("Failed to download image:"), + link + ))?; + WebClient::download_stream(&file_name, r).try_err(format!( + "{} {}", + gettext("Failed to download image:"), + link + ))?; println!( "{} {} -> {}", gettext("Downloaded image:"), @@ -293,17 +380,18 @@ impl Main { (&re["urls"]["original"]).as_str() } else { (&re["illust"][format!("{}", id)]["urls"]["original"]).as_str() - }.try_err(gettext("Failed to get original picture's link."))?; - let file_name = get_file_name_from_url(link).try_err(format!("{} {}", gettext("Failed to get file name from url:"), link))?; + } + .try_err(gettext("Failed to get original picture's link."))?; + let file_name = get_file_name_from_url(link).try_err(format!( + "{} {}", + gettext("Failed to get file name from url:"), + link + ))?; let file_name = base.join(file_name); if file_name.exists() { let overwrite = match helper.overwrite() { - Some(overwrite) => { - overwrite - } - None => { - ask_need_overwrite(file_name.to_str().unwrap()) - } + Some(overwrite) => overwrite, + None => ask_need_overwrite(file_name.to_str().unwrap()), }; if !overwrite { #[cfg(feature = "exif")] @@ -319,8 +407,16 @@ impl Main { return Ok(()); } } - let r = pw.download_image(link).await.try_err(format!("{} {}", gettext("Failed to download image:"), link))?; - WebClient::download_stream(&file_name, r).try_err(format!("{} {}", gettext("Failed to download image:"), link))?; + let r = pw.download_image(link).await.try_err(format!( + "{} {}", + gettext("Failed to download image:"), + link + ))?; + WebClient::download_stream(&file_name, r).try_err(format!( + "{} {}", + gettext("Failed to download image:"), + link + ))?; println!( "{} {} -> {}", gettext("Downloaded image:"), diff --git a/src/downloader/downloader.rs b/src/downloader/downloader.rs index 8d19e87..15c08d8 100644 --- a/src/downloader/downloader.rs +++ b/src/downloader/downloader.rs @@ -1,9 +1,9 @@ -use super::pd_file::PdFile; -use super::pd_file::PdFileResult; use super::enums::DownloaderResult; use super::enums::DownloaderStatus; use super::error::DownloaderError; use super::local_file::LocalFile; +use super::pd_file::PdFile; +use super::pd_file::PdFileResult; use super::tasks::check_tasks; use crate::ext::atomic::AtomicQuick; use crate::ext::io::ClearFile; @@ -13,11 +13,11 @@ use crate::gettext; use crate::opthelper::OptHelper; use crate::utils::ask_need_overwrite; use crate::utils::get_file_name_from_url; -use crate::webclient::WebClient; use crate::webclient::ToHeaders; +use crate::webclient::WebClient; +use indicatif::MultiProgress; use indicatif::ProgressBar; use indicatif::ProgressStyle; -use indicatif::MultiProgress; use reqwest::IntoUrl; use std::borrow::Cow; use std::collections::HashMap; @@ -30,9 +30,9 @@ use std::io::Write; use std::ops::Deref; use std::ops::DerefMut; use std::path::Path; +use std::sync::atomic::AtomicBool; use std::sync::Arc; use std::sync::RwLock; -use std::sync::atomic::AtomicBool; use std::time::Duration; use tokio::task::JoinHandle; use url::Url; @@ -41,7 +41,7 @@ use url::Url; pub trait GetTargetFileName { /// Get the target file name. /// The target file name just used in the message in progress bar. - /// + /// /// If is unknown, return [None] is fine. fn get_target_file_name(&self) -> Option { None @@ -79,44 +79,47 @@ impl DownloaderInternal { /// * `header` - HTTP headers /// * `path` - The path to store downloaded file. /// * `overwrite` - Whether to overwrite file - pub fn new + ?Sized>(url: U, headers: H, path: Option<&P>, overwrite: Option) -> Result, DownloaderError> { + pub fn new + ?Sized>( + url: U, + headers: H, + path: Option<&P>, + overwrite: Option, + ) -> Result, DownloaderError> { let h = match headers.to_headers() { - Some(h) => { h } - None => { HashMap::new() } + Some(h) => h, + None => HashMap::new(), }; let mut already_exists = false; let pd_file = match path { Some(p) => { let p = p.as_ref(); match PdFile::open(p)? { - PdFileResult::TargetExisted => { - match overwrite { - Some(overwrite) => { - if !overwrite { - return Ok(DownloaderResult::Canceled); - } else { - remove_file(p)?; - PdFile::new() - } - } - None => { - if !ask_need_overwrite(p.to_str().unwrap()) { - return Ok(DownloaderResult::Canceled); - } else { - remove_file(p)?; - PdFile::new() - } + PdFileResult::TargetExisted => match overwrite { + Some(overwrite) => { + if !overwrite { + return Ok(DownloaderResult::Canceled); + } else { + remove_file(p)?; + PdFile::new() } } - } - PdFileResult::Ok(p) => { p } + None => { + if !ask_need_overwrite(p.to_str().unwrap()) { + return Ok(DownloaderResult::Canceled); + } else { + remove_file(p)?; + PdFile::new() + } + } + }, + PdFileResult::Ok(p) => p, PdFileResult::ExistedOk(p) => { already_exists = true; p } } } - None => { PdFile::new() } + None => PdFile::new(), }; let file = match path { Some(p) => { @@ -126,7 +129,7 @@ impl DownloaderInternal { Some(LocalFile::create(p)?) } } - None => { None } + None => None, }; Ok(DownloaderResult::Ok(Self { client: Arc::new(WebClient::default()), @@ -143,7 +146,7 @@ impl DownloaderInternal { } } -impl DownloaderInternal { +impl DownloaderInternal { /// Add a new task to tasks /// * `task` - Task pub fn add_task(&self, task: JoinHandle>) { @@ -153,7 +156,7 @@ impl DownloaderI /// Clear all datas in file pub fn clear_file(&self) -> std::io::Result<()> { match self.file.get_mut().deref_mut() { - Some(f) => { f.clear_file()? } + Some(f) => f.clear_file()?, None => {} }; Ok(()) @@ -174,7 +177,7 @@ impl DownloaderI Some(bars) => { bar = bars.add(bar); } - None => { } + None => {} } self.progress_bar.qstore(true); self.progress.get_mut().replace(bar); @@ -190,8 +193,8 @@ impl DownloaderI /// Finishes the progress bar and sets a message pub fn finish_progress_bar_with_message(&self, msg: impl Into>) { match self.progress.get_ref().deref() { - Some(p) => { p.finish_with_message(msg) } - None => { } + Some(p) => p.finish_with_message(msg), + None => {} } } @@ -199,7 +202,8 @@ impl DownloaderI /// Get the file name from url. /// If not available, use `(Unknown)` pub fn get_file_name(&self) -> String { - get_file_name_from_url(self.url.deref().clone()).unwrap_or(String::from(gettext("(Unknown)"))) + get_file_name_from_url(self.url.deref().clone()) + .unwrap_or(String::from(gettext("(Unknown)"))) } #[inline] @@ -212,8 +216,8 @@ impl DownloaderI /// Get the target file name pub fn get_target_file_name(&self) -> Option { match self.file.get_ref().deref() { - Some(f) => { f.get_target_file_name() } - None => { None } + Some(f) => f.get_target_file_name(), + None => None, } } @@ -221,8 +225,8 @@ impl DownloaderI /// Advances the position of the progress bar by `delta` pub fn inc_progress_bar(&self, delta: u64) { match self.progress.get_ref().deref() { - Some(p) => { p.inc(delta) } - None => { } + Some(p) => p.inc(delta), + None => {} } } @@ -258,8 +262,8 @@ impl DownloaderI /// * `data` - Data pub fn seek(&self, pos: SeekFrom) -> Result { match self.file.get_mut().deref_mut() { - Some(f) => { Ok(f.seek(pos)?) } - None => { Ok(0) } + Some(f) => Ok(f.seek(pos)?), + None => Ok(0), } } @@ -279,8 +283,8 @@ impl DownloaderI /// Sets the length of the progress bar pub fn set_progress_bar_length(&self, length: u64) { match self.progress.get_ref().deref() { - Some(p) => { p.set_length(length) } - None => { } + Some(p) => p.set_length(length), + None => {} } } @@ -288,8 +292,8 @@ impl DownloaderI /// Sets the position of the progress bar pub fn set_progress_bar_position(&self, pos: u64) { match self.progress.get_ref().deref() { - Some(p) => { p.set_position(pos) } - None => { } + Some(p) => p.set_position(pos), + None => {} } } @@ -297,8 +301,8 @@ impl DownloaderI /// Sets the current message of the progress bar pub fn set_progress_bar_message(&self, msg: impl Into>) { match self.progress.get_ref().deref() { - Some(p) => { p.set_message(msg) } - None => { } + Some(p) => p.set_message(msg), + None => {} } } @@ -306,11 +310,11 @@ impl DownloaderI /// * `data` - Data pub fn write(&self, data: &[u8]) -> Result<(), DownloaderError> { match self.file.get_mut().deref_mut() { - Some(f) => { f.write_all(data)? } + Some(f) => f.write_all(data)?, None => {} } Ok(()) - } + } } /// A file downloader @@ -325,13 +329,20 @@ impl Downloader { /// * `header` - HTTP headers /// * `path` - The path to store downloaded file. /// * `overwrite` - Whether to overwrite file - pub fn new + ?Sized>(url: U, headers: H, path: Option<&P>, overwrite: Option) -> Result, DownloaderError> { - Ok(match DownloaderInternal::::new(url, headers, path, overwrite)? { - DownloaderResult::Ok(d) => { - DownloaderResult::Ok(Self { downloader: Arc::new(d) }) - } - DownloaderResult::Canceled => { DownloaderResult::Canceled } - }) + pub fn new + ?Sized>( + url: U, + headers: H, + path: Option<&P>, + overwrite: Option, + ) -> Result, DownloaderError> { + Ok( + match DownloaderInternal::::new(url, headers, path, overwrite)? { + DownloaderResult::Ok(d) => DownloaderResult::Ok(Self { + downloader: Arc::new(d), + }), + DownloaderResult::Canceled => DownloaderResult::Canceled, + }, + ) } } @@ -346,9 +357,9 @@ macro_rules! define_downloader_fn { } } -impl Downloader { +impl Downloader { /// Start download if download not started. - /// + /// /// Returns the status of the Downloader pub fn download(&self) -> DownloaderStatus { if !self.is_created() { @@ -389,20 +400,41 @@ impl D pub fn handle_options(&self, helper: &OptHelper, mults: Option>) { if helper.use_progress_bar() { let style = ProgressStyle::default_bar() - .template(helper.progress_bar_template().as_ref()).unwrap() + .template(helper.progress_bar_template().as_ref()) + .unwrap() .progress_chars("#>-"); match mults { - Some(v) => { self.enable_progress_bar(style, Some(&v)); } - None => { self.enable_progress_bar(style, None); } + Some(v) => { + self.enable_progress_bar(style, Some(&v)); + } + None => { + self.enable_progress_bar(style, None); + } } } else { self.disable_progress_bar(); } } - define_downloader_fn!(is_created, bool, "Returns true if the downloader is created just now."); - define_downloader_fn!(is_downloading, bool, "Returns true if the downloader is downloading now."); - define_downloader_fn!(is_multi_threads, bool, "Returns true if is multiple thread mode."); - define_downloader_fn!(is_downloaded, bool, "Returns true if the downloader is downloaded complete."); + define_downloader_fn!( + is_created, + bool, + "Returns true if the downloader is created just now." + ); + define_downloader_fn!( + is_downloading, + bool, + "Returns true if the downloader is downloading now." + ); + define_downloader_fn!( + is_multi_threads, + bool, + "Returns true if is multiple thread mode." + ); + define_downloader_fn!( + is_downloaded, + bool, + "Returns true if the downloader is downloaded complete." + ); } #[tokio::test(flavor = "multi_thread", worker_threads = 4)] @@ -414,7 +446,13 @@ async fn test_downloader() { } let url = "https://i.pximg.net/img-original/img/2022/06/12/23/49/43/99014872_p0.png"; let pb = p.join("99014872_p0.png"); - let downloader = Downloader::::new(url, json::object!{"referer": "https://www.pixiv.net/"}, Some(&pb), Some(true)).unwrap(); + let downloader = Downloader::::new( + url, + json::object! {"referer": "https://www.pixiv.net/"}, + Some(&pb), + Some(true), + ) + .unwrap(); match downloader { DownloaderResult::Ok(v) => { assert_eq!(v.is_created(), true); @@ -423,6 +461,8 @@ async fn test_downloader() { v.join().await.unwrap(); assert_eq!(v.is_downloaded(), true); } - DownloaderResult::Canceled => { panic!("This should not happened.") } + DownloaderResult::Canceled => { + panic!("This should not happened.") + } } } diff --git a/src/downloader/error.rs b/src/downloader/error.rs index d3343ef..80efae2 100644 --- a/src/downloader/error.rs +++ b/src/downloader/error.rs @@ -1,9 +1,9 @@ use crate::downloader::pd_file::PdFileError; use crate::gettext; use http::status::StatusCode; -use tokio::time::error::Elapsed; -use tokio::task::JoinError; use std::fmt::Display; +use tokio::task::JoinError; +use tokio::time::error::Elapsed; /// File downloader's error #[derive(Debug, derive_more::From)] @@ -39,19 +39,13 @@ impl Display for DownloaderError { f.write_str(gettext("Errors occured when operating files: "))?; e.fmt(f) } - Self::String(e) => { - f.write_str(e) - } + Self::String(e) => f.write_str(e), Self::ErrorStatusCode(e) => { f.write_str("HTTP ERROR ")?; e.fmt(f) } - Self::Timeout(e) => { - e.fmt(f) - } - Self::JoinError(e) => { - e.fmt(f) - } + Self::Timeout(e) => e.fmt(f), + Self::JoinError(e) => e.fmt(f), } } } diff --git a/src/downloader/local_file.rs b/src/downloader/local_file.rs index f3a314a..24535b5 100644 --- a/src/downloader/local_file.rs +++ b/src/downloader/local_file.rs @@ -1,7 +1,7 @@ -use crate::ext::io::ClearFile; use super::downloader::GetTargetFileName; -use std::fs::File; +use crate::ext::io::ClearFile; use std::fs::remove_file; +use std::fs::File; use std::io::Seek; use std::io::Write; use std::ops::Deref; @@ -60,8 +60,8 @@ impl GetTargetFileName for LocalFile { #[inline] fn get_target_file_name(&self) -> Option { match self.path.to_str() { - Some(s) => { Some(String::from(s)) } - None => { None } + Some(s) => Some(String::from(s)), + None => None, } } } diff --git a/src/downloader/mod.rs b/src/downloader/mod.rs index 61aeac8..4c57590 100644 --- a/src/downloader/mod.rs +++ b/src/downloader/mod.rs @@ -11,6 +11,6 @@ pub mod pd_file; /// Deal download tasks pub mod tasks; pub use downloader::Downloader; -pub use error::DownloaderError; pub use enums::DownloaderResult; +pub use error::DownloaderError; pub use local_file::LocalFile; diff --git a/src/downloader/pd_file/enums.rs b/src/downloader/pd_file/enums.rs index 08ad67f..a5c979a 100644 --- a/src/downloader/pd_file/enums.rs +++ b/src/downloader/pd_file/enums.rs @@ -97,9 +97,9 @@ impl PdFilePartStatus { impl Display for PdFilePartStatus { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::Waited => { f.write_str("PdFilePartStatus::Waited") } - Self::Downloading => { f.write_str("PdFilePartStatus::Downloading") } - Self::Downloaded => { f.write_str("PdFilePartStatus::Downloaded") } + Self::Waited => f.write_str("PdFilePartStatus::Waited"), + Self::Downloading => f.write_str("PdFilePartStatus::Downloading"), + Self::Downloaded => f.write_str("PdFilePartStatus::Downloaded"), } } } diff --git a/src/downloader/pd_file/error.rs b/src/downloader/pd_file/error.rs index 76bce55..7538ae7 100644 --- a/src/downloader/pd_file/error.rs +++ b/src/downloader/pd_file/error.rs @@ -30,7 +30,9 @@ impl Display for PdFileError { f.write_str(gettext("Invalid pd file."))?; } Self::Unsupported => { - f.write_str(gettext("The pd file is newer version, please update the program."))?; + f.write_str(gettext( + "The pd file is newer version, please update the program.", + ))?; } Self::Utf8Error(e) => { f.write_str(gettext("Failed to decode UTF-8: "))?; diff --git a/src/downloader/pd_file/file.rs b/src/downloader/pd_file/file.rs index bfb8551..53918b4 100644 --- a/src/downloader/pd_file/file.rs +++ b/src/downloader/pd_file/file.rs @@ -1,7 +1,7 @@ -use crate::downloader::pd_file::error::PdFileError; use crate::downloader::pd_file::enums::PdFileResult; use crate::downloader::pd_file::enums::PdFileStatus; use crate::downloader::pd_file::enums::PdFileType; +use crate::downloader::pd_file::error::PdFileError; use crate::downloader::pd_file::part_status::PdFilePartStatus; use crate::downloader::pd_file::version::PdFileVersion; use crate::ext::atomic::AtomicQuick; @@ -14,12 +14,12 @@ use crate::ext::try_err::TryErr2; use crate::gettext; use int_enum::IntEnum; use std::convert::AsRef; -use std::fs::File; #[cfg(test)] use std::fs::create_dir; #[cfg(test)] use std::fs::metadata; use std::fs::remove_file; +use std::fs::File; use std::io::Read; use std::io::Seek; use std::io::SeekFrom; @@ -27,11 +27,11 @@ use std::io::Write; use std::ops::Drop; use std::path::Path; use std::path::PathBuf; -use std::sync::Arc; -use std::sync::RwLock; use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicU32; use std::sync::atomic::AtomicU64; +use std::sync::Arc; +use std::sync::RwLock; lazy_static! { #[doc(hidden)] @@ -40,7 +40,7 @@ lazy_static! { /// The offset of the status in pd file const STATUS_OFFSET: SeekFrom = SeekFrom::Start(10); -/// The offset of the file_size in pd file +/// The offset of the file_size in pd file const FILE_SIZE_OFFSET: SeekFrom = SeekFrom::Start(12); /// The offset of the downloaded_file_size in pd file const DOWNLOADED_FILE_SIZE_OFFSET: SeekFrom = SeekFrom::Start(20); @@ -137,7 +137,9 @@ impl PdFile { pub fn force_close(&self) { let mut f = self.file.get_mut(); match f.as_mut() { - Some(_) => { f.take(); } + Some(_) => { + f.take(); + } None => {} } } @@ -167,7 +169,7 @@ impl PdFile { /// Increase the downloaded file size. /// * `size` - The file size want to added. - /// + /// /// Returns the downloaded file size pub fn inc(&self, size: u64) -> Result { let mut downloaded_size = self.downloaded_file_size.qload(); @@ -219,7 +221,10 @@ impl PdFile { pub fn open + ?Sized>(path: &P) -> Result { let p = path.as_ref(); let mut pb = PathBuf::from(p); - let mut file_name = pb.file_name().try_err(gettext("Path need have a file name."))?.to_owned(); + let mut file_name = pb + .file_name() + .try_err(gettext("Path need have a file name."))? + .to_owned(); file_name.push(".pd"); pb.set_file_name(&file_name); if p.exists() { @@ -235,14 +240,19 @@ impl PdFile { } else { let f = PdFile::new(); f.open_with_create_file(&pb)?; - f.set_file_name(p.file_name().try_err(gettext("Path need have a file name."))?.to_str().unwrap_or("(null)"))?; + f.set_file_name( + p.file_name() + .try_err(gettext("Path need have a file name."))? + .to_str() + .unwrap_or("(null)"), + )?; Ok(PdFileResult::Ok(f)) } } /// Create a new [PdFile] instance from the pd file. /// * `path` - The path to the pd file. - /// + /// /// Returns errors or a new instance. pub fn read_from_file + ?Sized>(path: &P) -> Result { let p = path.as_ref(); @@ -291,7 +301,10 @@ impl PdFile { /// Create a new file and prepare to write data to it. /// If file alreay exists, will remove it first. /// * `path` - The path to the pd file. - pub fn open_with_create_file + ?Sized>(&self, path: &P) -> Result<(), PdFileError> { + pub fn open_with_create_file + ?Sized>( + &self, + path: &P, + ) -> Result<(), PdFileError> { let p = path.as_ref(); if p.exists() { remove_file(p)?; @@ -313,7 +326,7 @@ impl PdFile { } Ok(()) } - None => { Ok(()) } + None => Ok(()), } } @@ -371,7 +384,7 @@ impl PdFile { /// Set the target size of the file. If unknown, set this to 0. /// * `file_size` - The target size of the file. - /// + /// /// This will also set the status to downloading. pub fn set_file_size(&self, file_size: u64) -> Result<(), PdFileError> { self.file_size.qstore(file_size); @@ -402,7 +415,10 @@ impl PdFile { f.seek(SeekFrom::Start(0))?; f.write_all(&MAGIC_WORDS)?; self.version.write_to(&mut f)?; - let file_name = self.file_name.get_ref().try_err2(gettext("File name is not set."))?; + let file_name = self + .file_name + .get_ref() + .try_err2(gettext("File name is not set."))?; let file_name = file_name.as_bytes(); f.write_le_u32(file_name.len() as u32)?; f.write_le_u8(self.status.get_ref().int_value())?; diff --git a/src/downloader/pd_file/part_status.rs b/src/downloader/pd_file/part_status.rs index 610d2ac..65f8b93 100644 --- a/src/downloader/pd_file/part_status.rs +++ b/src/downloader/pd_file/part_status.rs @@ -22,13 +22,20 @@ pub struct OutOfBoundsError { impl OutOfBoundsError { pub fn new + ?Sized>(t: &S, v: T) -> Self { - Self { t: String::from(t.as_ref()), v: v } + Self { + t: String::from(t.as_ref()), + v: v, + } } } impl Display for OutOfBoundsError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!("Failed to set type {} with value {}", self.t.as_str(), self.v)) + f.write_fmt(format_args!( + "Failed to set type {} with value {}", + self.t.as_str(), + self.v + )) } } @@ -43,7 +50,11 @@ struct PdFilePartStatusInternal { impl Debug for PdFilePartStatusInternal { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!("{{ status: {:?}, downloaded_size: {:?} }}", self.status(), self.downloaded_size())) + f.write_fmt(format_args!( + "{{ status: {:?}, downloaded_size: {:?} }}", + self.status(), + self.downloaded_size() + )) } } @@ -61,7 +72,9 @@ impl PdFilePartStatus { let mut status = PdFilePartStatusInternal::new(); status.set_status(PdFilePartStatus2::Waited); status.set_downloaded_size(0); - Self { status: RwLock::new(status) } + Self { + status: RwLock::new(status), + } } #[inline] @@ -79,20 +92,19 @@ impl PdFilePartStatus { /// Set the new downloaded size pub fn set_downloaded_size(&self, new_size: u32) -> Result<(), PdFileError> { match self.status.get_mut().set_downloaded_size_checked(new_size) { - Ok(_) => { Ok(()) } - Err(_) => { - Err(PdFileError::from(OutOfBoundsError::new("u32", new_size))) - } + Ok(_) => Ok(()), + Err(_) => Err(PdFileError::from(OutOfBoundsError::new("u32", new_size))), } } /// Set the status of this part pub fn set_status(&self, status: PdFilePartStatus2) -> Result<(), PdFileError> { match self.status.get_mut().set_status_checked(status) { - Ok(_) => { Ok(()) } - Err(_) => { - Err(PdFileError::from(OutOfBoundsError::new("PdFilePartStatus", status))) - } + Ok(_) => Ok(()), + Err(_) => Err(PdFileError::from(OutOfBoundsError::new( + "PdFilePartStatus", + status, + ))), } } @@ -117,11 +129,14 @@ impl PdFilePartStatus { /// Create a new instance of the [PdFilePartStatus] from bytes. /// * `bytes` - The data /// * `offset` - The offset of the needed data - /// + /// /// Returns a new instance if succeed otherwise a Error because the data is less than 4 bytes. /// # Panics /// Will panic if unwanted error occured - pub fn from_bytes + ?Sized>(bytes: &T, offset: usize) -> Result { + pub fn from_bytes + ?Sized>( + bytes: &T, + offset: usize, + ) -> Result { let value = bytes.as_ref(); if (value.len() - offset) < 4 { Err(gettext("At least 4 bytes is needed."))?; @@ -135,7 +150,9 @@ impl PdFilePartStatus { ds += (value[offset + 2] as u32) * 0x40_00; ds += (value[offset + 3] as u32) * 0x40_00_00; status.set_downloaded_size(ds); - Ok(Self { status: RwLock::new(status) }) + Ok(Self { + status: RwLock::new(status), + }) } /// Get bytes @@ -153,7 +170,7 @@ impl PdFilePartStatus { /// Create a new instance of the [PdFilePartStatus] from reader /// * `reader` - The reader which implement the [Read] trait - /// + /// /// Returns Error or [PdFilePartStatus] instance. pub fn read_from(reader: &mut R) -> Result { let mut buf = [0u8; 4]; @@ -163,7 +180,7 @@ impl PdFilePartStatus { /// Write version bytes to writer. /// * `writer` - The writer which implement the [Write] trait - /// + /// /// Returns io Result. pub fn write_to(&self, writer: &mut W) -> std::io::Result<()> { writer.write_all(&self.to_bytes()) diff --git a/src/downloader/pd_file/version.rs b/src/downloader/pd_file/version.rs index 11781fa..23ee416 100644 --- a/src/downloader/pd_file/version.rs +++ b/src/downloader/pd_file/version.rs @@ -27,7 +27,7 @@ impl PdFileVersion { /// Create a new instance of the [PdFileVersion] from bytes. /// * `bytes` - The data /// * `offset` - The offset of the needed data - /// + /// /// Returns a new instance if succeed otherwise a Error because the data is less than 2 bytes. pub fn from_bytes + ?Sized>(bytes: &T, offset: usize) -> Result { let value = bytes.as_ref(); @@ -53,7 +53,7 @@ impl PdFileVersion { /// Create a new instance of the [PdFileVersion] from reader /// * `reader` - The reader which implement the [Read] trait - /// + /// /// Returns io Error or [PdFileVersion] instance. pub fn read_from(reader: &mut R) -> std::io::Result { let mut buf = [0u8; 2]; @@ -63,7 +63,7 @@ impl PdFileVersion { /// Write version bytes to writer. /// * `writer` - The writer which implement the [Write] trait - /// + /// /// Returns io Result. pub fn write_to(&self, writer: &mut W) -> std::io::Result<()> { writer.write_all(&self.to_bytes()) @@ -104,8 +104,8 @@ impl PartialOrd for PdFileVersion { impl + ?Sized> PartialEq for PdFileVersion { fn eq(&self, other: &T) -> bool { match Self::from_bytes(other, 0) { - Ok(v) => { v == *self } - Err(_) => { false } + Ok(v) => v == *self, + Err(_) => false, } } } @@ -115,8 +115,8 @@ impl + ?Sized> PartialEq for PdFileVersion { impl + ?Sized> PartialOrd for PdFileVersion { fn partial_cmp(&self, other: &T) -> Option { match Self::from_bytes(other, 0) { - Ok(v) => { Some(self.cmp(&v)) } - Err(_) => { None } + Ok(v) => Some(self.cmp(&v)), + Err(_) => None, } } } diff --git a/src/downloader/tasks.rs b/src/downloader/tasks.rs index c621666..f6525c2 100644 --- a/src/downloader/tasks.rs +++ b/src/downloader/tasks.rs @@ -1,23 +1,27 @@ +use super::downloader::DownloaderInternal; +use super::downloader::GetTargetFileName; +use super::error::DownloaderError; use crate::ext::io::ClearFile; use crate::ext::rw_lock::GetRwLock; use crate::ext::try_err::TryErr; use crate::gettext; -use super::downloader::GetTargetFileName; -use super::error::DownloaderError; -use super::downloader::DownloaderInternal; use futures_util::StreamExt; use http_content_range::ContentRange; use reqwest::Response; use spin_on::spin_on; -use std::ops::Deref; use std::io::Seek; use std::io::SeekFrom; use std::io::Write; +use std::ops::Deref; use std::sync::Arc; use std::time::Duration; /// Create a download tasks in simple thread mode. -pub async fn create_download_tasks_simple(d: Arc>) -> Result<(), DownloaderError> { +pub async fn create_download_tasks_simple< + T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName, +>( + d: Arc>, +) -> Result<(), DownloaderError> { let mut start = if d.pd.is_downloading() { d.pd.get_downloaded_file_size() } else { @@ -44,10 +48,18 @@ pub async fn create_download_tasks_simple { - true - } - _ => { false } + ContentRange::Unknown => true, + _ => false, } } else { true @@ -80,7 +90,11 @@ pub async fn create_download_tasks_simple\".").replace("", d.get_file_name().as_str())); + d.set_progress_bar_message( + gettext("Downloading \"\".").replace("", d.get_file_name().as_str()), + ); } handle_download(d, result).await } /// Handle download process -pub async fn handle_download(d: Arc>, re: Response) -> Result<(), DownloaderError> { +pub async fn handle_download( + d: Arc>, + re: Response, +) -> Result<(), DownloaderError> { let mut stream = re.bytes_stream(); let is_multi = d.is_multi_threads(); loop { let mut n = stream.next(); let re = tokio::time::timeout(std::time::Duration::from_secs(10), &mut n).await; match re { - Ok(s) => { - match s { - Some(data) => { - match data { - Ok(data) => { - if !is_multi { - let len = data.len() as u64; - d.pd.inc(len)?; - if d.enabled_progress_bar() { - d.inc_progress_bar(len); - } - } - d.write(&data)?; - } - Err(e) => { - if !is_multi { - d.pd.clear()?; - if d.enabled_progress_bar() { - d.set_progress_bar_position(0); - d.set_progress_bar_message(format!("{} {}", gettext("Error when downloading file:"), e)); - } - } - return Err(DownloaderError::from(e)); - } - } - } - None => { + Ok(s) => match s { + Some(data) => match data { + Ok(data) => { if !is_multi { - d.pd.complete()?; + let len = data.len() as u64; + d.pd.inc(len)?; if d.enabled_progress_bar() { - d.finish_progress_bar_with_message(format!("{} {}", gettext("Downloaded file:"), d.get_target_file_name().unwrap_or(String::from("(unknown)")))); + d.inc_progress_bar(len); } } - break; + d.write(&data)?; } + Err(e) => { + if !is_multi { + d.pd.clear()?; + if d.enabled_progress_bar() { + d.set_progress_bar_position(0); + d.set_progress_bar_message(format!( + "{} {}", + gettext("Error when downloading file:"), + e + )); + } + } + return Err(DownloaderError::from(e)); + } + }, + None => { + if !is_multi { + d.pd.complete()?; + if d.enabled_progress_bar() { + d.finish_progress_bar_with_message(format!( + "{} {}", + gettext("Downloaded file:"), + d.get_target_file_name() + .unwrap_or(String::from("(unknown)")) + )); + } + } + break; } - } + }, Err(e) => { if !is_multi { d.pd.clear()?; if d.enabled_progress_bar() { d.set_progress_bar_position(0); - d.set_progress_bar_message(format!("{} {}", gettext("Error when downloading file:"), e)); + d.set_progress_bar_message(format!( + "{} {}", + gettext("Error when downloading file:"), + e + )); } } return Err(DownloaderError::from(e)); @@ -165,7 +193,11 @@ pub async fn handle_download(d: Arc>) -> Result<(), DownloaderError> { +pub async fn check_tasks< + T: Seek + Write + Send + Sync + ClearFile + GetTargetFileName + 'static, +>( + d: Arc>, +) -> Result<(), DownloaderError> { if !d.is_multi_threads() { let task = tokio::spawn(create_download_tasks_simple(Arc::clone(&d))); d.add_task(task); diff --git a/src/error.rs b/src/error.rs index 3778b46..2dcf5f8 100644 --- a/src/error.rs +++ b/src/error.rs @@ -22,21 +22,17 @@ impl From<&str> for PixivDownloaderError { macro_rules! concat_pixiv_downloader_error { ($exp1:expr, $exp2:expr) => { $exp1 = match $exp1 { - Ok(x) => { - match $exp2 { - Ok(_) => { Ok(x) } - Err(e) => { Err(PixivDownloaderError::from(e)) } + Ok(x) => match $exp2 { + Ok(_) => Ok(x), + Err(e) => Err(PixivDownloaderError::from(e)), + }, + Err(e) => match $exp2 { + Ok(_) => Err(e), + Err(e2) => { + println!("{}", e); + Err(PixivDownloaderError::from(e2)) } - } - Err(e) => { - match $exp2 { - Ok(_) => { Err(e) } - Err(e2) => { - println!("{}", e); - Err(PixivDownloaderError::from(e2)) - } - } - } + }, } - } + }; } diff --git a/src/exif.rs b/src/exif.rs index a2b746b..e2d6524 100644 --- a/src/exif.rs +++ b/src/exif.rs @@ -528,7 +528,11 @@ impl BorrowMut for ExifData { impl Deref for ExifData { type Target = ExifDataRef; fn deref(&self) -> &Self::Target { - unsafe { ExifDataRef::from_const_handle(_exif::exif_data_get_ref(self.to_raw_handle()) as *const ExifDataRef) } + unsafe { + ExifDataRef::from_const_handle( + _exif::exif_data_get_ref(self.to_raw_handle()) as *const ExifDataRef + ) + } } } @@ -717,7 +721,7 @@ impl ExifImage { } /// Write metadata back to the image. - /// + /// /// All existing metadata sections in the image are either created, replaced, or erased. /// If values for a given metadata type have been assigned, a section for that metadata type will either be created or replaced. /// If no values have been assigned to a given metadata type, any exists section for that metadata type will be removed from the image. diff --git a/src/ext/atomic.rs b/src/ext/atomic.rs index 04dbc43..683c602 100644 --- a/src/ext/atomic.rs +++ b/src/ext/atomic.rs @@ -26,7 +26,7 @@ macro_rules! impl_atomic_quick_with_atomic { self.store(value, Ordering::SeqCst) } } - } + }; } impl_atomic_quick_with_atomic!(std::sync::atomic::AtomicBool, bool); diff --git a/src/ext/cstr.rs b/src/ext/cstr.rs index 599ffb1..891aa15 100644 --- a/src/ext/cstr.rs +++ b/src/ext/cstr.rs @@ -2,9 +2,9 @@ use c_fixed_string::CFixedStr; #[cfg(feature = "c_fixed_string")] use c_fixed_string::CFixedString; -use std::ffi::NulError; use std::ffi::CStr; use std::ffi::CString; +use std::ffi::NulError; use std::fmt::Display; #[derive(Debug, derive_more::From, PartialEq)] @@ -15,7 +15,7 @@ pub enum ToCStrError { impl Display for ToCStrError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::Null(e) => { e.fmt(f) } + Self::Null(e) => e.fmt(f), } } } @@ -58,7 +58,7 @@ impl ToCStr for String { impl ToCStr for CFixedStr { fn to_cstr(&self) -> Result { Ok(self.to_c_str().into_owned()) - } + } } #[cfg(feature = "c_fixed_string")] diff --git a/src/ext/flagset.rs b/src/ext/flagset.rs index 0b89189..445d1e3 100644 --- a/src/ext/flagset.rs +++ b/src/ext/flagset.rs @@ -1,5 +1,5 @@ -use flagset::Flags; use flagset::FlagSet; +use flagset::Flags; pub trait ToFlagSet { fn to_flag_set(&self) -> FlagSet; @@ -8,7 +8,10 @@ pub trait ToFlagSet { } } -impl ToFlagSet for T where FlagSet: From { +impl ToFlagSet for T +where + FlagSet: From, +{ fn to_flag_set(&self) -> FlagSet { FlagSet::from(self.clone()) } @@ -20,11 +23,14 @@ impl ToFlagSet for FlagSet { } } -impl ToFlagSet for Option where FlagSet: From { +impl ToFlagSet for Option +where + FlagSet: From, +{ fn to_flag_set(&self) -> FlagSet { match self { - Some(s) => { FlagSet::from(s.clone()) } - None => { FlagSet::default() } + Some(s) => FlagSet::from(s.clone()), + None => FlagSet::default(), } } } diff --git a/src/ext/io.rs b/src/ext/io.rs index 5a1141c..426ecf5 100644 --- a/src/ext/io.rs +++ b/src/ext/io.rs @@ -23,7 +23,7 @@ pub trait StructRead { define_struct_reader_fn!(i128); /// Read exact number of bytes. /// * `size` - The number of bytes - /// + /// /// Returns io error or the bytes. fn read_bytes(&mut self, size: usize) -> Result, Self::Error>; } diff --git a/src/ext/json.rs b/src/ext/json.rs index 43715ca..43d2d8b 100644 --- a/src/ext/json.rs +++ b/src/ext/json.rs @@ -34,8 +34,8 @@ impl ToJson for &T { impl ToJson for Option { fn to_json(&self) -> Option { match self { - Some(d) => { d.to_json() } - None => { None } + Some(d) => d.to_json(), + None => None, } } } @@ -52,7 +52,10 @@ impl ToJson for RwLockWriteGuard<'_, T> { } } -pub trait FromJson where Self: Sized { +pub trait FromJson +where + Self: Sized, +{ type Err; fn from_json(v: T) -> Result; } diff --git a/src/ext/replace.rs b/src/ext/replace.rs index ec8a67d..170fb5f 100644 --- a/src/ext/replace.rs +++ b/src/ext/replace.rs @@ -7,18 +7,18 @@ use std::sync::RwLockWriteGuard; pub trait ReplaceWith { /// Replace current value with another value /// * `another` - another value - /// + /// /// Returns the old value. fn replace_with(&mut self, another: T) -> T; } /// Replace current value with another value -/// +/// /// If you want to mutably borrows, please use [ReplaceWith] instead. pub trait ReplaceWith2 { /// Replace current value with another value /// * `another` - another value - /// + /// /// Returns the old value. fn replace_with2(&self, another: T) -> T; } diff --git a/src/ext/rw_lock.rs b/src/ext/rw_lock.rs index 7989963..617e366 100644 --- a/src/ext/rw_lock.rs +++ b/src/ext/rw_lock.rs @@ -15,7 +15,9 @@ impl GetRwLock for RwLock { fn get_ref<'a>(&'a self) -> RwLockReadGuard<'a, Self::Target> { loop { match self.try_read() { - Ok(f) => { return f; } + Ok(f) => { + return f; + } Err(_) => { spin_on(tokio::time::sleep(Duration::new(0, 1_000_000))); } @@ -25,7 +27,9 @@ impl GetRwLock for RwLock { fn get_mut<'a>(&'a self) -> RwLockWriteGuard<'a, Self::Target> { loop { match self.try_write() { - Ok(f) => { return f; } + Ok(f) => { + return f; + } Err(_) => { spin_on(tokio::time::sleep(Duration::new(0, 1_000_000))); } diff --git a/src/ext/try_err.rs b/src/ext/try_err.rs index 6979d6d..118b46a 100644 --- a/src/ext/try_err.rs +++ b/src/ext/try_err.rs @@ -13,8 +13,8 @@ pub trait TryErr { impl, E> TryErr2 for Option { fn try_err2(&self, v: E) -> Result { match self { - Some(r) => { Ok(r.to_owned()) } - None => { Err(v) } + Some(r) => Ok(r.to_owned()), + None => Err(v), } } } @@ -22,8 +22,8 @@ impl, E> TryErr2 for Option { impl TryErr for Option { fn try_err(self, err: E) -> Result { match self { - Some(v) => { Ok(v) } - None => { Err(err) } + Some(v) => Ok(v), + None => Err(err), } } } @@ -31,8 +31,8 @@ impl TryErr for Option { impl TryErr for Result { fn try_err(self, err: E) -> Result { match self { - Ok(v) => { Ok(v) } - Err(_) => { Err(err) } + Ok(v) => Ok(v), + Err(_) => Err(err), } } } diff --git a/src/ext/use_or_not.rs b/src/ext/use_or_not.rs index 61758d7..651fdf4 100644 --- a/src/ext/use_or_not.rs +++ b/src/ext/use_or_not.rs @@ -1,7 +1,7 @@ use crate::ext::json::FromJson; use crate::ext::json::ToJson; -use crate::gettext; use crate::ext::try_err::TryErr; +use crate::gettext; use std::str::FromStr; #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] @@ -15,15 +15,18 @@ pub enum UseOrNot { } /// Convert to bool (whether to enable some features) -pub trait ToBool where Self: AsRef { +pub trait ToBool +where + Self: AsRef, +{ /// Auto detect function. fn detect(&self) -> bool; /// Return whether to enable some features fn to_bool(&self) -> bool { match self.as_ref() { - UseOrNot::Auto => { self.detect() } - UseOrNot::Yes => { true } - UseOrNot::No => { false } + UseOrNot::Auto => self.detect(), + UseOrNot::Yes => true, + UseOrNot::No => false, } } } diff --git a/src/i18n.rs b/src/i18n.rs index 5e64068..632af9f 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -119,7 +119,10 @@ fn open_mo_file(molang: &str) -> Option { { let mut p = pb.clone(); p.pop(); - p.push(format!("share/locale/{}/LC_MESSAGES/pixiv_downloader.mo", molang.replace("-", "_").as_str())); + p.push(format!( + "share/locale/{}/LC_MESSAGES/pixiv_downloader.mo", + molang.replace("-", "_").as_str() + )); if p.exists() { let f = File::open(p); match f { diff --git a/src/list.rs b/src/list.rs index ad19b30..f51d9f4 100644 --- a/src/list.rs +++ b/src/list.rs @@ -44,12 +44,15 @@ impl AsRef> for NonTailList { impl Clone for NonTailList { fn clone(&self) -> Self { Self { - data: self.data.clone() + data: self.data.clone(), } } } -impl Debug for NonTailList where Vec: Debug { +impl Debug for NonTailList +where + Vec: Debug, +{ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Vec::::fmt(&self.data, f) } @@ -57,9 +60,7 @@ impl Debug for NonTailList where Vec: Debug { impl Default for NonTailList { fn default() -> Self { - Self { - data: Vec::new(), - } + Self { data: Vec::new() } } } @@ -73,17 +74,13 @@ impl From<&[T]> for NonTailList { impl From> for NonTailList { fn from(list: Vec) -> Self { - Self { - data: list, - } + Self { data: list } } } impl From<&Vec> for NonTailList { fn from(list: &Vec) -> Self { - Self { - data: list.clone(), - } + Self { data: list.clone() } } } @@ -95,7 +92,7 @@ impl FromStr for NonTailList { /// ``` /// let l: NonTailList = NonTailList::from_str("1,2,3").unwrap(); /// ``` - fn from_str(s: &str) -> Result{ + fn from_str(s: &str) -> Result { let mut l: Vec = Vec::new(); let r = s.split(","); for i in r { @@ -103,9 +100,7 @@ impl FromStr for NonTailList { let a = i.parse::()?; l.push(a); } - Ok(Self { - data: l, - }) + Ok(Self { data: l }) } } @@ -144,7 +139,10 @@ impl IndexMut for NonTailList { } } -impl PartialEq> for NonTailList where T: PartialEq { +impl PartialEq> for NonTailList +where + T: PartialEq, +{ fn eq(&self, other: &Vec) -> bool { &self.data == other } diff --git a/src/main.rs b/src/main.rs index 2888cb8..a5ec5b7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,20 +7,20 @@ extern crate derive_more; #[cfg(feature = "flagset")] extern crate flagset; extern crate futures_util; -extern crate json; extern crate http; extern crate http_content_range; extern crate indicatif; extern crate int_enum; +extern crate json; #[macro_use] extern crate lazy_static; #[cfg(all(feature = "link-cplusplus", target_env = "gnu"))] extern crate link_cplusplus; extern crate modular_bitfield; extern crate proc_macros; -extern crate tokio; extern crate regex; extern crate reqwest; +extern crate tokio; extern crate url; extern crate urlparse; #[cfg(feature = "utf16string")] @@ -50,8 +50,8 @@ mod exif; mod ext; mod i18n; mod list; -mod opthelper; mod opt; +mod opthelper; mod opts; mod parser; mod pixiv_link; diff --git a/src/opthelper.rs b/src/opthelper.rs index ffb110d..7961bb9 100644 --- a/src/opthelper.rs +++ b/src/opthelper.rs @@ -4,9 +4,9 @@ use crate::ext::replace::ReplaceWith2; use crate::ext::rw_lock::GetRwLock; use crate::ext::use_or_not::ToBool; use crate::ext::use_or_not::UseOrNot; +use crate::list::NonTailList; use crate::opt::use_progress_bar::UseProgressBar; use crate::opts::CommandOpts; -use crate::list::NonTailList; use crate::retry_interval::parse_retry_interval_from_json; use crate::settings::SettingStore; use std::sync::Arc; @@ -58,15 +58,20 @@ impl OptHelper { pub fn update(&self, opt: CommandOpts, settings: SettingStore) { if settings.have("author-name-filters") { - self._author_name_filters.replace_with2(AuthorNameFilter::from_json(settings.get("author-name-filters").unwrap()).unwrap()); + self._author_name_filters.replace_with2( + AuthorNameFilter::from_json(settings.get("author-name-filters").unwrap()).unwrap(), + ); } - self._use_progress_bar.replace_with2(if opt.use_progress_bar.is_some() { - Some(UseProgressBar::from(opt.use_progress_bar.unwrap())) - } else if settings.have("use-progress-bar") { - Some(UseProgressBar::from(UseOrNot::from_json(settings.get("use-progress-bar").unwrap()).unwrap())) - } else { - None - }); + self._use_progress_bar + .replace_with2(if opt.use_progress_bar.is_some() { + Some(UseProgressBar::from(opt.use_progress_bar.unwrap())) + } else if settings.have("use-progress-bar") { + Some(UseProgressBar::from( + UseOrNot::from_json(settings.get("use-progress-bar").unwrap()).unwrap(), + )) + } else { + None + }); self.opt.replace_with2(opt); self.settings.replace_with2(settings); } @@ -138,7 +143,11 @@ impl OptHelper { /// Return progress bar's template pub fn progress_bar_template(&self) -> String { if self.settings.get_ref().have("progress-bar-template") { - return self.settings.get_ref().get_str("progress-bar-template").unwrap() + return self + .settings + .get_ref() + .get_str("progress-bar-template") + .unwrap(); } String::from("[{elapsed_precise}] [{wide_bar:.green/yellow}] {bytes}/{total_bytes} ({bytes_per_sec}, {eta}) {msg:40}") } @@ -146,11 +155,21 @@ impl OptHelper { /// Return whether to download multiple images at the same time. pub fn download_multiple_images(&self) -> bool { match self.opt.get_ref().download_multiple_images { - Some(r) => { return r; } + Some(r) => { + return r; + } None => {} } - if self.settings.get_ref().have_bool("download-multiple-images") { - return self.settings.get_ref().get_bool("download-multiple-images").unwrap(); + if self + .settings + .get_ref() + .have_bool("download-multiple-images") + { + return self + .settings + .get_ref() + .get_bool("download-multiple-images") + .unwrap(); } false } @@ -170,7 +189,7 @@ impl Default for OptHelper { } } -lazy_static!{ +lazy_static! { #[doc(hidden)] pub static ref HELPER: Arc = Arc::new(OptHelper::default()); } diff --git a/src/opts.rs b/src/opts.rs index 00d8880..480701f 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -139,8 +139,8 @@ pub fn print_usage(prog: &str, opts: &Options) { /// Prase bool string pub fn parse_bool>(s: Option) -> Result, String> { let tmp = match s { - Some(s) => { Some(s.as_ref().to_lowercase()) } - None => { None } + Some(s) => Some(s.as_ref().to_lowercase()), + None => None, }; match tmp { Some(t) => { @@ -156,7 +156,7 @@ pub fn parse_bool>(s: Option) -> Result, String> { Err(format!("{} {}", gettext("Invalid boolean value:"), t)) } } - None => { Ok(None) } + None => Ok(None), } } @@ -165,8 +165,15 @@ pub fn parse_bool>(s: Option) -> Result, String> { /// * `key` - The key of the option. /// * `default` - The value if option is present but the data is not obtained. /// * `callback` - The function to process the obtained data. -pub fn parse_optional_opt(opts: &getopts::Matches, key: &str, default: T, callback: F) -> Result, E> - where F: Fn(Option) -> Result, E> { +pub fn parse_optional_opt( + opts: &getopts::Matches, + key: &str, + default: T, + callback: F, +) -> Result, E> +where + F: Fn(Option) -> Result, E>, +{ if !opts.opt_present(key) { return Ok(None); } @@ -312,7 +319,8 @@ pub fn parse_cmd() -> Option { let yes = result.opt_present("yes"); let no = result.opt_present("no"); re.as_mut().unwrap().overwrite = if yes && no { - if result.opt_positions("yes").last().unwrap() > result.opt_positions("no").last().unwrap() { + if result.opt_positions("yes").last().unwrap() > result.opt_positions("no").last().unwrap() + { Some(true) } else { Some(false) @@ -329,7 +337,11 @@ pub fn parse_cmd() -> Option { let s = s.trim(); let c = s.parse::(); if c.is_err() { - println!("{} {}", gettext("Retry count must be an non-negative integer:"), c.unwrap_err()); + println!( + "{} {}", + gettext("Retry count must be an non-negative integer:"), + c.unwrap_err() + ); return None; } re.as_mut().unwrap().retry = Some(c.unwrap()); @@ -338,7 +350,11 @@ pub fn parse_cmd() -> Option { let s = result.opt_str("retry-interval").unwrap(); let r = parse_retry_interval_from_str(s.as_str()); if r.is_err() { - println!("{} {}", gettext("Failed to parse retry interval:"), r.unwrap_err()); + println!( + "{} {}", + gettext("Failed to parse retry interval:"), + r.unwrap_err() + ); return None; } re.as_mut().unwrap().retry_interval = Some(r.unwrap()); @@ -352,7 +368,13 @@ pub fn parse_cmd() -> Option { let s = result.opt_str("use-progress-bar").unwrap(); let r = UseOrNot::from_str(s.as_str()); if r.is_err() { - println!("{} {}", gettext("Failed to parse :").replace("", "use-progress-bar").as_str(), r.unwrap_err()); + println!( + "{} {}", + gettext("Failed to parse :") + .replace("", "use-progress-bar") + .as_str(), + r.unwrap_err() + ); return None; } re.as_mut().unwrap().use_progress_bar = Some(r.unwrap()); @@ -360,7 +382,13 @@ pub fn parse_cmd() -> Option { match parse_optional_opt(&result, "download-multiple-images", true, parse_bool) { Ok(b) => re.as_mut().unwrap().download_multiple_images = b, Err(e) => { - println!("{} {}", gettext("Failed to parse :").replace("", "download-multiple-images").as_str(), e); + println!( + "{} {}", + gettext("Failed to parse :") + .replace("", "download-multiple-images") + .as_str(), + e + ); return None; } } diff --git a/src/parser/metadata.rs b/src/parser/metadata.rs index dc0bdbc..40a1e0b 100644 --- a/src/parser/metadata.rs +++ b/src/parser/metadata.rs @@ -65,8 +65,8 @@ impl MetaDataParser { false } } - Node::Comment(_) => { false } - Node::Text(_) => { false } + Node::Comment(_) => false, + Node::Text(_) => false, } } diff --git a/src/pixiv_link.rs b/src/pixiv_link.rs index 70c9424..741e54e 100644 --- a/src/pixiv_link.rs +++ b/src/pixiv_link.rs @@ -92,7 +92,7 @@ impl TryInto for PixivID { type Error = (); fn try_into(self) -> Result { match self { - Self::Artwork(id) => { Ok(id) } + Self::Artwork(id) => Ok(id), } } } @@ -101,7 +101,7 @@ impl TryInto for &PixivID { type Error = (); fn try_into(self) -> Result { match *self { - PixivID::Artwork(id) => { Ok(id) } + PixivID::Artwork(id) => Ok(id), } } } diff --git a/src/pixiv_web.rs b/src/pixiv_web.rs index 4cf09e1..551485f 100644 --- a/src/pixiv_web.rs +++ b/src/pixiv_web.rs @@ -9,11 +9,11 @@ use json::JsonValue; use reqwest::IntoUrl; use reqwest::Response; use spin_on::spin_on; +use std::sync::atomic::AtomicBool; use std::sync::Arc; use std::sync::RwLock; use std::sync::RwLockReadGuard; use std::sync::RwLockWriteGuard; -use std::sync::atomic::AtomicBool; use std::time::Duration; /// A client which use Pixiv's web API @@ -40,7 +40,9 @@ impl PixivWebClient { async fn aget_data_as_mut<'a>(&'a self) -> RwLockWriteGuard<'a, Option> { loop { match self.data.try_write() { - Ok(f) => { return f; } + Ok(f) => { + return f; + } Err(_) => { tokio::time::sleep(Duration::new(0, 1_000_000)).await; } @@ -55,7 +57,9 @@ impl PixivWebClient { async fn aget_data<'a>(&'a self) -> RwLockReadGuard<'a, Option> { loop { match self.data.try_read() { - Ok(f) => { return f; } + Ok(f) => { + return f; + } Err(_) => { tokio::time::sleep(Duration::new(0, 1_000_000)).await; } @@ -82,11 +86,16 @@ impl PixivWebClient { self.client.set_header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"); let l = helper.language(); if l.is_some() { - self.client.set_header("Accept-Language", l.as_ref().unwrap()); - self.params.get_mut().replace(json::object! { "lang": l.as_ref().unwrap().replace("-", "_").as_str() }); + self.client + .set_header("Accept-Language", l.as_ref().unwrap()); + self.params + .get_mut() + .replace(json::object! { "lang": l.as_ref().unwrap().replace("-", "_").as_str() }); } else { self.client.set_header("Accept-Language", "ja"); - self.params.get_mut().replace(json::object! { "lang": "ja" }); + self.params + .get_mut() + .replace(json::object! { "lang": "ja" }); } self.inited.qstore(true); true @@ -103,7 +112,10 @@ impl PixivWebClient { pub async fn check_login(&self) -> bool { self.auto_init(); - let r = self.client.get_with_param("https://www.pixiv.net/", self.params.get_ref(), None).await; + let r = self + .client + .get_with_param("https://www.pixiv.net/", self.params.get_ref(), None) + .await; if r.is_none() { return false; } @@ -116,7 +128,11 @@ impl PixivWebClient { } let data = r.text_with_charset("UTF-8").await; if data.is_err() { - println!("{} {}", gettext("Failed to get main page:"), data.unwrap_err()); + println!( + "{} {}", + gettext("Failed to get main page:"), + data.unwrap_err() + ); return false; } let data = data.unwrap(); @@ -126,7 +142,11 @@ impl PixivWebClient { return false; } if get_helper().verbose() { - println!("{}\n{}", gettext("Main page's data:"), p.value.as_ref().unwrap().pretty(2).as_str()); + println!( + "{}\n{}", + gettext("Main page's data:"), + p.value.as_ref().unwrap().pretty(2).as_str() + ); } self.get_data_as_mut().replace(p.value.unwrap()); true @@ -183,7 +203,10 @@ impl PixivWebClient { pub async fn download_image(&self, url: U) -> Option { self.auto_init(); - let r = self.client.get(url, json::object!{"referer": "https://www.pixiv.net/"}).await; + let r = self + .client + .get(url, json::object! {"referer": "https://www.pixiv.net/"}) + .await; if r.is_none() { return None; } @@ -197,9 +220,16 @@ impl PixivWebClient { Some(r) } - pub async fn adownload_image(&self, url: U, pdf: &Option) -> Option { + pub async fn adownload_image( + &self, + url: U, + pdf: &Option, + ) -> Option { self.auto_init(); - let r = self.client.get(url, json::object!{"referer": "https://www.pixiv.net/"}).await; + let r = self + .client + .get(url, json::object! {"referer": "https://www.pixiv.net/"}) + .await; if r.is_none() { return None; } @@ -215,21 +245,39 @@ impl PixivWebClient { pub async fn get_artwork_ajax(&self, id: u64) -> Option { self.auto_init(); - let r = self.client.get_with_param(format!("https://www.pixiv.net/ajax/illust/{}", id), self.params.get_ref(), None).await; + let r = self + .client + .get_with_param( + format!("https://www.pixiv.net/ajax/illust/{}", id), + self.params.get_ref(), + None, + ) + .await; if r.is_none() { return None; } let r = r.unwrap(); let v = self.deal_json(r).await; if get_helper().verbose() && v.is_some() { - println!("{} {}", gettext("Artwork's data:"), v.as_ref().unwrap().pretty(2)); + println!( + "{} {}", + gettext("Artwork's data:"), + v.as_ref().unwrap().pretty(2) + ); } v } pub async fn get_artwork(&self, id: u64) -> Option { self.auto_init(); - let r = self.client.get_with_param(format!("https://www.pixiv.net/artworks/{}", id), self.params.get_ref(), None).await; + let r = self + .client + .get_with_param( + format!("https://www.pixiv.net/artworks/{}", id), + self.params.get_ref(), + None, + ) + .await; if r.is_none() { return None; } @@ -242,7 +290,11 @@ impl PixivWebClient { } let data = r.text_with_charset("UTF-8").await; if data.is_err() { - println!("{} {}", gettext("Failed to get artwork page:"), data.unwrap_err()); + println!( + "{} {}", + gettext("Failed to get artwork page:"), + data.unwrap_err() + ); return None; } let data = data.unwrap(); @@ -252,35 +304,61 @@ impl PixivWebClient { return None; } if get_helper().verbose() { - println!("{} {}", gettext("Artwork's data:"), p.value.as_ref().unwrap().pretty(2)); + println!( + "{} {}", + gettext("Artwork's data:"), + p.value.as_ref().unwrap().pretty(2) + ); } Some(p.value.unwrap()) } pub async fn get_illust_pages(&self, id: u64) -> Option { self.auto_init(); - let r = self.client.get_with_param(format!("https://www.pixiv.net/ajax/illust/{}/pages", id), self.params.get_ref(), None).await; + let r = self + .client + .get_with_param( + format!("https://www.pixiv.net/ajax/illust/{}/pages", id), + self.params.get_ref(), + None, + ) + .await; if r.is_none() { return None; } let r = r.unwrap(); let v = self.deal_json(r).await; if get_helper().verbose() && v.is_some() { - println!("{} {}", gettext("Artwork's page data:"), v.as_ref().unwrap().pretty(2)); + println!( + "{} {}", + gettext("Artwork's page data:"), + v.as_ref().unwrap().pretty(2) + ); } v } pub async fn get_ugoira(&self, id: u64) -> Option { self.auto_init(); - let r = self.client.get_with_param(format!("https://www.pixiv.net/ajax/illust/{}/ugoira_meta", id), self.params.get_ref(), None).await; + let r = self + .client + .get_with_param( + format!("https://www.pixiv.net/ajax/illust/{}/ugoira_meta", id), + self.params.get_ref(), + None, + ) + .await; if r.is_none() { return None; } let r = r.unwrap(); let v = self.deal_json(r).await; if get_helper().verbose() && v.is_some() { - println!("{} {}", gettext("Ugoira's data:"), v.as_ref().unwrap().pretty(2)); + println!( + "{} {}", + gettext("Ugoira's data:"), + v.as_ref().unwrap().pretty(2) + ); } v } @@ -305,7 +383,11 @@ impl Drop for PixivWebClient { let c = get_helper().cookies(); if c.is_some() { if !self.client.save_cookies(c.as_ref().unwrap()) { - println!("{} {}", gettext("Warning: Failed to save cookies file:"), c.as_ref().unwrap()); + println!( + "{} {}", + gettext("Warning: Failed to save cookies file:"), + c.as_ref().unwrap() + ); } } } diff --git a/src/retry_interval.rs b/src/retry_interval.rs index e597f88..e9051e1 100644 --- a/src/retry_interval.rs +++ b/src/retry_interval.rs @@ -1,6 +1,6 @@ -use crate::ext::json::ToJson; use crate::dur::Dur; use crate::dur::DurType; +use crate::ext::json::ToJson; use crate::gettext; use crate::list::NonTailList; use json::JsonValue; @@ -16,7 +16,9 @@ pub fn parse_retry_interval_from_str(s: &str) -> Result, & Ok(NonTailList::from(r)) } -pub fn parse_retry_interval_from_json(s: T) -> Result, &'static str> { +pub fn parse_retry_interval_from_json( + s: T, +) -> Result, &'static str> { let obj = s.to_json(); if obj.is_none() { return Err(gettext("Failed to get JSON object.")); @@ -28,16 +30,14 @@ pub fn parse_retry_interval_from_json(s: T) -> Result { r += Duration::new(num, 0); } - None => { - match obj.as_f64() { - Some(num) => { - r += Duration::from_secs_f64(num); - } - None => { - return Err(gettext("Failed to parse JSON number.")); - } + None => match obj.as_f64() { + Some(num) => { + r += Duration::from_secs_f64(num); } - } + None => { + return Err(gettext("Failed to parse JSON number.")); + } + }, } } else if obj.is_array() { for v in obj.members() { @@ -46,16 +46,14 @@ pub fn parse_retry_interval_from_json(s: T) -> Result { r += Duration::new(num, 0); } - None => { - match v.as_f64() { - Some(num) => { - r += Duration::from_secs_f64(num); - } - None => { - return Err(gettext("Failed to parse JSON number.")); - } + None => match v.as_f64() { + Some(num) => { + r += Duration::from_secs_f64(num); } - } + None => { + return Err(gettext("Failed to parse JSON number.")); + } + }, } } else { return Err(gettext("Unsupported JSON type.")); @@ -74,11 +72,25 @@ pub fn check_retry_interval(s: &JsonValue) -> bool { #[test] fn test_parse_retry_interval() { let l = parse_retry_interval_from_str("2, 3, 4").unwrap(); - assert_eq!(l, vec![Duration::new(2, 0), Duration::new(3, 0), Duration::new(4, 0)]); + assert_eq!( + l, + vec![ + Duration::new(2, 0), + Duration::new(3, 0), + Duration::new(4, 0) + ] + ); let l = parse_retry_interval_from_json(json::parse("123").unwrap()).unwrap(); assert_eq!(l, vec![Duration::new(123, 0)]); let l = parse_retry_interval_from_json(json::parse("123.7").unwrap()).unwrap(); assert_eq!(l, vec![Duration::new(123, 700_000_000)]); let l = parse_retry_interval_from_json(json::array![123, 123.7, 230]).unwrap(); - assert_eq!(l, vec![Duration::new(123, 0), Duration::new(123, 700_000_000), Duration::new(230, 0)]); + assert_eq!( + l, + vec![ + Duration::new(123, 0), + Duration::new(123, 700_000_000), + Duration::new(230, 0) + ] + ); } diff --git a/src/settings.rs b/src/settings.rs index 274c440..c89c504 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -294,8 +294,8 @@ impl SettingStore { pub fn get_bool(&self, key: &str) -> Option { match self.data.get(key) { - Some(obj) => { obj.as_bool() } - None => { None } + Some(obj) => obj.as_bool(), + None => None, } } @@ -318,14 +318,14 @@ impl SettingStore { pub fn have_bool(&self, key: &str) -> bool { match self.data.get(key) { - Some(obj) => { obj.is_boolean() } - None => { false } + Some(obj) => obj.is_boolean(), + None => false, } } pub fn have_str(&self, key: &str) -> bool { let obj = self.data.get(key); - if obj.is_none() { + if obj.is_none() { return false; } let obj = obj.unwrap(); diff --git a/src/ugoira.rs b/src/ugoira.rs index 18e0f28..02bdc9a 100644 --- a/src/ugoira.rs +++ b/src/ugoira.rs @@ -5,8 +5,8 @@ use crate::ext::cstr::ToCStr; use crate::ext::cstr::ToCStrError; use crate::ext::json::ToJson; use crate::ext::rawhandle::ToRawHandle; -use crate::gettext; use crate::ext::try_err::TryErr; +use crate::gettext; use std::convert::AsRef; use std::default::Default; use std::ffi::CStr; @@ -14,7 +14,7 @@ use std::ffi::OsStr; use std::fmt::Debug; use std::fmt::Display; #[cfg(test)] -use std::fs::{File, create_dir}; +use std::fs::{create_dir, File}; #[cfg(test)] use std::io::Read; use std::ops::Drop; @@ -52,20 +52,24 @@ pub enum UgoiraError { impl Display for UgoiraError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::String(s) => { f.write_str(s) } - Self::Utf8(s) => { f.write_fmt(format_args!("{} {}", gettext("Failed to decode string with UTF-8:"), s)) } - Self::ToCStr(s) => { f.write_fmt(format_args!("{}", s)) } - Self::FfmpegError(s) => { f.write_fmt(format_args!("{}", s)) } - Self::CodeError(s) => { f.write_fmt(format_args!("{}", s)) } - Self::ZipError(s) => { f.write_fmt(format_args!("{}", s)) } - Self::ZipError2(s) => { f.write_fmt(format_args!("{}", s)) } + Self::String(s) => f.write_str(s), + Self::Utf8(s) => f.write_fmt(format_args!( + "{} {}", + gettext("Failed to decode string with UTF-8:"), + s + )), + Self::ToCStr(s) => f.write_fmt(format_args!("{}", s)), + Self::FfmpegError(s) => f.write_fmt(format_args!("{}", s)), + Self::CodeError(s) => f.write_fmt(format_args!("{}", s)), + Self::ZipError(s) => f.write_fmt(format_args!("{}", s)), + Self::ZipError2(s) => f.write_fmt(format_args!("{}", s)), } } } impl From<&str> for UgoiraError { fn from(s: &str) -> Self { - Self::String(String::from(s)) + Self::String(String::from(s)) } } @@ -103,19 +107,19 @@ pub struct UgoiraCodeError { impl UgoiraCodeError { fn to_str(&self) -> &'static str { match self.code { - UGOIRA_OK => { "OK" } - UGOIRA_NULL_POINTER => { gettext("Arguments have null pointers.") } - UGOIRA_INVALID_MAX_FPS => { gettext("Invalid max fps.") } - UGOIRA_INVALID_FRAMES => { gettext("Invalid frames.") } - UGOIRA_INVALID_CRF => { gettext("Invalid crf.") } - UGOIRA_REMOVE_OUTPUT_FILE_FAILED => { gettext("Can not remove output file.") } - UGOIRA_OOM => { gettext("Out of memory.") } - UGOIRA_NO_VIDEO_STREAM => { gettext("No video stream available in the file.") } - UGOIRA_NO_AVAILABLE_DECODER => { gettext("No available decoder.") } - UGOIRA_NO_AVAILABLE_ENCODER => { gettext("No available encoder.") } - UGOIRA_OPEN_FILE => { gettext("Failed to open output file.") } - UGOIRA_UNABLE_SCALE => { gettext("Unable to scale image.") } - _ => { gettext("Unknown error.") } + UGOIRA_OK => "OK", + UGOIRA_NULL_POINTER => gettext("Arguments have null pointers."), + UGOIRA_INVALID_MAX_FPS => gettext("Invalid max fps."), + UGOIRA_INVALID_FRAMES => gettext("Invalid frames."), + UGOIRA_INVALID_CRF => gettext("Invalid crf."), + UGOIRA_REMOVE_OUTPUT_FILE_FAILED => gettext("Can not remove output file."), + UGOIRA_OOM => gettext("Out of memory."), + UGOIRA_NO_VIDEO_STREAM => gettext("No video stream available in the file."), + UGOIRA_NO_AVAILABLE_DECODER => gettext("No available decoder."), + UGOIRA_NO_AVAILABLE_ENCODER => gettext("No available encoder."), + UGOIRA_OPEN_FILE => gettext("Failed to open output file."), + UGOIRA_UNABLE_SCALE => gettext("Unable to scale image."), + _ => gettext("Unknown error."), } } } @@ -134,9 +138,7 @@ impl Display for UgoiraCodeError { impl From for UgoiraCodeError { fn from(v: c_int) -> Self { - Self { - code: v, - } + Self { code: v } } } @@ -161,15 +163,21 @@ impl UgoiraZipError { impl Display for UgoiraZipError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(self.to_str().unwrap_or(format!("{} {}", gettext("Failed to get error message:"), self.code)).as_str()) + f.write_str( + self.to_str() + .unwrap_or(format!( + "{} {}", + gettext("Failed to get error message:"), + self.code + )) + .as_str(), + ) } } impl From for UgoiraZipError { fn from(v: c_int) -> Self { - Self { - code: v, - } + Self { code: v } } } @@ -200,14 +208,26 @@ impl Debug for UgoiraZipError2 { f.write_str("UgoiraError2 { None }") } else { let err = unsafe { *self.err }; - f.write_fmt(format_args!("UgoiraZipError2 {{ {}, {} }}", err.sys_err, err.zip_err )) + f.write_fmt(format_args!( + "UgoiraZipError2 {{ {}, {} }}", + err.sys_err, err.zip_err + )) } } } impl Display for UgoiraZipError2 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(self.to_str().unwrap_or(format!("{} {}, {}", gettext("Failed to get error message:"), unsafe { (*self.err).sys_err }, unsafe { (*self.err).zip_err })).as_str()) + f.write_str( + self.to_str() + .unwrap_or(format!( + "{} {}, {}", + gettext("Failed to get error message:"), + unsafe { (*self.err).sys_err }, + unsafe { (*self.err).zip_err } + )) + .as_str(), + ) } } @@ -222,9 +242,7 @@ impl Drop for UgoiraZipError2 { impl From<*mut _ugoira::zip_error_t> for UgoiraZipError2 { fn from(err: *mut _ugoira::zip_error_t) -> Self { - Self { - err, - } + Self { err } } } @@ -285,7 +303,9 @@ impl UgoiraFrames { } pub fn from_json(value: T) -> Result { - let obj = value.to_json().try_err(gettext("Failed to get JSON object."))?; + let obj = value + .to_json() + .try_err(gettext("Failed to get JSON object."))?; if !obj.is_array() { Err(gettext("Unsupported JSON type."))?; } @@ -349,15 +369,43 @@ impl ToRawHandle<_ugoira::AVDictionary> for AVDict { } } -pub fn convert_ugoira_to_mp4 + ?Sized, D: AsRef + ?Sized, F: AsRef + ?Sized, O: AsRef + ?Sized, M: AsRef + ?Sized>(src: &S, dest: &D, frames: &F, max_fps: f32, opts: &O, metadata: &M) -> Result<(), UgoiraError> { +pub fn convert_ugoira_to_mp4< + S: AsRef + ?Sized, + D: AsRef + ?Sized, + F: AsRef + ?Sized, + O: AsRef + ?Sized, + M: AsRef + ?Sized, +>( + src: &S, + dest: &D, + frames: &F, + max_fps: f32, + opts: &O, + metadata: &M, +) -> Result<(), UgoiraError> { let src = src.as_ref(); let dest = dest.as_ref(); let frames = frames.as_ref(); let opts = opts.as_ref(); let metadata = metadata.as_ref(); - let src = src.to_str().try_err(gettext("Failed to convert path."))?.to_cstr()?; - let dest = dest.to_str().try_err(gettext("Failed to convert path."))?.to_cstr()?; - let re = unsafe { _ugoira::convert_ugoira_to_mp4(src.as_ptr(), dest.as_ptr(), frames.to_const_handle(), max_fps, opts.to_const_handle(), metadata.to_const_handle()) }; + let src = src + .to_str() + .try_err(gettext("Failed to convert path."))? + .to_cstr()?; + let dest = dest + .to_str() + .try_err(gettext("Failed to convert path."))? + .to_cstr()?; + let re = unsafe { + _ugoira::convert_ugoira_to_mp4( + src.as_ptr(), + dest.as_ptr(), + frames.to_const_handle(), + max_fps, + opts.to_const_handle(), + metadata.to_const_handle(), + ) + }; if re.code != 0 { Err(re)?; } @@ -422,5 +470,12 @@ fn test_convert_ugoira_to_mp4() -> Result<(), UgoiraError> { metadata.set("title", "動く nachoneko :3", None).unwrap(); metadata.set("artist", "甘城なつき", None).unwrap(); let options = AVDict::new(); - convert_ugoira_to_mp4("./testdata/74841737_ugoira600x600.zip", target, &frames, 60f32, &options, &metadata) + convert_ugoira_to_mp4( + "./testdata/74841737_ugoira600x600.zip", + target, + &frames, + 60f32, + &options, + &metadata, + ) } diff --git a/src/utils.rs b/src/utils.rs index 24962cc..ba7b5b5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -56,7 +56,11 @@ pub fn get_file_name_from_url(url: U) -> Option { let path = Path::new(u.path()); let re = path.file_name(); if re.is_none() { - println!("{} {}", gettext("Failed to get file name from path:"), u.path()); + println!( + "{} {}", + gettext("Failed to get file name from path:"), + u.path() + ); return None; } let r = re.unwrap().to_str(); diff --git a/src/webclient.rs b/src/webclient.rs index c67d11c..80af249 100644 --- a/src/webclient.rs +++ b/src/webclient.rs @@ -17,16 +17,16 @@ use std::collections::HashMap; use std::convert::TryInto; use std::default::Default; use std::ffi::OsStr; -use std::fs::File; use std::fs::remove_file; +use std::fs::File; use std::io::Write; use std::path::Path; +use std::sync::atomic::AtomicBool; +use std::sync::atomic::AtomicU64; use std::sync::Arc; use std::sync::RwLock; use std::sync::RwLockReadGuard; use std::sync::RwLockWriteGuard; -use std::sync::atomic::AtomicBool; -use std::sync::atomic::AtomicU64; use std::time::Duration; /// Convert data to HTTP headers map @@ -102,8 +102,8 @@ pub struct WebClient { impl WebClient { /// Create a new instance of client - /// - /// This function will not handle any basic options, please use [Self::default()] instead. + /// + /// This function will not handle any basic options, please use [Self::default()] instead. pub fn new() -> Self { Self { client: Client::new(), @@ -118,7 +118,9 @@ impl WebClient { pub async fn aget_cookies_as_mut<'a>(&'a self) -> RwLockWriteGuard<'a, CookieJar> { loop { match self.cookies.try_write() { - Ok(f) => { return f; } + Ok(f) => { + return f; + } Err(_) => { tokio::time::sleep(Duration::new(0, 1_000_000)).await; } @@ -133,7 +135,9 @@ impl WebClient { pub async fn aget_cookies<'a>(&'a self) -> RwLockReadGuard<'a, CookieJar> { loop { match self.cookies.try_read() { - Ok(f) => { return f; } + Ok(f) => { + return f; + } Err(_) => { tokio::time::sleep(Duration::new(0, 1_000_000)).await; } @@ -145,10 +149,14 @@ impl WebClient { spin_on(self.aget_cookies()) } - pub async fn aget_headers_as_mut<'a>(&'a self) -> RwLockWriteGuard<'a, HashMap> { + pub async fn aget_headers_as_mut<'a>( + &'a self, + ) -> RwLockWriteGuard<'a, HashMap> { loop { match self.headers.try_write() { - Ok(f) => { return f; } + Ok(f) => { + return f; + } Err(_) => { tokio::time::sleep(Duration::new(0, 1_000_000)).await; } @@ -163,7 +171,9 @@ impl WebClient { pub async fn aget_headers<'a>(&'a self) -> RwLockReadGuard<'a, HashMap> { loop { match self.headers.try_read() { - Ok(f) => { return f; } + Ok(f) => { + return f; + } Err(_) => { tokio::time::sleep(Duration::new(0, 1_000_000)).await; } @@ -180,10 +190,14 @@ impl WebClient { self.retry.qload() } - pub async fn aget_retry_interval_as_mut<'a>(&'a self) -> RwLockWriteGuard<'a, Option>> { + pub async fn aget_retry_interval_as_mut<'a>( + &'a self, + ) -> RwLockWriteGuard<'a, Option>> { loop { match self.retry_interval.try_write() { - Ok(f) => { return f; } + Ok(f) => { + return f; + } Err(_) => { tokio::time::sleep(Duration::new(0, 1_000_000)).await; } @@ -191,14 +205,20 @@ impl WebClient { } } - pub fn get_retry_interval_as_mut<'a>(&'a self) -> RwLockWriteGuard<'a, Option>> { + pub fn get_retry_interval_as_mut<'a>( + &'a self, + ) -> RwLockWriteGuard<'a, Option>> { spin_on(self.aget_retry_interval_as_mut()) } - pub async fn aget_retry_interval<'a>(&'a self) -> RwLockReadGuard<'a, Option>> { + pub async fn aget_retry_interval<'a>( + &'a self, + ) -> RwLockReadGuard<'a, Option>> { loop { match self.retry_interval.try_read() { - Ok(f) => { return f; } + Ok(f) => { + return f; + } Err(_) => { tokio::time::sleep(Duration::new(0, 1_000_000)).await; } @@ -243,7 +263,7 @@ impl WebClient { /// Read cookies from file. /// * `file_name`: File name - /// + /// /// returns true if readed successfully. /// # Note /// If read failed, will clean all entries in the current [CookieJar] @@ -258,7 +278,7 @@ impl WebClient { /// Save cookies to file /// * `file_name`: File name - /// + /// /// returns true if saved successfully. pub fn save_cookies(&self, file_name: &str) -> bool { self.get_cookies_as_mut().save(file_name) @@ -267,10 +287,11 @@ impl WebClient { /// Set new HTTP header /// * `key` - The key of the new HTTP header /// * `value` - The value of the new HTTP value - /// + /// /// Returns the old HTTP header value if presented. pub fn set_header(&self, key: &str, value: &str) -> Option { - self.get_headers_as_mut().insert(String::from(key), String::from(value)) + self.get_headers_as_mut() + .insert(String::from(key), String::from(value)) } /// Set retry times, 0 means disable @@ -293,7 +314,12 @@ impl WebClient { /// client.get_with_param("https://test.com/a", json::array![["daa", "param1"]], None); /// ``` /// It will GET `https://test.com/a?data=param1`, `https://test.com/a?daa=%7B%22ad%22%3A%22test%22%7D`, `https://test.com/a?daa=param1` - pub async fn get_with_param(&self, url: U, param: J, headers: H) -> Option { + pub async fn get_with_param( + &self, + url: U, + param: J, + headers: H, + ) -> Option { let u = url.into_url(); if u.is_err() { println!("{} \"{}\"", gettext("Can not parse URL:"), u.unwrap_err()); @@ -360,7 +386,11 @@ impl WebClient { } /// Send Get Requests - pub async fn get(&self, url: U, headers: H) -> Option { + pub async fn get( + &self, + url: U, + headers: H, + ) -> Option { let mut count = 0u64; let retry = self.get_retry(); while count <= retry { @@ -370,13 +400,24 @@ impl WebClient { } count += 1; if count <= retry { - let t = self.get_retry_interval().as_ref().unwrap()[(count - 1).try_into().unwrap()]; + let t = + self.get_retry_interval().as_ref().unwrap()[(count - 1).try_into().unwrap()]; if !t.is_zero() { - println!("{}", gettext("Retry after seconds.").replace("", format!("{}", t.as_secs_f64()).as_str()).as_str()); + println!( + "{}", + gettext("Retry after seconds.") + .replace("", format!("{}", t.as_secs_f64()).as_str()) + .as_str() + ); tokio::time::sleep(t).await; } } - println!("{}", gettext("Retry times now.").replace("", format!("{}", count).as_str()).as_str()); + println!( + "{}", + gettext("Retry times now.") + .replace("", format!("{}", count).as_str()) + .as_str() + ); } None } @@ -428,14 +469,14 @@ impl WebClient { /// * `file_name` - File name /// * `r` - Response /// * `opt` - Options - /// + /// /// Note: If file already exists, will remove existing file first. pub fn download_stream + ?Sized>(file_name: &S, r: Response) -> Result<(), ()> { let content_length = r.content_length(); let opt = get_helper(); let use_progress_bar = match &content_length { - Some(_) => { opt.use_progress_bar() } - None => { false } + Some(_) => opt.use_progress_bar(), + None => false, }; let mut bar = if use_progress_bar { Some(ProgressBar::new(content_length.unwrap())) @@ -443,9 +484,12 @@ impl WebClient { None }; if bar.is_some() { - bar.as_mut().unwrap().set_style(ProgressStyle::default_bar() - .template(opt.progress_bar_template().as_ref()).unwrap() - .progress_chars("#>-")); + bar.as_mut().unwrap().set_style( + ProgressStyle::default_bar() + .template(opt.progress_bar_template().as_ref()) + .unwrap() + .progress_chars("#>-"), + ); } let mut downloaded = 0usize; let p = Path::new(file_name); @@ -458,7 +502,10 @@ impl WebClient { } if bar.is_some() { let tmp = p.file_name().unwrap_or(p.as_os_str()); - bar.as_mut().unwrap().set_message(gettext("Downloading \"\".").replace("", tmp.to_str().unwrap_or(""))); + bar.as_mut().unwrap().set_message( + gettext("Downloading \"\".") + .replace("", tmp.to_str().unwrap_or("")), + ); } let f = File::create(p); if f.is_err() { @@ -469,7 +516,11 @@ impl WebClient { let mut stream = r.bytes_stream(); while let Some(data) = spin_on(stream.next()) { if data.is_err() { - println!("{} {}", gettext("Error when downloading file:"), data.unwrap_err()); + println!( + "{} {}", + gettext("Error when downloading file:"), + data.unwrap_err() + ); return Err(()); } let data = data.unwrap(); @@ -493,7 +544,7 @@ impl Default for WebClient { let opt = get_helper(); c.set_verbose(opt.verbose()); match opt.retry() { - Some(retry) => { c.set_retry(retry) } + Some(retry) => c.set_retry(retry), None => {} } c.get_retry_interval_as_mut().replace(opt.retry_interval());