Skip to main content

MultipartParser

Struct MultipartParser 

Source
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>>

Source

pub fn new( boundary: Boundary, limits: &Limits, policy: &Policy, ) -> Result<Self, FormError>

Available on crate feature 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>

Source

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[..])?;
Source

pub fn parse<'p>( &'p mut self, input: &'p [u8], eof: bool, ) -> Result<Step<'p>, FormError>

Consumes a prefix of input and returns one event. eof = true says input ends the body.

§Errors

Every multipart error (see the crate’s docs/API.md); Poisoned after any error until reset.

Source

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.

Source

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.

Source

pub const fn bytes_seen(&self) -> u64

Body bytes consumed so far.

Source

pub const fn parts_seen(&self) -> u32

Parts started so far.

Source

pub const fn files_seen(&self) -> u32

File parts counted so far.

Source

pub fn is_done(&self) -> bool

Whether the close delimiter was read.

Source

pub const fn limits(&self) -> &Limits

The limits the parser was built with.

Source

pub const fn policy(&self) -> &Policy

The policy the parser was built with.

Source

pub fn captured_token(&self) -> Option<&str>

The token field’s value, once its part has ended.

Source

pub fn declared_charset(&self) -> Option<&[u8]>

The value of the last complete _charset_ field.

Trait Implementations§

Source§

impl<B: AsMut<[u8]> + AsRef<[u8]>> Debug for MultipartParser<B>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<B: AsMut<[u8]> + AsRef<[u8]>> Drop for MultipartParser<B>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

§

impl<B> Freeze for MultipartParser<B>
where B: Freeze,

§

impl<B> RefUnwindSafe for MultipartParser<B>
where B: RefUnwindSafe,

§

impl<B> Send for MultipartParser<B>
where B: Send,

§

impl<B> Sync for MultipartParser<B>
where B: Sync,

§

impl<B> Unpin for MultipartParser<B>
where B: Unpin,

§

impl<B> UnsafeUnpin for MultipartParser<B>
where B: UnsafeUnpin,

§

impl<B> UnwindSafe for MultipartParser<B>
where B: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.