steamkit/util/
task_extensions.rs1use std::fmt;
4use std::future::Future;
5use std::pin::Pin;
6use std::task::{Context, Poll};
7
8use tokio_util::sync::CancellationToken;
9
10use crate::error::SteamError;
11
12pub struct IgnoringCancellation<F> {
14 inner: Pin<Box<F>>,
16 token: CancellationToken,
18}
19
20impl<F> IgnoringCancellation<F> {
21 pub fn new(inner: F, token: CancellationToken) -> IgnoringCancellation<F> {
24 IgnoringCancellation {
25 inner: Box::pin(inner),
26 token,
27 }
28 }
29}
30
31impl<F> fmt::Debug for IgnoringCancellation<F> {
32 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
33 formatter
34 .debug_struct("IgnoringCancellation")
35 .field("cancelled", &self.token.is_cancelled())
36 .finish()
37 }
38}
39
40impl<F> Future for IgnoringCancellation<F>
41where
42 F: Future<Output = Result<(), SteamError>>,
43{
44 type Output = Result<(), SteamError>;
45
46 fn poll(self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Self::Output> {
47 let this = self.get_mut();
48
49 match this.inner.as_mut().poll(context) {
50 Poll::Pending => Poll::Pending,
51 Poll::Ready(Ok(())) => Poll::Ready(Ok(())),
52 Poll::Ready(Err(error)) => {
53 if matches!(error, SteamError::Cancelled) && this.token.is_cancelled() {
54 Poll::Ready(Ok(()))
55 } else {
56 Poll::Ready(Err(error))
57 }
58 }
59 }
60 }
61}
62
63pub fn ignoring_cancellation<F>(task: F, token: CancellationToken) -> IgnoringCancellation<F>
66where
67 F: Future<Output = Result<(), SteamError>>,
68{
69 IgnoringCancellation::new(task, token)
70}
71
72pub trait TaskExtensions: Future<Output = Result<(), SteamError>> + Sized {
74 fn ignoring_cancellation(self, token: CancellationToken) -> IgnoringCancellation<Self> {
77 IgnoringCancellation::new(self, token)
78 }
79}
80
81impl<F> TaskExtensions for F where F: Future<Output = Result<(), SteamError>> + Sized {}