micro_http/protocol/
message.rs

1use bytes::{Buf, Bytes};
2
3/// Represents a HTTP message that can either be a header or payload.
4///
5/// This enum is used to handle both request and response messages in the HTTP protocol.
6/// The generic parameter `T` typically represents the header type (request or response header),
7/// while `Data` represents the type of the payload data (defaults to `Bytes`).
8pub enum Message<T, Data: Buf = Bytes> {
9    /// Contains the header information of type `T`
10    Header(T),
11    /// Contains a chunk of payload data or EOF marker
12    Payload(PayloadItem<Data>),
13}
14
15/// Represents an item in the HTTP message payload stream.
16///
17/// This enum is used by the payload decoder to produce either data chunks
18/// or signal the end of the payload stream (EOF).
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub enum PayloadItem<Data: Buf = Bytes> {
21    /// A chunk of payload data
22    Chunk(Data),
23    /// Marks the end of the payload stream
24    Eof,
25}
26
27/// Represents the size information of an HTTP payload.
28///
29/// This enum is used to determine how the payload should be processed:
30/// - Known length: Process exact number of bytes
31/// - Chunked: Process using chunked transfer encoding
32/// - Empty: No payload to process
33#[derive(Debug, Copy, Clone, PartialEq, Eq)]
34pub enum PayloadSize {
35    /// Payload with known length in bytes
36    Length(u64),
37    /// Payload using chunked transfer encoding
38    Chunked,
39    /// Empty payload (no body)
40    Empty,
41}
42
43impl PayloadSize {
44    #[inline(always)]
45    pub fn new_chunked() -> Self {
46        PayloadSize::Chunked
47    }
48
49    #[inline(always)]
50    pub fn new_empty() -> Self {
51        PayloadSize::Empty
52    }
53
54    #[inline(always)]
55    pub fn new_length(length: u64) -> Self {
56        PayloadSize::Length(length)
57    }
58
59    /// Returns true if the payload uses chunked transfer encoding
60    #[inline]
61    pub fn is_chunked(&self) -> bool {
62        matches!(self, PayloadSize::Chunked)
63    }
64
65    /// Returns true if the payload is empty
66    #[inline]
67    pub fn is_empty(&self) -> bool {
68        matches!(self, PayloadSize::Empty)
69    }
70}
71
72impl<T> Message<T> {
73    /// Returns true if this message contains payload data
74    #[inline]
75    pub fn is_payload(&self) -> bool {
76        matches!(self, Message::Payload(_))
77    }
78
79    /// Returns true if this message contains header information
80    #[inline]
81    pub fn is_header(&self) -> bool {
82        matches!(self, Message::Header(_))
83    }
84
85    /// Converts the message into a PayloadItem if it contains payload data
86    ///
87    /// Returns None if the message contains header information
88    pub fn into_payload_item(self) -> Option<PayloadItem> {
89        match self {
90            Message::Header(_) => None,
91            Message::Payload(payload_item) => Some(payload_item),
92        }
93    }
94}
95
96/// Converts bytes into a Message
97///
98/// This allows bytes to be directly converted into a Message for sending payload data.
99/// The generic type T is unused since this only creates payload messages.
100impl<T> From<Bytes> for Message<T> {
101    fn from(bytes: Bytes) -> Self {
102        Self::Payload(PayloadItem::Chunk(bytes))
103    }
104}
105
106impl<D: Buf> PayloadItem<D> {
107    /// Returns true if this item represents the end of the payload stream
108    #[inline]
109    pub fn is_eof(&self) -> bool {
110        matches!(self, PayloadItem::Eof)
111    }
112
113    /// Returns true if this item contains chunk data
114    #[inline]
115    pub fn is_chunk(&self) -> bool {
116        matches!(self, PayloadItem::Chunk(_))
117    }
118}
119
120impl PayloadItem {
121    /// Returns a reference to the contained bytes if this is a Chunk
122    ///
123    /// Returns None if this is an EOF marker
124    pub fn as_bytes(&self) -> Option<&Bytes> {
125        match self {
126            PayloadItem::Chunk(bytes) => Some(bytes),
127            PayloadItem::Eof => None,
128        }
129    }
130
131    /// Returns a mutable reference to the contained bytes if this is a Chunk
132    ///
133    /// Returns None if this is an EOF marker
134    pub fn as_mut_bytes(&mut self) -> Option<&mut Bytes> {
135        match self {
136            PayloadItem::Chunk(bytes) => Some(bytes),
137            PayloadItem::Eof => None,
138        }
139    }
140
141    /// Consumes the PayloadItem and returns the contained bytes if this is a Chunk
142    ///
143    /// Returns None if this is an EOF marker
144    pub fn into_bytes(self) -> Option<Bytes> {
145        match self {
146            PayloadItem::Chunk(bytes) => Some(bytes),
147            PayloadItem::Eof => None,
148        }
149    }
150}