extern crate ureq;
use std::error::Error;
use ureq::Agent;
#[derive(Debug, Clone)]
pub struct Doi {
pub doi: Option<String>,
agent: Agent,
}
impl Doi {
pub fn new<S: Into<String>>(doi: S) -> Self {
Self {
doi: Some(doi.into()),
agent: DoiBuilder::default_agent(),
}
}
pub fn is_set(&self) -> bool {
self.doi.is_some()
}
pub fn get_doi(&self) -> Result<String, Box<dyn Error>> {
match &self.doi {
Some(doi) => Ok(doi.clone()),
None => Err("DOI is not set".into()),
}
}
pub fn set_doi<S: Into<String>>(&mut self, doi: S) {
self.doi = Some(doi.into());
}
pub fn https_url(&self) -> String {
format!("https://doi.org/{}", self.doi.as_ref().unwrap())
}
pub fn resolve(&self) -> Result<String, Box<dyn Error>> {
let url = self.https_url();
match self.agent.head(&url).call() {
Ok(response) | Err(ureq::Error::Status(418, response)) => {
let resolved_link = response.get_url().to_string();
Ok(resolved_link)
}
Err(e) => Err(Box::new(e)),
}
}
}
impl Default for Doi {
fn default() -> Self {
Self {
doi: None,
agent: DoiBuilder::default_agent(),
}
}
}
impl PartialEq for Doi {
fn eq(&self, other: &Self) -> bool {
match (&self.doi, &other.doi) {
(Some(doi1), Some(doi2)) => doi1.to_lowercase() == doi2.to_lowercase(),
(None, None) => true,
_ => false,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct DoiBuilder {
doi: Option<String>,
env_proxy: bool,
proxy: Option<ureq::Proxy>,
}
impl DoiBuilder {
pub fn new() -> Self {
Self {
doi: None,
env_proxy: true,
proxy: None,
}
}
pub fn doi<S: Into<String>>(&mut self, doi: S) -> &mut Self {
self.doi = Some(doi.into());
self
}
pub fn env_proxy(&mut self, env_proxy: bool) -> &mut Self {
self.env_proxy = env_proxy;
self
}
pub fn proxy<S: Into<String>>(&mut self, proxy: S) -> Result<&mut Self, Box<dyn Error>> {
self.proxy = Some(ureq::Proxy::new(proxy.into())?);
Ok(self)
}
#[cfg(feature = "proxy")]
pub fn default_agent() -> Agent {
ureq::AgentBuilder::new().try_proxy_from_env(true).build()
}
#[cfg(not(feature = "proxy"))]
pub fn default_agent() -> Agent {
ureq::AgentBuilder::new().build()
}
pub fn build(&self) -> Doi {
#[cfg(feature = "proxy")]
let build_agent = || -> Agent {
if let Some(proxy) = &self.proxy {
ureq::AgentBuilder::new().proxy(proxy.clone()).build()
} else {
ureq::AgentBuilder::new()
.try_proxy_from_env(self.env_proxy)
.build()
}
};
#[cfg(not(feature = "proxy"))]
let build_agent = || -> Agent { ureq::AgentBuilder::new().build() };
Doi {
doi: self.doi.clone(),
agent: build_agent(),
}
}
}
#[cfg(feature = "metadata")]
mod metadata;
#[cfg(feature = "metadata")]
pub use metadata::{DoiMetadata, DoiMetadataPerson, DoiMetadataType, JsonValue};