bitfold_protocol/
packet.rs

1//! Packet types and structures for the command-based protocol.
2//!
3//! This module provides the core packet types used throughout the protocol:
4//! - `Packet`: User-facing packet with payload and guarantees
5//! - `PacketInfo`: Non-owning packet metadata for processing
6//! - `IncomingPackets`: Collection type for returning 0, 1, or many packets
7//! - Delivery and ordering guarantee enums
8
9use std::{collections::VecDeque, convert::TryFrom, net::SocketAddr, sync::Arc};
10
11use bitfold_core::{
12    either::Either,
13    error::{DecodingErrorKind, ErrorKind},
14};
15
16/// 16-bit sequence number type used by protocol.
17pub type SequenceNumber = u16;
18
19/// Helper trait to convert enums to u8 values for wire format.
20pub trait EnumConverter {
21    /// The enum type this converter works with.
22    type Enum;
23
24    /// Converts the enum to a u8 for serialization.
25    fn to_u8(&self) -> u8;
26}
27
28// ============================================================================
29// Delivery and Ordering Guarantees
30// ============================================================================
31
32/// Enum to specify how a packet should be delivered.
33#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq)]
34pub enum DeliveryGuarantee {
35    /// Packet may or may not be delivered
36    Unreliable,
37    /// Packet will be delivered
38    Reliable,
39}
40
41impl EnumConverter for DeliveryGuarantee {
42    type Enum = DeliveryGuarantee;
43
44    /// Returns an integer value from `DeliveryGuarantee` enum.
45    fn to_u8(&self) -> u8 {
46        *self as u8
47    }
48}
49
50impl TryFrom<u8> for DeliveryGuarantee {
51    type Error = ErrorKind;
52    /// Gets the `DeliveryGuarantee` enum instance from integer value.
53    fn try_from(value: u8) -> Result<Self, Self::Error> {
54        match value {
55            0 => Ok(DeliveryGuarantee::Unreliable),
56            1 => Ok(DeliveryGuarantee::Reliable),
57            _ => Err(ErrorKind::DecodingError(DecodingErrorKind::DeliveryGuarantee)),
58        }
59    }
60}
61
62/// Enum to specify how a packet should be arranged.
63#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Default)]
64pub enum OrderingGuarantee {
65    /// No arranging will be done.
66    #[default]
67    None,
68    /// Packets will be arranged in sequence.
69    Sequenced(Option<u8>),
70    /// Packets will be arranged in order.
71    Ordered(Option<u8>),
72    /// Unsequenced delivery - prevents duplicates but allows out-of-order.
73    Unsequenced,
74}
75
76impl EnumConverter for OrderingGuarantee {
77    type Enum = OrderingGuarantee;
78
79    /// Returns the integer value from `OrderingGuarantee` enum.
80    fn to_u8(&self) -> u8 {
81        match self {
82            OrderingGuarantee::None => 0,
83            OrderingGuarantee::Sequenced(_) => 1,
84            OrderingGuarantee::Ordered(_) => 2,
85            OrderingGuarantee::Unsequenced => 3,
86        }
87    }
88}
89
90impl TryFrom<u8> for OrderingGuarantee {
91    type Error = ErrorKind;
92    /// Returns the `OrderingGuarantee` enum instance from integer value.
93    fn try_from(value: u8) -> Result<Self, Self::Error> {
94        match value {
95            0 => Ok(OrderingGuarantee::None),
96            1 => Ok(OrderingGuarantee::Sequenced(None)),
97            2 => Ok(OrderingGuarantee::Ordered(None)),
98            3 => Ok(OrderingGuarantee::Unsequenced),
99            _ => Err(ErrorKind::DecodingError(DecodingErrorKind::OrderingGuarantee)),
100        }
101    }
102}
103
104/// Id to identify a certain packet type.
105#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
106pub enum PacketType {
107    /// Full packet that is not fragmented
108    Packet = 0,
109    /// Fragment of a full packet
110    Fragment = 1,
111    /// Heartbeat packet
112    Heartbeat = 2,
113}
114
115impl EnumConverter for PacketType {
116    type Enum = PacketType;
117
118    fn to_u8(&self) -> u8 {
119        *self as u8
120    }
121}
122
123impl TryFrom<u8> for PacketType {
124    type Error = ErrorKind;
125    fn try_from(value: u8) -> Result<Self, Self::Error> {
126        match value {
127            0 => Ok(PacketType::Packet),
128            1 => Ok(PacketType::Fragment),
129            2 => Ok(PacketType::Heartbeat),
130            _ => Err(ErrorKind::DecodingError(DecodingErrorKind::PacketType)),
131        }
132    }
133}
134
135// ============================================================================
136// Packet Structures
137// ============================================================================
138
139/// User-friendly packet containing payload, endpoint, and guarantees.
140#[derive(Clone, PartialEq, Eq, Debug)]
141pub struct Packet {
142    addr: SocketAddr,
143    payload: Arc<[u8]>,
144    delivery: DeliveryGuarantee,
145    ordering: OrderingGuarantee,
146    channel_id: u8,
147}
148
149impl Packet {
150    /// Creates a new packet with the specified guarantees and channel.
151    pub fn new(
152        addr: SocketAddr,
153        payload: Arc<[u8]>,
154        delivery: DeliveryGuarantee,
155        ordering: OrderingGuarantee,
156        channel_id: u8,
157    ) -> Packet {
158        Packet { addr, payload, delivery, ordering, channel_id }
159    }
160
161    /// Creates an unreliable, unordered packet on channel 0 (fire-and-forget).
162    pub fn unreliable(addr: SocketAddr, payload: Vec<u8>) -> Packet {
163        Packet {
164            addr,
165            payload: Arc::<[u8]>::from(payload),
166            delivery: DeliveryGuarantee::Unreliable,
167            ordering: OrderingGuarantee::None,
168            channel_id: 0,
169        }
170    }
171
172    /// Creates an unreliable, sequenced packet on channel 0 (drops out-of-order).
173    pub fn unreliable_sequenced(
174        addr: SocketAddr,
175        payload: Vec<u8>,
176        stream_id: Option<u8>,
177    ) -> Packet {
178        Packet {
179            addr,
180            payload: Arc::<[u8]>::from(payload),
181            delivery: DeliveryGuarantee::Unreliable,
182            ordering: OrderingGuarantee::Sequenced(stream_id),
183            channel_id: 0,
184        }
185    }
186
187    /// Creates an unreliable, unsequenced packet on channel 0 (prevents duplicates, allows out-of-order).
188    pub fn unsequenced(addr: SocketAddr, payload: Vec<u8>) -> Packet {
189        Packet {
190            addr,
191            payload: Arc::<[u8]>::from(payload),
192            delivery: DeliveryGuarantee::Unreliable,
193            ordering: OrderingGuarantee::Unsequenced,
194            channel_id: 0,
195        }
196    }
197
198    /// Creates a reliable, unordered packet on channel 0 (guaranteed delivery).
199    pub fn reliable_unordered(addr: SocketAddr, payload: Vec<u8>) -> Packet {
200        Packet {
201            addr,
202            payload: Arc::<[u8]>::from(payload),
203            delivery: DeliveryGuarantee::Reliable,
204            ordering: OrderingGuarantee::None,
205            channel_id: 0,
206        }
207    }
208
209    /// Creates a reliable, ordered packet on channel 0 (TCP-like).
210    pub fn reliable_ordered(addr: SocketAddr, payload: Vec<u8>, stream_id: Option<u8>) -> Packet {
211        Packet {
212            addr,
213            payload: Arc::<[u8]>::from(payload),
214            delivery: DeliveryGuarantee::Reliable,
215            ordering: OrderingGuarantee::Ordered(stream_id),
216            channel_id: 0,
217        }
218    }
219
220    /// Creates a reliable, sequenced packet on channel 0 (keeps latest).
221    pub fn reliable_sequenced(addr: SocketAddr, payload: Vec<u8>, stream_id: Option<u8>) -> Packet {
222        Packet {
223            addr,
224            payload: Arc::<[u8]>::from(payload),
225            delivery: DeliveryGuarantee::Reliable,
226            ordering: OrderingGuarantee::Sequenced(stream_id),
227            channel_id: 0,
228        }
229    }
230
231    /// Creates an unreliable, unordered packet on specified channel (fire-and-forget).
232    pub fn unreliable_on_channel(addr: SocketAddr, payload: Vec<u8>, channel_id: u8) -> Packet {
233        Packet {
234            addr,
235            payload: Arc::<[u8]>::from(payload),
236            delivery: DeliveryGuarantee::Unreliable,
237            ordering: OrderingGuarantee::None,
238            channel_id,
239        }
240    }
241
242    /// Creates a reliable, unordered packet on specified channel (guaranteed delivery).
243    pub fn reliable_on_channel(addr: SocketAddr, payload: Vec<u8>, channel_id: u8) -> Packet {
244        Packet {
245            addr,
246            payload: Arc::<[u8]>::from(payload),
247            delivery: DeliveryGuarantee::Reliable,
248            ordering: OrderingGuarantee::None,
249            channel_id,
250        }
251    }
252
253    /// Returns a slice of the packet payload.
254    pub fn payload(&self) -> &[u8] {
255        &self.payload
256    }
257
258    /// Consumes the packet and returns the payload.
259    pub fn into_payload(self) -> Arc<[u8]> {
260        self.payload
261    }
262
263    /// Returns a clone of the underlying Arc payload for zero-copy sharing.
264    pub fn payload_arc(&self) -> Arc<[u8]> {
265        self.payload.clone()
266    }
267
268    /// Returns the remote endpoint address.
269    pub fn addr(&self) -> SocketAddr {
270        self.addr
271    }
272
273    /// Returns the delivery guarantee for this packet.
274    pub fn delivery_guarantee(&self) -> DeliveryGuarantee {
275        self.delivery
276    }
277
278    /// Returns the ordering guarantee for this packet.
279    pub fn order_guarantee(&self) -> OrderingGuarantee {
280        self.ordering
281    }
282
283    /// Returns the channel ID for this packet.
284    pub fn channel_id(&self) -> u8 {
285        self.channel_id
286    }
287}
288
289/// Non-owning packet metadata used during processing.
290#[derive(Debug)]
291pub struct PacketInfo<'a> {
292    /// Type of packet (user data, heartbeat, fragment, etc.)
293    pub packet_type: PacketType,
294    /// Reference to the packet payload
295    pub payload: &'a [u8],
296    /// Delivery guarantee for this packet
297    pub delivery: DeliveryGuarantee,
298    /// Ordering guarantee for this packet
299    pub ordering: OrderingGuarantee,
300}
301
302impl<'a> PacketInfo<'a> {
303    /// Creates packet info for user data with specified guarantees.
304    pub fn user_packet(
305        payload: &'a [u8],
306        delivery: DeliveryGuarantee,
307        ordering: OrderingGuarantee,
308    ) -> Self {
309        PacketInfo { packet_type: PacketType::Packet, payload, delivery, ordering }
310    }
311
312    /// Creates packet info for a heartbeat/keepalive packet.
313    pub fn heartbeat_packet(payload: &'a [u8]) -> Self {
314        PacketInfo {
315            packet_type: PacketType::Heartbeat,
316            payload,
317            delivery: DeliveryGuarantee::Unreliable,
318            ordering: OrderingGuarantee::None,
319        }
320    }
321}
322
323// ============================================================================
324// Collection Types for Packet Processing
325// ============================================================================
326
327/// Iterator over 0, 1, or many items.
328#[derive(Debug)]
329pub struct ZeroOrMore<T> {
330    data: Either<Option<T>, VecDeque<T>>,
331}
332
333impl<T> ZeroOrMore<T> {
334    pub(crate) fn zero() -> Self {
335        Self { data: Either::Left(None) }
336    }
337    pub(crate) fn one(data: T) -> Self {
338        Self { data: Either::Left(Some(data)) }
339    }
340    pub(crate) fn many(vec: VecDeque<T>) -> Self {
341        Self { data: Either::Right(vec) }
342    }
343}
344
345impl<T> Iterator for ZeroOrMore<T> {
346    type Item = T;
347    fn next(&mut self) -> Option<Self::Item> {
348        match &mut self.data {
349            Either::Left(option) => option.take(),
350            Either::Right(vec) => vec.pop_front(),
351        }
352    }
353}
354
355/// Collection of incoming packets (0, 1, or many) with their types.
356/// Used by command-based packet processing to return variable numbers of packets.
357#[derive(Debug)]
358pub struct IncomingPackets {
359    data: ZeroOrMore<(Packet, PacketType)>,
360}
361
362impl IncomingPackets {
363    /// Creates an empty collection (no packets received).
364    pub fn zero() -> Self {
365        Self { data: ZeroOrMore::zero() }
366    }
367
368    /// Creates a collection with a single packet and type.
369    pub fn one(packet: Packet, packet_type: PacketType) -> Self {
370        Self { data: ZeroOrMore::one((packet, packet_type)) }
371    }
372
373    /// Creates a collection with multiple packets.
374    pub fn many(vec: VecDeque<(Packet, PacketType)>) -> Self {
375        Self { data: ZeroOrMore::many(vec) }
376    }
377}
378
379impl IntoIterator for IncomingPackets {
380    type Item = (Packet, PacketType);
381    type IntoIter = ZeroOrMore<Self::Item>;
382    fn into_iter(self) -> Self::IntoIter {
383        self.data
384    }
385}