1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright 2016 `multipart` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
//! Client- and server-side abstractions for HTTP `multipart/form-data` requests.
//!
//! ### Features:
//! This documentation is built with all features enabled.
//!
//! * `client`: The client-side abstractions for generating multipart requests.
//!
//! * `server`: The server-side abstractions for parsing multipart requests.
//!
//! * `mock`: Provides mock implementations of core `client` and `server` traits for debugging
//! or non-standard use.
//!
//! * `hyper`: Integration with the [Hyper](https://crates.io/crates/hyper) HTTP library
//! for client and/or server depending on which other feature flags are set.
//!
//! * `iron`: Integration with the [Iron](http://crates.io/crates/iron) web application
//! framework. See the [`server::iron`](server/iron/index.html) module for more information.
//!
//! * `nickel` (returning in 0.14!): Integration with the [Nickel](https://crates.io/crates/nickel)
//! web application framework. See the [`server::nickel`](server/nickel/index.html) module for more
//! information.
//!
//! * `tiny_http`: Integration with the [`tiny_http`](https://crates.io/crates/tiny_http)
//! crate. See the [`server::tiny_http`](server/tiny_http/index.html) module for more information.
//!
//! ### Note: Work in Progress
//! I have left a number of Request-for-Comments (RFC) questions on various APIs and other places
//! in the code as there are some cases where I'm not sure what the desirable behavior is.
//!
//! I have opened an issue as a place to collect responses and discussions for these questions
//! [on Github](https://github.com/abonander/multipart/issues/96). Please quote the RFC-statement
//! (and/or link to its source line) and provide your feedback there.
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", deny(clippy))]
#![cfg_attr(feature = "bench", feature(test))]
#![deny(missing_docs)]

#[macro_use]
extern crate log;

extern crate mime;
extern crate mime_guess;
extern crate rand;
extern crate tempfile;

#[cfg(feature = "quick-error")]
#[macro_use]
extern crate quick_error;

#[cfg(feature = "server")]
extern crate safemem;

#[cfg(feature = "hyper")]
extern crate hyper;

#[cfg(feature = "iron")]
extern crate iron;

#[cfg(feature = "tiny_http")]
extern crate tiny_http;

#[cfg(test)]
extern crate env_logger;

#[cfg(any(feature = "mock", test))]
pub mod mock;

use rand::Rng;

/// Chain a series of results together, with or without previous results.
///
/// ```
/// #[macro_use] extern crate multipart;
///
/// fn try_add_one(val: u32) -> Result<u32, u32> {
///     if val < 5 {
///         Ok(val + 1)
///     } else {
///         Err(val)
///     }
/// }
///
/// fn main() {
///     let res = chain_result! {
///         try_add_one(1),
///         prev -> try_add_one(prev),
///         prev -> try_add_one(prev),
///         prev -> try_add_one(prev)
///     };
///
///     println!("{:?}", res);
/// }
///
/// ```
#[macro_export]
macro_rules! chain_result {
    ($first_expr:expr, $($try_expr:expr),*) => (
        $first_expr $(.and_then(|_| $try_expr))*
    );
    ($first_expr:expr, $($($arg:ident),+ -> $try_expr:expr),*) => (
        $first_expr $(.and_then(|$($arg),+| $try_expr))*
    );
}

#[cfg(feature = "client")]
pub mod client;
#[cfg(feature = "server")]
pub mod server;

#[cfg(all(test, feature = "client", feature = "server"))]
mod local_test;

fn random_alphanumeric(len: usize) -> String {
    rand::thread_rng()
        .sample_iter(&rand::distributions::Alphanumeric)
        .take(len)
        .map(|c| c as char)
        .collect()
}

#[cfg(test)]
fn init_log() {
    let _ = env_logger::try_init();
}