<commit_before>//! # Leaky Bucket Rate-Limiting (as a meter) in Rust
//!
//! This crate provides generic rate-limiting interfaces and
//! implements a few rate-limiting algorithms for programs that need
//! to regulate the rate of their outgoing requests.
//!
//! This crate currently provides in-memory implementations of a by-key
//! (limits enforced per key, e.g. an IP address or a customer ID) and a
//! simple (one limit per object) state tracker.
//!
//! The simple (one limit per object) state tracker can be used in
//! `no_std` environments, such as embedded systems.
//!
//! ## Interface
//!
//! This crate implements two "serious" rate-limiting/traffic-shaping
//! algorithms:
//! [GCRA](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm)
//! and a [Leaky
//! Bucket](https://en.wikipedia.org/wiki/Leaky_bucket#As_a_meter). An
//! "unserious" implementation is provided also: The
//! [`Allower`](example_algorithms/struct.Allower.html), which returns
//! "Yes" to all rate-limiting queries.
//!
//! The Generic Cell Rate Algorithm can be used by in an in-memory
//! rate limiter like so:
//!
//! ``` rust
//! use std::num::NonZeroU32;
//! use ratelimit_meter::{DirectRateLimiter, GCRA};
//!
//! # #[macro_use] extern crate nonzero_ext;
//! # extern crate ratelimit_meter;
//! # #[cfg(feature = "std")]
//! # fn main () {
//! let mut lim = DirectRateLimiter::<GCRA>::per_second(nonzero!(50u32)); // Allow 50 units per second
//! assert_eq!(Ok(()), lim.check());
//! # }
//! # #[cfg(not(feature = "std"))]
//! # fn main() {}
//! ```
//!
//! The rate-limiter interface is intentionally geared towards only
//! providing callers with the information they need to make decisions
//! about what to do with each cell. Deciders return additional
//! information about why a cell should be denied alongside the
//! decision. This allows callers to e.g. provide better error
//! messages to users.
//!
//! As a consequence, the `ratelimit_meter` crate does not provide any
//! facility to wait until a cell would be allowed - if you require
//! this, you should use the
//! [`NonConformance`](struct.NonConformance.html) returned with
//! negative decisions and have the program wait using the method best
//! suited for this, e.g. an event loop.
//!
//! ## Using this crate effectively
//!
//! Many of the parameters in use by this crate are `NonZeroU32` -
//! since they are not very ergonomic to construct from constants
//! using stdlib means, I recommend using the
//! [nonzero_ext](https://crates.io/crates/nonzero_ext) crate, which
//! comes with a macro `nonzero!()`. This macro makes it far easier to
//! construct rate limiters without cluttering your code.
//!
//! ## Rate-limiting Algorithms
//!
//! ### Design and implementation of GCRA
//!
//! The GCRA limits the rate of cells by determining when the "next"
//! cell is expected to arrive; any cells that arrive before that time
//! are classified as non-conforming; the methods for checking cells
//! also return an expected arrival time for these cells, so that
//! callers can choose to wait (adding jitter), or reject the cell.
//!
//! Since using the GCRA results in a much smoother usage pattern, it
//! appears to be very useful for "outgoing" traffic behaviors,
//! e.g. throttling API call rates, or emails sent to a person in a
//! period of time.
//!
//! Unlike token or leaky bucket algorithms, the GCRA assumes that all
//! units of work are of the same "weight", and so allows some
//! optimizations which result in much more concise and fast code (it
//! does not even use multiplication or division in the "hot" path).
//!
//! See [the documentation of the GCRA type](algorithms/gcra/struct.GCRA.html) for
//! more details on its implementation and on trade-offs that apply to
//! it.
//!
//! ### Design and implementation of the leaky bucket
//!
//! In contrast to the GCRA, the leaky bucket algorithm does not place
//! any constraints on the next cell's arrival time: Whenever there is
//! capacity left in the bucket, it can be used. This means that the
//! distribution of "yes" decisions from heavy usage on the leaky
//! bucket rate-limiter will be clustered together. On average, the
//! cell rates of both the GCRA and the leaky bucket will be the same,
//! but in terms of observable behavior, the leaky bucket will appear
//! to allow requests at a more predictable rate.
//!
//! This kind of behavior is usually what people of online APIs expect
//! these days, which makes the leaky bucket a very popular technique
//! for rate-limiting on these kinds of services.
//!
//! The leaky bucket algorithm implemented in this crate is fairly
//! standard: It only updates the bucket fill gauge when a cell is
//! checked, and supports checking "batches" of cells in a single call
//! with no problems.
//!
//! ## Thread-safe operation
//!
//! The in-memory implementations in this crate use parking_lot
//! mutexes to ensure rate-limiting operations can happen safely
//! across threads.
//!
//! Example:
//!
//! ```
//! use std::thread;
//! use std::num::NonZeroU32;
//! use std::time::Duration;
//! use ratelimit_meter::{DirectRateLimiter, GCRA};
//!
//! # #[macro_use] extern crate nonzero_ext;
//! # extern crate ratelimit_meter;
//! # #[cfg(feature = "std")]
//! # fn main () {
//! // Allow 50 units/second across all threads:
//! let mut lim = DirectRateLimiter::<GCRA>::per_second(nonzero!(50u32));
//! let mut thread_lim = lim.clone();
//! thread::spawn(move || { assert_eq!(Ok(()), thread_lim.check());});
//! assert_eq!(Ok(()), lim.check());
//! # }
//! # #[cfg(not(feature = "std"))]
//! # fn main() {}
//! ```
//!
//! ## Usage with `no_std`
//!
//! `ratelimit_meter` can be used in `no_std` crates, with a reduced
//! feature set. These features are available:
//!
//! * [`DirectRateLimiter`](state/direct/struct.DirectRateLimiter.html)
//!   for a single rate-limiting history per limit,
//! * measurements using relative timestamps (`Duration`) by default,
//! * extensibility for integrating a custom time source.
//!
//! The following things are not available in `no_std` builds by default:
//!
//! * `check` and `check_n` - unless you implement a custom time
//!   source, you have to pass a timestamp to check the rate-limit
//!   against.
//! * [`KeyedRateLimiter`](state/keyed/struct.KeyedRateLimiter.html) -
//!   the keyed state representation requires too much of `std` right
//!   now to be feasible to implement.
//!
//! To use the crate, turn off default features and enable the
//! `"no_std"` feature, like so:
//!
//! ``` toml
//! [dependencies.ratelimit_meter]
//! version = "..."
//! default-features = false
//! features = ["no_std"]
//! ```
//!
//! ### Implementing your own custom time source in `no_std`
//!
//! On platforms that do have a clock or other time source, you can
//! use that time source to implement a trait provided by
//! `ratelimit_meter`, which will enable the `check` and `check_n`
//! methods on rate limiters. Here is an example:
//!
//! ```rust,ignore
//! // MyTimeSource is what provides your timestamps. Since it probably
//! // doesn't live in your crate, we make a newtype:
//! use ratelimit_meter::instant;
//! struct MyInstant(MyTimeSource);
//!
//! impl instant::Relative for MyInstant {
//!     fn duration_since(&self, other: Self) -> Duration {
//!         self.duration_since(other)
//!     }
//! }
//!
//! impl instant::Absolute for MyInstant {
//!     fn now() -> Self {
//!         MyTimeSource::now()
//!     }
//! }
//!
//! impl Add<Duration> for MyInstant {
//!     type Output = MyInstant;
//!     fn add(self, rhs: Duration) -> Always {
//!         self.0 + rhs
//!     }
//! }
//!
//! impl Sub<Duration> for MyInstant {
//!     type Output = MyInstant;
//!     fn sub(self, rhs: Duration) -> Always {
//!         self.0 - rhs
//!     }
//! }
//! ```
//!
//! Then, using that type to create a rate limiter with that time
//! source is a little more verbose. It looks like this:
//!
//! ```rust,ignore
//! let mut lim = DirectRateLimiter::<GCRA<MyInstant>,MyInstant>::per_second(nonzero!(50u32));
//! lim.check().ok();
//! ```

// Allow using the alloc crate
#![cfg_attr(not(feature = "std"), feature(alloc))]
// Allow using ratelimit_meter without std
#![cfg_attr(not(feature = "std"), no_std)]
// Deny warnings
#![cfg_attr(feature = "cargo-clippy", deny(warnings))]

pub mod algorithms;
mod errors;
pub mod example_algorithms;
pub mod instant;
pub mod state;
pub mod test_utilities;
mod thread_safety;

#[macro_use]
extern crate nonzero_ext;

#[cfg(feature = "std")]
extern crate evmap;
#[cfg(feature = "std")]
extern crate parking_lot;

#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
extern crate spin;

pub use self::algorithms::LeakyBucket;
pub use self::algorithms::NonConformance;
pub use self::algorithms::GCRA;

pub use self::state::DirectRateLimiter;

#[cfg(feature = "std")]
pub use self::state::KeyedRateLimiter;

pub use self::errors::*;

/// A facade around all the types we need from std/core crates, to
/// avoid unnecessary cfg-conditionalization everywhere.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;

        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::clone::Clone;
    pub use self::core::cmp::{Eq, Ord, PartialEq};
    pub use self::core::default::Default;
    pub use self::core::fmt::Debug;
    pub use self::core::marker::{Copy, PhantomData, Send, Sized, Sync};
    pub use self::core::num::NonZeroU32;
    pub use self::core::ops::{Add, Sub};
    pub use self::core::time::Duration;

    pub use self::core::cmp;
    pub use self::core::fmt;

    /// Imports that are only available on std.
    #[cfg(feature = "std")]
    mod std {
        pub use std::collections::hash_map::RandomState;
        pub use std::hash::{BuildHasher, Hash};
        pub use std::sync::Arc;
        pub use std::time::Instant;
    }

    #[cfg(feature = "no_std")]
    mod no_std {
        pub use alloc::sync::Arc;
    }

    #[cfg(feature = "std")]
    pub use self::std::*;

    #[cfg(not(feature = "std"))]
    pub use self::no_std::*;
}
<commit_msg>Drop a bunch of extern crate clauses that we no longer need<commit_after>//! # Leaky Bucket Rate-Limiting (as a meter) in Rust
//!
//! This crate provides generic rate-limiting interfaces and
//! implements a few rate-limiting algorithms for programs that need
//! to regulate the rate of their outgoing requests.
//!
//! This crate currently provides in-memory implementations of a by-key
//! (limits enforced per key, e.g. an IP address or a customer ID) and a
//! simple (one limit per object) state tracker.
//!
//! The simple (one limit per object) state tracker can be used in
//! `no_std` environments, such as embedded systems.
//!
//! ## Interface
//!
//! This crate implements two "serious" rate-limiting/traffic-shaping
//! algorithms:
//! [GCRA](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm)
//! and a [Leaky
//! Bucket](https://en.wikipedia.org/wiki/Leaky_bucket#As_a_meter). An
//! "unserious" implementation is provided also: The
//! [`Allower`](example_algorithms/struct.Allower.html), which returns
//! "Yes" to all rate-limiting queries.
//!
//! The Generic Cell Rate Algorithm can be used by in an in-memory
//! rate limiter like so:
//!
//! ``` rust
//! use std::num::NonZeroU32;
//! use ratelimit_meter::{DirectRateLimiter, GCRA};
//!
//! # #[macro_use] extern crate nonzero_ext;
//! # extern crate ratelimit_meter;
//! # #[cfg(feature = "std")]
//! # fn main () {
//! let mut lim = DirectRateLimiter::<GCRA>::per_second(nonzero!(50u32)); // Allow 50 units per second
//! assert_eq!(Ok(()), lim.check());
//! # }
//! # #[cfg(not(feature = "std"))]
//! # fn main() {}
//! ```
//!
//! The rate-limiter interface is intentionally geared towards only
//! providing callers with the information they need to make decisions
//! about what to do with each cell. Deciders return additional
//! information about why a cell should be denied alongside the
//! decision. This allows callers to e.g. provide better error
//! messages to users.
//!
//! As a consequence, the `ratelimit_meter` crate does not provide any
//! facility to wait until a cell would be allowed - if you require
//! this, you should use the
//! [`NonConformance`](struct.NonConformance.html) returned with
//! negative decisions and have the program wait using the method best
//! suited for this, e.g. an event loop.
//!
//! ## Using this crate effectively
//!
//! Many of the parameters in use by this crate are `NonZeroU32` -
//! since they are not very ergonomic to construct from constants
//! using stdlib means, I recommend using the
//! [nonzero_ext](https://crates.io/crates/nonzero_ext) crate, which
//! comes with a macro `nonzero!()`. This macro makes it far easier to
//! construct rate limiters without cluttering your code.
//!
//! ## Rate-limiting Algorithms
//!
//! ### Design and implementation of GCRA
//!
//! The GCRA limits the rate of cells by determining when the "next"
//! cell is expected to arrive; any cells that arrive before that time
//! are classified as non-conforming; the methods for checking cells
//! also return an expected arrival time for these cells, so that
//! callers can choose to wait (adding jitter), or reject the cell.
//!
//! Since using the GCRA results in a much smoother usage pattern, it
//! appears to be very useful for "outgoing" traffic behaviors,
//! e.g. throttling API call rates, or emails sent to a person in a
//! period of time.
//!
//! Unlike token or leaky bucket algorithms, the GCRA assumes that all
//! units of work are of the same "weight", and so allows some
//! optimizations which result in much more concise and fast code (it
//! does not even use multiplication or division in the "hot" path).
//!
//! See [the documentation of the GCRA type](algorithms/gcra/struct.GCRA.html) for
//! more details on its implementation and on trade-offs that apply to
//! it.
//!
//! ### Design and implementation of the leaky bucket
//!
//! In contrast to the GCRA, the leaky bucket algorithm does not place
//! any constraints on the next cell's arrival time: Whenever there is
//! capacity left in the bucket, it can be used. This means that the
//! distribution of "yes" decisions from heavy usage on the leaky
//! bucket rate-limiter will be clustered together. On average, the
//! cell rates of both the GCRA and the leaky bucket will be the same,
//! but in terms of observable behavior, the leaky bucket will appear
//! to allow requests at a more predictable rate.
//!
//! This kind of behavior is usually what people of online APIs expect
//! these days, which makes the leaky bucket a very popular technique
//! for rate-limiting on these kinds of services.
//!
//! The leaky bucket algorithm implemented in this crate is fairly
//! standard: It only updates the bucket fill gauge when a cell is
//! checked, and supports checking "batches" of cells in a single call
//! with no problems.
//!
//! ## Thread-safe operation
//!
//! The in-memory implementations in this crate use parking_lot
//! mutexes to ensure rate-limiting operations can happen safely
//! across threads.
//!
//! Example:
//!
//! ```
//! use std::thread;
//! use std::num::NonZeroU32;
//! use std::time::Duration;
//! use ratelimit_meter::{DirectRateLimiter, GCRA};
//!
//! # #[macro_use] extern crate nonzero_ext;
//! # extern crate ratelimit_meter;
//! # #[cfg(feature = "std")]
//! # fn main () {
//! // Allow 50 units/second across all threads:
//! let mut lim = DirectRateLimiter::<GCRA>::per_second(nonzero!(50u32));
//! let mut thread_lim = lim.clone();
//! thread::spawn(move || { assert_eq!(Ok(()), thread_lim.check());});
//! assert_eq!(Ok(()), lim.check());
//! # }
//! # #[cfg(not(feature = "std"))]
//! # fn main() {}
//! ```
//!
//! ## Usage with `no_std`
//!
//! `ratelimit_meter` can be used in `no_std` crates, with a reduced
//! feature set. These features are available:
//!
//! * [`DirectRateLimiter`](state/direct/struct.DirectRateLimiter.html)
//!   for a single rate-limiting history per limit,
//! * measurements using relative timestamps (`Duration`) by default,
//! * extensibility for integrating a custom time source.
//!
//! The following things are not available in `no_std` builds by default:
//!
//! * `check` and `check_n` - unless you implement a custom time
//!   source, you have to pass a timestamp to check the rate-limit
//!   against.
//! * [`KeyedRateLimiter`](state/keyed/struct.KeyedRateLimiter.html) -
//!   the keyed state representation requires too much of `std` right
//!   now to be feasible to implement.
//!
//! To use the crate, turn off default features and enable the
//! `"no_std"` feature, like so:
//!
//! ``` toml
//! [dependencies.ratelimit_meter]
//! version = "..."
//! default-features = false
//! features = ["no_std"]
//! ```
//!
//! ### Implementing your own custom time source in `no_std`
//!
//! On platforms that do have a clock or other time source, you can
//! use that time source to implement a trait provided by
//! `ratelimit_meter`, which will enable the `check` and `check_n`
//! methods on rate limiters. Here is an example:
//!
//! ```rust,ignore
//! // MyTimeSource is what provides your timestamps. Since it probably
//! // doesn't live in your crate, we make a newtype:
//! use ratelimit_meter::instant;
//! struct MyInstant(MyTimeSource);
//!
//! impl instant::Relative for MyInstant {
//!     fn duration_since(&self, other: Self) -> Duration {
//!         self.duration_since(other)
//!     }
//! }
//!
//! impl instant::Absolute for MyInstant {
//!     fn now() -> Self {
//!         MyTimeSource::now()
//!     }
//! }
//!
//! impl Add<Duration> for MyInstant {
//!     type Output = MyInstant;
//!     fn add(self, rhs: Duration) -> Always {
//!         self.0 + rhs
//!     }
//! }
//!
//! impl Sub<Duration> for MyInstant {
//!     type Output = MyInstant;
//!     fn sub(self, rhs: Duration) -> Always {
//!         self.0 - rhs
//!     }
//! }
//! ```
//!
//! Then, using that type to create a rate limiter with that time
//! source is a little more verbose. It looks like this:
//!
//! ```rust,ignore
//! let mut lim = DirectRateLimiter::<GCRA<MyInstant>,MyInstant>::per_second(nonzero!(50u32));
//! lim.check().ok();
//! ```

// Allow using the alloc crate
#![cfg_attr(not(feature = "std"), feature(alloc))]
// Allow using ratelimit_meter without std
#![cfg_attr(not(feature = "std"), no_std)]
// Deny warnings
#![cfg_attr(feature = "cargo-clippy", deny(warnings))]

pub mod algorithms;
mod errors;
pub mod example_algorithms;
pub mod instant;
pub mod state;
pub mod test_utilities;
mod thread_safety;

#[macro_use]
extern crate nonzero_ext;

#[cfg(not(feature = "std"))]
extern crate alloc;

pub use self::algorithms::LeakyBucket;
pub use self::algorithms::NonConformance;
pub use self::algorithms::GCRA;

pub use self::state::DirectRateLimiter;

#[cfg(feature = "std")]
pub use self::state::KeyedRateLimiter;

pub use self::errors::*;

/// A facade around all the types we need from std/core crates, to
/// avoid unnecessary cfg-conditionalization everywhere.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;

        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::clone::Clone;
    pub use self::core::cmp::{Eq, Ord, PartialEq};
    pub use self::core::default::Default;
    pub use self::core::fmt::Debug;
    pub use self::core::marker::{Copy, PhantomData, Send, Sized, Sync};
    pub use self::core::num::NonZeroU32;
    pub use self::core::ops::{Add, Sub};
    pub use self::core::time::Duration;

    pub use self::core::cmp;
    pub use self::core::fmt;

    /// Imports that are only available on std.
    #[cfg(feature = "std")]
    mod std {
        pub use std::collections::hash_map::RandomState;
        pub use std::hash::{BuildHasher, Hash};
        pub use std::sync::Arc;
        pub use std::time::Instant;
    }

    #[cfg(feature = "no_std")]
    mod no_std {
        pub use alloc::sync::Arc;
    }

    #[cfg(feature = "std")]
    pub use self::std::*;

    #[cfg(not(feature = "std"))]
    pub use self::no_std::*;
}
<|endoftext|>


<commit_before>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! # **glib**, **gobject** and **gio** bindings for Rust
//!
//! This library contains
//!
//! - bindings to some essential GLib, GObject, GIO types and APIs,
//!
//! - common building blocks used in both handmade and machine generated
//! bindings to GTK+ and other GLib-based libraries.
//!
//! It is the foundation for higher level libraries with uniform Rusty (safe and
//! strongly typed) APIs. It avoids exposing GLib-specific data types where
//! possible and is not meant to provide comprehensive GLib bindings, which
//! would often amount to duplicating the Rust Standard Library or other utility
//! crates.
//!
//! The library is a work in progress: expect missing functionality and breaking
//! changes.
//!
//! # Dynamic typing
//!
//! Most types in the GLib family have type identifiers
//! ([`Type`](types/enum.Type.html)). Their corresponding Rust types implement
//! the [`StaticType`](types/trait.StaticType.html) trait.
//!
//! Dynamically typed [`Value`](value/index.html) can carry values of any `T:
//! StaticType`.
//!
//! [`Variant`](variant/index.html) can carry values of `T: StaticVariantType`.
//!
//! # Errors
//!
//! Errors are represented by [`Error`](error/struct.Error.html), which can
//! carry values from various [error
//! domains](error/trait.ErrorDomain.html#implementors) (such as
//! [`FileError`](enum.FileError.html)).
//!
//! # Objects
//!
//! Each class and interface has a corresponding smart pointer struct
//! representing an instance of that type (e.g. `Object` for `GObject`,
//! `gtk::Widget` for `GtkWidget`). They are reference counted and feature
//! interior mutability similarly to Rust's `Rc<RefCell<T>>` idiom.
//! Consequently, cloning objects is cheap and their methods never require
//! mutable borrows. Two smart pointers are equal iff they point to the same
//! object.
//!
//! The root of the object hierarchy is [`Object`](object/struct.Object.html).
//! Inheritance and subtyping is denoted with the [`IsA`](object/trait.IsA.html)
//! marker trait. The [`Cast`](object/trait.Cast.html) trait enables upcasting
//! and downcasting.
//!
//! Interfaces and non-leaf classes also have corresponding traits (e.g.
//! `ObjectExt` and `gtk::WidgetExt`), which are blanketly implemented for all
//! their subtypes.
//!
//! # Under the hood
//!
//! GLib-based libraries largely operate on pointers to various boxed or
//! reference counted structures so the bindings have to implement corresponding
//! smart pointers (wrappers), which encapsulate resource management and safety
//! checks. Such wrappers are defined via the
//! [`glib_wrapper!`](macro.glib_wrapper!.html) macro, which uses abstractions
//! defined in the [`wrapper`](wrapper/index.html), [`boxed`](boxed/index.html),
//! [`shared`](shared/index.html) and [`object`](object/index.html) modules.
//!
//! The [`translate`](translate/index.html) module defines and partly implements
//! conversions between high level Rust types (including the aforementioned
//! wrappers) and their FFI counterparts.

#![cfg_attr(feature = "cargo-clippy", allow(doc_markdown))]

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate glib_sys as ffi;
extern crate gobject_sys as gobject_ffi;

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

use std::ffi::CStr;
pub use bytes::Bytes;
pub use string::String;
pub use closure::Closure;
pub use error::{Error, BoolError};
pub use file_error::FileError;
pub use object::{
    Cast,
    IsA,
    IsClassFor,
    Object,
    ObjectExt,
    ObjectClass,
    WeakRef,
    SendWeakRef,
};
pub use signal::{
    SignalHandlerId,
    signal_handler_block,
    signal_handler_disconnect,
    signal_handler_unblock,
    signal_stop_emission_by_name
};

pub use types::{
    StaticType,
    Type,
};
pub use value::{
    ToValue,
    ToSendValue,
    TypedValue,
    SendValue,
    Value,
    AnyValue,
    AnySendValue,
};
pub use variant::{
    StaticVariantType,
    ToVariant,
    Variant,
};
pub use variant_type::{
    VariantTy,
    VariantType,
};
pub use time_val::{
    TimeVal,
    get_current_time,
};
pub use enums::{
    UserDirectory,
    EnumClass,
    EnumValue,
    FlagsClass,
    FlagsValue,
    FlagsBuilder,
};

#[macro_use]
pub mod wrapper;
#[macro_use]
pub mod boxed;
#[macro_use]
pub mod shared;
#[macro_use]
pub mod object;

pub use auto::*;
pub use auto::functions::*;
#[cfg_attr(feature = "cargo-clippy", allow(let_and_return))]
#[cfg_attr(feature = "cargo-clippy", allow(let_unit_value))]
#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#[allow(non_upper_case_globals)]
mod auto;

pub use gobject::*;
mod gobject;

mod bytes;
mod string;
pub mod char;
pub use char::*;
mod checksum;
pub mod closure;
pub mod error;
mod enums;
mod file_error;
mod key_file;
pub mod prelude;
pub mod signal;
pub mod source;
pub use source::*;
mod time_val;
pub mod translate;
pub mod types;
mod utils;
pub use utils::*;
pub mod value;
pub mod variant;
mod variant_type;
mod main_context;
mod date;
pub use date::Date;
mod value_array;
pub use value_array::ValueArray;
mod param_spec;
pub use param_spec::ParamSpec;
mod quark;
pub use quark::Quark;

pub mod send_unique;
pub use send_unique::{
    SendUniqueCell,
    SendUnique,
};

#[cfg(feature="futures")]
mod main_context_futures;
#[cfg(feature="futures")]
mod source_futures;
#[cfg(feature="futures")]
pub use source_futures::*;

// Actual thread IDs can be reused by the OS once the old thread finished.
// This works around it by using our own counter for threads.
//
// Taken from the fragile crate
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
fn next_thread_id() -> usize {
    static mut COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
    unsafe { COUNTER.fetch_add(1, Ordering::SeqCst) }
}

pub(crate) fn get_thread_id() -> usize {
    thread_local!(static THREAD_ID: usize = next_thread_id());
    THREAD_ID.with(|&x| x)
}

#[macro_use]
#[cfg(any(feature = "dox", feature="subclassing"))]
pub mod subclass;
<commit_msg>Add a link to the subclass module in the main library documentation<commit_after>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! # **glib**, **gobject** and **gio** bindings for Rust
//!
//! This library contains
//!
//! - bindings to some essential GLib, GObject, GIO types and APIs,
//!
//! - common building blocks used in both handmade and machine generated
//! bindings to GTK+ and other GLib-based libraries.
//!
//! It is the foundation for higher level libraries with uniform Rusty (safe and
//! strongly typed) APIs. It avoids exposing GLib-specific data types where
//! possible and is not meant to provide comprehensive GLib bindings, which
//! would often amount to duplicating the Rust Standard Library or other utility
//! crates.
//!
//! The library is a work in progress: expect missing functionality and breaking
//! changes.
//!
//! # Dynamic typing
//!
//! Most types in the GLib family have type identifiers
//! ([`Type`](types/enum.Type.html)). Their corresponding Rust types implement
//! the [`StaticType`](types/trait.StaticType.html) trait.
//!
//! Dynamically typed [`Value`](value/index.html) can carry values of any `T:
//! StaticType`.
//!
//! [`Variant`](variant/index.html) can carry values of `T: StaticVariantType`.
//!
//! # Errors
//!
//! Errors are represented by [`Error`](error/struct.Error.html), which can
//! carry values from various [error
//! domains](error/trait.ErrorDomain.html#implementors) (such as
//! [`FileError`](enum.FileError.html)).
//!
//! # Objects
//!
//! Each class and interface has a corresponding smart pointer struct
//! representing an instance of that type (e.g. `Object` for `GObject`,
//! `gtk::Widget` for `GtkWidget`). They are reference counted and feature
//! interior mutability similarly to Rust's `Rc<RefCell<T>>` idiom.
//! Consequently, cloning objects is cheap and their methods never require
//! mutable borrows. Two smart pointers are equal iff they point to the same
//! object.
//!
//! The root of the object hierarchy is [`Object`](object/struct.Object.html).
//! Inheritance and subtyping is denoted with the [`IsA`](object/trait.IsA.html)
//! marker trait. The [`Cast`](object/trait.Cast.html) trait enables upcasting
//! and downcasting.
//!
//! Interfaces and non-leaf classes also have corresponding traits (e.g.
//! `ObjectExt` and `gtk::WidgetExt`), which are blanketly implemented for all
//! their subtypes.
//!
//! For creating new subclasses of `Object` or other object types this crate has to be compiled
//! with the `subclassing` feature to enable the [`subclass`](subclass/index.html) module. Check
//! the module's documentation for further details and a code example.
//!
//! # Under the hood
//!
//! GLib-based libraries largely operate on pointers to various boxed or
//! reference counted structures so the bindings have to implement corresponding
//! smart pointers (wrappers), which encapsulate resource management and safety
//! checks. Such wrappers are defined via the
//! [`glib_wrapper!`](macro.glib_wrapper!.html) macro, which uses abstractions
//! defined in the [`wrapper`](wrapper/index.html), [`boxed`](boxed/index.html),
//! [`shared`](shared/index.html) and [`object`](object/index.html) modules.
//!
//! The [`translate`](translate/index.html) module defines and partly implements
//! conversions between high level Rust types (including the aforementioned
//! wrappers) and their FFI counterparts.

#![cfg_attr(feature = "cargo-clippy", allow(doc_markdown))]

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate glib_sys as ffi;
extern crate gobject_sys as gobject_ffi;

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

use std::ffi::CStr;
pub use bytes::Bytes;
pub use string::String;
pub use closure::Closure;
pub use error::{Error, BoolError};
pub use file_error::FileError;
pub use object::{
    Cast,
    IsA,
    IsClassFor,
    Object,
    ObjectExt,
    ObjectClass,
    WeakRef,
    SendWeakRef,
};
pub use signal::{
    SignalHandlerId,
    signal_handler_block,
    signal_handler_disconnect,
    signal_handler_unblock,
    signal_stop_emission_by_name
};

pub use types::{
    StaticType,
    Type,
};
pub use value::{
    ToValue,
    ToSendValue,
    TypedValue,
    SendValue,
    Value,
    AnyValue,
    AnySendValue,
};
pub use variant::{
    StaticVariantType,
    ToVariant,
    Variant,
};
pub use variant_type::{
    VariantTy,
    VariantType,
};
pub use time_val::{
    TimeVal,
    get_current_time,
};
pub use enums::{
    UserDirectory,
    EnumClass,
    EnumValue,
    FlagsClass,
    FlagsValue,
    FlagsBuilder,
};

#[macro_use]
pub mod wrapper;
#[macro_use]
pub mod boxed;
#[macro_use]
pub mod shared;
#[macro_use]
pub mod object;

pub use auto::*;
pub use auto::functions::*;
#[cfg_attr(feature = "cargo-clippy", allow(let_and_return))]
#[cfg_attr(feature = "cargo-clippy", allow(let_unit_value))]
#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#[allow(non_upper_case_globals)]
mod auto;

pub use gobject::*;
mod gobject;

mod bytes;
mod string;
pub mod char;
pub use char::*;
mod checksum;
pub mod closure;
pub mod error;
mod enums;
mod file_error;
mod key_file;
pub mod prelude;
pub mod signal;
pub mod source;
pub use source::*;
mod time_val;
pub mod translate;
pub mod types;
mod utils;
pub use utils::*;
pub mod value;
pub mod variant;
mod variant_type;
mod main_context;
mod date;
pub use date::Date;
mod value_array;
pub use value_array::ValueArray;
mod param_spec;
pub use param_spec::ParamSpec;
mod quark;
pub use quark::Quark;

pub mod send_unique;
pub use send_unique::{
    SendUniqueCell,
    SendUnique,
};

#[cfg(feature="futures")]
mod main_context_futures;
#[cfg(feature="futures")]
mod source_futures;
#[cfg(feature="futures")]
pub use source_futures::*;

// Actual thread IDs can be reused by the OS once the old thread finished.
// This works around it by using our own counter for threads.
//
// Taken from the fragile crate
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
fn next_thread_id() -> usize {
    static mut COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
    unsafe { COUNTER.fetch_add(1, Ordering::SeqCst) }
}

pub(crate) fn get_thread_id() -> usize {
    thread_local!(static THREAD_ID: usize = next_thread_id());
    THREAD_ID.with(|&x| x)
}

#[macro_use]
#[cfg(any(feature = "dox", feature="subclassing"))]
pub mod subclass;
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![allow(unused_imports)]

#[macro_use]
extern crate nom;

extern crate crc;

use nom::{HexDisplay,Needed,IResult,ErrorKind,le_i32,le_u32,le_u8,le_u16,length_value,FileProducer};
use nom::Err;
use nom::IResult::*;

struct A {
  a: u8,
  b: u8
}

enum RProp {
    Array(Box<[RProp]>),
    Bool(bool),
    Byte(u8),
    Float(f32),
    Int(u32),
    Name(String),
    QWord(u64),
    Str(String)
}

named!(length_encoded,
    chain!(
        size: le_u32 ~
        crc: le_u32 ~
        data: take!(size),
        || {data}
    )
);

/// Text is encoded with a leading int that denotes the number of bytes that
/// the text spans. The last byte in the text will be null terminated, so we trim
/// it off. It may seem redundant to store this information, but stackoverflow contains
/// a nice reasoning for why it may have been done this way:
/// http://stackoverflow.com/questions/6293457/why-are-c-net-strings-length-prefixed-and-null-terminated
named!(text_encoded<&[u8], &str>,
    chain!(
        size: le_u32 ~
        data: take_str!(size - 1) ~
        take!(1),
        || {data}
    )
);

named!(str_prop<&[u8], RProp>, map!(map!(text_encoded, str::to_string), RProp::Str));

named!(rprop_encoded<&[u8], RProp>,
  switch!(text_encoded,
    "ArrayProperty" => call!(str_prop) |
    "BoolProperty" => call!(str_prop) |
    "ByteProperty" => call!(str_prop)|
    "FloatProperty" => call!(str_prop) |
    "IntProperty" => call!(str_prop) |
    "NameProperty" => call!(str_prop) |
    "QWordProperty" => call!(str_prop) |
    "StrProperty" => call!(str_prop)
  )
);

named!(f<&[u8],A>,
    chain!(
        header_size:  le_i32 ~
        header_crc:   le_i32 ~
        header:       take!(header_size) ~
        content_size: le_i32 ~
        content_crc:  le_i32 ~
        content:      take!(content_size),
        || {A {a: 0, b: 0}}
    )
);

#[cfg(test)]
mod tests {
    use nom::IResult::{Done, Error, Incomplete};
    use nom::Needed::Size;

    #[test]
    fn missing_header_data() {
        let data = include_bytes!("../assets/rumble.replay");
        let r = super::length_encoded(&data[..8]);
        assert_eq!(r, Incomplete(Size(4776)));
    }

    #[test]
    fn incomplete_header_data() {
        let data = include_bytes!("../assets/rumble.replay");
        let r = super::length_encoded(&data[..9]);
        assert_eq!(r, Incomplete(Size(4776)));
    }

    #[test]
    fn missing_header() {
        let r = super::length_encoded(&[]);
        assert_eq!(r, Incomplete(Size(4)));
    }

    #[test]
    fn missing_crc_data() {
        let data = include_bytes!("../assets/rumble.replay");
        let r = super::length_encoded(&data[..4]);
        assert_eq!(r, Incomplete(Size(8)));
    }

    #[test]
    fn parse_a_header_with_zero_data() {
        let data = [0, 0, 0, 0, 0, 0, 0, 0];
        let r = super::length_encoded(&data);
        assert_eq!(r, Done(&[][..], &[][..]));
    }

    #[test]
    fn parse_text_encoding() {
        // dd skip=16 count=28 if=rumble.replay of=text.replay bs=1
        let data = include_bytes!("../assets/text.replay");
        let r = super::text_encoded(data);
        assert_eq!(r, Done(&[][..], "TAGame.Replay_Soccar_TA"));
    }
}
<commit_msg>Rustfmt<commit_after>#![allow(dead_code)]
#![allow(unused_imports)]

#[macro_use]
extern crate nom;

extern crate crc;

use nom::{HexDisplay, Needed, IResult, ErrorKind, le_i32, le_u32, le_u8, le_u16, length_value,
          FileProducer};
use nom::Err;
use nom::IResult::*;

struct A {
    a: u8,
    b: u8,
}

enum RProp {
    Array(Box<[RProp]>),
    Bool(bool),
    Byte(u8),
    Float(f32),
    Int(u32),
    Name(String),
    QWord(u64),
    Str(String),
}

named!(length_encoded,
       chain!(
        size: le_u32 ~
        crc: le_u32 ~
        data: take!(size),
        || {data}
    ));

/// Text is encoded with a leading int that denotes the number of bytes that
/// the text spans. The last byte in the text will be null terminated, so we trim
/// it off. It may seem redundant to store this information, but stackoverflow contains
/// a nice reasoning for why it may have been done this way:
///
/// http://stackoverflow.com/questions/6293457/why-are-c-net-strings-length-prefixed-and-null-terminated
named!(text_encoded<&[u8], &str>,
    chain!(
        size: le_u32 ~
        data: take_str!(size - 1) ~
        take!(1),
        || {data}
    )
);

named!(str_prop<&[u8], RProp>, map!(map!(text_encoded, str::to_string), RProp::Str));

named!(rprop_encoded<&[u8], RProp>,
  switch!(text_encoded,
    "ArrayProperty" => call!(str_prop) |
    "BoolProperty" => call!(str_prop) |
    "ByteProperty" => call!(str_prop)|
    "FloatProperty" => call!(str_prop) |
    "IntProperty" => call!(str_prop) |
    "NameProperty" => call!(str_prop) |
    "QWordProperty" => call!(str_prop) |
    "StrProperty" => call!(str_prop)
  )
);

named!(f<&[u8],A>,
    chain!(
        header_size:  le_i32 ~
        header_crc:   le_i32 ~
        header:       take!(header_size) ~
        content_size: le_i32 ~
        content_crc:  le_i32 ~
        content:      take!(content_size),
        || {A {a: 0, b: 0}}
    )
);

#[cfg(test)]
mod tests {
    use nom::IResult::{Done, Error, Incomplete};
    use nom::Needed::Size;

    #[test]
    fn missing_header_data() {
        let data = include_bytes!("../assets/rumble.replay");
        let r = super::length_encoded(&data[..8]);
        assert_eq!(r, Incomplete(Size(4776)));
    }

    #[test]
    fn incomplete_header_data() {
        let data = include_bytes!("../assets/rumble.replay");
        let r = super::length_encoded(&data[..9]);
        assert_eq!(r, Incomplete(Size(4776)));
    }

    #[test]
    fn missing_header() {
        let r = super::length_encoded(&[]);
        assert_eq!(r, Incomplete(Size(4)));
    }

    #[test]
    fn missing_crc_data() {
        let data = include_bytes!("../assets/rumble.replay");
        let r = super::length_encoded(&data[..4]);
        assert_eq!(r, Incomplete(Size(8)));
    }

    #[test]
    fn parse_a_header_with_zero_data() {
        let data = [0, 0, 0, 0, 0, 0, 0, 0];
        let r = super::length_encoded(&data);
        assert_eq!(r, Done(&[][..], &[][..]));
    }

    #[test]
    fn parse_text_encoding() {
        // dd skip=16 count=28 if=rumble.replay of=text.replay bs=1
        let data = include_bytes!("../assets/text.replay");
        let r = super::text_encoded(data);
        assert_eq!(r, Done(&[][..], "TAGame.Replay_Soccar_TA"));
    }
}
<|endoftext|>


<commit_before>//! The goal of this crate is to provide Rust bindings to the Web APIs and to allow
//! a high degree of interoperability between Rust and JavaScript.
//!
//! ## Examples
//!
//! You can directly embed JavaScript code into Rust:
//!
//! ```rust
//! let message = "Hello, 世界!";
//! let result = js! {
//!     alert( @{message} );
//!     return 2 + 2 * 2;
//! };
//!
//! println!( "2 + 2 * 2 = {:?}", result );
//! ```
//!
//! Even closures are supported:
//!
//! ```rust
//! let print_hello = |name: String| {
//!     println!( "Hello, {}!", name );
//! };
//!
//! js! {
//!     var print_hello = @{print_hello};
//!     print_hello( "Bob" );
//!     print_hello.drop(); // Necessary to clean up the closure on Rust's side.
//! }
//! ```
//!
//! You can also pass arbitrary structures thanks to [serde]:
//!
//! ```rust
//! #[derive(Serialize)]
//! struct Person {
//!     name: String,
//!     age: i32
//! }
//!
//! js_serializable!( Person );
//!
//! js! {
//!     var person = @{person};
//!     console.log( person.name + " is " + person.age + " years old." );
//! };
//! ```
//!
//! [serde]: https://serde.rs/
//!
//! This crate also exposes a number of Web APIs, for example:
//!
//! ```rust
//! let button = document().query_selector( "#hide-button" ).unwrap();
//! button.add_event_listener( move |_: ClickEvent| {
//!     for anchor in document().query_selector_all( "#main a" ) {
//!         js!( @{anchor}.style = "display: none;"; );
//!     }
//! });
//! ```

#![deny(
    missing_docs,
    missing_debug_implementations,
    trivial_numeric_casts,
    unstable_features,
    unused_import_braces,
    unused_qualifications
)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![recursion_limit="1500"]

#[cfg(feature = "serde")]
#[macro_use]
extern crate serde as serde_crate;

#[cfg(any(test, feature = "serde_json"))]
extern crate serde_json;

#[cfg(all(test, feature = "serde"))]
#[macro_use]
extern crate serde_derive;

#[macro_use]
mod webcore;
mod webapi;
mod ecosystem;

pub use webcore::initialization::{
    initialize,
    event_loop
};
pub use webcore::value::{
    Undefined,
    Null,
    Value,
    Reference
};
pub use webcore::number::Number;
pub use webcore::object::Object;
pub use webcore::array::Array;

#[cfg(feature = "serde")]
/// A module with serde-related APIs.
pub mod serde {
    pub use ecosystem::serde::{
        ConversionError,
        Serde
    };
}

/// A module with bindings to the Web APIs.
pub mod web {
    pub use webapi::window::{
        Window,
        window
    };
    pub use webapi::document::{
        Document,
        document
    };
    pub use webapi::global::{
        set_timeout,
        alert
    };
    pub use webapi::cross_origin_setting::CrossOriginSetting;
    pub use webapi::date::Date;
    pub use webapi::event_target::{IEventTarget, EventTarget, EventListenerHandle};
    pub use webapi::node::{INode, Node, CloneKind};
    pub use webapi::element::{IElement, Element};
    pub use webapi::html_element::{IHtmlElement, HtmlElement};
    pub use webapi::window_or_worker::IWindowOrWorker;
    pub use webapi::token_list::TokenList;
    pub use webapi::node_list::NodeList;
    pub use webapi::string_map::StringMap;
    pub use webapi::storage::Storage;
    pub use webapi::location::Location;
    pub use webapi::array_buffer::ArrayBuffer;
    pub use webapi::typed_array::TypedArray;

    /// A module containing error types.
    pub mod error {
        pub use webapi::node::NotFoundError;
    }

    /// A module containing HTML DOM elements.
    pub mod html_element {
        pub use webapi::html_elements::ImageElement;
        pub use webapi::html_elements::InputElement;
    }

    /// A module containing JavaScript DOM events.
    pub mod event {
        pub use webapi::event::{
            ConcreteEvent,

            IEvent,
            IKeyboardEvent,
            IUiEvent,
            IMouseEvent,
            IFocusEvent,
            IProgressEvent,

            EventPhase,
            KeyboardLocation,
            ModifierKey,
            MouseButton,

            ChangeEvent,
            KeypressEvent,
            ClickEvent,
            DoubleClickEvent,
            FocusEvent,
            BlurEvent,
            HashChangeEvent,
            LoadEvent,
            ProgressEvent,
            LoadStartEvent,
            LoadEndEvent,
            AbortEvent,
            ErrorEvent,
            InputEvent
        };
    }
}

/// A module containing stable counterparts to currently
/// unstable Rust features.
pub mod unstable {
    pub use webcore::try_from::{
        TryFrom,
        TryInto
    };

    pub use webcore::void::Void;
}

#[doc(hidden)]
pub mod private {
    pub use webcore::ffi::exports::*;
    pub use webcore::serialization::{
        JsSerializable,
        JsSerializableOwned,
        PreallocatedArena,
        SerializedValue
    };

    pub use webcore::newtype::{
        IntoNewtype,
        Newtype
    };

    pub use webcore::value::{
        FromReference,
        FromReferenceUnchecked
    };

    #[cfg(feature = "serde")]
    pub use ecosystem::serde::{
        to_value,
        from_value
    };

    // This is to prevent an unused_mut warnings in macros, because an `allow` doesn't work apparently?
    #[allow(dead_code)]
    #[inline(always)]
    pub fn noop< T >( _: &mut T ) {}
}
<commit_msg>Publish TextNode struct<commit_after>//! The goal of this crate is to provide Rust bindings to the Web APIs and to allow
//! a high degree of interoperability between Rust and JavaScript.
//!
//! ## Examples
//!
//! You can directly embed JavaScript code into Rust:
//!
//! ```rust
//! let message = "Hello, 世界!";
//! let result = js! {
//!     alert( @{message} );
//!     return 2 + 2 * 2;
//! };
//!
//! println!( "2 + 2 * 2 = {:?}", result );
//! ```
//!
//! Even closures are supported:
//!
//! ```rust
//! let print_hello = |name: String| {
//!     println!( "Hello, {}!", name );
//! };
//!
//! js! {
//!     var print_hello = @{print_hello};
//!     print_hello( "Bob" );
//!     print_hello.drop(); // Necessary to clean up the closure on Rust's side.
//! }
//! ```
//!
//! You can also pass arbitrary structures thanks to [serde]:
//!
//! ```rust
//! #[derive(Serialize)]
//! struct Person {
//!     name: String,
//!     age: i32
//! }
//!
//! js_serializable!( Person );
//!
//! js! {
//!     var person = @{person};
//!     console.log( person.name + " is " + person.age + " years old." );
//! };
//! ```
//!
//! [serde]: https://serde.rs/
//!
//! This crate also exposes a number of Web APIs, for example:
//!
//! ```rust
//! let button = document().query_selector( "#hide-button" ).unwrap();
//! button.add_event_listener( move |_: ClickEvent| {
//!     for anchor in document().query_selector_all( "#main a" ) {
//!         js!( @{anchor}.style = "display: none;"; );
//!     }
//! });
//! ```

#![deny(
    missing_docs,
    missing_debug_implementations,
    trivial_numeric_casts,
    unstable_features,
    unused_import_braces,
    unused_qualifications
)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![recursion_limit="1500"]

#[cfg(feature = "serde")]
#[macro_use]
extern crate serde as serde_crate;

#[cfg(any(test, feature = "serde_json"))]
extern crate serde_json;

#[cfg(all(test, feature = "serde"))]
#[macro_use]
extern crate serde_derive;

#[macro_use]
mod webcore;
mod webapi;
mod ecosystem;

pub use webcore::initialization::{
    initialize,
    event_loop
};
pub use webcore::value::{
    Undefined,
    Null,
    Value,
    Reference
};
pub use webcore::number::Number;
pub use webcore::object::Object;
pub use webcore::array::Array;

#[cfg(feature = "serde")]
/// A module with serde-related APIs.
pub mod serde {
    pub use ecosystem::serde::{
        ConversionError,
        Serde
    };
}

/// A module with bindings to the Web APIs.
pub mod web {
    pub use webapi::window::{
        Window,
        window
    };
    pub use webapi::document::{
        Document,
        document
    };
    pub use webapi::global::{
        set_timeout,
        alert
    };
    pub use webapi::cross_origin_setting::CrossOriginSetting;
    pub use webapi::date::Date;
    pub use webapi::event_target::{IEventTarget, EventTarget, EventListenerHandle};
    pub use webapi::node::{INode, Node, CloneKind};
    pub use webapi::element::{IElement, Element};
    pub use webapi::text_node::TextNode;
    pub use webapi::html_element::{IHtmlElement, HtmlElement};
    pub use webapi::window_or_worker::IWindowOrWorker;
    pub use webapi::token_list::TokenList;
    pub use webapi::node_list::NodeList;
    pub use webapi::string_map::StringMap;
    pub use webapi::storage::Storage;
    pub use webapi::location::Location;
    pub use webapi::array_buffer::ArrayBuffer;
    pub use webapi::typed_array::TypedArray;

    /// A module containing error types.
    pub mod error {
        pub use webapi::node::NotFoundError;
    }

    /// A module containing HTML DOM elements.
    pub mod html_element {
        pub use webapi::html_elements::ImageElement;
        pub use webapi::html_elements::InputElement;
    }

    /// A module containing JavaScript DOM events.
    pub mod event {
        pub use webapi::event::{
            ConcreteEvent,

            IEvent,
            IKeyboardEvent,
            IUiEvent,
            IMouseEvent,
            IFocusEvent,
            IProgressEvent,

            EventPhase,
            KeyboardLocation,
            ModifierKey,
            MouseButton,

            ChangeEvent,
            KeypressEvent,
            ClickEvent,
            DoubleClickEvent,
            FocusEvent,
            BlurEvent,
            HashChangeEvent,
            LoadEvent,
            ProgressEvent,
            LoadStartEvent,
            LoadEndEvent,
            AbortEvent,
            ErrorEvent,
            InputEvent
        };
    }
}

/// A module containing stable counterparts to currently
/// unstable Rust features.
pub mod unstable {
    pub use webcore::try_from::{
        TryFrom,
        TryInto
    };

    pub use webcore::void::Void;
}

#[doc(hidden)]
pub mod private {
    pub use webcore::ffi::exports::*;
    pub use webcore::serialization::{
        JsSerializable,
        JsSerializableOwned,
        PreallocatedArena,
        SerializedValue
    };

    pub use webcore::newtype::{
        IntoNewtype,
        Newtype
    };

    pub use webcore::value::{
        FromReference,
        FromReferenceUnchecked
    };

    #[cfg(feature = "serde")]
    pub use ecosystem::serde::{
        to_value,
        from_value
    };

    // This is to prevent an unused_mut warnings in macros, because an `allow` doesn't work apparently?
    #[allow(dead_code)]
    #[inline(always)]
    pub fn noop< T >( _: &mut T ) {}
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do Cap'n Proto code generation within a Cargo build.
//!
//! In your Cargo.toml:
//!
//! ```ignore
//!   [build-dependencies.capnpc]
//!   git = "https://github.com/dwrensha/capnpc-rust.git"
//! ```
//!
//! In your build.rs, call
//!
//! ```ignore
//! ::capnpc::compile(Path::new("schema"),
//!                   [Path::new("schema/foo.capnp"),
//!                    Path::new("schema/bar.capnp")]);
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

#![feature(globs)]

#![crate_name="capnpc"]
#![crate_type = "lib"]

extern crate capnp;

pub mod schema_capnp;
pub mod codegen;

pub fn compile(prefix : Path, files : &[Path]) {
    let out_dir = Path::new(::std::os::getenv("OUT_DIR").unwrap());
    let cwd = ::std::os::getcwd();
    ::std::os::change_dir(&out_dir);

    let mut command = ::std::io::Command::new("capnp");
    command
        .arg("compile")
        .arg("-o/bin/cat")
        .arg(format!("--src-prefix={}", cwd.join(prefix).display()));

    for file in files.iter() {
        command.arg(format!("{}", cwd.join(file).display()));
    }

    command.stdout(::std::io::process::CreatePipe(false, true));

    match command.spawn() {
        Ok(ref mut p) =>  {
            let mut child_stdout = p.stdout.take().unwrap();
            ::codegen::main(&mut child_stdout).unwrap();
            p.wait().unwrap();
        }
        Err(e) => {
            panic!("could not start process: {}", e);
        }
    }

}

<commit_msg>directory operations now return IoResults<commit_after>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do Cap'n Proto code generation within a Cargo build.
//!
//! In your Cargo.toml:
//!
//! ```ignore
//!   [build-dependencies.capnpc]
//!   git = "https://github.com/dwrensha/capnpc-rust.git"
//! ```
//!
//! In your build.rs, call
//!
//! ```ignore
//! ::capnpc::compile(Path::new("schema"),
//!                   [Path::new("schema/foo.capnp"),
//!                    Path::new("schema/bar.capnp")]);
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

#![feature(globs)]

#![crate_name="capnpc"]
#![crate_type = "lib"]

extern crate capnp;

pub mod schema_capnp;
pub mod codegen;

pub fn compile(prefix : Path, files : &[Path]) {
    let out_dir = Path::new(::std::os::getenv("OUT_DIR").unwrap());
    let cwd = ::std::os::getcwd().unwrap();
    ::std::os::change_dir(&out_dir).unwrap();

    let mut command = ::std::io::Command::new("capnp");
    command
        .arg("compile")
        .arg("-o/bin/cat")
        .arg(format!("--src-prefix={}", cwd.join(prefix).display()));

    for file in files.iter() {
        command.arg(format!("{}", cwd.join(file).display()));
    }

    command.stdout(::std::io::process::CreatePipe(false, true));

    match command.spawn() {
        Ok(ref mut p) =>  {
            let mut child_stdout = p.stdout.take().unwrap();
            ::codegen::main(&mut child_stdout).unwrap();
            p.wait().unwrap();
        }
        Err(e) => {
            panic!("could not start process: {}", e);
        }
    }

}

<|endoftext|>


<commit_before>// Copyright © 2015 by Michael Dilger (of New Zealand)
// This code is licensed under the MIT license (see LICENSE-MIT for details)

//! This crate parses and processes a stream of data that contains
//! `multipart/form-data` content.
//!
//! The main entry point is `read_formdata`

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

extern crate httparse;
extern crate hyper;
#[macro_use]
extern crate mime;
extern crate textnonce;
#[macro_use]
extern crate log;
extern crate encoding;

extern crate mime_multipart;

mod error;
mod form_data;
#[cfg(test)]
mod mock;

pub use error::Error;
pub use form_data::FormData;

use std::io::{Read, Write};
use hyper::header::{Headers, ContentDisposition, DispositionParam, ContentType,
                    DispositionType};
use mime_multipart::{Node, Part};
use mime::{Mime, TopLevel, SubLevel};

/// Parse MIME `multipart/form-data` information from a stream as a `FormData`.
pub fn read_formdata<S: Read>(stream: &mut S, headers: &Headers) -> Result<FormData, Error>
{
    let nodes = try!(mime_multipart::read_multipart_body(stream, headers, false));

    let mut formdata = FormData::new();
    try!(fill_formdata(&mut formdata, nodes));
    Ok(formdata)
}

// order and nesting are irrelevant, so we interate through the nodes and put them
// into one of two buckets (fields and files);  If a multipart node is found, it uses
// the name in its headers as the key (rather than the name in the headers of the
// subparts), which is how multiple file uploads work.
fn fill_formdata(formdata: &mut FormData, nodes: Vec<Node>) -> Result<(), Error>
{
    for node in nodes {
        match node {
            Node::Part(part) => {
                let cd_name: Option<String> = {
                    let cd: &ContentDisposition = match part.headers.get() {
                        Some(cd) => cd,
                        None => return Err(Error::MissingDisposition),
                    };
                    get_content_disposition_name(&cd)
                };
                let key = try!(cd_name.ok_or(Error::NoName));
                let val = try!(String::from_utf8(part.body));
                formdata.fields.push((key, val));
            },
            Node::File(part) => {
                let cd_name: Option<String> = {
                    let cd: &ContentDisposition = match part.headers.get() {
                        Some(cd) => cd,
                        None => return Err(Error::MissingDisposition),
                    };
                    get_content_disposition_name(&cd)
                };
                let key = try!(cd_name.ok_or(Error::NoName));
                formdata.files.push((key, part));
            }
            Node::Multipart((headers, nodes)) => {
                let cd_name: Option<String> = {
                    let cd: &ContentDisposition = match headers.get() {
                        Some(cd) => cd,
                        None => return Err(Error::MissingDisposition),
                    };
                    get_content_disposition_name(&cd)
                };
                let key = try!(cd_name.ok_or(Error::NoName));
                for node in nodes {
                    match node {
                        Node::Part(part) => {
                            let val = try!(String::from_utf8(part.body));
                            formdata.fields.push((key.clone(), val));
                        },
                        Node::File(part) => {
                            formdata.files.push((key.clone(), part));
                        },
                        _ => { } // don't recurse deeper
                    }
                }
            }
        }
    }
    Ok(())
}

#[inline]
fn get_content_disposition_name(cd: &ContentDisposition) -> Option<String> {
    if let Some(&DispositionParam::Ext(_, ref value)) = cd.parameters.iter()
        .find(|&x| match *x {
            DispositionParam::Ext(ref token,_) => &*token == "name",
            _ => false,
        })
    {
        Some(value.clone())
    } else {
        None
    }
}

/// Stream out `multipart/form-data` body content matching the passed in `formdata`.  This
/// does not stream out headers, so the caller must stream those out before calling
/// write_formdata().
///
/// Note: File field names to be set in the headers in the FilePart; the FormData.files vector
/// pair first elements are not used herein.

pub fn write_formdata<S: Write>(stream: &mut S, formdata: &FormData) -> Result<usize, Error>
{
    // Translate to Nodes
    let mut nodes: Vec<Node> = Vec::with_capacity(formdata.fields.len() + formdata.files.len());

    for &(ref name, ref value) in &formdata.fields {
        let mut h = Headers::new();
        h.set(ContentType(Mime(TopLevel::Text, SubLevel::Plain, vec![])));
        h.set(ContentDisposition {
            disposition: DispositionType::Ext("form-data".to_owned()),
            parameters: vec![DispositionParam::Ext("name".to_owned(), name.clone())],
        });
        nodes.push( Node::Part( Part {
            headers: h,
            body: value.as_bytes().to_owned(),
        }));
    }

    for &(ref _name, ref filepart) in &formdata.files {
        // FIXME: maybe ensure the content-disposition formdata 'name' equals `_name`
        nodes.push( Node::File( filepart.clone() ) );
    }

    let boundary = ::mime_multipart::generate_boundary();

    // Write out
    let count = try!(::mime_multipart::write_multipart(stream, &boundary, &nodes));

    Ok(count)
}

#[cfg(test)]
mod tests {
    extern crate tempdir;

    use super::*;

    use std::net::SocketAddr;
    use std::fs::File;
    use std::io::Write;

    use hyper::buffer::BufReader;
    use hyper::net::NetworkStream;
    use hyper::server::Request as HyperRequest;
    use hyper::header::{Headers, ContentDisposition, DispositionParam, ContentType,
                        DispositionType};
    use mime_multipart::FilePart;
    use mime::{Mime, TopLevel, SubLevel};

    use mock::MockStream;

    #[test]
    fn parser() {
        let input = b"POST / HTTP/1.1\r\n\
                      Host: example.domain\r\n\
                      Content-Type: multipart/form-data; boundary=\"abcdefg\"\r\n\
                      Content-Length: 1000\r\n\
                      \r\n\
                      --abcdefg\r\n\
                      Content-Disposition: form-data; name=\"field1\"\r\n\
                      \r\n\
                      data1\r\n\
                      --abcdefg\r\n\
                      Content-Disposition: form-data; name=\"field2\"; filename=\"image.gif\"\r\n\
                      Content-Type: image/gif\r\n\
                      \r\n\
                      This is a file\r\n\
                      with two lines\r\n\
                      --abcdefg\r\n\
                      Content-Disposition: form-data; name=\"field3\"; filename=\"file.txt\"\r\n\
                      \r\n\
                      This is a file\r\n\
                      --abcdefg--";

        let mut mock = MockStream::with_input(input);

        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);
        let sock: SocketAddr = "127.0.0.1:80".parse().unwrap();
        let req = HyperRequest::new(&mut stream, sock).unwrap();
        let (_, _, headers, _, _, mut reader) = req.deconstruct();

        match read_formdata(&mut reader, &headers) {
            Ok(form_data) => {
                assert_eq!(form_data.fields.len(), 1);
                for (key, val) in form_data.fields {
                    if &key == "field1" {
                        assert_eq!(&val, "data1");
                    }
                }

                assert_eq!(form_data.files.len(), 2);
                for (key, file) in form_data.files {
                    if &key == "field2" {
                        assert_eq!(file.size, Some(30));
                        assert_eq!(&*file.filename().unwrap().unwrap(), "image.gif");
                        assert_eq!(file.content_type().unwrap(), mime!(Image/Gif));
                    } else if &key == "field3" {
                        assert_eq!(file.size, Some(14));
                        assert_eq!(&*file.filename().unwrap().unwrap(), "file.txt");
                        assert!(file.content_type().is_none());
                    }
                }
            },
            Err(err) => panic!("{}", err),
        }
    }

    #[test]
    fn multi_file_parser() {
        let input = b"POST / HTTP/1.1\r\n\
                      Host: example.domain\r\n\
                      Content-Type: multipart/form-data; boundary=\"abcdefg\"\r\n\
                      Content-Length: 1000\r\n\
                      \r\n\
                      --abcdefg\r\n\
                      Content-Disposition: form-data; name=\"field1\"\r\n\
                      \r\n\
                      data1\r\n\
                      --abcdefg\r\n\
                      Content-Disposition: form-data; name=\"field2\"; filename=\"image.gif\"\r\n\
                      Content-Type: image/gif\r\n\
                      \r\n\
                      This is a file\r\n\
                      with two lines\r\n\
                      --abcdefg\r\n\
                      Content-Disposition: form-data; name=\"field2\"; filename=\"file.txt\"\r\n\
                      \r\n\
                      This is a file\r\n\
                      --abcdefg--";

        let mut mock = MockStream::with_input(input);

        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);
        let sock: SocketAddr = "127.0.0.1:80".parse().unwrap();
        let req = HyperRequest::new(&mut stream, sock).unwrap();
        let (_, _, headers, _, _, mut reader) = req.deconstruct();

        match read_formdata(&mut reader, &headers) {
            Ok(form_data) => {
                assert_eq!(form_data.fields.len(), 1);
                for (key, val) in form_data.fields {
                    if &key == "field1" {
                        assert_eq!(&val, "data1");
                    }
                }

                assert_eq!(form_data.files.len(), 2);
                let (ref key, ref file) = form_data.files[0];

                assert_eq!(key, "field2");
                assert_eq!(file.size, Some(30));
                assert_eq!(&*file.filename().unwrap().unwrap(), "image.gif");
                assert_eq!(file.content_type().unwrap(), mime!(Image/Gif));

                let (ref key, ref file) = form_data.files[1];
                assert!(key == "field2");
                assert_eq!(file.size, Some(14));
                assert_eq!(&*file.filename().unwrap().unwrap(), "file.txt");
                assert!(file.content_type().is_none());

            },
            Err(err) => panic!("{}", err),
        }
    }

    #[test]
    fn mixed_parser() {
        let input = b"POST / HTTP/1.1\r\n\
                      Host: example.domain\r\n\
                      Content-Type: multipart/form-data; boundary=AaB03x\r\n\
                      Content-Length: 1000\r\n\
                      \r\n\
                      --AaB03x\r\n\
                      Content-Disposition: form-data; name=\"submit-name\"\r\n\
                      \r\n\
                      Larry\r\n\
                      --AaB03x\r\n\
                      Content-Disposition: form-data; name=\"files\"\r\n\
                      Content-Type: multipart/mixed; boundary=BbC04y\r\n\
                      \r\n\
                      --BbC04y\r\n\
                      Content-Disposition: file; filename=\"file1.txt\"\r\n\
                      \r\n\
                      ... contents of file1.txt ...\r\n\
                      --BbC04y\r\n\
                      Content-Disposition: file; filename=\"awesome_image.gif\"\r\n\
                      Content-Type: image/gif\r\n\
                      Content-Transfer-Encoding: binary\r\n\
                      \r\n\
                      ... contents of awesome_image.gif ...\r\n\
                      --BbC04y--\r\n\
                      --AaB03x--";

        let mut mock = MockStream::with_input(input);

        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);
        let sock: SocketAddr = "127.0.0.1:80".parse().unwrap();
        let req = HyperRequest::new(&mut stream, sock).unwrap();
        let (_, _, headers, _, _, mut reader) = req.deconstruct();

        match read_formdata(&mut reader, &headers) {
            Ok(form_data) => {
                assert_eq!(form_data.fields.len(), 1);
                for (key, val) in form_data.fields {
                    if &key == "submit-name" {
                        assert_eq!(&val, "Larry");
                    }
                }

                assert_eq!(form_data.files.len(), 2);
                for (key, file) in form_data.files {
                    assert_eq!(&key, "files");
                    match &file.filename().unwrap().unwrap()[..] {
                        "file1.txt" => {
                            assert_eq!(file.size, Some(29));
                            assert!(file.content_type().is_none());
                        }
                        "awesome_image.gif" => {
                            assert_eq!(file.size, Some(37));
                            assert_eq!(file.content_type().unwrap(), mime!(Image/Gif));
                        },
                        _ => unreachable!(),
                    }
                }
            },
            Err(err) => panic!("{}", err),
        }
    }

    #[test]
    fn simple_writer() {
        // Create a simple short file for testing
        let tmpdir = tempdir::TempDir::new("formdata_test").unwrap();
        let tmppath = tmpdir.path().join("testfile");
        let mut tmpfile = File::create(tmppath.clone()).unwrap();
        writeln!(tmpfile, "this is example file content").unwrap();

        let mut photo_headers = Headers::new();
        photo_headers.set(ContentType(Mime(TopLevel::Image, SubLevel::Gif, vec![])));
        photo_headers.set(ContentDisposition {
            disposition: DispositionType::Ext("form-data".to_owned()),
            parameters: vec![DispositionParam::Ext("name".to_owned(), "photo".to_owned()),
                             DispositionParam::Ext("filename".to_owned(), "mike.gif".to_owned())],
        });

        let formdata = FormData {
            fields: vec![ ("name".to_owned(), "Mike".to_owned()),
                            ("age".to_owned(), "46".to_owned()) ],
            files: vec![ ("photo".to_owned(), FilePart::new(photo_headers, &tmppath)) ],
        };

        let mut output: Vec<u8> = Vec::new();
        match write_formdata(&mut output, &formdata) {
            Ok(count) => assert_eq!(count, 568),
            Err(e) => panic!("Unable to write formdata: {}", e),
        }

        println!("{}", String::from_utf8_lossy(&output));
    }
}
<commit_msg>write_formdata to create/rewrite Content-Disposition header<commit_after>// Copyright © 2015 by Michael Dilger (of New Zealand)
// This code is licensed under the MIT license (see LICENSE-MIT for details)

//! This crate parses and processes a stream of data that contains
//! `multipart/form-data` content.
//!
//! The main entry point is `read_formdata`

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

extern crate httparse;
extern crate hyper;
#[macro_use]
extern crate mime;
extern crate textnonce;
#[macro_use]
extern crate log;
extern crate encoding;

extern crate mime_multipart;

mod error;
mod form_data;
#[cfg(test)]
mod mock;

pub use error::Error;
pub use form_data::FormData;

use std::io::{Read, Write};
use hyper::header::{Headers, ContentDisposition, DispositionParam, ContentType,
                    DispositionType};
use mime_multipart::{Node, Part};
use mime::{Mime, TopLevel, SubLevel};

/// Parse MIME `multipart/form-data` information from a stream as a `FormData`.
pub fn read_formdata<S: Read>(stream: &mut S, headers: &Headers) -> Result<FormData, Error>
{
    let nodes = try!(mime_multipart::read_multipart_body(stream, headers, false));

    let mut formdata = FormData::new();
    try!(fill_formdata(&mut formdata, nodes));
    Ok(formdata)
}

// order and nesting are irrelevant, so we interate through the nodes and put them
// into one of two buckets (fields and files);  If a multipart node is found, it uses
// the name in its headers as the key (rather than the name in the headers of the
// subparts), which is how multiple file uploads work.
fn fill_formdata(formdata: &mut FormData, nodes: Vec<Node>) -> Result<(), Error>
{
    for node in nodes {
        match node {
            Node::Part(part) => {
                let cd_name: Option<String> = {
                    let cd: &ContentDisposition = match part.headers.get() {
                        Some(cd) => cd,
                        None => return Err(Error::MissingDisposition),
                    };
                    get_content_disposition_name(&cd)
                };
                let key = try!(cd_name.ok_or(Error::NoName));
                let val = try!(String::from_utf8(part.body));
                formdata.fields.push((key, val));
            },
            Node::File(part) => {
                let cd_name: Option<String> = {
                    let cd: &ContentDisposition = match part.headers.get() {
                        Some(cd) => cd,
                        None => return Err(Error::MissingDisposition),
                    };
                    get_content_disposition_name(&cd)
                };
                let key = try!(cd_name.ok_or(Error::NoName));
                formdata.files.push((key, part));
            }
            Node::Multipart((headers, nodes)) => {
                let cd_name: Option<String> = {
                    let cd: &ContentDisposition = match headers.get() {
                        Some(cd) => cd,
                        None => return Err(Error::MissingDisposition),
                    };
                    get_content_disposition_name(&cd)
                };
                let key = try!(cd_name.ok_or(Error::NoName));
                for node in nodes {
                    match node {
                        Node::Part(part) => {
                            let val = try!(String::from_utf8(part.body));
                            formdata.fields.push((key.clone(), val));
                        },
                        Node::File(part) => {
                            formdata.files.push((key.clone(), part));
                        },
                        _ => { } // don't recurse deeper
                    }
                }
            }
        }
    }
    Ok(())
}

#[inline]
fn get_content_disposition_name(cd: &ContentDisposition) -> Option<String> {
    if let Some(&DispositionParam::Ext(_, ref value)) = cd.parameters.iter()
        .find(|&x| match *x {
            DispositionParam::Ext(ref token,_) => &*token == "name",
            _ => false,
        })
    {
        Some(value.clone())
    } else {
        None
    }
}

/// Stream out `multipart/form-data` body content matching the passed in `formdata`.  This
/// does not stream out headers, so the caller must stream those out before calling
/// write_formdata().

pub fn write_formdata<S: Write>(stream: &mut S, formdata: &FormData) -> Result<usize, Error>
{
    // Translate to Nodes
    let mut nodes: Vec<Node> = Vec::with_capacity(formdata.fields.len() + formdata.files.len());

    for &(ref name, ref value) in &formdata.fields {
        let mut h = Headers::new();
        h.set(ContentType(Mime(TopLevel::Text, SubLevel::Plain, vec![])));
        h.set(ContentDisposition {
            disposition: DispositionType::Ext("form-data".to_owned()),
            parameters: vec![DispositionParam::Ext("name".to_owned(), name.clone())],
        });
        nodes.push( Node::Part( Part {
            headers: h,
            body: value.as_bytes().to_owned(),
        }));
    }

    for &(ref name, ref filepart) in &formdata.files {
        let mut filepart = filepart.clone();
        // We leave all headers that the caller specified, except that we rewrite
        // Content-Disposition.
        while filepart.headers.remove::<ContentDisposition>() { };
        let filename = match filepart.path.file_name() {
            Some(fname) => fname.to_string_lossy().into_owned(),
            None => return Err(Error::NotAFile),
        };
        filepart.headers.set(ContentDisposition {
            disposition: DispositionType::Ext("form-data".to_owned()),
            parameters: vec![DispositionParam::Ext("name".to_owned(), name.clone()),
                             DispositionParam::Ext("filename".to_owned(), filename)],
        });
        nodes.push( Node::File( filepart ) );
    }

    let boundary = ::mime_multipart::generate_boundary();

    // Write out
    let count = try!(::mime_multipart::write_multipart(stream, &boundary, &nodes));

    Ok(count)
}

#[cfg(test)]
mod tests {
    extern crate tempdir;

    use super::{FormData, write_formdata, read_formdata};

    use std::net::SocketAddr;
    use std::fs::File;
    use std::io::Write;

    use hyper::buffer::BufReader;
    use hyper::net::NetworkStream;
    use hyper::server::Request as HyperRequest;
    use hyper::header::{Headers, ContentDisposition, DispositionParam, ContentType,
                        DispositionType};
    use mime_multipart::FilePart;
    use mime::{Mime, TopLevel, SubLevel};

    use mock::MockStream;

    #[test]
    fn parser() {
        let input = b"POST / HTTP/1.1\r\n\
                      Host: example.domain\r\n\
                      Content-Type: multipart/form-data; boundary=\"abcdefg\"\r\n\
                      Content-Length: 1000\r\n\
                      \r\n\
                      --abcdefg\r\n\
                      Content-Disposition: form-data; name=\"field1\"\r\n\
                      \r\n\
                      data1\r\n\
                      --abcdefg\r\n\
                      Content-Disposition: form-data; name=\"field2\"; filename=\"image.gif\"\r\n\
                      Content-Type: image/gif\r\n\
                      \r\n\
                      This is a file\r\n\
                      with two lines\r\n\
                      --abcdefg\r\n\
                      Content-Disposition: form-data; name=\"field3\"; filename=\"file.txt\"\r\n\
                      \r\n\
                      This is a file\r\n\
                      --abcdefg--";

        let mut mock = MockStream::with_input(input);

        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);
        let sock: SocketAddr = "127.0.0.1:80".parse().unwrap();
        let req = HyperRequest::new(&mut stream, sock).unwrap();
        let (_, _, headers, _, _, mut reader) = req.deconstruct();

        match read_formdata(&mut reader, &headers) {
            Ok(form_data) => {
                assert_eq!(form_data.fields.len(), 1);
                for (key, val) in form_data.fields {
                    if &key == "field1" {
                        assert_eq!(&val, "data1");
                    }
                }

                assert_eq!(form_data.files.len(), 2);
                for (key, file) in form_data.files {
                    if &key == "field2" {
                        assert_eq!(file.size, Some(30));
                        assert_eq!(&*file.filename().unwrap().unwrap(), "image.gif");
                        assert_eq!(file.content_type().unwrap(), mime!(Image/Gif));
                    } else if &key == "field3" {
                        assert_eq!(file.size, Some(14));
                        assert_eq!(&*file.filename().unwrap().unwrap(), "file.txt");
                        assert!(file.content_type().is_none());
                    }
                }
            },
            Err(err) => panic!("{}", err),
        }
    }

    #[test]
    fn multi_file_parser() {
        let input = b"POST / HTTP/1.1\r\n\
                      Host: example.domain\r\n\
                      Content-Type: multipart/form-data; boundary=\"abcdefg\"\r\n\
                      Content-Length: 1000\r\n\
                      \r\n\
                      --abcdefg\r\n\
                      Content-Disposition: form-data; name=\"field1\"\r\n\
                      \r\n\
                      data1\r\n\
                      --abcdefg\r\n\
                      Content-Disposition: form-data; name=\"field2\"; filename=\"image.gif\"\r\n\
                      Content-Type: image/gif\r\n\
                      \r\n\
                      This is a file\r\n\
                      with two lines\r\n\
                      --abcdefg\r\n\
                      Content-Disposition: form-data; name=\"field2\"; filename=\"file.txt\"\r\n\
                      \r\n\
                      This is a file\r\n\
                      --abcdefg--";

        let mut mock = MockStream::with_input(input);

        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);
        let sock: SocketAddr = "127.0.0.1:80".parse().unwrap();
        let req = HyperRequest::new(&mut stream, sock).unwrap();
        let (_, _, headers, _, _, mut reader) = req.deconstruct();

        match read_formdata(&mut reader, &headers) {
            Ok(form_data) => {
                assert_eq!(form_data.fields.len(), 1);
                for (key, val) in form_data.fields {
                    if &key == "field1" {
                        assert_eq!(&val, "data1");
                    }
                }

                assert_eq!(form_data.files.len(), 2);
                let (ref key, ref file) = form_data.files[0];

                assert_eq!(key, "field2");
                assert_eq!(file.size, Some(30));
                assert_eq!(&*file.filename().unwrap().unwrap(), "image.gif");
                assert_eq!(file.content_type().unwrap(), mime!(Image/Gif));

                let (ref key, ref file) = form_data.files[1];
                assert!(key == "field2");
                assert_eq!(file.size, Some(14));
                assert_eq!(&*file.filename().unwrap().unwrap(), "file.txt");
                assert!(file.content_type().is_none());

            },
            Err(err) => panic!("{}", err),
        }
    }

    #[test]
    fn mixed_parser() {
        let input = b"POST / HTTP/1.1\r\n\
                      Host: example.domain\r\n\
                      Content-Type: multipart/form-data; boundary=AaB03x\r\n\
                      Content-Length: 1000\r\n\
                      \r\n\
                      --AaB03x\r\n\
                      Content-Disposition: form-data; name=\"submit-name\"\r\n\
                      \r\n\
                      Larry\r\n\
                      --AaB03x\r\n\
                      Content-Disposition: form-data; name=\"files\"\r\n\
                      Content-Type: multipart/mixed; boundary=BbC04y\r\n\
                      \r\n\
                      --BbC04y\r\n\
                      Content-Disposition: file; filename=\"file1.txt\"\r\n\
                      \r\n\
                      ... contents of file1.txt ...\r\n\
                      --BbC04y\r\n\
                      Content-Disposition: file; filename=\"awesome_image.gif\"\r\n\
                      Content-Type: image/gif\r\n\
                      Content-Transfer-Encoding: binary\r\n\
                      \r\n\
                      ... contents of awesome_image.gif ...\r\n\
                      --BbC04y--\r\n\
                      --AaB03x--";

        let mut mock = MockStream::with_input(input);

        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);
        let sock: SocketAddr = "127.0.0.1:80".parse().unwrap();
        let req = HyperRequest::new(&mut stream, sock).unwrap();
        let (_, _, headers, _, _, mut reader) = req.deconstruct();

        match read_formdata(&mut reader, &headers) {
            Ok(form_data) => {
                assert_eq!(form_data.fields.len(), 1);
                for (key, val) in form_data.fields {
                    if &key == "submit-name" {
                        assert_eq!(&val, "Larry");
                    }
                }

                assert_eq!(form_data.files.len(), 2);
                for (key, file) in form_data.files {
                    assert_eq!(&key, "files");
                    match &file.filename().unwrap().unwrap()[..] {
                        "file1.txt" => {
                            assert_eq!(file.size, Some(29));
                            assert!(file.content_type().is_none());
                        }
                        "awesome_image.gif" => {
                            assert_eq!(file.size, Some(37));
                            assert_eq!(file.content_type().unwrap(), mime!(Image/Gif));
                        },
                        _ => unreachable!(),
                    }
                }
            },
            Err(err) => panic!("{}", err),
        }
    }

    #[test]
    fn simple_writer() {
        // Create a simple short file for testing
        let tmpdir = tempdir::TempDir::new("formdata_test").unwrap();
        let tmppath = tmpdir.path().join("testfile");
        let mut tmpfile = File::create(tmppath.clone()).unwrap();
        writeln!(tmpfile, "this is example file content").unwrap();

        let mut photo_headers = Headers::new();
        photo_headers.set(ContentType(Mime(TopLevel::Image, SubLevel::Gif, vec![])));
        photo_headers.set(ContentDisposition {
            disposition: DispositionType::Ext("form-data".to_owned()),
            parameters: vec![DispositionParam::Ext("name".to_owned(), "photo".to_owned()),
                             DispositionParam::Ext("filename".to_owned(), "mike.gif".to_owned())],
        });

        let formdata = FormData {
            fields: vec![ ("name".to_owned(), "Mike".to_owned()),
                            ("age".to_owned(), "46".to_owned()) ],
            files: vec![ ("photo".to_owned(), FilePart::new(photo_headers, &tmppath)) ],
        };

        let mut output: Vec<u8> = Vec::new();
        match write_formdata(&mut output, &formdata) {
            Ok(count) => assert_eq!(count, 568),
            Err(e) => panic!("Unable to write formdata: {}", e),
        }

        println!("{}", String::from_utf8_lossy(&output));
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;

use std::net::TcpStream;
use std::io::prelude::*;
use std::collections::HashMap;
use rustc_serialize::json;

pub struct WhoIs {
    server: String,
}

impl WhoIs {
    pub fn new(x: String)-> WhoIs {
        WhoIs {
            server: x
        }
    }
    pub fn lookup(&mut self) -> String {
        let mut result = String::new();
        let target = self.server.to_owned();
        let tld = target.split(".").last().expect("nope");
        let query = match tld {
            "com" | "net" => "DOMAIN",
            _ => ""
        };
        let server = self.get_server(&tld);
        let mut client = TcpStream::connect((&*server, 43u16)).expect("Could not connect to server!!");
        match client.write_all(format!("{} {}\n", query, target).as_bytes()) {
            Ok(_) => (),
            Err(e) => panic!("Could not write to client {}", e)
        }
        client.read_to_string(&mut result).unwrap();
        if result.contains("Whois Server:") {
            return self.lookup2(&*result)
        }
        else {
            let clean = result.replace("http:", "").replace("https:","");
            return self.parse_data(clean)
        }
    }
    fn parse_data(&self, result: String) -> String {
        let mut data = HashMap::new();
        for c in result.lines() {
            let mut line = c.split(':');
            let key = line.next().unwrap();
            let value = match line.next() {
                Some(value) => value,
                None => continue
            };
            data.insert(key, value.trim());
        }
        return json::encode(&data).unwrap()
    }

    fn lookup2(&mut self, result: &str) -> String {
        let mut result2 = String::new();
        let line = &result.lines().find(|i| i.contains("Whois Server:")).expect("not found");
        let target = line.split_whitespace().last().unwrap().to_owned();
        let mut client = TcpStream::connect((&*target, 43u16)).expect("Could not connect to server!!");
        match client.write_all(format!("{}\n", self.server).as_bytes()) {
            Ok(_) => (),
            Err(e) => panic!("Could not write to client {}", e)
        }
        client.read_to_string(&mut result2).unwrap();
        let clean = result2.replace("http:", "").replace("https:","");
        self.parse_data(clean)
    }

    fn get_server(&self, target: &str) -> String {   //this will give me verisign-grs
        let mut result = String::new();
        let mut client = TcpStream::connect("whois.iana.org:43").expect("Could not connect to server!");
        match client.write_all(format!("{}\n", target).as_bytes()) {
            Ok(_) => (),
            Err(e) => panic!("Could not write to client {}", e)
        }
        client.read_to_string(&mut result).unwrap();
        let line = &result.lines().find(|i| i.starts_with("whois:")).unwrap();
        let foo = line.split_whitespace().last().unwrap().to_owned();
        //println!("{}", foo);
        foo
    }
}
<commit_msg>remove ambiguous .expect()'s<commit_after>extern crate rustc_serialize;

use std::net::TcpStream;
use std::io::prelude::*;
use std::collections::HashMap;
use rustc_serialize::json;

pub struct WhoIs {
    server: String,
}

impl WhoIs {
    pub fn new(x: String)-> WhoIs {
        WhoIs {
            server: x
        }
    }
    pub fn lookup(&mut self) -> String {
        let mut result = String::new();
        let target = self.server.to_owned();
        let tld = target.split(".").last().expect("Invalid URL?");
        let query = match tld {
            "com" | "net" => "DOMAIN",
            _ => ""
        };
        let server = self.get_server(&tld);
        let mut client = TcpStream::connect((&*server, 43u16)).expect("Could not connect to server!!");
        match client.write_all(format!("{} {}\n", query, target).as_bytes()) {
            Ok(_) => (),
            Err(e) => panic!("Could not write to client {}", e)
        }
        client.read_to_string(&mut result).unwrap();
        if result.contains("Whois Server:") {
            return self.lookup2(&*result)
        }
        else {
            let clean = result.replace("http:", "").replace("https:","");
            return self.parse_data(clean)
        }
    }
    fn parse_data(&self, result: String) -> String {
        let mut data = HashMap::new();
        for c in result.lines() {
            let mut line = c.split(':');
            let key = line.next().unwrap();
            let value = match line.next() {
                Some(value) => value,
                None => continue
            };
            data.insert(key, value.trim());
        }
        return json::encode(&data).unwrap()
    }

    fn lookup2(&mut self, result: &str) -> String {
        let mut result2 = String::new();
        let line = &result.lines().find(|i| i.contains("Whois Server:")).unwrap();
        let target = line.split_whitespace().last().unwrap().to_owned();
        let mut client = TcpStream::connect((&*target, 43u16)).expect("Could not connect to server!!");
        match client.write_all(format!("{}\n", self.server).as_bytes()) {
            Ok(_) => (),
            Err(e) => panic!("Could not write to client {}", e)
        }
        client.read_to_string(&mut result2).unwrap();
        let clean = result2.replace("http:", "").replace("https:","");
        self.parse_data(clean)
    }

    fn get_server(&self, target: &str) -> String {   //this will give me verisign-grs
        let mut result = String::new();
        let mut client = TcpStream::connect("whois.iana.org:43").expect("Could not connect to server!");
        match client.write_all(format!("{}\n", target).as_bytes()) {
            Ok(_) => (),
            Err(e) => panic!("Could not write to client {}", e)
        }
        client.read_to_string(&mut result).unwrap();
        let line = &result.lines().find(|i| i.starts_with("whois:")).unwrap();
        let foo = line.split_whitespace().last().unwrap().to_owned();
        //println!("{}", foo);
        foo
    }
}
<|endoftext|>


<commit_before>// (C) 2015 Viktor Dahl <pazaconyoman@gmail.com>
// This file is licensed under the same terms as Rust itself.

#![no_std]

extern crate unreachable;
extern crate nodrop;

pub use sort::{sort, sort_by, sort_by_key, insertion_sort, heapsort};
pub use float::{sort_floats};

mod sort;
mod float;
<commit_msg>Copy documentation from README.md to crate documentation<commit_after>// (C) 2015 Viktor Dahl <pazaconyoman@gmail.com>
// This file is licensed under the same terms as Rust itself.
//! This crate implements the introsort sorting algorithm.
//!
//! ## Interface ##
//! The interface is similar to the standard library `sort` and `sort_by`
//! functions.
//!
//! An example:
//!
//! ```rust
//! extern crate quickersort;
//!
//! fn main() {
//!     let mut ss = vec!["Introsort", "or", "introspective", "sort", "is",
//!                       "a", "hybrid", "sorting", "algorithm", "that",
//!                       "provides", "both", "fast", "average",
//!                       "performance", "and", "(asymptotically)", "optimal",
//!                       "worst-case", "performance"];
//!     quickersort::sort(&mut ss[..]);
//!     println!("alphabetically");
//!     for s in ss.iter() { println!("\t{}", s); }
//!     quickersort::sort_by(&mut ss[..], &|a, b| a.len().cmp(&b.len()));
//!     println!("\nby length");
//!     for s in ss.iter() { println!("\t{}", s); }
//! }
//! ```
//!
//! Unlike the standard library sort function, introsort is _not_ a stable sort.
//!
//! ## Details ##
//! At its heart, it is a dual-pivot quicksort. For partition with many equal
//! elements, it will instead use a single-pivot quicksort optimized for this
//! case. It detects excessive recursion during quicksort and switches to
//! heapsort if need be, guaranteeing O(n log(n)) runtime on all inputs. For
//! small partitions it uses insertion sort instead of quicksort.
//!
//! Unlike the `std` sort, it does not allocate.
//!
//! ## Performance ##
//! It is quite fast, outperforming the standard sort on all data sets I have
//! tried. The performance difference varies depending on the characteristics of
//! the data. On large, completely random arrays, introsort is only 5-10% faster
//! than the standard sort. However, introsort's performance is greatly improved
//! if the data has few unique values or is (partially) sorted (including
//! reversed data). For sorted data, introsort is ~4-5 times faster, and for
//! data with few unique values it can be more than
//! 20 times faster.
//!
//! ## Floating point ##
//! The crate, if built with the "float" feature (which is the default), also
//! includes a `sort_floats` function. Floating point numbers are not `Ord`,
//! only `PartialOrd`, so `sort` can not be used on them. The ordering used by
//! `sort_floats` is
//!
//! ``` | -inf | < 0 | -0 | +0 | > 0 | +inf | NaN | ```
//!
//! `sort_floats` is much more efficient than passing a comparator function
//! implementing this ordering to `sort_by`.

#![no_std]

extern crate unreachable;
extern crate nodrop;

pub use sort::{sort, sort_by, sort_by_key, insertion_sort, heapsort};
pub use float::{sort_floats};

mod sort;
mod float;
<|endoftext|>


<commit_before>//! This crate serves utilities for testing crates using rust-ndarray
//!
//! Contents
//! ----------
//! - [assertions](assert/index.html)
//! - [distributions for real/complex numbers](random/index.html)

extern crate rand;
extern crate ndarray;
extern crate float_cmp;
extern crate num_complex;

pub mod prelude;
pub mod assert;
pub mod random;
<commit_msg>Fix eng<commit_after>//! This is utility crate for testing crates using rust-ndarray
//!
//! Contents
//! ----------
//! - [assertions](assert/index.html)
//! - [distributions for real/complex numbers](random/index.html)

extern crate rand;
extern crate ndarray;
extern crate float_cmp;
extern crate num_complex;

pub mod prelude;
pub mod assert;
pub mod random;
<|endoftext|>