emissary_core/i2np/
delivery_status.rs

1// Permission is hereby granted, free of charge, to any person obtaining a
2// copy of this software and associated documentation files (the "Software"),
3// to deal in the Software without restriction, including without limitation
4// the rights to use, copy, modify, merge, publish, distribute, sublicense,
5// and/or sell copies of the Software, and to permit persons to whom the
6// Software is furnished to do so, subject to the following conditions:
7//
8// The above copyright notice and this permission notice shall be included in
9// all copies or substantial portions of the Software.
10//
11// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
16// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19use bytes::{BufMut, BytesMut};
20use nom::{
21    number::complete::{be_u32, be_u64},
22    IResult,
23};
24
25use core::time::Duration;
26
27/// Delivery status.
28pub struct DeliveryStatus {
29    /// Message ID.
30    pub message_id: u32,
31
32    /// Timestamp as duration since UNIX epoch.
33    pub timestamp: Duration,
34}
35
36impl DeliveryStatus {
37    /// Attempt to parse [`DeliveryStatus`] from `input`.
38    ///
39    /// Returns the parsed message and rest of `input` on success.
40    pub fn parse_frame(input: &[u8]) -> IResult<&[u8], Self> {
41        let (rest, message_id) = be_u32(input)?;
42        let (rest, timestamp) = be_u64(rest)?;
43
44        Ok((
45            rest,
46            Self {
47                message_id,
48                timestamp: Duration::from_millis(timestamp),
49            },
50        ))
51    }
52
53    /// Attempt to parse `input` into [`DeliveryStatus`].
54    pub fn parse(input: &[u8]) -> Option<Self> {
55        Self::parse_frame(input).ok().map(|(_, message)| message)
56    }
57
58    /// Serialize [`DeliveryStatus`] into a byte vector.
59    pub fn serialize(self) -> BytesMut {
60        let mut out = BytesMut::with_capacity(4 + 8);
61
62        out.put_u32(self.message_id);
63        out.put_u64(self.timestamp.as_millis() as u64);
64
65        out
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn serialize_deserialize() {
75        let serialized = DeliveryStatus {
76            message_id: 13371338u32,
77            timestamp: Duration::from_millis(13391440),
78        }
79        .serialize();
80
81        let DeliveryStatus {
82            message_id,
83            timestamp,
84        } = DeliveryStatus::parse(&serialized).unwrap();
85        assert_eq!(message_id, 13371338u32);
86        assert_eq!(timestamp, Duration::from_millis(13391440));
87    }
88}