mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
62 lines
1.2 KiB
Rust
62 lines
1.2 KiB
Rust
use std::{pin::Pin, task::{Context, Poll}, time::Duration};
|
|
|
|
use futures::{FutureExt, Stream, StreamExt};
|
|
use tokio::time::{Instant, Sleep, sleep};
|
|
|
|
pub struct Debounce<S>
|
|
where
|
|
S: Stream,
|
|
{
|
|
stream: S,
|
|
interval: Duration,
|
|
|
|
sleep: Sleep,
|
|
last: Option<S::Item>,
|
|
}
|
|
|
|
impl<S> Debounce<S>
|
|
where
|
|
S: Stream + Unpin,
|
|
{
|
|
pub fn new(stream: S, interval: Duration) -> Self {
|
|
Self { stream, interval, sleep: sleep(Duration::ZERO), last: None }
|
|
}
|
|
}
|
|
|
|
impl<S> Stream for Debounce<S>
|
|
where
|
|
S: Stream + Unpin,
|
|
{
|
|
type Item = S::Item;
|
|
|
|
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
|
let (mut stream, interval, mut sleep, last) = unsafe {
|
|
let me = self.get_unchecked_mut();
|
|
(Pin::new(&mut me.stream), me.interval, Pin::new_unchecked(&mut me.sleep), &mut me.last)
|
|
};
|
|
|
|
if sleep.poll_unpin(cx).is_ready()
|
|
&& let Some(last) = last.take()
|
|
{
|
|
return Poll::Ready(Some(last));
|
|
}
|
|
|
|
while let Poll::Ready(next) = stream.poll_next_unpin(cx) {
|
|
match next {
|
|
Some(next) => {
|
|
*last = Some(next);
|
|
}
|
|
None if last.is_none() => {
|
|
return Poll::Ready(None);
|
|
}
|
|
None => {
|
|
sleep.reset(Instant::now());
|
|
return Poll::Pending;
|
|
}
|
|
}
|
|
}
|
|
|
|
sleep.reset(Instant::now() + interval);
|
|
Poll::Pending
|
|
}
|
|
}
|