diff --git a/src/ipdb.rs b/src/ipdb.rs index 83d676a..a6b0df0 100644 --- a/src/ipdb.rs +++ b/src/ipdb.rs @@ -14,6 +14,13 @@ pub enum DbType { } impl DbType { + const fn name(&self) -> &'static str { + match self { + Self::Asn => "ASN", + Self::Geo => "geolocation", + } + } + const fn url(&self) -> &'static str { match self { Self::Asn => { @@ -25,14 +32,7 @@ impl DbType { } } - const fn name(&self) -> &'static str { - match self { - Self::Asn => "ASN", - Self::Geo => "geolocation", - } - } - - pub async fn db_path(&self) -> color_eyre::Result { + async fn db_path(&self) -> color_eyre::Result { let mut cache_path = get_cache_path().await.wrap_err("failed to get cache path")?; match self { @@ -50,40 +50,6 @@ impl DbType { Ok(db_path) } - async fn read_etag( - &self, - ) -> color_eyre::Result> { - let path = self.etag_path().await?; - match tokio::fs::read_to_string(&path).await { - Ok(text) => Ok(text.parse().ok()), - Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(None), - Err(e) => Err(e).wrap_err_with(move || { - format!("failed to read file {} to string", path.display()) - }), - } - } - - async fn remove_etag(&self) -> color_eyre::Result<()> { - let path = self.etag_path().await?; - match tokio::fs::remove_file(&path).await { - Ok(()) => Ok(()), - Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(()), - Err(e) => Err(e).wrap_err_with(move || { - format!("failed to remove {}", path.display()) - }), - } - } - - async fn save_etag( - &self, - etag: reqwest::header::HeaderValue, - ) -> color_eyre::Result<()> { - let path = self.etag_path().await?; - tokio::fs::write(&path, etag).await.wrap_err_with(move || { - format!("failed to write to file {}", path.display()) - }) - } - async fn save_db( &self, mut response: reqwest::Response, @@ -115,7 +81,41 @@ impl DbType { Ok(()) } - pub async fn download_db( + async fn save_etag( + &self, + etag: reqwest::header::HeaderValue, + ) -> color_eyre::Result<()> { + let path = self.etag_path().await?; + tokio::fs::write(&path, etag).await.wrap_err_with(move || { + format!("failed to write to file {}", path.display()) + }) + } + + async fn read_etag( + &self, + ) -> color_eyre::Result> { + let path = self.etag_path().await?; + match tokio::fs::read_to_string(&path).await { + Ok(text) => Ok(text.parse().ok()), + Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(None), + Err(e) => Err(e).wrap_err_with(move || { + format!("failed to read file {} to string", path.display()) + }), + } + } + + async fn remove_etag(&self) -> color_eyre::Result<()> { + let path = self.etag_path().await?; + match tokio::fs::remove_file(&path).await { + Ok(()) => Ok(()), + Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(()), + Err(e) => Err(e).wrap_err_with(move || { + format!("failed to remove {}", path.display()) + }), + } + } + + pub async fn download( self, http_client: reqwest::Client, #[cfg(feature = "tui")] tx: tokio::sync::mpsc::UnboundedSender, @@ -200,4 +200,16 @@ impl DbType { }) } } + + pub async fn open_mmap( + self, + ) -> color_eyre::Result> { + let path = self.db_path().await?; + tokio::task::spawn_blocking(move || maxminddb::Reader::open_mmap(path)) + .await + .wrap_err("failed to spawn tokio blocking task")? + .wrap_err_with(move || { + format!("failed to open {} database", self.name()) + }) + } } diff --git a/src/main.rs b/src/main.rs index fb3bc91..f5f21c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -96,7 +96,7 @@ async fn main() -> color_eyre::Result<()> { let tx = tx.clone(); output_dependencies_tasks.spawn(async move { ipdb::DbType::Asn - .download_db( + .download( http_client, #[cfg(feature = "tui")] tx, @@ -111,7 +111,7 @@ async fn main() -> color_eyre::Result<()> { let tx = tx.clone(); output_dependencies_tasks.spawn(async move { ipdb::DbType::Geo - .download_db( + .download( http_client, #[cfg(feature = "tui")] tx, diff --git a/src/output.rs b/src/output.rs index 9fb15d8..65ea61c 100644 --- a/src/output.rs +++ b/src/output.rs @@ -65,30 +65,16 @@ pub async fn save_proxies( } if config.output.json.enabled { + #[expect(clippy::if_then_some_else_none)] let maybe_asn_db = if config.output.json.include_asn { - let path = ipdb::DbType::Asn.db_path().await?; - Some( - tokio::task::spawn_blocking(move || { - maxminddb::Reader::open_mmap(path) - }) - .await - .wrap_err("failed to spawn tokio blocking task")? - .wrap_err("failed to open ASN database")?, - ) + Some(ipdb::DbType::Asn.open_mmap().await?) } else { None }; + #[expect(clippy::if_then_some_else_none)] let maybe_geo_db = if config.output.json.include_geolocation { - let path = ipdb::DbType::Geo.db_path().await?; - Some( - tokio::task::spawn_blocking(move || { - maxminddb::Reader::open_mmap(path) - }) - .await - .wrap_err("failed to spawn tokio blocking task")? - .wrap_err("failed to open geolocation database")?, - ) + Some(ipdb::DbType::Geo.open_mmap().await?) } else { None };