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