base_web_multipart/lib.rs
1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4//! MIME multipart bodies, as RFC 2046 defines them and RFC 7578 uses them for form data, parsed and written without I/O.
5//!
6//! [`MultipartParser`] is fed bytes as they arrive and reports each part's header section and content as borrowed slices, never copying them, with [`MultipartLimits`] on the structure a hostile body could inflate. A part's header section is interpreted with `base-message`, through [`PartHeaders`] or a section of your own, and [`ContentDisposition`] reads form field names and filenames, following the [`ParameterRules`] of forms or of other MIME parts. [`MultipartWriter`] writes a body, refusing header lines and content that would change its structure for a reader, with a [`Boundary`] generated from 192 random bits.
7//!
8//! ```
9//! use base_web_multipart::{Boundary, ContentDisposition, MultipartWriter, ParameterRules, PartHeaders, parts};
10//! use base_message::FieldSection;
11//!
12//! let boundary = Boundary::generate();
13//! let mut writer = MultipartWriter::new(boundary.clone());
14//! let mut body = Vec::new();
15//! let disposition = ContentDisposition::form_data("greeting")?.to_string();
16//! writer.start_part([("Content-Disposition", disposition.as_bytes())], &mut body)?;
17//! writer.write_content(b"hello", &mut body)?;
18//! writer.finish(&mut body);
19//!
20//! for part in parts(&body, &boundary) {
21//! let part = part?;
22//! let headers = PartHeaders::interpret(part.head())?;
23//! let disposition = headers.content_disposition.expect("each form part has a disposition");
24//! assert_eq!((disposition.name(ParameterRules::FormData)?.as_deref(), part.content()), (Some("greeting"), &b"hello"[..]));
25//! }
26//! # Ok::<(), Box<dyn std::error::Error>>(())
27//! ```
28//!
29//! The crate frames parts only. Forms, with their limits on fields and uploads, belong to `base-web-content`, and HTTP transport to `base-http`. The [Getting Started](https://github.com/base-rs/base-web-multipart/blob/main/context/getting-started.md) guide covers parsing a streamed body and writing one.
30
31mod boundary;
32mod content_disposition;
33mod content_transfer_encoding;
34mod content_type;
35mod multipart_error;
36mod multipart_event;
37mod multipart_limits;
38mod multipart_parser;
39mod multipart_writer;
40mod parameter_rules;
41mod part_head;
42mod part_headers;
43mod parts;
44mod syntax;
45
46pub use boundary::{Boundary, BoundaryError};
47pub use content_disposition::ContentDisposition;
48pub use content_transfer_encoding::ContentTransferEncoding;
49pub use content_type::ContentType;
50pub use multipart_error::{MultipartError, MultipartErrorKind};
51pub use multipart_event::{MultipartEvent, Parsed};
52pub use multipart_limits::MultipartLimits;
53pub use multipart_parser::MultipartParser;
54pub use multipart_writer::{MultipartWriteError, MultipartWriter};
55pub use parameter_rules::ParameterRules;
56pub use part_head::{PartFields, PartHead};
57pub use part_headers::PartHeaders;
58pub use parts::{Part, Parts, parts};
59
60#[cfg(doctest)]
61#[doc = include_str!("../readme.md")]
62struct Readme;
63
64#[cfg(doctest)]
65#[doc = include_str!("../context/getting-started.md")]
66struct GettingStartedGuide;