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}