nostd_multipart/lib.rs
1//! Heap-free, panic-free, streaming `multipart/form-data` parser and encoder for
2//! `#![no_std]`.
3//!
4//! The crate is *sans-IO*: you feed bytes to [`Parser::parse`] and get back at most
5//! one [`Event`] per call plus the number of bytes consumed. Part data is yielded
6//! as sub-slices of your own input buffer (zero-copy). Only part headers are
7//! copied, into a line buffer whose size is the const generic `LINE`.
8//!
9//! The normative specification is `DESIGN.md` in the repository; the rule numbers
10//! referenced in the source (`rule 3`, ...) point there.
11//!
12//! ```
13//! use nostd_multipart::{Event, Parser};
14//!
15//! let body = b"--xyz\r\nContent-Disposition: form-data; name=\"f\"\r\n\r\nhello\r\n--xyz--";
16//! let mut p: Parser<'_> = Parser::new(b"xyz").unwrap();
17//! let mut pos = 0;
18//! let mut data = Vec::new();
19//! loop {
20//! let (used, ev) = p.parse(&body[pos..], true).unwrap();
21//! pos += used;
22//! match ev {
23//! Some(Event::Data(d)) => data.extend_from_slice(d),
24//! Some(Event::Finished) => break,
25//! _ => {}
26//! }
27//! }
28//! assert_eq!(data, b"hello");
29//! ```
30#![no_std]
31#![forbid(unsafe_code)]
32#![cfg_attr(
33 not(test),
34 deny(
35 clippy::panic,
36 clippy::unwrap_used,
37 clippy::expect_used,
38 clippy::indexing_slicing,
39 clippy::arithmetic_side_effects,
40 clippy::unreachable,
41 clippy::todo,
42 clippy::unimplemented
43 )
44)]
45#![deny(missing_docs, rust_2018_idioms, unused_must_use)]
46#![warn(clippy::all, clippy::pedantic)]
47#![allow(clippy::module_name_repetitions)]
48
49mod chars;
50mod disposition;
51mod encoder;
52mod error;
53mod parser;
54
55#[cfg(kani)]
56mod kani;
57
58#[cfg(any(feature = "embedded-io", feature = "embedded-io-async"))]
59mod io;
60
61pub use disposition::{content_disposition, ContentDisposition, Decoded, ParamValue};
62pub use encoder::{boundary_from_random, Encoder, Part};
63pub use error::Error;
64pub use parser::{Event, Parser, MAX_PADDING};
65
66#[cfg(feature = "embedded-io")]
67pub use io::MultipartReader;
68#[cfg(feature = "embedded-io-async")]
69pub use io::MultipartReaderAsync;
70#[cfg(any(feature = "embedded-io", feature = "embedded-io-async"))]
71pub use io::ReadError;