Skip to main content

cliquenet/msg/
trailer.rs

1use bytes::Bytes;
2
3use crate::msg::{MsgId, Slot};
4
5const STD: u8 = 0;
6const NO_ACK: u8 = 1;
7
8/// Meta information appended at the end of a message.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum Trailer {
11    Std {
12        /// The slot the message corresponds to.
13        slot: Slot,
14        /// The message ID.
15        id: MsgId,
16    },
17    NoAck {
18        /// The slot the message corresponds to.
19        slot: Slot,
20    },
21    Unknown,
22}
23
24impl Trailer {
25    pub const MAX_SIZE: usize = u8::MAX as usize;
26
27    pub(crate) fn from_bytes(bytes: &mut Bytes) -> Option<Self> {
28        if bytes.len() < 2 {
29            return None;
30        }
31        let len = bytes.len();
32        let trailer_len = bytes[len - 1];
33        let trailer_typ = bytes[len - 2];
34        match trailer_typ {
35            STD => {
36                if trailer_len != 16 {
37                    return None;
38                }
39                let id = u64::from_be_bytes(bytes[len - 10..len - 2].try_into().ok()?);
40                let slot = u64::from_be_bytes(bytes[len - 18..len - 10].try_into().ok()?);
41                bytes.truncate(len - 18);
42                Some(Self::Std {
43                    slot: Slot(slot),
44                    id: MsgId(id),
45                })
46            },
47            NO_ACK => {
48                if trailer_len != 8 {
49                    return None;
50                }
51                let slot = u64::from_be_bytes(bytes[len - 10..len - 2].try_into().ok()?);
52                bytes.truncate(len - 10);
53                Some(Self::NoAck { slot: Slot(slot) })
54            },
55            _ => {
56                let trailer_len = 2 + usize::from(trailer_len);
57                if trailer_len > len {
58                    return None;
59                }
60                bytes.truncate(len - trailer_len);
61                Some(Self::Unknown)
62            },
63        }
64    }
65
66    pub(crate) fn to_bytes(self) -> TrailerBytes {
67        match self {
68            Self::Std { slot, id } => {
69                let mut buf = [0; 18];
70                buf[..8].copy_from_slice(&slot.0.to_be_bytes()[..]);
71                buf[8..16].copy_from_slice(&id.0.to_be_bytes()[..]);
72                buf[16] = STD;
73                buf[17] = 16;
74                TrailerBytes::Std(buf)
75            },
76            Self::NoAck { slot } => {
77                let mut buf = [0; 10];
78                buf[..8].copy_from_slice(&slot.0.to_be_bytes()[..]);
79                buf[8] = NO_ACK;
80                buf[9] = 8;
81                TrailerBytes::NoAck(buf)
82            },
83            Self::Unknown => {
84                unreachable!("nothing constructs an unknown trailer")
85            },
86        }
87    }
88}
89
90#[derive(Debug, Clone, Copy)]
91pub(crate) enum TrailerBytes {
92    Std([u8; 18]),
93    NoAck([u8; 10]),
94}
95
96impl AsRef<[u8]> for TrailerBytes {
97    fn as_ref(&self) -> &[u8] {
98        match self {
99            Self::Std(a) => &a[..],
100            Self::NoAck(a) => &a[..],
101        }
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use bytes::Bytes;
108    use quickcheck::{Arbitrary, Gen, quickcheck};
109
110    use super::Trailer;
111    use crate::msg::{MsgId, Slot};
112
113    impl Arbitrary for Trailer {
114        fn arbitrary(g: &mut Gen) -> Self {
115            match bool::arbitrary(g) {
116                true => Self::Std {
117                    slot: Slot(u64::arbitrary(g)),
118                    id: MsgId(u64::arbitrary(g)),
119                },
120                false => Self::NoAck {
121                    slot: Slot(u64::arbitrary(g)),
122                },
123            }
124        }
125    }
126
127    quickcheck! {
128        fn prop_to_bytes_from_bytes_id(t1: Trailer) -> bool {
129            let mut b = Bytes::copy_from_slice(t1.to_bytes().as_ref());
130            let t2 = Trailer::from_bytes(&mut b);
131            Some(t1) == t2
132        }
133    }
134}