Created
October 30, 2023 23:54
-
-
Save ryanmcgrath/51b813ece220fd33d337208697fa400b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::collections::HashMap; | |
use std::future::Future; | |
use std::pin::Pin; | |
use std::sync::{Arc, Mutex}; | |
use std::task::{Context, Poll}; | |
// Just placeholders. | |
type CronetPtr = i32; | |
type CronetError = Box<dyn std::error::Error>; | |
type CronetResponse = String; | |
#[derive(Debug)] | |
pub enum HTTPMethod { | |
GET, | |
POST, | |
// etc.. | |
} | |
#[derive(Debug)] | |
struct CronetEngineInner { | |
ptr: CronetPtr, | |
callbacks: Mutex<HashMap<CronetPtr, CronetPtr>> | |
} | |
#[derive(Clone, Debug)] | |
pub struct CronetEngine { | |
inner: Arc<CronetEngineInner>, | |
} | |
impl CronetEngine { | |
pub fn new() -> Self { | |
Self { | |
inner: Arc::new(CronetEngineInner { | |
ptr: 0, | |
callbacks: Mutex::new(HashMap::new()) | |
}), | |
} | |
} | |
pub fn request<S>(&self, url: S) -> CronetRequestBuilder | |
where | |
S: Into<String>, | |
{ | |
CronetRequestBuilder::new(self.clone(), url) | |
} | |
pub fn execute( | |
&self, | |
request: CronetRequestBuilderContext | |
) -> impl Future<Output = Result<CronetResponse, CronetError>> { | |
// File the request with the engine, setting any necessary ffi hooks for handling | |
// callbacks, set the necessary fields for Future checking on request, then just | |
// return it so the caller can await it | |
CronetRequest { | |
engine: self.clone(), | |
// Whatever is necessary to check for request state | |
} | |
} | |
} | |
#[derive(Debug)] | |
pub struct CronetRequest { | |
engine: CronetEngine, | |
// Any other necessary pieces~ | |
} | |
impl Future for CronetRequest { | |
type Output = Result<CronetResponse, CronetError>; | |
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | |
println!("Checking request status..."); | |
// Check the status of this request - maybe each request gets tagged in `execute`? | |
// | |
// let this = unsafe { self.get_unchecked_mut() }; | |
// | |
// if let Some(request) = this.engine.get(...) { | |
// // Check request state, return Ready (w/ Response) or Pending | |
// } else { | |
// cx.waker().wake_by_ref(); | |
// Poll::Pending | |
// } | |
cx.waker().wake_by_ref(); | |
Poll::Pending | |
} | |
} | |
#[derive(Debug)] | |
pub struct CronetRequestBuilderContext { | |
pub url: String, | |
pub http_method: HTTPMethod | |
} | |
#[derive(Debug)] | |
pub struct CronetRequestBuilder { | |
engine: CronetEngine, | |
context: CronetRequestBuilderContext | |
} | |
impl CronetRequestBuilder { | |
pub fn new<S>(engine: CronetEngine, url: S) -> Self | |
where | |
S: Into<String>, | |
{ | |
let context = CronetRequestBuilderContext { | |
url: url.into(), | |
http_method: HTTPMethod::GET | |
}; | |
Self { | |
engine, | |
context | |
} | |
} | |
pub fn method(mut self, method: HTTPMethod) -> Self { | |
self.context.http_method = method; | |
self | |
} | |
pub fn send(self) -> impl Future<Output = Result<CronetResponse, CronetError>> { | |
self.engine.execute(self.context) | |
} | |
} | |
#[tokio::main(flavor = "current_thread")] | |
async fn main() -> Result<(), Box<dyn std::error::Error>> { | |
let engine = CronetEngine::new(); | |
let request = engine.request("https://rymc.io/") | |
.method(HTTPMethod::POST) | |
.send().await?; | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment