Skip to content

Instantly share code, notes, and snippets.

@ssrlive
Created April 6, 2025 15:14
Show Gist options
  • Save ssrlive/7d7801c0ccee5501a60f1483af9d9549 to your computer and use it in GitHub Desktop.
Save ssrlive/7d7801c0ccee5501a60f1483af9d9549 to your computer and use it in GitHub Desktop.
pin-project-lite usage
// pin-project-lite = { version = "0.2", default-features = false }
#[cfg(test)]
mod tests {
use std::future::Future;
#[tokio::test]
async fn test_ipstack_tcp_stream() {
let fut = foo();
let ret = Map::new(fut, |i| i * 2).await;
println!("{}", ret);
}
async fn foo() -> i32 {
42
}
/*
struct Map<Fut, F, T>
where
Fut: Future,
F: FnOnce(Fut::Output) -> T,
{
fut: Fut,
f: Option<F>,
}
// */
pin_project_lite::pin_project! {
struct Map<Fut, F, T>
where
Fut: Future,
F: FnOnce(Fut::Output) -> T,
{
#[pin]
fut: Fut,
f: Option<F>,
}
}
impl<Fut, F, T> Map<Fut, F, T>
where
Fut: Future,
F: FnOnce(Fut::Output) -> T,
{
fn new(fut: Fut, f: F) -> Self {
Self { fut, f: Some(f) }
}
}
impl<Fut, F, T> Future for Map<Fut, F, T>
where
Fut: Future,
F: FnOnce(Fut::Output) -> T,
{
type Output = T;
fn poll(mut self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output> {
/*
let fut = unsafe { self.as_mut().map_unchecked_mut(|s| &mut s.fut) };
let output = std::task::ready!(fut.poll(cx));
let f = unsafe { &mut self.as_mut().get_unchecked_mut().f.take() };
match f.take() {
Some(f) => std::task::Poll::Ready(f(output)),
None => panic!("Future polled after completion"),
}
// */
let myself = self.as_mut().project();
let fut = myself.fut;
let output = std::task::ready!(fut.poll(cx));
let f = myself.f.take();
match f {
Some(f) => std::task::Poll::Ready(f(output)),
None => panic!("Future polled after completion"),
}
}
}
}
@ssrlive
Copy link
Author

ssrlive commented Apr 6, 2025

FutureExt usage

#[cfg(test)]
mod tests {
    use std::future::Future;

    #[tokio::test]
    async fn test_ipstack_tcp_stream() {
        let fut = foo();
        // let ret = Map::new(fut, |i| i * 2).await;
        let ret = fut.map(|i| i * 2).await;
        println!("{}", ret);
    }

    trait FutureExt: Future {
        fn map<F, T>(self, f: F) -> Map<Self, F, T>
        where
            Self: Sized,
            F: FnOnce(Self::Output) -> T,
        {
            Map::new(self, f)
        }
    }
    impl<Fut: Future> FutureExt for Fut {}

    async fn foo() -> i32 {
        42
    }

    /*
    struct Map<Fut, F, T>
    where
        Fut: Future,
        F: FnOnce(Fut::Output) -> T,
    {
        fut: Fut,
        f: Option<F>,
    }
    // */

    pin_project_lite::pin_project! {
        struct Map<Fut, F, T>
        where
            Fut: Future,
            F: FnOnce(Fut::Output) -> T,
        {
            #[pin]
            fut: Fut,
            f: Option<F>,
        }
    }

    impl<Fut, F, T> Map<Fut, F, T>
    where
        Fut: Future,
        F: FnOnce(Fut::Output) -> T,
    {
        fn new(fut: Fut, f: F) -> Self {
            Self { fut, f: Some(f) }
        }
    }

    impl<Fut, F, T> Future for Map<Fut, F, T>
    where
        Fut: Future,
        F: FnOnce(Fut::Output) -> T,
    {
        type Output = T;

        fn poll(mut self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output> {
            /*
            let fut = unsafe { self.as_mut().map_unchecked_mut(|s| &mut s.fut) };
            let output = std::task::ready!(fut.poll(cx));
            let f = unsafe { &mut self.as_mut().get_unchecked_mut().f.take() };
            match f.take() {
                Some(f) => std::task::Poll::Ready(f(output)),
                None => panic!("Future polled after completion"),
            }
            // */
            let myself = self.as_mut().project();
            let fut = myself.fut;
            let output = std::task::ready!(fut.poll(cx));
            let f = myself.f.take();
            match f {
                Some(f) => std::task::Poll::Ready(f(output)),
                None => panic!("Future polled after completion"),
            }
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment