pubmed_client/europe_pmc/
supplementary.rs1use std::path::{Path, PathBuf};
8
9use tokio::fs as tokio_fs;
10use tracing::{info, instrument};
11
12use pubmed_parser::ParseError;
13
14use crate::error::{PubMedError, Result};
15
16use super::client::EuropePmcClient;
17use super::id::EuropePmcId;
18
19impl EuropePmcClient {
20 #[instrument(skip(self), fields(id = %id))]
26 pub async fn fetch_supplementary_files(&self, id: &EuropePmcId) -> Result<Vec<u8>> {
27 let endpoint = format!("{}/supplementaryFiles", id.id);
28 let response = self
29 .executor()
30 .get_endpoint(&self.base_url, &endpoint, &[])
31 .await?;
32 let bytes = response.bytes().await.map_err(PubMedError::from)?;
33 Ok(bytes.to_vec())
34 }
35
36 #[instrument(skip(self, output_path), fields(id = %id))]
41 pub async fn download_supplementary_files(
42 &self,
43 id: &EuropePmcId,
44 output_path: impl AsRef<Path>,
45 ) -> Result<PathBuf> {
46 let output_path = output_path.as_ref().to_path_buf();
47 if let Some(parent) = output_path.parent() {
48 tokio_fs::create_dir_all(parent)
49 .await
50 .map_err(|e| ParseError::IoError {
51 message: format!("failed to create directory {}: {e}", parent.display()),
52 })?;
53 }
54
55 let bytes = self.fetch_supplementary_files(id).await?;
56 tokio_fs::write(&output_path, &bytes)
57 .await
58 .map_err(|e| ParseError::IoError {
59 message: format!("failed to write {}: {e}", output_path.display()),
60 })?;
61
62 info!(id = %id, path = %output_path.display(), bytes = bytes.len(), "Downloaded supplementary files");
63 Ok(output_path)
64 }
65}