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.
24 pub struct ConnectDatagram {
27 data: Option<Vec<u8>>,
30 impl ConnectDatagram {
31 /// Creates a new [`ConnectDatagram`] based on an intended recipient and message body.
33 /// This will return a [`DatagramEmptyError`] if the `data` parameter contains no bytes, or
34 /// in other words, when there is no message body.
36 /// The version field is decided by the library version and used to maintain backwards
37 /// compatibility with previous datagram formats.
39 pub fn new(recipient: u16, data: Vec<u8>) -> Result<Self, DatagramEmptyError> {
47 Err(DatagramEmptyError)
51 /// Gets the version number of the datagram.
53 pub fn version(&self) -> u8 {
57 /// Gets the recipient of the datagram.
59 pub fn recipient(&self) -> u16 {
63 /// Gets the message body of the datagram.
65 pub fn data(&self) -> Option<&Vec<u8>> {
69 /// Takes ownership of the message body of the datagram.
71 pub fn take_data(&mut self) -> Option<Vec<u8>> {
75 /// Calculates the serialized byte-size of the datagram.
77 pub fn size(&self) -> usize {
78 let data_len = if let Some(data) = self.data() {
87 /// Constructs a serialized representation of the datagram.
89 pub(crate) fn bytes(&self) -> Vec<u8> {
90 let mut bytes = Vec::with_capacity(self.size());
92 bytes.extend(&self.version.to_be_bytes());
93 bytes.extend(&self.recipient.to_be_bytes());
95 if let Some(data) = self.data() {
96 bytes.extend(data.as_slice());
102 /// Serializes the datagram.
104 pub fn encode(&self) -> Vec<u8> {
105 let size: u32 = (self.size()) as u32;
107 let mut bytes = Vec::from(size.to_be_bytes());
108 bytes.extend(self.bytes());
113 /// Deserializes the datagram from a `source`.
115 pub fn decode(source: &mut (dyn Read + Send + Sync)) -> anyhow::Result<Self> {
117 let mut payload_size_bytes: [u8; 4] = [0; 4];
118 source.read_exact(&mut payload_size_bytes)?;
119 let payload_size = u32::from_be_bytes(payload_size_bytes);
121 // read whole payload
122 let mut payload_bytes = vec![0; payload_size as usize];
123 source.read_exact(payload_bytes.as_mut_slice())?;
126 let version_bytes = payload_bytes.remove(0);
127 let version = u8::from_be(version_bytes);
130 let mut recipient_bytes: [u8; 2] = [0; 2];
131 for i in 0..recipient_bytes.len() {
132 recipient_bytes[i] = payload_bytes.remove(0);
134 let recipient = u16::from_be_bytes(recipient_bytes);
137 let data = payload_bytes;
146 Err(anyhow::Error::from(DatagramEmptyError))
153 use crate::protocol::ConnectDatagram;
157 fn encoded_size() -> anyhow::Result<()> {
158 let mut data = Vec::new();
162 assert_eq!(5, data.len());
164 let sample = ConnectDatagram::new(1, data)?;
165 assert_eq!(7 + 5, sample.encode().len());
171 fn take_data() -> anyhow::Result<()> {
172 let mut data = Vec::new();
177 let mut sample = ConnectDatagram::new(1, data)?;
179 let taken_data = sample.take_data().unwrap();
180 assert!(sample.data().is_none());
181 assert_eq!(5, taken_data.len());
187 async fn encode_and_decode() -> anyhow::Result<()> {
188 let mut data = Vec::new();
192 assert_eq!(5, data.len());
194 let sample = ConnectDatagram::new(1, data)?;
196 let mut payload = sample.encode();
197 assert_eq!(7 + 5, payload.len());
199 let mut cursor: Cursor<&mut [u8]> = Cursor::new(payload.as_mut());
200 let sample_back_res = ConnectDatagram::decode(&mut cursor);
201 assert!(sample_back_res.is_ok());
203 let sample_back = sample_back_res.unwrap();
204 assert_eq!(sample_back.version(), 1);
205 assert_eq!(sample_back.recipient(), 1);
206 assert_eq!(sample_back.data().unwrap().len(), 5);