use core::{
future::{ready, Future, Ready},
pin::Pin,
task,
};
use serde::de::DeserializeOwned;
use crate::helpers::CallFuture;
use crate::prelude::*;
use crate::{error::TransportError, helpers::json_rpc};
use crate::{Error, Transport};
#[derive(Clone)]
pub struct PinkHttp {
url: String,
}
impl PinkHttp {
pub fn new(url: impl Into<String>) -> Self {
Self { url: url.into() }
}
}
struct Response(Result<Vec<u8>, Error>);
impl Future for Response {
type Output = Result<Vec<u8>, Error>;
fn poll(mut self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
task::Poll::Ready(core::mem::replace(&mut self.0, Ok(vec![])))
}
}
type RpcResult = Result<Vec<u8>, Error>;
impl Transport for PinkHttp {
type Out = Ready<RpcResult>;
fn execute(&self, method: &'static str, params: Vec<crate::Value>) -> Self::Out {
let request = json_rpc::encode_request(method, params);
let body = request.as_bytes();
let headers: Vec<(String, String)> = vec![("Content-Type".into(), "application/json".into())];
let response = pink::http_post!(&self.url, body, headers);
if response.status_code / 100 != 2 {
return ready(Err(Error::Transport(TransportError::Code(response.status_code))));
}
ready(Ok(response.body))
}
}
impl<T: DeserializeOwned> CallFuture<T, Ready<RpcResult>> {
pub fn resolve(self) -> <Self as Future>::Output {
resolve_ready(self)
}
}
pub fn resolve_ready<F: Future>(fut: F) -> <F as Future>::Output {
let waker = futures::task::noop_waker_ref();
let mut cx = task::Context::from_waker(waker);
use task::Poll::*;
pin_mut!(fut);
match fut.poll(&mut cx) {
Ready(v) => v,
Pending => panic!("Failed to resolve a ready future"),
}
}