aspero_engine/
standard.rs1use std::sync::Arc;
4
5use aspero_core::{Error, HttpClient, ResiliencePolicy};
6
7use crate::transport::{Paced, ReqwestClient};
8use crate::{Cache, Engine, EngineBuilder};
9
10#[cfg(feature = "crossref")]
11pub use aspero_crossref::CrossrefConfig;
12#[cfg(feature = "datacite")]
13pub use aspero_datacite::DataciteConfig;
14#[cfg(feature = "doi")]
15pub use aspero_doi::DoiConfig;
16#[cfg(feature = "europepmc")]
17pub use aspero_europepmc::EuropePmcConfig;
18#[cfg(feature = "openalex")]
19pub use aspero_openalex::OpenAlexConfig;
20#[cfg(feature = "openlibrary")]
21pub use aspero_openlibrary::OpenLibraryConfig;
22
23#[derive(Clone, Default)]
25#[non_exhaustive]
26pub struct StandardConfig {
27 pub mailto: Option<String>,
29 pub cache: Option<Arc<dyn Cache>>,
31 #[cfg(feature = "openalex")]
32 pub openalex: Option<OpenAlexConfig>,
33 #[cfg(feature = "crossref")]
34 pub crossref: Option<CrossrefConfig>,
35 #[cfg(feature = "datacite")]
36 pub datacite: Option<DataciteConfig>,
37 #[cfg(feature = "doi")]
38 pub doi: Option<DoiConfig>,
39 #[cfg(feature = "europepmc")]
40 pub europepmc: Option<EuropePmcConfig>,
41 #[cfg(feature = "openlibrary")]
42 pub openlibrary: Option<OpenLibraryConfig>,
43}
44
45pub fn standard(config: StandardConfig) -> Result<Engine, Error> {
55 let user_agent = match &config.mailto {
56 Some(mailto) => format!("aspero/{} (mailto:{mailto})", env!("CARGO_PKG_VERSION")),
57 None => format!("aspero/{}", env!("CARGO_PKG_VERSION")),
58 };
59 #[allow(unused_variables)]
61 let client = |label: &str, policy: &ResiliencePolicy| -> Result<Arc<dyn HttpClient>, Error> {
62 let inner = Arc::new(ReqwestClient::new(&user_agent, policy.attempt_timeout)?);
63 Ok(Arc::new(Paced::new(label, inner, policy.min_interval)))
64 };
65
66 let mut builder: EngineBuilder = Engine::builder();
67 if let Some(cache) = config.cache {
68 builder = builder.cache(cache);
69 }
70
71 #[cfg(feature = "openalex")]
72 if let Some(oa) = config.openalex {
73 use aspero_openalex::OpenAlex;
74 let policy = OpenAlex::default_policy();
75 let provider = OpenAlex::new(oa, client("openalex", &policy)?);
76 builder = builder.provider(Arc::new(provider), policy, 10);
77 }
78
79 #[cfg(feature = "crossref")]
80 if let Some(mut cr) = config.crossref {
81 use aspero_crossref::Crossref;
82 if cr.mailto.is_none() {
83 cr.mailto = config.mailto.clone();
84 }
85 let policy = Crossref::default_policy();
86 let provider = Crossref::new(cr, client("crossref", &policy)?);
87 builder = builder.provider(Arc::new(provider), policy, 20);
88 }
89
90 #[cfg(feature = "datacite")]
91 if let Some(dc) = config.datacite {
92 use aspero_datacite::Datacite;
93 let policy = Datacite::default_policy();
94 let provider = Datacite::new(dc, client("datacite", &policy)?);
95 builder = builder.provider(Arc::new(provider), policy, 25);
96 }
97
98 #[cfg(feature = "doi")]
99 if let Some(doi) = config.doi {
100 use aspero_doi::DoiOrg;
101 let policy = DoiOrg::default_policy();
102 let provider = DoiOrg::new(doi, client("doi", &policy)?);
103 builder = builder.provider(Arc::new(provider), policy, 30);
104 }
105
106 #[cfg(feature = "europepmc")]
107 if let Some(epmc) = config.europepmc {
108 use aspero_europepmc::EuropePmc;
109 let policy = EuropePmc::default_policy();
110 let provider = EuropePmc::new(epmc, client("europepmc", &policy)?);
111 builder = builder.provider(Arc::new(provider), policy, 35);
112 }
113
114 #[cfg(feature = "openlibrary")]
115 if let Some(ol) = config.openlibrary {
116 use aspero_openlibrary::OpenLibrary;
117 let policy = OpenLibrary::default_policy();
118 let provider = OpenLibrary::new(ol, client("openlibrary", &policy)?);
119 builder = builder.provider(Arc::new(provider), policy, 40);
120 }
121
122 Ok(builder.build())
123}