use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum TransferPoll {
Failed = 0,
Bootstrapping = 1,
Bootstrapped = 2,
WaitingForInput = 3,
Transferring = 4,
Success = 5,
}
impl TransferPoll {
pub fn from_wire(value: i64) -> Option<Self> {
Some(match value {
0 => Self::Failed,
1 => Self::Bootstrapping,
2 => Self::Bootstrapped,
3 => Self::WaitingForInput,
4 => Self::Transferring,
5 => Self::Success,
_ => return None,
})
}
}
#[derive(Debug, Default)]
pub struct RoomTable {
states: HashMap<u64, TransferPoll>,
failures: HashMap<u64, String>,
}
impl RoomTable {
pub fn get(&self, room: u64) -> Option<TransferPoll> {
self.states.get(&room).copied()
}
pub fn update(&mut self, room: u64, status: TransferPoll) {
let entry = self.states.entry(room).or_insert(status);
*entry = if *entry == TransferPoll::Failed || status == TransferPoll::Failed {
TransferPoll::Failed
} else {
(*entry).max(status)
};
}
pub fn record_failure(&mut self, room: u64, reason: impl Into<String>) {
self.failures.insert(room, reason.into());
}
pub fn has_failure(&self, room: u64) -> bool {
self.failures.contains_key(&room)
}
pub fn failure(&self, room: u64) -> Option<&str> {
self.failures.get(&room).map(String::as_str)
}
pub fn remove(&mut self, room: u64) {
self.states.remove(&room);
self.failures.remove(&room);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn states_advance_and_failure_sticks() {
let mut table = RoomTable::default();
table.update(1, TransferPoll::Bootstrapped);
table.update(1, TransferPoll::Bootstrapping);
assert_eq!(table.get(1), Some(TransferPoll::Bootstrapped));
table.update(1, TransferPoll::Failed);
table.update(1, TransferPoll::Success);
assert_eq!(table.get(1), Some(TransferPoll::Failed));
assert_eq!(table.get(2), None);
assert_eq!(TransferPoll::from_wire(5), Some(TransferPoll::Success));
assert_eq!(TransferPoll::from_wire(9), None);
}
}