6 /// Encountered when trying to construct a [`ConnectDatagram`] with an empty message body.
8 #[derive(Debug, Clone)]
9 pub struct DatagramEmptyError;
11 impl Error for DatagramEmptyError {}
13 impl std::fmt::Display for DatagramEmptyError {
14 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
17 "datagram cannot be constructed when provided payload is empty"
22 /// A simple packet format containing a version, recipient tag, and message body.
25 pub struct ConnectDatagram {
28 data: Option<Vec<u8>>,
31 impl ConnectDatagram {
32 /// Creates a new [`ConnectDatagram`] based on an intended recipient and message body.
34 /// This will return a [`DatagramEmptyError`] if the `data` parameter contains no bytes, or
35 /// in other words, when there is no message body.
37 /// The version field is decided by the library version and used to maintain backwards
38 /// compatibility with previous datagram formats.
40 pub fn new(recipient: u16, data: Vec<u8>) -> Result<Self, DatagramEmptyError> {
48 Err(DatagramEmptyError)
52 /// Gets the version number of the datagram.
54 pub fn version(&self) -> u8 {
58 /// Gets the recipient of the datagram.
60 pub fn recipient(&self) -> u16 {
64 /// Gets the message body of the datagram.
66 pub fn data(&self) -> Option<&Vec<u8>> {
70 /// Takes ownership of the message body of the datagram.
72 pub fn take_data(&mut self) -> Option<Vec<u8>> {
76 /// Calculates the serialized byte-size of the datagram.
78 pub fn size(&self) -> usize {
79 let data_len = if let Some(data) = self.data() {
88 /// Constructs a serialized representation of the datagram contents.
90 pub(crate) fn bytes(&self) -> Vec<u8> {
91 let mut bytes = Vec::with_capacity(self.size());
93 bytes.extend(&self.version.to_be_bytes());
94 bytes.extend(&self.recipient.to_be_bytes());
96 if let Some(data) = self.data() {
97 bytes.extend(data.as_slice());
103 /// Serializes the datagram.
105 pub fn encode(self) -> Vec<u8> {
106 let size: u32 = (self.size()) as u32;
108 let mut bytes = Vec::from(size.to_be_bytes());
109 bytes.extend(self.bytes());
114 /// Deserializes the datagram from a `source`.
116 pub fn decode(source: &mut (dyn Read + Send + Sync)) -> anyhow::Result<Self> {
118 let mut payload_size_bytes: [u8; 4] = [0; 4];
119 source.read_exact(&mut payload_size_bytes)?;
120 let payload_size = u32::from_be_bytes(payload_size_bytes);
122 // read whole payload
123 let mut payload_bytes = vec![0; payload_size as usize];
124 source.read_exact(payload_bytes.as_mut_slice())?;
127 let version_bytes = payload_bytes.remove(0);
128 let version = u8::from_be(version_bytes);
131 let mut recipient_bytes: [u8; 2] = [0; 2];
132 for i in 0..recipient_bytes.len() {
133 recipient_bytes[i] = payload_bytes.remove(0);
135 let recipient = u16::from_be_bytes(recipient_bytes);
138 let data = payload_bytes;
147 Err(anyhow::Error::from(DatagramEmptyError))
154 use crate::protocol::ConnectDatagram;
158 fn encoded_size() -> anyhow::Result<()> {
159 let mut data = Vec::new();
163 assert_eq!(5, data.len());
165 let sample = ConnectDatagram::new(1, data)?;
166 assert_eq!(7 + 5, sample.encode().len());
172 fn take_data() -> anyhow::Result<()> {
173 let mut data = Vec::new();
178 let mut sample = ConnectDatagram::new(1, data)?;
180 let taken_data = sample.take_data().unwrap();
181 assert!(sample.data().is_none());
182 assert_eq!(5, taken_data.len());
188 async fn encode_and_decode() -> anyhow::Result<()> {
189 let mut data = Vec::new();
193 assert_eq!(5, data.len());
195 let sample = ConnectDatagram::new(1, data)?;
197 let mut payload = sample.encode();
198 assert_eq!(7 + 5, payload.len());
200 let mut cursor: Cursor<&mut [u8]> = Cursor::new(payload.as_mut());
201 let sample_back_res = ConnectDatagram::decode(&mut cursor);
202 assert!(sample_back_res.is_ok());
204 let sample_back = sample_back_res.unwrap();
205 assert_eq!(sample_back.version(), 1);
206 assert_eq!(sample_back.recipient(), 1);
207 assert_eq!(sample_back.data().unwrap().len(), 5);