1#![no_std]
94#![doc(html_root_url = "https://docs.rs/form-net")]
95#![cfg_attr(docsrs, feature(doc_cfg))]
96#![forbid(unsafe_code)]
97#![deny(missing_docs)]
98#![cfg_attr(
99 not(test),
100 deny(
101 clippy::unwrap_used,
102 clippy::expect_used,
103 clippy::panic,
104 clippy::indexing_slicing,
105 clippy::arithmetic_side_effects,
106 clippy::todo,
107 clippy::unimplemented,
108 clippy::unreachable,
109 clippy::dbg_macro,
110 clippy::print_stdout,
111 clippy::print_stderr
112 )
113)]
114
115#[cfg(any(feature = "alloc", test))]
116extern crate alloc;
117#[cfg(any(feature = "std", test))]
118extern crate std;
119
120#[cfg(target_has_atomic = "32")]
121mod digest;
122mod error;
123#[cfg(feature = "alloc")]
124mod extract;
125mod hook;
126#[cfg(feature = "std")]
127mod io;
128mod kind;
129mod limits;
130mod multipart;
131#[cfg(feature = "random")]
132mod random;
133mod scan;
134#[cfg(feature = "fs")]
135mod store;
136mod urlencoded;
137mod wipe;
138
139#[cfg(feature = "alloc")]
140#[doc(hidden)]
141pub use alloc::vec::Vec as __Vec;
142#[cfg(target_has_atomic = "32")]
143#[cfg_attr(docsrs, doc(cfg(target_has_atomic = "32")))]
144pub use digest::RefusalDigest;
145pub use error::{
146 EncodingError, ExtractError, FormError, Limit, Location, PolicyRefusal, SyntaxError,
147};
148#[cfg(feature = "alloc")]
149#[doc(hidden)]
150pub use extract::{__push_field_error, __unknown, __value_error};
151#[cfg(feature = "alloc")]
152#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
153pub use extract::{
154 FileData, FileValue, FormBuilder, FormErrors, FromField, FromForm, Secret, ValueError,
155};
156#[cfg(feature = "alloc")]
157#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
158pub use hook::MemorySink;
159pub use hook::{DiscardSink, Inspector, NoInspector, Refusal, Sink, TokenCheck, Verdict};
160pub use kind::FormKind;
161pub use limits::{
162 EmptyFilePolicy, ExtendedFilenamePolicy, HeaderPolicy, Limits, PercentPolicy, Policy,
163 TokenField, TokenPlacement,
164};
165pub use multipart::boundary::{Boundary, MAX_BOUNDARY_LEN, MAX_DELIMITER_LEN};
166#[cfg(feature = "alloc")]
167#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
168pub use multipart::driver::{Driver, Progress};
169pub use multipart::filename::{FileName, FileNameSource};
170#[cfg(feature = "alloc")]
171#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
172pub use multipart::owned_head::OwnedPartHead;
173pub use multipart::parser::{
174 Charset, ContentType, Event, Headers, MultipartParser, PartHead, PartKind, PartSummary, Step,
175};
176#[cfg(feature = "std")]
177#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
178pub use multipart::writer::MultipartWriter;
179pub use multipart::writer::encode_part_head;
180#[cfg(feature = "alloc")]
181#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
182pub use multipart::{
183 Multipart, Part, parse_multipart, parse_multipart_inspected, parse_multipart_with,
184};
185pub use urlencoded::decode::decode_into;
186pub use urlencoded::encode::encode_into;
187#[cfg(feature = "alloc")]
188#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
189pub use urlencoded::encode::{Serializer, serialize_urlencoded};
190pub use urlencoded::raw::{RawPair, RawPairs, raw_pairs};
191pub use urlencoded::stream::{UrlencodedEvent, UrlencodedParser, UrlencodedStep};
192#[cfg(feature = "alloc")]
193#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
194pub use urlencoded::{
195 Form, Pairs, pairs, parse_query, parse_urlencoded, parse_urlencoded_inspected,
196 parse_urlencoded_with,
197};
198
199#[cfg(feature = "std")]
200#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
201pub use io::{MultipartReader, PartReader};
202#[cfg(feature = "fs")]
203#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
204pub use store::{
205 SpillBudget, SpillMode, SpillQuota, Store, StoreError, StoreSink, StoreStats, StoredFile,
206 StoredReader, Upload, UploadSession, read_multipart, sweep,
207};
208
209pub const VERSION: &str = env!("CARGO_PKG_VERSION");
211
212#[cfg(test)]
213mod tests {
214 use super::VERSION;
215
216 #[test]
217 fn test_version_matches_manifest() {
218 assert_eq!(VERSION, env!("CARGO_PKG_VERSION"));
219 assert_eq!(VERSION.split('.').count(), 3, "expected MAJOR.MINOR.PATCH");
220 }
221
222 #[test]
224 #[cfg(target_pointer_width = "64")]
225 fn test_the_api_size_table_holds() {
226 use core::mem::size_of;
227 assert_eq!(size_of::<super::Boundary>(), 149);
228 assert!(size_of::<super::FormError>() <= 48);
229 assert_eq!(size_of::<super::Limits>(), 72);
230 assert_eq!(size_of::<super::RawPair<'static>>(), 48);
231 assert!(size_of::<super::MultipartParser<&mut [u8]>>() <= 384);
232 #[cfg(feature = "alloc")]
234 assert!(size_of::<super::MultipartParser<alloc::vec::Vec<u8>>>() <= 1024);
235 #[cfg(feature = "fs")]
236 assert!(size_of::<super::UploadSession>() <= 1024);
237 }
238
239 #[test]
240 fn test_public_types_are_send_and_sync() {
241 fn send_sync<T: Send + Sync>() {}
242 send_sync::<super::Limits>();
243 send_sync::<super::Policy>();
244 send_sync::<super::Boundary>();
245 send_sync::<super::FormError>();
246 send_sync::<super::RefusalDigest<2>>();
247 send_sync::<super::MultipartParser<&mut [u8]>>();
248 #[cfg(feature = "alloc")]
249 {
250 send_sync::<super::MultipartParser<alloc::vec::Vec<u8>>>();
251 send_sync::<super::Form>();
252 send_sync::<super::Multipart<'static>>();
253 send_sync::<super::OwnedPartHead>();
254 send_sync::<super::MemorySink>();
255 send_sync::<super::Driver<alloc::vec::Vec<u8>, super::MemorySink>>();
256 send_sync::<super::FileData>();
257 send_sync::<super::Secret>();
258 }
259 #[cfg(feature = "std")]
260 send_sync::<super::MultipartReader<std::fs::File>>();
261 #[cfg(feature = "fs")]
262 {
263 send_sync::<super::Store>();
264 send_sync::<super::StoreSink>();
265 send_sync::<super::StoredFile>();
266 send_sync::<super::Upload>();
267 send_sync::<super::UploadSession>();
268 }
269 }
270}
271
272#[cfg(all(doctest, feature = "fs", feature = "unicode"))]
275#[doc = include_str!("../docs/API.md")]
276struct ApiExamples;