Last active
October 18, 2024 15:31
-
-
Save dicej/9d9869eddd7544b59843df5a0b8c88d8 to your computer and use it in GitHub Desktop.
Async bindgen snippets
This file contains 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
interface handler { | |
use types.{request, response, error-code}; | |
handle: func( | |
request: request, | |
) -> result<response, error-code>; | |
} |
This file contains 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
// spawn-style bindings | |
impl Handler for Component { | |
/// Return a response which echoes the request headers, body, and trailers. | |
async fn handle(request: Request) -> Result<Response, ErrorCode> { | |
let (headers, body) = Request::into_parts(request); | |
if false { | |
// This is the easy and efficient way to do it... | |
Ok(Response::new(headers, body)) | |
} else { | |
// ...but we do it the more difficult, less efficient way here to exercise various component model | |
// features (e.g. `future`s, `stream`s, and post-return asynchronous execution): | |
let (trailers_tx, trailers_rx) = async_support::new_future(); | |
let (mut pipe_tx, pipe_rx) = async_support::new_stream(); | |
async_support::spawn(async move { | |
let mut body_rx = body.stream().expect("response body stream should be available"); | |
loop { | |
match body_rx.next().await { | |
Some(Err(e)) => { | |
_ = pipe_tx.send(Err(e)).await; | |
return; | |
} | |
Some(Ok(chunk)) => { | |
if pipe_tx.send(Ok(chunk)).await.is_err() { | |
return; | |
} | |
} | |
None => break; | |
} | |
} | |
drop(pipe_tx); | |
if let Ok(Some(trailers)) = Body::finish(body).await { | |
_ = trailers_tx.send(trailers).await; | |
} | |
}); | |
Ok(Response::new( | |
headers, | |
Body::new(pipe_rx, Some(trailers_rx)), | |
)) | |
} | |
} | |
} |
This file contains 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
// implicit-outparam-style bindings | |
impl Handler for Component { | |
/// Send a response via `response_out` which echoes the request headers, body, and trailers. | |
async fn handle(request: Request, response_out: oneshot::Sender<Result<Response, ErrorCode>>) { | |
let (headers, body) = Request::into_parts(request); | |
if false { | |
// This is the easy and efficient way to do it... | |
_ = response_out.send(Ok(Response::new(headers, body))) | |
} else { | |
// ...but we do it the more difficult, less efficient way here to exercise various component model | |
// features (e.g. `future`s, `stream`s, and post-return asynchronous execution): | |
let (trailers_tx, trailers_rx) = async_support::new_future(); | |
let (mut pipe_tx, pipe_rx) = async_support::new_stream(); | |
let result = response_out.send(Ok(Response::new( | |
headers, | |
Body::new(pipe_rx, Some(trailers_rx)), | |
))); | |
if result.is_err() { | |
return; | |
} | |
let mut body_rx = body.stream().expect("response body stream should be available"); | |
loop { | |
match body_rx.next().await { | |
Some(Err(e)) => { | |
_ = pipe_tx.send(Err(e)).await; | |
return; | |
} | |
Some(Ok(chunk)) => { | |
if pipe_tx.send(Ok(chunk)).await.is_err() { | |
return; | |
} | |
} | |
None => break; | |
} | |
} | |
drop(pipe_tx); | |
if let Ok(Some(trailers)) = Body::finish(body).await { | |
_ = trailers_tx.send(trailers).await; | |
} | |
} | |
} | |
} |
This file contains 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
interface handler { | |
use types.{request, response, error-code}; | |
// Idea: make the write ends of `stream` and `future` available as types | |
// (`stream-sender` and `future-sender`, respectively) which can be | |
// passed across component boundaries, and use `future-sender` to provide | |
// "return value and keep running"-style execution while also being able | |
// to return errors after "returning" a response. | |
handle: func( | |
request: request, | |
response-out: future-sender<response> | |
) -> result<_, error-code>; | |
} |
This file contains 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
// explicit-outparam-style bindings | |
impl Handler for Component { | |
/// Send a response via `response_out` which echoes the request headers, body, and trailers. | |
async fn handle(request: Request, response_out: FutureSender<Response>) -> Result<(), ErrorCode> { | |
let (headers, body) = Request::into_parts(request); | |
if false { | |
// This is the easy and efficient way to do it... | |
response_out.send(Response::new(headers, body))?; | |
} else { | |
// ...but we do it the more difficult, less efficient way here to exercise various component model | |
// features (e.g. `future`s, `stream`s, and post-return asynchronous execution): | |
let (trailers_tx, trailers_rx) = async_support::new_future(); | |
let (mut pipe_tx, pipe_rx) = async_support::new_stream(); | |
response_out.send(Response::new( | |
headers, | |
Body::new(pipe_rx, Some(trailers_rx)), | |
))?; | |
let mut body_rx = body.stream().expect("response body stream should be available"); | |
while let Some(chunk) = body_rx.try_next().await? { | |
pipe_tx.send(chunk).await?; | |
} | |
drop(pipe_tx); | |
if let Some(trailers) = Body::finish(body).await? { | |
trailers_tx.send(trailers).await?; | |
} | |
} | |
Ok(()) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment