Skip to main content

cliquenet/msg/
hello.rs

1use std::time::Duration;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub enum Hello {
5    Ok,
6    BackOff(Duration),
7    Unknown,
8}
9
10impl Hello {
11    pub fn is_ok(&self) -> bool {
12        matches!(self, Self::Ok)
13    }
14
15    pub fn backoff_duration(&self) -> Option<Duration> {
16        if let Self::BackOff(d) = self {
17            Some(*d)
18        } else {
19            None
20        }
21    }
22}
23
24impl Hello {
25    pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
26        match bytes.first()? {
27            0 => Some(Self::Ok),
28            1 => {
29                let d = u64::from_be_bytes(bytes.get(1..9)?.try_into().ok()?);
30                Some(Self::BackOff(Duration::from_secs(d)))
31            },
32            _ => Some(Self::Unknown),
33        }
34    }
35
36    pub fn to_bytes(&self) -> HelloBytes {
37        match self {
38            Self::Ok => HelloBytes::Ok([0]),
39            Self::BackOff(d) => {
40                let mut b = [1; 9];
41                b[1..].copy_from_slice(&d.as_secs().to_be_bytes());
42                HelloBytes::BackOff(b)
43            },
44            Self::Unknown => unreachable!("nothing constructs Hello::Unknown"),
45        }
46    }
47}
48
49pub(crate) enum HelloBytes {
50    Ok([u8; 1]),
51    BackOff([u8; 9]),
52}
53
54impl AsRef<[u8]> for HelloBytes {
55    fn as_ref(&self) -> &[u8] {
56        match self {
57            Self::Ok(a) => &a[..],
58            Self::BackOff(a) => &a[..],
59        }
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use std::time::Duration;
66
67    use quickcheck::{Arbitrary, Gen, quickcheck};
68
69    use super::Hello;
70
71    impl Arbitrary for Hello {
72        fn arbitrary(g: &mut Gen) -> Self {
73            match bool::arbitrary(g) {
74                true => Self::Ok,
75                false => Self::BackOff(Duration::from_secs(u64::arbitrary(g))),
76            }
77        }
78    }
79
80    quickcheck! {
81        fn prop_to_bytes_from_bytes_id(h1: Hello) -> bool {
82            let b = h1.to_bytes();
83            let h2 = Hello::from_bytes(b.as_ref());
84            Some(h1) == h2
85        }
86    }
87}