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}