rust_rcs_core/internet/body/
mod.rs

1// Copyright 2023 宋昊文
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15pub 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 serialize(&self) -> Vec<u8> {
50    //     match self {
51    //         Body::Raw(data) => data.clone(),
52    //         Body::Message(message) => message.serialize(),
53    //         Body::Multipart(multipart) => multipart.serialize(),
54    //     }
55    // }
56
57    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
120// impl Clone for Body {
121//     fn clone(&self) -> Self {
122//         match self {
123//             Body::Raw(inner) => Body::Raw(inner.clone()),
124//             Body::Message(inner) => Body::Message(inner.clone()),
125//             Body::Multipart(inner) => Body::Multipart(inner.clone()),
126//             Body::Streamed(inner) => panic!(""),
127//         }
128//     }
129// }
130
131impl 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}