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
use std::net::SocketAddr;

use bincode::{encode_into_std_write, error::EncodeError};

use crate::{
    header::{Peers, Reliability, HEADER_SIZE},
    protocol::MAX_PACKAGE_SIZE,
    tasks::communicator::BINCODE_CONF,
    MAX_DATAGRAM_SIZE,
};

/// A package to be send.
pub struct OutPackage {
    /// First [`HEADER_SIZE`] bytes are reserved for the header. Payload must
    /// follow.
    data: Vec<u8>,
    reliability: Reliability,
    peers: Peers,
    target: SocketAddr,
}

impl OutPackage {
    /// Creates a package from a single message.
    pub fn encode_single<E>(
        message: &E,
        reliability: Reliability,
        peers: Peers,
        target: SocketAddr,
    ) -> Result<Self, EncodeError>
    where
        E: bincode::Encode,
    {
        let mut data = Vec::with_capacity(HEADER_SIZE + 1);
        data.extend([0; HEADER_SIZE]);
        encode_into_std_write(message, &mut data, BINCODE_CONF)?;
        Ok(Self::new(data, reliability, peers, target))
    }

    /// # Panics
    ///
    /// If `data` is longer than [`MAX_PACKAGE_SIZE`].
    pub fn from_slice(
        data: &[u8],
        reliability: Reliability,
        peers: Peers,
        target: SocketAddr,
    ) -> Self {
        assert!(data.len() <= MAX_PACKAGE_SIZE);

        let mut full_data = Vec::with_capacity(HEADER_SIZE + data.len());
        full_data.extend([0; HEADER_SIZE]);
        full_data.extend(data);
        Self::new(full_data, reliability, peers, target)
    }

    /// # Arguments
    ///
    /// * `data` - data to be send. The message data must start exactly at
    ///   [`HEADER_SIZE`]. The initial bytes are reserved for the header. The
    ///   header is not filled by the caller.
    ///
    /// * `reliability` - package delivery reliability mode.
    ///
    /// * `target` - package recipient.
    ///
    /// # Panics
    ///
    /// * If data length is smaller or equal to header size..
    ///
    /// * If data is longer than [`MAX_DATAGRAM_SIZE`].
    pub(super) fn new(
        data: Vec<u8>,
        reliability: Reliability,
        peers: Peers,
        target: SocketAddr,
    ) -> Self {
        assert!(data.len() > HEADER_SIZE);
        assert!(data.len() <= MAX_DATAGRAM_SIZE);
        Self {
            data,
            reliability,
            peers,
            target,
        }
    }

    /// Returns package data.
    ///
    /// The data start at [`HEADER_SIZE`] so that header may be written
    /// to the beginning of the vector.
    pub(crate) fn data(self) -> Vec<u8> {
        self.data
    }

    /// Returns slice to the payload part (without header) of the data.
    pub(crate) fn data_slice(&self) -> &[u8] {
        &self.data[HEADER_SIZE..]
    }

    pub(crate) fn reliability(&self) -> Reliability {
        self.reliability
    }

    pub(crate) fn peers(&self) -> Peers {
        self.peers
    }

    pub(crate) fn target(&self) -> SocketAddr {
        self.target
    }
}