rust_rcs_core/internet/body/
mod.rs1pub mod message_body;
16pub mod multipart_body;
17pub mod streamed_body;
18
19use std::{
20 fmt,
21 fs::File,
22 io::{Read, Seek},
23 pin::Pin,
24 task::{Context, Poll},
25};
26
27use crate::io::{DynamicChain, Serializable};
28
29use futures::AsyncRead;
30use message_body::MessageBody;
31use multipart_body::MultipartBody;
32use streamed_body::StreamedBody;
33
34use self::streamed_body::StreamSource;
35
36#[derive(Debug)]
37pub enum BodySerializationError {
38 IO,
39}
40
41pub enum Body {
42 Raw(Vec<u8>),
43 Message(MessageBody),
44 Multipart(MultipartBody),
45 Streamed(StreamedBody),
46}
47
48impl Serializable for Body {
49 fn estimated_size(&self) -> usize {
58 match self {
59 Body::Raw(data) => data.len(),
60 Body::Message(message) => message.estimated_size(),
61 Body::Multipart(multipart) => multipart.estimated_size(),
62 Body::Streamed(stream) => stream.stream_size,
63 }
64 }
65}
66
67impl Body {
68 pub fn construct_raw(data: &[u8]) -> Body {
69 Body::Raw(data.to_vec())
70 }
71
72 pub fn construct_message(data: &[u8]) -> Result<Body, &'static str> {
73 Ok(Body::Message(MessageBody::construct(data)?))
74 }
75
76 pub fn construct_multipart(data: &[u8], boundary: &[u8]) -> Result<Body, &'static str> {
77 Ok(Body::Multipart(MultipartBody::construct(data, boundary)?))
78 }
79
80 pub fn reader(&self) -> Result<BodyReader, BodySerializationError> {
81 match self {
82 Body::Raw(data) => Ok(BodyReader::Raw(RawBodyReader { data, pos: 0 })),
83 Body::Message(message) => {
84 let mut readers = Vec::new();
85 message.get_readers(&mut readers)?;
86 let chain = DynamicChain::new(readers);
87 Ok(BodyReader::Message(chain))
88 }
89 Body::Multipart(multipart) => {
90 let mut readers = Vec::new();
91 multipart.get_readers(&mut readers)?;
92 let chain = DynamicChain::new(readers);
93 Ok(BodyReader::Multipart(chain))
94 }
95 Body::Streamed(stream) => match &stream.stream_source {
96 StreamSource::File((path, skip)) => {
97 if let Ok(mut f) = File::open(path) {
98 if *skip != 0 {
99 if let Ok(skip) = (*skip).try_into() {
100 if let Ok(skipped) = f.seek(std::io::SeekFrom::Start(skip)) {
101 if skipped == skip {
102 return Ok(BodyReader::FileBacked(f));
103 }
104 }
105 }
106
107 return Err(BodySerializationError::IO);
108 }
109
110 return Ok(BodyReader::FileBacked(f));
111 }
112
113 Err(BodySerializationError::IO)
114 }
115 },
116 }
117 }
118}
119
120impl fmt::Debug for Body {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 match self {
134 Body::Raw(data) => {
135 write!(f, "Raw [u8; {}]", data.len())
136 }
137 Body::Message(message) => {
138 write!(f, "{:?}", message)
139 }
140 Body::Multipart(multipart) => {
141 write!(f, "{:?}", multipart)
142 }
143 Body::Streamed(stream) => {
144 write!(f, "Streamd [u8; {}]", stream.stream_size)
145 }
146 }
147 }
148}
149
150pub enum BodyReader<'a> {
151 Raw(RawBodyReader<'a>),
152 Message(DynamicChain<'a>),
153 Multipart(DynamicChain<'a>),
154 FileBacked(File),
155}
156
157impl Read for BodyReader<'_> {
158 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
159 match self {
160 BodyReader::Raw(reader) => reader.read(buf),
161 BodyReader::Message(reader) => reader.read(buf),
162 BodyReader::Multipart(reader) => reader.read(buf),
163 BodyReader::FileBacked(f) => f.read(buf),
164 }
165 }
166}
167
168impl AsyncRead for BodyReader<'_> {
169 fn poll_read(
170 self: Pin<&mut Self>,
171 cx: &mut Context<'_>,
172 buf: &mut [u8],
173 ) -> Poll<std::io::Result<usize>> {
174 let r = self.get_mut();
175 match r {
176 BodyReader::Raw(reader) => Pin::new(reader).poll_read(cx, buf),
177 BodyReader::Message(reader) => Pin::new(reader).poll_read(cx, buf),
178 BodyReader::Multipart(reader) => Pin::new(reader).poll_read(cx, buf),
179 BodyReader::FileBacked(f) => Poll::Ready(f.read(buf)),
180 }
181 }
182}
183
184pub struct RawBodyReader<'a> {
185 data: &'a Vec<u8>,
186 pos: usize,
187}
188
189impl Read for RawBodyReader<'_> {
190 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
191 let mut i = 0;
192 while self.pos + i < self.data.len() && i < buf.len() {
193 buf[i] = self.data[self.pos + i];
194 i += 1;
195 }
196 self.pos += i;
197 Ok(i)
198 }
199}
200
201impl AsyncRead for RawBodyReader<'_> {
202 fn poll_read(
203 self: Pin<&mut Self>,
204 _cx: &mut Context<'_>,
205 buf: &mut [u8],
206 ) -> Poll<std::io::Result<usize>> {
207 let r = self.get_mut();
208 Poll::Ready(r.read(buf))
209 }
210}
211
212pub struct VectorReader {
213 data: Vec<u8>,
214 pos: usize,
215}
216
217impl VectorReader {
218 pub fn new(data: Vec<u8>) -> VectorReader {
219 VectorReader { data, pos: 0 }
220 }
221}
222
223impl Read for VectorReader {
224 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
225 let mut i = 0;
226 while self.pos + i < self.data.len() && i < buf.len() {
227 buf[i] = self.data[self.pos + i];
228 i += 1;
229 }
230 self.pos += i;
231 Ok(i)
232 }
233}
234
235impl AsyncRead for VectorReader {
236 fn poll_read(
237 self: Pin<&mut Self>,
238 _cx: &mut Context<'_>,
239 buf: &mut [u8],
240 ) -> Poll<std::io::Result<usize>> {
241 let r = self.get_mut();
242 Poll::Ready(r.read(buf))
243 }
244}