1
//! Code to remotely notify other crates about changes in the status of the
2
//! `GuardMgr`.
3

            
4
use std::{pin::Pin, task::Poll};
5

            
6
use crate::skew::SkewEstimate;
7
use educe::Educe;
8
use futures::{Stream, StreamExt};
9
use tor_basic_utils::skip_fmt;
10

            
11
/// A stream of [`SkewEstimate`] events.
12
///
13
/// Note that this stream can be lossy: if multiple events trigger before you
14
/// read from it, you will only get the most recent estimate.
15
//
16
// SEMVER NOTE: this type is re-exported from tor-circmgr.
17
#[derive(Clone, Educe)]
18
#[educe(Debug)]
19
pub struct ClockSkewEvents {
20
    /// The `postage::watch::Receiver` that we're wrapping.
21
    ///
22
    /// We wrap this type so that we don't expose its entire API, and so that we
23
    /// can migrate to some other implementation in the future if we want.
24
    #[educe(Debug(method = "skip_fmt"))]
25
    pub(crate) inner: postage::watch::Receiver<Option<SkewEstimate>>,
26
}
27

            
28
impl Stream for ClockSkewEvents {
29
    type Item = Option<SkewEstimate>;
30

            
31
176
    fn poll_next(
32
176
        mut self: Pin<&mut Self>,
33
176
        cx: &mut std::task::Context<'_>,
34
176
    ) -> Poll<Option<Self::Item>> {
35
176
        self.inner.poll_next_unpin(cx)
36
176
    }
37
}
38
impl ClockSkewEvents {
39
    /// Return our best estimate of our current clock skew, based on reports from the
40
    /// guards and fallbacks we have contacted.
41
    pub fn get(&self) -> Option<SkewEstimate> {
42
        self.inner.borrow().clone()
43
    }
44
}