use fnroute::{Input, Param, RouteContext, Router, State};
use std::{
future::Future,
pin::Pin,
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
};
#[derive(Clone)]
struct AppState {
name: String,
}
#[derive(Clone)]
struct Payload {
action: String,
}
async fn hello() -> &'static str {
"hello"
}
async fn user(
Param(id): Param<u64>,
Input(payload): Input<Payload>,
State(state): State<AppState>,
) -> String {
format!("{} user {id} {}", state.name, payload.action)
}
fn sync_user(Param(id): Param<u64>, State(state): State<AppState>) -> String {
format!("{} sync user {id}", state.name)
}
fn main() {
block_on(run());
}
async fn run() {
let app = Router::<String>::new()
.with_state(AppState {
name: "demo".to_string(),
})
.route("hello", hello)
.route("users/:id", user)
.route_sync("sync-users/:id", sync_user);
let hello = app.call("hello").await.unwrap();
let user = app
.call_with(RouteContext::new("users/42").input(Payload {
action: "saved".to_string(),
}))
.await
.unwrap();
let sync_user = app.call("sync-users/7").await.unwrap();
println!("{hello}");
println!("{user}");
println!("{sync_user}");
}
fn block_on<F>(future: F) -> F::Output
where
F: Future,
{
let waker = noop_waker();
let mut context = Context::from_waker(&waker);
let mut future = Box::pin(future);
loop {
match Pin::as_mut(&mut future).poll(&mut context) {
Poll::Ready(output) => return output,
Poll::Pending => std::thread::yield_now(),
}
}
}
fn noop_waker() -> Waker {
unsafe fn clone(_: *const ()) -> RawWaker {
noop_raw_waker()
}
unsafe fn wake(_: *const ()) {}
unsafe fn wake_by_ref(_: *const ()) {}
unsafe fn drop(_: *const ()) {}
fn noop_raw_waker() -> RawWaker {
RawWaker::new(
std::ptr::null(),
&RawWakerVTable::new(clone, wake, wake_by_ref, drop),
)
}
unsafe { Waker::from_raw(noop_raw_waker()) }
}