use std::borrow::Cow;
use std::task::Poll;
use crate::Span;
use crate::local::LocalSpan;
impl<T: std::future::Future> FutureExt for T {}
pub trait FutureExt: std::future::Future + Sized {
#[inline]
fn in_span(self, span: Span) -> InSpan<Self> {
InSpan {
inner: self,
span: Some(span),
}
}
#[inline]
fn enter_on_poll(self, name: impl Into<Cow<'static, str>>) -> EnterOnPoll<Self> {
EnterOnPoll {
inner: self,
name: name.into(),
}
}
}
#[pin_project::pin_project]
pub struct InSpan<T> {
#[pin]
inner: T,
span: Option<Span>,
}
impl<T: std::future::Future> std::future::Future for InSpan<T> {
type Output = T::Output;
fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
let this = self.project();
let _guard = this.span.as_ref().map(|s| s.set_local_parent());
let res = this.inner.poll(cx);
match res {
r @ Poll::Pending => r,
other => {
this.span.take();
other
}
}
}
}
#[pin_project::pin_project]
pub struct EnterOnPoll<T> {
#[pin]
inner: T,
name: Cow<'static, str>,
}
impl<T: std::future::Future> std::future::Future for EnterOnPoll<T> {
type Output = T::Output;
fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
let this = self.project();
let _guard = LocalSpan::enter_with_local_parent(this.name.clone());
this.inner.poll(cx)
}
}