datagram/lib.rs
1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/nimble-rust/nimble
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use std::io::Result;
6
7/// Trait for sending datagrams.
8///
9/// The `DatagramSender` trait provides a standardized interface for transmitting
10/// datagram-based messages, (e.g. UDP communication). Implementors
11/// handle the specifics of datagram transmission, including serialization and
12/// interfacing with underlying transport protocols.
13pub trait DatagramSender {
14 /// Sends a datagram containing the provided data.
15 ///
16 /// # Arguments
17 ///
18 /// * `buf` - An octet slice to be sent as a datagram.
19 ///
20 /// # Returns
21 ///
22 /// * `Ok(())` if the datagram was sent successfully.
23 /// * `Err(io::Error)` if an error occurred during sending.
24 fn send(&mut self, buf: &[u8]) -> Result<()>;
25}
26
27/// Trait for receiving datagrams.
28///
29/// The `DatagramReceiver` trait provides a standardized interface for receiving
30/// datagram-based messages, (e.g. UDP communication). Implementors
31/// of this trait handle the specifics of datagram reception, including deserialization
32/// and interfacing with underlying transport protocols.
33pub trait DatagramReceiver {
34 /// Receives a datagram and stores it into the provided buffer.
35 ///
36 /// # Arguments
37 ///
38 /// * `buf` - A mutable byte slice where the received datagram will be stored.
39 ///
40 /// # Returns
41 ///
42 /// * `Ok(usize)` - The number of bytes written to the buffer.
43 /// * `Err(io::Error)` - If an error occurred during reception.
44 ///
45 /// # Errors
46 ///
47 /// Returns an `io::Error` if the datagram could not be received. Common error
48 /// scenarios include network failures, invalid data formats, or issues with
49 /// the underlying transport mechanism.
50 fn receive(&mut self, buf: &mut [u8]) -> Result<usize>;
51}
52
53/// A trait that combines sending and receiving datagrams.
54pub trait DatagramCommunicator: DatagramSender + DatagramReceiver {}
55
56impl<T> DatagramCommunicator for T where T: DatagramSender + DatagramReceiver {}
57
58/// Trait for encoding datagrams.
59pub trait DatagramEncoder {
60 fn encode(&mut self, buf: &[u8]) -> Result<Vec<u8>>;
61}
62
63/// Trait for decoding datagrams.
64pub trait DatagramDecoder {
65 fn decode(&mut self, buf: &[u8]) -> Result<Vec<u8>>;
66}
67
68pub trait DatagramCodec: DatagramEncoder + DatagramDecoder {}
69impl<T> DatagramCodec for T where T: DatagramEncoder + DatagramDecoder {}
70
71/// A trait for parsing and interpreting datagrams. Somewhat similar to DatagramDecoder, but instead
72/// it returns part of the same buf instead of creating a new
73pub trait DatagramParser {
74 /// Parses the entire datagram, validating both the header and footer.
75 ///
76 /// # Arguments
77 ///
78 /// * `buf` - A slice containing the entire datagram.
79 ///
80 /// # Returns
81 ///
82 /// * `io::Result<&'a [u8]>` - The slice that is available for reading.
83 fn parse<'a>(&mut self, buf: &'a [u8]) -> Result<&'a [u8]>;
84}
85
86use std::fmt;
87use std::io;
88
89#[derive(Debug)]
90pub enum DatagramError {
91 BufferFull,
92 ItemSizeTooBig,
93 IoError(io::Error),
94 OtherError(String),
95}
96
97impl fmt::Display for DatagramError {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 match self {
100 DatagramError::BufferFull => write!(f, "Buffer is full"),
101 DatagramError::IoError(err) => write!(f, "I/O error: {}", err),
102 DatagramError::OtherError(err) => write!(f, "strange error: {}", err),
103 DatagramError::ItemSizeTooBig => write!(f, "Item size is too big"),
104 }
105 }
106}
107
108impl From<io::Error> for DatagramError {
109 fn from(err: io::Error) -> Self {
110 DatagramError::IoError(err)
111 }
112}
113
114impl std::error::Error for DatagramError {}
115
116/// A trait for building datagrams by adding headers and footers. Somewhat similar to
117/// DatagramCodec, but uses an internal buffer instead of returning a new Vec<u8>.
118///
119/// Implementations of this trait are responsible for writing the necessary
120/// headers and footers to an octet buffer, defining where the payload can be
121/// written, and finalizing the datagram so it is ready for transmission.
122pub trait DatagramBuilder {
123 /// Pushes data into the current datagram.
124 ///
125 /// # Arguments
126 ///
127 /// * `data` - A slice of data to be added to the datagram.
128 ///
129 /// # Returns
130 ///
131 /// * `io::Result<DatagramError>` - Indicates success or failure.
132 fn push(&mut self, data: &[u8]) -> std::result::Result<(), DatagramError>;
133
134 /// Finalizes the datagram and returns the current octets of the datagram.
135 ///
136 /// # Returns
137 ///
138 /// * `&[u8]` - The octets of the datagram.
139 fn finalize(&mut self) -> io::Result<Vec<u8>>;
140
141 // Checks if at least one push has happened after new() or clear()
142 fn is_empty(&self) -> bool;
143
144 /// Clears the buffer and writes a new header to be able to start a new datagram.
145 fn clear(&mut self) -> io::Result<()>;
146}