use std::{future::Future, string::FromUtf8Error}; use reqwest::{Method, StatusCode}; const LD_CONTENT_TYPE: &str = "application/ld+json"; #[derive(Debug)] pub(crate) struct ResolveError(pub String); impl From for ResolveError { fn from(err: reqwest::Error) -> Self { Self(err.to_string()) } } impl From for ResolveError { fn from(e: FromUtf8Error) -> Self { Self(format!( "invalid schema format (tried utf8): {}", e.to_string() )) } } pub(super) struct Resolver { client: reqwest::Client, } impl Resolver { pub fn new() -> Self { Self { client: reqwest::ClientBuilder::new().build().unwrap(), } } async fn get(&self, iri: String, ok: F) -> Result where F: FnOnce(reqwest::Response) -> Fut, Fut: Future>, { let resp = self .client .request(Method::GET, iri) .header("Accept", LD_CONTENT_TYPE) .send() .await?; match resp.status() { StatusCode::OK => Ok(ok(resp).await?), status => Err(ResolveError(format!("non-ok status: {}", status))), } } pub async fn resolve_into<'a, T>(&self, iri: String) -> Result where T: for<'de> serde::Deserialize<'de>, { Ok(self .get(iri, |resp| async { Ok(resp.json().await?) }) .await?) } pub async fn resolve(&self, iri: String) -> Result, ResolveError> { Ok(self .get(iri, |resp| async { Ok(resp.bytes().await?.to_vec()) }) .await?) } }