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    /// Returns true if the payload uses chunked transfer encoding
45    #[inline]
46    pub fn is_chunked(&self) -> bool {
47        matches!(self, PayloadSize::Chunked)
48    }
49
50    /// Returns true if the payload is empty
51    #[inline]
52    pub fn is_empty(&self) -> bool {
53        matches!(self, PayloadSize::Empty)
54    }
55}
56
57impl<T> Message<T> {
58    /// Returns true if this message contains payload data
59    #[inline]
60    pub fn is_payload(&self) -> bool {
61        matches!(self, Message::Payload(_))
62    }
63
64    /// Returns true if this message contains header information
65    #[inline]
66    pub fn is_header(&self) -> bool {
67        matches!(self, Message::Header(_))
68    }
69
70    /// Converts the message into a PayloadItem if it contains payload data
71    ///
72    /// Returns None if the message contains header information
73    pub fn into_payload_item(self) -> Option<PayloadItem> {
74        match self {
75            Message::Header(_) => None,
76            Message::Payload(payload_item) => Some(payload_item),
77        }
78    }
79}
80
81/// Converts bytes into a Message
82///
83/// This allows bytes to be directly converted into a Message for sending payload data.
84/// The generic type T is unused since this only creates payload messages.
85impl<T> From<Bytes> for Message<T> {
86    fn from(bytes: Bytes) -> Self {
87        Self::Payload(PayloadItem::Chunk(bytes))
88    }
89}
90
91impl<D: Buf> PayloadItem<D> {
92    /// Returns true if this item represents the end of the payload stream
93    #[inline]
94    pub fn is_eof(&self) -> bool {
95        matches!(self, PayloadItem::Eof)
96    }
97
98    /// Returns true if this item contains chunk data
99    #[inline]
100    pub fn is_chunk(&self) -> bool {
101        matches!(self, PayloadItem::Chunk(_))
102    }
103}
104
105impl PayloadItem {
106    /// Returns a reference to the contained bytes if this is a Chunk
107    ///
108    /// Returns None if this is an EOF marker
109    pub fn as_bytes(&self) -> Option<&Bytes> {
110        match self {
111            PayloadItem::Chunk(bytes) => Some(bytes),
112            PayloadItem::Eof => None,
113        }
114    }
115
116    /// Returns a mutable reference to the contained bytes if this is a Chunk
117    ///
118    /// Returns None if this is an EOF marker
119    pub fn as_mut_bytes(&mut self) -> Option<&mut Bytes> {
120        match self {
121            PayloadItem::Chunk(bytes) => Some(bytes),
122            PayloadItem::Eof => None,
123        }
124    }
125
126    /// Consumes the PayloadItem and returns the contained bytes if this is a Chunk
127    ///
128    /// Returns None if this is an EOF marker
129    pub fn into_bytes(self) -> Option<Bytes> {
130        match self {
131            PayloadItem::Chunk(bytes) => Some(bytes),
132            PayloadItem::Eof => None,
133        }
134    }
135}