use crate::types::LastFmError;
use crate::Result;
use std::time::Duration;
use tokio::sync::watch;
#[derive(Clone, Debug)]
pub struct CancellationState {
tx: watch::Sender<bool>,
}
impl Default for CancellationState {
fn default() -> Self {
Self::new()
}
}
impl CancellationState {
pub fn new() -> Self {
let (tx, _rx) = watch::channel(false);
Self { tx }
}
pub fn cancel(&self) {
let _ = self.tx.send(true);
}
pub fn reset(&self) {
let _ = self.tx.send(false);
}
pub fn is_cancelled(&self) -> bool {
*self.tx.borrow()
}
pub fn subscribe(&self) -> watch::Receiver<bool> {
self.tx.subscribe()
}
}
fn cancelled_error() -> LastFmError {
LastFmError::Io(std::io::Error::new(
std::io::ErrorKind::Interrupted,
"cancelled",
))
}
pub async fn sleep_with_cancel(
mut cancel_rx: watch::Receiver<bool>,
duration: Duration,
) -> Result<()> {
if *cancel_rx.borrow() {
return Err(cancelled_error());
}
let sleeper = tokio::time::sleep(duration);
tokio::pin!(sleeper);
tokio::select! {
_ = &mut sleeper => Ok(()),
_ = async {
loop {
if cancel_rx.changed().await.is_err() {
break;
}
if *cancel_rx.borrow() {
break;
}
}
} => Err(cancelled_error()),
}
}