base_web_multipart/
parts.rs1use crate::{Boundary, MultipartError, MultipartEvent, MultipartLimits, MultipartParser, PartHead};
5use std::fmt;
6use std::iter::FusedIterator;
7
8#[derive(Clone, Copy, PartialEq, Eq)]
10pub struct Part<'a> {
11 head: PartHead<'a>,
12 content: &'a [u8],
13}
14
15impl<'a> Part<'a> {
16 pub fn head(&self) -> PartHead<'a> {
18 self.head
19 }
20
21 pub fn content(&self) -> &'a [u8] {
23 self.content
24 }
25}
26
27impl fmt::Debug for Part<'_> {
29 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
30 formatter
31 .debug_struct("Part")
32 .field("head", &self.head)
33 .field("content", &format_args!("<{} bytes>", self.content.len()))
34 .finish()
35 }
36}
37
38#[derive(Clone)]
40pub struct Parts<'a> {
41 parser: MultipartParser,
42 body: &'a [u8],
43 position: usize,
44 failed: bool,
45}
46
47pub fn parts<'a>(body: &'a [u8], boundary: &Boundary) -> Parts<'a> {
67 Parts::with_limits(body, boundary, MultipartLimits::default())
68}
69
70impl<'a> Parts<'a> {
71 pub fn with_limits(body: &'a [u8], boundary: &Boundary, limits: MultipartLimits) -> Self {
73 Self {
74 parser: MultipartParser::with_limits(boundary, limits),
75 body,
76 position: 0,
77 failed: false,
78 }
79 }
80
81 fn next_part(&mut self) -> Result<Option<Part<'a>>, MultipartError> {
82 let body = self.body;
83 let (mut head, mut content, mut start) = (None, self.position..self.position, None);
84 loop {
85 let parsed = self.parser.parse(&body[self.position..])?;
86 self.position += parsed.consumed;
87 match parsed.event {
88 MultipartEvent::Part(part) => {
89 head = Some(part);
90 content = self.position..self.position;
91 start = None;
92 }
93 MultipartEvent::Content(piece) => {
95 content = *start.get_or_insert(self.position - piece.len())..self.position
96 }
97 MultipartEvent::PartEnd => {
98 return Ok(head.map(|head| Part {
99 head,
100 content: &body[content],
101 }));
102 }
103 MultipartEvent::End => return Ok(None),
104 MultipartEvent::Incomplete => return self.parser.finish().and(Ok(None)),
106 }
107 }
108 }
109}
110
111impl fmt::Debug for Parts<'_> {
113 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
114 formatter
115 .debug_struct("Parts")
116 .field("position", &self.position)
117 .field("length", &self.body.len())
118 .finish()
119 }
120}
121
122impl<'a> Iterator for Parts<'a> {
123 type Item = Result<Part<'a>, MultipartError>;
124
125 fn next(&mut self) -> Option<Self::Item> {
126 if self.failed {
127 return None;
128 }
129 let result = self.next_part().transpose();
130 self.failed = !matches!(result, Some(Ok(_)));
131 result
132 }
133}
134
135impl FusedIterator for Parts<'_> {}