Compare commits
No commits in common. "66fa21f50f669abc28fb145f4c1c830040324abc" and "9f97a2cae3ffdf95b6a762ecce7ff0a47142b902" have entirely different histories.
66fa21f50f
...
9f97a2cae3
1 changed files with 32 additions and 43 deletions
|
@ -7,6 +7,15 @@ fn runtime() -> &'static tokio::runtime::Runtime {
|
|||
})
|
||||
}
|
||||
|
||||
impl<T> schema::SubsonicResponse<T> {
|
||||
fn fixup(self) -> Result<T, Error> {
|
||||
match self {
|
||||
Self::Ok { inner } => Ok(inner),
|
||||
Self::Failed { error } => Err(Error::SubsonicError(error)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
UrlParseError(url::ParseError),
|
||||
|
@ -87,48 +96,7 @@ impl Client {
|
|||
})
|
||||
}
|
||||
|
||||
async fn send<T: serde::de::DeserializeOwned + Send + 'static>(
|
||||
&self,
|
||||
request: reqwest::RequestBuilder,
|
||||
) -> Result<T, Error> {
|
||||
// FIXME: is an entire channel per request overkill? maybe pool them?
|
||||
let (sender, receiver) = async_channel::bounded(1);
|
||||
|
||||
// let tokio take care of the request + further json parsing
|
||||
// this is because reqwest doesn't like the glib main loop
|
||||
// note that this is why those silly bounds on T are needed, because we're
|
||||
// sending back the result of the query from another thread
|
||||
let future = request.send();
|
||||
runtime().spawn(async move {
|
||||
// wrap this logic in a fn so we can use ?
|
||||
async fn perform<T: serde::de::DeserializeOwned + Send + 'static>(
|
||||
response: Result<reqwest::Response, reqwest::Error>,
|
||||
) -> Result<schema::SubsonicResponse<T>, reqwest::Error> {
|
||||
Ok(response?
|
||||
.error_for_status()?
|
||||
.json::<schema::SubsonicResponseOuter<T>>()
|
||||
.await?
|
||||
.subsonic_response)
|
||||
}
|
||||
|
||||
sender
|
||||
.send(perform(future.await).await)
|
||||
.await
|
||||
.expect("could not send subsonic response back to the main loop");
|
||||
});
|
||||
|
||||
let response = receiver
|
||||
.recv()
|
||||
.await
|
||||
.expect("could not receive subsonic response from tokio")?;
|
||||
|
||||
match response {
|
||||
schema::SubsonicResponse::Ok { inner } => Ok(inner),
|
||||
schema::SubsonicResponse::Failed { error } => Err(Error::SubsonicError(error)),
|
||||
}
|
||||
}
|
||||
|
||||
async fn get<T: serde::de::DeserializeOwned + Send + 'static>(
|
||||
async fn get<T: serde::de::DeserializeOwned>(
|
||||
&self,
|
||||
path: &[&str],
|
||||
query: &[(&str, &str)],
|
||||
|
@ -138,7 +106,28 @@ impl Client {
|
|||
// literally can't fail
|
||||
.unwrap_or_else(|_| unsafe { std::hint::unreachable_unchecked() })
|
||||
.extend(path);
|
||||
self.send(self.client.get(url).query(query)).await
|
||||
|
||||
// FIXME: is an entire channel per request overkill? maybe pool them?
|
||||
let (sender, receiver) = async_channel::bounded(1);
|
||||
|
||||
let future = self.client.get(url).query(query).send();
|
||||
runtime().spawn(async move {
|
||||
let response = future.await;
|
||||
sender
|
||||
.send(response)
|
||||
.await
|
||||
.expect("could not send subsonic response back to the main loop");
|
||||
});
|
||||
|
||||
receiver
|
||||
.recv()
|
||||
.await
|
||||
.expect("could not receive subsonic response from tokio")?
|
||||
.error_for_status()?
|
||||
.json::<schema::SubsonicResponseOuter<T>>()
|
||||
.await?
|
||||
.subsonic_response
|
||||
.fixup()
|
||||
}
|
||||
|
||||
pub async fn ping(&self) -> Result<(), Error> {
|
||||
|
|
Loading…
Reference in a new issue