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, __repeated_wire_name, __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, Headers, MultipartEvent, MultipartParser, MultipartStep, PartHead,
175 PartKind, PartSummary,
176};
177#[cfg(feature = "std")]
178#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
179pub use multipart::writer::MultipartWriter;
180pub use multipart::writer::encode_part_head;
181#[cfg(feature = "alloc")]
182#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
183pub use multipart::{
184 Multipart, Part, parse_multipart, parse_multipart_inspected, parse_multipart_with,
185};
186pub use urlencoded::decode::decode_into;
187pub use urlencoded::encode::encode_into;
188#[cfg(feature = "alloc")]
189#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
190pub use urlencoded::encode::{Serializer, serialize_urlencoded};
191pub use urlencoded::raw::{RawPair, RawPairs, raw_pairs};
192pub use urlencoded::stream::{UrlencodedEvent, UrlencodedParser, UrlencodedStep};
193#[cfg(feature = "alloc")]
194#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
195pub use urlencoded::{
196 Form, Pairs, pairs, parse_query, parse_urlencoded, parse_urlencoded_inspected,
197 parse_urlencoded_with,
198};
199
200#[cfg(feature = "std")]
201#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
202pub use io::{MultipartReader, PartReader};
203#[cfg(feature = "fs")]
204#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
205pub use store::{
206 SpillBudget, SpillMode, SpillQuota, Store, StoreError, StoreSink, StoreStats, StoredFile,
207 StoredReader, Upload, UploadSession, read_multipart, read_multipart_inspected,
208 read_multipart_with, sweep,
209};
210
211pub const VERSION: &str = env!("CARGO_PKG_VERSION");
213
214#[cfg(test)]
215mod tests {
216 use super::VERSION;
217
218 #[test]
219 fn test_version_matches_manifest() {
220 assert_eq!(VERSION, env!("CARGO_PKG_VERSION"));
221 assert_eq!(VERSION.split('.').count(), 3, "expected MAJOR.MINOR.PATCH");
222 }
223
224 #[test]
226 #[cfg(target_pointer_width = "64")]
227 fn test_the_api_size_table_holds() {
228 use core::mem::size_of;
229 assert_eq!(size_of::<super::Boundary>(), 149);
230 assert!(size_of::<super::FormError>() <= 48);
231 assert_eq!(size_of::<super::Limits>(), 72);
232 assert_eq!(size_of::<super::RawPair<'static>>(), 48);
233 assert!(size_of::<super::MultipartParser<&mut [u8]>>() <= 384);
234 #[cfg(feature = "alloc")]
236 assert!(size_of::<super::MultipartParser<alloc::vec::Vec<u8>>>() <= 1024);
237 #[cfg(feature = "fs")]
238 assert!(size_of::<super::UploadSession>() <= 1024);
239 }
240
241 #[test]
242 fn test_public_types_are_send_and_sync() {
243 fn send_sync<T: Send + Sync>() {}
244 send_sync::<super::Limits>();
245 send_sync::<super::Policy>();
246 send_sync::<super::Boundary>();
247 send_sync::<super::FormError>();
248 send_sync::<super::RefusalDigest<2>>();
249 send_sync::<super::MultipartParser<&mut [u8]>>();
250 #[cfg(feature = "alloc")]
251 {
252 send_sync::<super::MultipartParser<alloc::vec::Vec<u8>>>();
253 send_sync::<super::Form>();
254 send_sync::<super::Multipart<'static>>();
255 send_sync::<super::OwnedPartHead>();
256 send_sync::<super::MemorySink>();
257 send_sync::<super::Driver<alloc::vec::Vec<u8>, super::MemorySink>>();
258 send_sync::<super::FileData>();
259 send_sync::<super::Secret>();
260 }
261 #[cfg(feature = "std")]
262 send_sync::<super::MultipartReader<std::fs::File>>();
263 #[cfg(feature = "fs")]
264 {
265 send_sync::<super::Store>();
266 send_sync::<super::StoreSink>();
267 send_sync::<super::StoredFile>();
268 send_sync::<super::Upload>();
269 send_sync::<super::UploadSession>();
270 }
271 }
272}
273
274#[cfg(all(doctest, feature = "fs", feature = "unicode"))]
277#[doc = include_str!("../docs/API.md")]
278struct ApiExamples;