mqtt_protocol_core/mqtt/packet/
packet_id.rs

1// MIT License
2//
3// Copyright (c) 2025 Takatoshi Kondo
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23use core::fmt::{Debug, Display};
24use core::hash::Hash;
25use num_traits::{Bounded, One, PrimInt};
26use serde::Serialize;
27
28/// Packet ID types with associated buffer operations
29pub trait IsPacketId:
30    PrimInt + One + Bounded + Debug + Display + Hash + Eq + Serialize + 'static
31{
32    /// Fixed-size buffer type
33    type Buffer: AsRef<[u8]> + AsMut<[u8]> + Clone + Default + Eq;
34
35    /// Convert packet ID to fixed-size buffer
36    fn to_buffer(&self) -> Self::Buffer;
37
38    /// Parse packet ID from buffer
39    fn from_buffer(buf: &[u8]) -> Self;
40}
41
42impl IsPacketId for u16 {
43    type Buffer = [u8; 2];
44
45    fn to_buffer(&self) -> Self::Buffer {
46        self.to_be_bytes()
47    }
48
49    fn from_buffer(buf: &[u8]) -> Self {
50        if buf.len() >= 2 {
51            u16::from_be_bytes([buf[0], buf[1]])
52        } else {
53            0
54        }
55    }
56}
57
58impl IsPacketId for u32 {
59    type Buffer = [u8; 4];
60
61    fn to_buffer(&self) -> Self::Buffer {
62        self.to_be_bytes()
63    }
64
65    fn from_buffer(buf: &[u8]) -> Self {
66        if buf.len() >= 4 {
67            u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]])
68        } else {
69            0
70        }
71    }
72}
73
74/// Trait for types that can be converted into an optional packet ID
75///
76/// This trait enables the packet_id() builder method to accept both direct values
77/// (e.g., `packet_id(42)`) and optional values (e.g., `packet_id(Some(42))` or `packet_id(None)`).
78///
79/// # Examples
80///
81/// ```
82/// use mqtt_protocol_core::mqtt::packet::IntoPacketId;
83///
84/// // Direct value
85/// let id1: Option<u16> = 42u16.into_packet_id();
86/// assert_eq!(id1, Some(42));
87///
88/// // Optional value
89/// let id2: Option<u16> = Some(42u16).into_packet_id();
90/// assert_eq!(id2, Some(42));
91///
92/// // None value
93/// let id3: Option<u16> = None::<u16>.into_packet_id();
94/// assert_eq!(id3, None);
95/// ```
96pub trait IntoPacketId<T> {
97    /// Convert self into an optional packet ID
98    fn into_packet_id(self) -> Option<T>;
99}
100
101// Implementations for u16
102
103/// Implementation for direct u16 packet ID values
104///
105/// Allows direct u16 values like `42u16` to be converted to `Some(42)`
106impl IntoPacketId<u16> for u16 {
107    fn into_packet_id(self) -> Option<u16> {
108        Some(self)
109    }
110}
111
112/// Implementation for optional u16 packet ID values
113///
114/// Allows optional values like `Some(42u16)` or `None::<u16>` to be passed through
115impl IntoPacketId<u16> for Option<u16> {
116    fn into_packet_id(self) -> Option<u16> {
117        self
118    }
119}
120
121// Implementations for u32
122
123/// Implementation for direct u32 packet ID values
124///
125/// Allows direct u32 values like `42u32` to be converted to `Some(42)`
126impl IntoPacketId<u32> for u32 {
127    fn into_packet_id(self) -> Option<u32> {
128        Some(self)
129    }
130}
131
132/// Implementation for optional u32 packet ID values
133///
134/// Allows optional values like `Some(42u32)` or `None::<u32>` to be passed through
135impl IntoPacketId<u32> for Option<u32> {
136    fn into_packet_id(self) -> Option<u32> {
137        self
138    }
139}