1use bytes::Bytes;
8use http::header::HeaderMap;
9
10pub mod parser;
11pub mod serializer;
12
13#[derive(Clone, Debug, Eq, PartialEq)]
15pub struct Part {
16 pub headers: HeaderMap,
17 pub body: Bytes,
18}
19
20pub use parser::{parse, ParserBuilder};
21pub use serializer::serialize;
22
23#[cfg(test)]
24mod tests {
25 use crate::{parse, serialize, Part};
26 use bytes::Bytes;
27 use futures::{StreamExt, TryStreamExt};
28 use http::HeaderMap;
29
30 #[tokio::test]
31 async fn roundtrip() {
32 let mut hdrs1 = HeaderMap::new();
33 hdrs1.insert(http::header::CONTENT_TYPE, "text/plain".parse().unwrap());
34 hdrs1.insert("X-My-Header1", "part1".parse().unwrap());
35 let mut hdrs2 = HeaderMap::new();
36 hdrs2.insert(http::header::CONTENT_TYPE, "text/plain".parse().unwrap());
37 hdrs2.insert("X-My-Header2", "part 2".parse().unwrap());
38 let input = vec![
39 Part {
40 headers: hdrs1,
41 body: Bytes::from("part 1 body"),
42 },
43 Part {
44 headers: hdrs2,
45 body: Bytes::from("this is part 2's body"),
46 },
47 ];
48 let byte_stream = serialize(
49 futures::stream::iter(input.clone()).map(|p| Ok::<_, std::convert::Infallible>(p)),
50 "my boundary",
51 );
52 let mut output: Vec<Part> = parse(byte_stream, "my boundary")
53 .try_collect()
54 .await
55 .unwrap();
56
57 for p in &mut output {
59 p.headers.remove(http::header::CONTENT_LENGTH);
60 }
61 assert_eq!(&input[..], &output[..]);
62 }
63}