Skip to main content

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}