1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
use std::ops::{Index, IndexMut};
use std::slice;

/// Kinds of timeouts needed to run the protocol logic
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct Timer(pub(crate) TimerKind);

#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum TimerKind {
    /// When to send an ack-eliciting probe packet or declare unacked packets lost
    LossDetection = 0,
    /// When to close the connection after no activity
    Idle = 1,
    /// When the close timer expires, the connection has been gracefully terminated.
    Close = 2,
    /// When keys are discarded because they should not be needed anymore
    KeyDiscard = 3,
    /// When to give up on validating a new path to the peer
    PathValidation = 4,
    /// When to send a `PING` frame to keep the connection alive
    KeepAlive = 5,
}

impl TimerKind {
    const VALUES: [Self; 6] = [
        TimerKind::LossDetection,
        TimerKind::Idle,
        TimerKind::Close,
        TimerKind::KeyDiscard,
        TimerKind::PathValidation,
        TimerKind::KeepAlive,
    ];
}

/// A table of data associated with each distinct kind of `Timer`
#[derive(Debug, Copy, Clone, Default)]
pub struct TimerTable<T> {
    data: [T; 6],
}

impl<T> TimerTable<T> {
    /// Create a table initialized with the value returned by `f` for each timer
    pub fn new(mut f: impl FnMut() -> T) -> Self {
        Self {
            data: [f(), f(), f(), f(), f(), f()],
        }
    }

    /// Iterate over the contained values
    pub fn iter(&self) -> TimerTableIter<T> {
        TimerTableIter {
            kind: TimerKind::VALUES.iter(),
            table: self,
        }
    }

    /// Mutably iterate over the contained values
    pub fn iter_mut(&mut self) -> TimerTableIterMut<T> {
        TimerTableIterMut {
            kind: TimerKind::VALUES.iter(),
            table: self.data.iter_mut(),
        }
    }
}

/// Iterator over a `TimerTable`
pub struct TimerTableIter<'a, T> {
    kind: slice::Iter<'static, TimerKind>,
    table: &'a TimerTable<T>,
}

impl<'a, T> Iterator for TimerTableIter<'a, T> {
    type Item = (Timer, &'a T);
    fn next(&mut self) -> Option<(Timer, &'a T)> {
        let timer = Timer(*self.kind.next()?);
        Some((timer, &self.table[timer]))
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.kind.size_hint()
    }
}

impl<'a, T> ExactSizeIterator for TimerTableIter<'a, T> {
    fn len(&self) -> usize {
        self.kind.len()
    }
}

/// Mutable iterator over a `TimerTable`
pub struct TimerTableIterMut<'a, T> {
    kind: slice::Iter<'static, TimerKind>,
    table: slice::IterMut<'a, T>,
}

impl<'a, T> Iterator for TimerTableIterMut<'a, T> {
    type Item = (Timer, &'a mut T);
    fn next(&mut self) -> Option<(Timer, &'a mut T)> {
        Some((Timer(*self.kind.next()?), self.table.next().unwrap()))
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.kind.size_hint()
    }
}

impl<'a, T> ExactSizeIterator for TimerTableIterMut<'a, T> {
    fn len(&self) -> usize {
        self.kind.len()
    }
}

impl<'a, T> IntoIterator for &'a TimerTable<T> {
    type Item = (Timer, &'a T);
    type IntoIter = TimerTableIter<'a, T>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, T> IntoIterator for &'a mut TimerTable<T> {
    type Item = (Timer, &'a mut T);
    type IntoIter = TimerTableIterMut<'a, T>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

impl<T> Index<Timer> for TimerTable<T> {
    type Output = T;
    fn index(&self, index: Timer) -> &T {
        &self.data[index.0 as usize]
    }
}

impl<T> IndexMut<Timer> for TimerTable<T> {
    fn index_mut(&mut self, index: Timer) -> &mut T {
        &mut self.data[index.0 as usize]
    }
}

impl slog::Value for Timer {
    fn serialize(
        &self,
        _: &slog::Record<'_>,
        key: slog::Key,
        serializer: &mut dyn slog::Serializer,
    ) -> slog::Result {
        serializer.emit_arguments(key, &format_args!("{:?}", self.0))
    }
}