pub struct MultipartParser<B: AsMut<[u8]> + AsRef<[u8]>> { /* private fields */ }Expand description
The sans-IO multipart/form-data parser.
Feed it bytes as they arrive, in chunks of any size split at any byte;
it returns one Event per call and how many bytes it consumed. The
events are identical for every split of the same body. It never
allocates after construction and never rescans a byte: the delimiter
search is a streaming Knuth-Morris-Pratt automaton with an eight-byte skip
to the next CR.
The buffer holds the header block, the decoded field name, the decoded
filename* (under AcceptAlone), the token, and the _charset_ value:
Limits::multipart_buffer_len bytes. It is wiped on reset and on
drop.
§Examples
use form_net::{Event, FormKind, Limits, MultipartParser, Policy};
let content_type = b"multipart/form-data; boundary=X";
let body = b"--X\r\nContent-Disposition: form-data; name=\"title\"\r\n\r\nHoliday\r\n--X--\r\n";
let FormKind::Multipart(boundary) = FormKind::detect(content_type)? else { unreachable!() };
let mut parser = MultipartParser::new(boundary, &Limits::DEFAULT, &Policy::DEFAULT)?;
let mut events = Vec::new();
let mut chunks = body.chunks(7).peekable(); // any split gives the same events
while let Some(chunk) = chunks.next() {
let last = chunks.peek().is_none();
let mut rest = chunk;
loop {
let step = parser.parse(rest, last)?;
rest = &rest[step.consumed..];
match step.event {
Event::PartStart(head) => events.push(format!("start {}", head.name())),
Event::Data(bytes) => events.push(format!("data {}", bytes.len())),
Event::PartEnd(summary) => events.push(format!("end {}", summary.bytes)),
Event::End => break,
Event::NeedInput => break,
_ => {}
}
}
}
assert!(parser.is_done());
assert_eq!(events.first().map(String::as_str), Some("start title"));
assert_eq!(events.last().map(String::as_str), Some("end 7"));Implementations§
Source§impl MultipartParser<Vec<u8>>
impl MultipartParser<Vec<u8>>
Sourcepub fn new(
boundary: Boundary,
limits: &Limits,
policy: &Policy,
) -> Result<Self, FormError>
Available on crate feature alloc only.
pub fn new( boundary: Boundary, limits: &Limits, policy: &Policy, ) -> Result<Self, FormError>
alloc only.A parser with its own buffer of
Limits::multipart_buffer_len bytes, allocated once.
§Errors
InvalidLimits from validating the limits with the policy.
§Examples
use form_net::{Boundary, Limits, MultipartParser, Policy};
let parser = MultipartParser::new(Boundary::new(b"X")?, &Limits::DEFAULT, &Policy::DEFAULT)?;
assert_eq!(parser.bytes_seen(), 0);Source§impl<B: AsMut<[u8]> + AsRef<[u8]>> MultipartParser<B>
impl<B: AsMut<[u8]> + AsRef<[u8]>> MultipartParser<B>
Sourcepub fn with_buffer(
boundary: Boundary,
limits: &Limits,
policy: &Policy,
buffer: B,
) -> Result<Self, FormError>
pub fn with_buffer( boundary: Boundary, limits: &Limits, policy: &Policy, buffer: B, ) -> Result<Self, FormError>
A parser over a buffer the caller provides; it never allocates.
§Errors
InvalidLimits; BufferTooSmall when buffer is shorter than
Limits::multipart_buffer_len.
§Examples
use form_net::{Boundary, Limits, MultipartParser, Policy};
const LIMITS: Limits = Limits::DEFAULT.with_max_part_header_bytes(1024);
const LEN: usize = LIMITS.multipart_buffer_len(&Policy::DEFAULT);
let mut buffer = [0u8; LEN];
let parser = MultipartParser::with_buffer(Boundary::new(b"X")?, &LIMITS, &Policy::DEFAULT, &mut buffer[..])?;Sourcepub fn skip_part(&mut self)
pub fn skip_part(&mut self)
Discards the rest of the current part: its bytes are consumed and
counted against the budgets but produce no Data events, and its
summary has skipped = true. Outside a part it does nothing.
Sourcepub fn reset(&mut self, boundary: Boundary)
pub fn reset(&mut self, boundary: Boundary)
Returns the parser to its initial state for a new body, wipes its buffer, and clears the poisoned state. It never allocates.
Sourcepub const fn bytes_seen(&self) -> u64
pub const fn bytes_seen(&self) -> u64
Body bytes consumed so far.
Sourcepub const fn parts_seen(&self) -> u32
pub const fn parts_seen(&self) -> u32
Parts started so far.
Sourcepub const fn files_seen(&self) -> u32
pub const fn files_seen(&self) -> u32
File parts counted so far.
Sourcepub fn captured_token(&self) -> Option<&str>
pub fn captured_token(&self) -> Option<&str>
The token field’s value, once its part has ended.
Sourcepub fn declared_charset(&self) -> Option<&[u8]>
pub fn declared_charset(&self) -> Option<&[u8]>
The value of the last complete _charset_ field.