<commit_before>// Rx -- Reactive programming for Rust
// Copyright 2016 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

//! Rx, a library for reactive programming in Rust.
//! Inspired by [Reactive Extensions for C#](https://rx.codeplex.com/).
//!
//! TODO: Add intro to observables for people who are unfamiliar with them.
//!
//! TODO: Add examples.
//!
//! # Simple Observables
//!
//! The `Option` and `Result` types implement `Observable`. These can be used
//! to create empty or singleton observables.
//!
//!  * `Some(x)` and `Ok(x)` both produce `x` upon subscription and complete
//!    immediately.
//!  * `None` does not produce any value and completes immediately upon
//!    subscription.
//!  * `Err(err)` fails with `err` upon subscription.
//!
//! Note that subscribing to an option or result does not modify it in any way.
//! (Subscribing requires a mutable reference, because in general, the
//! observable might want to store the observer.) For instance, the following
//! example prints “received 7” twice.
//!
//! ```
//! use rx::Observable;
//! let mut some = Some(7);
//! some.subscribe_next(|x| println!("received {}", x));
//! some.subscribe_next(|x| println!("received {}", x));
//! ```
//!
//! TODO: Could I have an `ImmutableObservable` to get rid of the mutability
//! requirement?

#![warn(missing_docs)]
#![feature(fn_traits, unboxed_closures)]

use std::iter::IntoIterator;

mod generate;
mod observable;
mod observer;
mod subject;
mod transform;

pub use generate::error;
pub use observable::Observable;
pub use observer::Observer;
pub use subject::Subject;

/// A subscription where `drop()` is a no-op.
pub struct UncancellableSubscription;

impl Drop for UncancellableSubscription {
    fn drop(&mut self) { }
}

/// Observable implementation for types that can be converted into an iterator.
///
/// Upon subscription, this pushes a value for every value returned by the
/// iterator and then completes (if the iterator is finite). The returned
/// subscription is not cancellable: if the observable completes, it completes
/// before the call to `subscribe()` returns. This observable does not fail.
impl<'i, I> Observable for &'i I where &'i I: IntoIterator, <&'i I as IntoIterator>::Item: Clone {
    type Item = <&'i I as IntoIterator>::Item;
    type Error = ();
    type Subscription = UncancellableSubscription;

    fn subscribe<O>(&mut self, mut observer: O) -> UncancellableSubscription
        where O: Observer<Self::Item, Self::Error> {
        for x in self.into_iter() {
            observer.on_next(x);
        }
        observer.on_completed();
        UncancellableSubscription
    }
}

/// Observable implementation for `Result`.
///
/// Upon subscription, this pushes either the result and completes, or the
/// observable fails with the error. The returned subscription is not
/// cancellable: the observable completes or fails before the call to
/// `subscribe()` returns.
impl<T: Clone, E: Clone> Observable for Result<T, E> {
    type Item = T;
    type Error = E;
    type Subscription = UncancellableSubscription;

    fn subscribe<O>(&mut self, mut observer: O) -> UncancellableSubscription
        where O: Observer<Self::Item, Self::Error> {
        match *self {
            Ok(ref item) => {
                observer.on_next(item.clone());
                observer.on_completed();
            }
            Err(ref error) => {
                observer.on_error(error.clone());
            }
        }
        UncancellableSubscription
    }
}

/// Observable implementation for `Option`.
///
/// Upon subscription, this pushes the value if the option is `Some`, and then
/// completes. If the option is `None` it completes immediately. The returned
/// subscription is not cancellable: the observable completes before the call to
/// `subscribe()` returns. This observable does not fail.
impl<T: Clone> Observable for Option<T> {
    type Item = T;
    type Error = ();
    type Subscription = UncancellableSubscription;

    fn subscribe<O>(&mut self, mut observer: O) -> UncancellableSubscription
        where O: Observer<Self::Item, Self::Error> {
        if let Some(ref item) = *self {
            observer.on_next(item.clone());
        }
        observer.on_completed();
        UncancellableSubscription
    }
}
<commit_msg>Add IntoIterator documentation example<commit_after>// Rx -- Reactive programming for Rust
// Copyright 2016 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

//! Rx, a library for reactive programming in Rust.
//! Inspired by [Reactive Extensions for C#](https://rx.codeplex.com/).
//!
//! TODO: Add intro to observables for people who are unfamiliar with them.
//!
//! TODO: Add examples.
//!
//! # Simple Observables
//!
//! The `Option` and `Result` types implement `Observable`. These can be used
//! to create empty or singleton observables.
//!
//!  * `Some(x)` and `Ok(x)` both produce `x` upon subscription and complete
//!    immediately.
//!  * `None` does not produce any value and completes immediately upon
//!    subscription.
//!  * `Err(err)` fails with `err` upon subscription.
//!
//! Note that subscribing to an option or result does not modify it in any way.
//! (Subscribing requires a mutable reference, because in general, the
//! observable might want to store the observer.) For instance, the following
//! example prints “received 7” twice.
//!
//! ```
//! use rx::Observable;
//! let mut some = Some(7);
//! some.subscribe_next(|x| println!("received {}", x));
//! some.subscribe_next(|x| println!("received {}", x));
//! ```
//!
//! Observables that push their values immediately upon subscription might not
//! seem all that useful at first sight, but they come in handy to construct
//! more complex observables.
//!
//! TODO: Add `continue_with` example once that has been implemented.
//!
//! TODO: Could I have an `ImmutableObservable` to get rid of the mutability
//! requirement?
//!
//! Anything that can be converted into an iterator is also an observable. Such
//! an observable pushes all its values immediately upon subscription. If the
//! iterator is infinite, the call to `subscribe()` will never return. The
//! following example prints the first five prime numbers:
//!
//! ```
//! use rx::Observable;
//! let mut primes = &[2u32, 3, 5, 7, 11];
//! primes.subscribe_next(|x| println!("received {}", x));
//! ```

#![warn(missing_docs)]
#![feature(fn_traits, unboxed_closures)]

use std::iter::IntoIterator;

mod generate;
mod observable;
mod observer;
mod subject;
mod transform;

pub use generate::error;
pub use observable::Observable;
pub use observer::Observer;
pub use subject::Subject;

/// A subscription where `drop()` is a no-op.
pub struct UncancellableSubscription;

impl Drop for UncancellableSubscription {
    fn drop(&mut self) { }
}

/// Observable implementation for types that can be converted into an iterator.
///
/// Upon subscription, this pushes a value for every value returned by the
/// iterator and then completes (if the iterator is finite). The returned
/// subscription is not cancellable: if the observable completes, it completes
/// before the call to `subscribe()` returns. This observable does not fail.
impl<'i, I> Observable for &'i I where &'i I: IntoIterator, <&'i I as IntoIterator>::Item: Clone {
    type Item = <&'i I as IntoIterator>::Item;
    type Error = ();
    type Subscription = UncancellableSubscription;

    fn subscribe<O>(&mut self, mut observer: O) -> UncancellableSubscription
        where O: Observer<Self::Item, Self::Error> {
        for x in self.into_iter() {
            observer.on_next(x);
        }
        observer.on_completed();
        UncancellableSubscription
    }
}

/// Observable implementation for `Result`.
///
/// Upon subscription, this pushes either the result and completes, or the
/// observable fails with the error. The returned subscription is not
/// cancellable: the observable completes or fails before the call to
/// `subscribe()` returns.
impl<T: Clone, E: Clone> Observable for Result<T, E> {
    type Item = T;
    type Error = E;
    type Subscription = UncancellableSubscription;

    fn subscribe<O>(&mut self, mut observer: O) -> UncancellableSubscription
        where O: Observer<Self::Item, Self::Error> {
        match *self {
            Ok(ref item) => {
                observer.on_next(item.clone());
                observer.on_completed();
            }
            Err(ref error) => {
                observer.on_error(error.clone());
            }
        }
        UncancellableSubscription
    }
}

/// Observable implementation for `Option`.
///
/// Upon subscription, this pushes the value if the option is `Some`, and then
/// completes. If the option is `None` it completes immediately. The returned
/// subscription is not cancellable: the observable completes before the call to
/// `subscribe()` returns. This observable does not fail.
impl<T: Clone> Observable for Option<T> {
    type Item = T;
    type Error = ();
    type Subscription = UncancellableSubscription;

    fn subscribe<O>(&mut self, mut observer: O) -> UncancellableSubscription
        where O: Observer<Self::Item, Self::Error> {
        if let Some(ref item) = *self {
            observer.on_next(item.clone());
        }
        observer.on_completed();
        UncancellableSubscription
    }
}
<|endoftext|>


<commit_before>//! This library can be used to acquire oauth2.0 authentication for services.
//!
//! For your application to use this library, you will have to obtain an application
//! id and secret by
//! [following this guide](https://developers.google.com/youtube/registering_an_application) (for
//! Google services) respectively the documentation of the API provider you want to connect to.
//!
//! # Device Flow Usage
//! As the `DeviceFlow` involves polling, the `DeviceFlowHelper` should be used
//! as means to adhere to the protocol, and remain resilient to all kinds of errors
//! that can occur on the way.
//!
//! # Service account "flow"
//! When using service account credentials, no user interaction is required. The access token
//! can be obtained automatically using the private key of the client (which you can download
//! from the API provider). See `examples/service_account/` for an example on how to use service
//! account credentials. See
//! [developers.google.com](https://developers.google.com/identity/protocols/OAuth2ServiceAccount)
//! for a detailed description of the protocol. This crate implements OAuth for Service Accounts
//! based on the Google APIs; it may or may not work with other providers.
//!
//! # Installed Flow Usage
//! The installed flow involves showing a URL to the user (or opening it in a browser)
//! and then either prompting the user to enter a displayed code, or make the authorizing
//! website redirect to a web server spun up by this library and running on localhost.
//!
//! In order to use the interactive method, use the `Interactive` `InstalledFlowReturnMethod`;
//! for the redirect method, use `HTTPRedirect`.
//!
//! You can implement your own `AuthenticatorDelegate` in order to customize the flow;
//! the installed flow uses the `present_user_url` method.
//!
//! The returned `Token` will be stored in memory in order to authorize future
//! API requests to the same scopes. The tokens can optionally be persisted to
//! disk by using `persist_tokens_to_disk` when creating the authenticator.
//!
//! The following example, which is derived from the (actual and runnable) example in
//! `examples/test-installed/`, shows the basics of using this crate:
//!
//! ```test_harness,no_run
//! use yup_oauth2::{InstalledFlowAuthenticator, InstalledFlowReturnMethod};
//!
//! #[tokio::main]
//! async fn main() {
//!     // Read application secret from a file. Sometimes it's easier to compile it directly into
//!     // the binary. The clientsecret file contains JSON like `{"installed":{"client_id": ... }}`
//!     let secret = yup_oauth2::read_application_secret("clientsecret.json")
//!         .await
//!         .expect("clientsecret.json");
//!
//!     // Create an authenticator that uses an InstalledFlow to authenticate. The
//!     // authentication tokens are persisted to a file named tokencache.json. The
//!     // authenticator takes care of caching tokens to disk and refreshing tokens once
//!     // they've expired.
//!     let mut auth = InstalledFlowAuthenticator::builder(secret, InstalledFlowReturnMethod::HTTPRedirect)
//!     .persist_tokens_to_disk("tokencache.json")
//!     .build()
//!     .await
//!     .unwrap();
//!
//!     let scopes = &["https://www.googleapis.com/auth/drive.file"];
//!
//!     // token(<scopes>) is the one important function of this crate; it does everything to
//!     // obtain a token that can be sent e.g. as Bearer token.
//!     match auth.token(scopes).await {
//!         Ok(token) => println!("The token is {:?}", token),
//!         Err(e) => println!("error: {:?}", e),
//!     }
//! }
//! ```
//!
#![deny(missing_docs)]
pub mod authenticator;
pub mod authenticator_delegate;
mod device;
pub mod error;
mod helper;
mod installed;
mod refresh;
mod service_account;
mod storage;
mod types;

#[doc(inline)]
pub use crate::authenticator::{
    DeviceFlowAuthenticator, InstalledFlowAuthenticator, ServiceAccountAuthenticator,
};

pub use crate::helper::*;
pub use crate::installed::InstalledFlowReturnMethod;

pub use crate::service_account::ServiceAccountKey;

#[doc(inline)]
pub use crate::error::Error;
pub use crate::types::{AccessToken, ApplicationSecret, ConsoleApplicationSecret};
<commit_msg>Doc: Remove reference to DeviceFlowHelper to fix #140.<commit_after>//! This library can be used to acquire oauth2.0 authentication for services.
//!
//! For your application to use this library, you will have to obtain an application
//! id and secret by
//! [following this guide](https://developers.google.com/youtube/registering_an_application) (for
//! Google services) respectively the documentation of the API provider you want to connect to.
//!
//! # Device Flow Usage
//! With an application secret you can get started right away, building a `DeviceFlowAuthenticator`
//! and obtaining tokens from it.
//!
//! # Service account "flow"
//! When using service account credentials, no user interaction is required. The access token
//! can be obtained automatically using the private key of the client (which you can download
//! from the API provider). See `examples/service_account/` for an example on how to use service
//! account credentials. See
//! [developers.google.com](https://developers.google.com/identity/protocols/OAuth2ServiceAccount)
//! for a detailed description of the protocol. This crate implements OAuth for Service Accounts
//! based on the Google APIs; it may or may not work with other providers.
//!
//! # Installed Flow Usage
//! The installed flow involves showing a URL to the user (or opening it in a browser)
//! and then either prompting the user to enter a displayed code, or make the authorizing
//! website redirect to a web server spun up by this library and running on localhost.
//!
//! In order to use the interactive method, use the `Interactive` `InstalledFlowReturnMethod`;
//! for the redirect method, use `HTTPRedirect`.
//!
//! You can implement your own `AuthenticatorDelegate` in order to customize the flow;
//! the installed flow uses the `present_user_url` method.
//!
//! The returned `Token` will be stored in memory in order to authorize future
//! API requests to the same scopes. The tokens can optionally be persisted to
//! disk by using `persist_tokens_to_disk` when creating the authenticator.
//!
//! The following example, which is derived from the (actual and runnable) example in
//! `examples/test-installed/`, shows the basics of using this crate:
//!
//! ```test_harness,no_run
//! use yup_oauth2::{InstalledFlowAuthenticator, InstalledFlowReturnMethod};
//!
//! #[tokio::main]
//! async fn main() {
//!     // Read application secret from a file. Sometimes it's easier to compile it directly into
//!     // the binary. The clientsecret file contains JSON like `{"installed":{"client_id": ... }}`
//!     let secret = yup_oauth2::read_application_secret("clientsecret.json")
//!         .await
//!         .expect("clientsecret.json");
//!
//!     // Create an authenticator that uses an InstalledFlow to authenticate. The
//!     // authentication tokens are persisted to a file named tokencache.json. The
//!     // authenticator takes care of caching tokens to disk and refreshing tokens once
//!     // they've expired.
//!     let mut auth = InstalledFlowAuthenticator::builder(secret, InstalledFlowReturnMethod::HTTPRedirect)
//!     .persist_tokens_to_disk("tokencache.json")
//!     .build()
//!     .await
//!     .unwrap();
//!
//!     let scopes = &["https://www.googleapis.com/auth/drive.file"];
//!
//!     // token(<scopes>) is the one important function of this crate; it does everything to
//!     // obtain a token that can be sent e.g. as Bearer token.
//!     match auth.token(scopes).await {
//!         Ok(token) => println!("The token is {:?}", token),
//!         Err(e) => println!("error: {:?}", e),
//!     }
//! }
//! ```
//!
#![deny(missing_docs)]
pub mod authenticator;
pub mod authenticator_delegate;
mod device;
pub mod error;
mod helper;
mod installed;
mod refresh;
mod service_account;
mod storage;
mod types;

#[doc(inline)]
pub use crate::authenticator::{
    DeviceFlowAuthenticator, InstalledFlowAuthenticator, ServiceAccountAuthenticator,
};

pub use crate::helper::*;
pub use crate::installed::InstalledFlowReturnMethod;

pub use crate::service_account::ServiceAccountKey;

#[doc(inline)]
pub use crate::error::Error;
pub use crate::types::{AccessToken, ApplicationSecret, ConsoleApplicationSecret};
<|endoftext|>


<commit_before>// Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0.

//! TiKV - A distributed key/value database
//!
//! TiKV ("Ti" stands for Titanium) is an open source distributed
//! transactional key-value database. Unlike other traditional NoSQL
//! systems, TiKV not only provides classical key-value APIs, but also
//! transactional APIs with ACID compliance. TiKV was originally
//! created to complement [TiDB], a distributed HTAP database
//! compatible with the MySQL protocol.
//!
//! [TiDB]: https://github.com/pingcap/tidb
//!
//! The design of TiKV is inspired by some great distributed systems
//! from Google, such as BigTable, Spanner, and Percolator, and some
//! of the latest achievements in academia in recent years, such as
//! the Raft consensus algorithm.

#![crate_type = "lib"]
#![cfg_attr(test, feature(test))]
#![recursion_limit = "400"]
#![feature(cell_update)]
#![feature(proc_macro_hygiene)]
#![feature(specialization)]
#![feature(const_fn)]
#![feature(box_patterns)]
#![feature(shrink_to)]
#![feature(drain_filter)]
#![feature(str_strip)]

#[macro_use(fail_point)]
extern crate fail;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate quick_error;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate slog_derive;
#[macro_use]
extern crate slog_global;
#[macro_use]
extern crate derive_more;
#[macro_use]
extern crate more_asserts;
#[macro_use]
extern crate vlog;
#[macro_use]
extern crate tikv_util;
#[macro_use]
extern crate failure;

#[cfg(test)]
extern crate test;

extern crate encryption;

pub mod config;
pub mod coprocessor;
pub mod import;
pub mod read_pool;
pub mod server;
pub mod storage;

/// Returns the tikv version information.
pub fn tikv_version_info() -> String {
    let fallback = "Unknown (env var does not exist when building)";
    format!(
        "\nRelease Version:   {}\
         \nGit Commit Hash:   {}\
         \nGit Commit Branch: {}\
         \nUTC Build Time:    {}\
         \nRust Version:      {}\
         \nEnable Features:   {}\
         \nProfile:           {}",
        env!("CARGO_PKG_VERSION"),
        option_env!("TIKV_BUILD_GIT_HASH").unwrap_or(fallback),
        option_env!("TIKV_BUILD_GIT_BRANCH").unwrap_or(fallback),
        option_env!("TIKV_BUILD_TIME").unwrap_or(fallback),
        option_env!("TIKV_BUILD_RUSTC_VERSION").unwrap_or(fallback),
        option_env!("TIKV_ENABLE_FEATURES")
            .unwrap_or(fallback)
            .trim(),
        option_env!("TIKV_PROFILE").unwrap_or(fallback),
    )
}

/// Prints the tikv version information to the standard output.
pub fn log_tikv_info() {
    info!("Welcome to TiKV");
    for line in tikv_version_info().lines().filter(|s| !s.is_empty()) {
        info!("{}", line);
    }
}
<commit_msg>add edition field for the version information (#7821)<commit_after>// Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0.

//! TiKV - A distributed key/value database
//!
//! TiKV ("Ti" stands for Titanium) is an open source distributed
//! transactional key-value database. Unlike other traditional NoSQL
//! systems, TiKV not only provides classical key-value APIs, but also
//! transactional APIs with ACID compliance. TiKV was originally
//! created to complement [TiDB], a distributed HTAP database
//! compatible with the MySQL protocol.
//!
//! [TiDB]: https://github.com/pingcap/tidb
//!
//! The design of TiKV is inspired by some great distributed systems
//! from Google, such as BigTable, Spanner, and Percolator, and some
//! of the latest achievements in academia in recent years, such as
//! the Raft consensus algorithm.

#![crate_type = "lib"]
#![cfg_attr(test, feature(test))]
#![recursion_limit = "400"]
#![feature(cell_update)]
#![feature(proc_macro_hygiene)]
#![feature(specialization)]
#![feature(const_fn)]
#![feature(box_patterns)]
#![feature(shrink_to)]
#![feature(drain_filter)]
#![feature(str_strip)]

#[macro_use(fail_point)]
extern crate fail;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate quick_error;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate slog_derive;
#[macro_use]
extern crate slog_global;
#[macro_use]
extern crate derive_more;
#[macro_use]
extern crate more_asserts;
#[macro_use]
extern crate vlog;
#[macro_use]
extern crate tikv_util;
#[macro_use]
extern crate failure;

#[cfg(test)]
extern crate test;

extern crate encryption;

pub mod config;
pub mod coprocessor;
pub mod import;
pub mod read_pool;
pub mod server;
pub mod storage;

/// Returns the tikv version information.
pub fn tikv_version_info() -> String {
    let fallback = "Unknown (env var does not exist when building)";
    format!(
        "\nRelease Version:   {}\
         \nEdition:           {}\
         \nGit Commit Hash:   {}\
         \nGit Commit Branch: {}\
         \nUTC Build Time:    {}\
         \nRust Version:      {}\
         \nEnable Features:   {}\
         \nProfile:           {}",
        env!("CARGO_PKG_VERSION"),
        option_env!("TIKV_EDITION").unwrap_or("Community"),
        option_env!("TIKV_BUILD_GIT_HASH").unwrap_or(fallback),
        option_env!("TIKV_BUILD_GIT_BRANCH").unwrap_or(fallback),
        option_env!("TIKV_BUILD_TIME").unwrap_or(fallback),
        option_env!("TIKV_BUILD_RUSTC_VERSION").unwrap_or(fallback),
        option_env!("TIKV_ENABLE_FEATURES")
            .unwrap_or(fallback)
            .trim(),
        option_env!("TIKV_PROFILE").unwrap_or(fallback),
    )
}

/// Prints the tikv version information to the standard output.
pub fn log_tikv_info() {
    info!("Welcome to TiKV");
    for line in tikv_version_info().lines().filter(|s| !s.is_empty()) {
        info!("{}", line);
    }
}
<|endoftext|>


<commit_before>extern crate mio;

use std::io;
use std::result;
use std::net::{SocketAddr, ToSocketAddrs};
use mio::{EventLoop, Handler, Token};
use mio::tcp::{TcpListener, TcpStream};

#[derive(Debug)]
pub struct HttpError;

pub type Result<T> = result::Result<T, HttpError>;

pub struct HttpConnection {
    tcp_stream: TcpStream,
}

impl HttpConnection {
    pub fn local_addr(&self) -> Result<SocketAddr> {
        self.tcp_stream.local_addr()
            .map_err(|_| HttpError)
    }

    pub fn peer_addr(&self) -> Result<SocketAddr> {
        self.tcp_stream.peer_addr()
            .map_err(|_| HttpError)
    }
}

pub struct HttpServer {
    tcp_listener: TcpListener,
}

impl HttpServer {
    pub fn bind<A: ToSocketAddrs>( addr: A ) -> Result<HttpServer> {
        unimplemented!()
    }

    pub fn accept(&self) -> Result<Option<HttpConnection>> {
        unimplemented!()
    }

    /// Registers itself on the given `EventLoop`.
    pub fn register_self<H : Handler>(
        &self, event_loop: &mut EventLoop<H>, token: Token)
        -> io::Result<()> {
        event_loop.register(&self.tcp_listener, token)
    }
}
<commit_msg>Use io::Error instead of custom error type<commit_after>extern crate mio;

use std::io::Result;
use std::net::{SocketAddr, ToSocketAddrs};
use mio::{EventLoop, Handler, Token};
use mio::tcp::{TcpListener, TcpStream};

pub struct HttpConnection {
    tcp_stream: TcpStream,
}

impl HttpConnection {
    pub fn local_addr(&self) -> Result<SocketAddr> {
        self.tcp_stream.local_addr()
    }

    pub fn peer_addr(&self) -> Result<SocketAddr> {
        self.tcp_stream.peer_addr()
    }
}

pub struct HttpServer {
    tcp_listener: TcpListener,
}

impl HttpServer {
    pub fn bind<A: ToSocketAddrs>( addr: A ) -> Result<HttpServer> {
        unimplemented!()
    }

    pub fn accept(&self) -> Result<Option<HttpConnection>> {
        unimplemented!()
    }

    /// Registers itself on the given `EventLoop`.
    pub fn register_self<H : Handler>(
        &self, event_loop: &mut EventLoop<H>, token: Token) -> Result<()> {
        event_loop.register(&self.tcp_listener, token)
    }
}
<|endoftext|>


<commit_before>extern crate image;

use std::num::Float;
use std::slice::Iter;

use image::{ImageBuffer, Rgb, RgbImage};

#[deriving(Show)]
struct HSL {
    hue: f32,
    sat: f32,
    lum: f32,
}

impl HSL {
    pub fn new(hue: f32, sat: f32, lum: f32) -> HSL {
        HSL { hue: hue, sat: sat, lum: lum }
    }

    // http://www.w3.org/TR/css3-color/#hsl-color
    pub fn rgb(&self) -> Rgb<u8> {
        let hue = self.hue / 360.0;
        let sat = self.sat / 100.0;
        let lum = self.lum / 100.0;

        let b =
            if lum <= 0.5 {
                lum * (sat + 1.0)
            } else {
                lum + sat - lum * sat
            };
        let a = lum * 2.0 - b;

        let r = HSL::hue_to_rgb(a, b, hue + 1.0/3.0);
        let g = HSL::hue_to_rgb(a, b, hue);
        let b = HSL::hue_to_rgb(a, b, hue - 1.0/3.0);

        Rgb([
            (r * 255.0).round() as u8,
            (g * 255.0).round() as u8,
            (b * 255.0).round() as u8])
    }

    fn hue_to_rgb(a: f32, b: f32, hue: f32) -> f32 {
        let h =
            if hue < 0.0 {
                hue + 1.0
            } else if hue > 1.0 {
                hue - 1.0
            } else {
                hue
            };
        if h < 1.0/6.0 { return a + (b - a) * 6.0 * h; }
        if h < 1.0/2.0 { return b; }
        if h < 2.0/3.0 { return a + (b - a) * (2.0/3.0 - h) * 6.0; }
        a
    }
}

struct Nibbler<'a> {
    byte: Option<u8>,
    bytes: Iter<'a, u8>,
}

impl<'a> Nibbler<'a> {
    pub fn new(bytes: &[u8]) -> Nibbler {
        Nibbler { bytes: bytes.iter(), byte: None }
    }
}

impl<'a> Iterator for Nibbler<'a> {
    type Item = u8;
    fn next(&mut self) -> Option<u8> {
        match self.byte {
            Some(value) => {
                self.byte = None;
                Some(value)
            },
            None => {
                match self.bytes.next() {
                    Some(value) => {
                        let hi = *value & 0xf0;
                        let lo = *value & 0x0f;
                        self.byte = Some(lo);
                        Some(hi >> 4)
                    },
                    None => None
                }
            },
        }
    }
}

pub struct Identicon<'a> {
    source: &'a[u8],
    size: u32,
}

impl<'a> Identicon<'a> {
    pub fn new(source: &[u8]) -> Identicon {
        Identicon { source: source, size: 420 }
    }

    // https://processing.org/reference/map_.html
    fn map(value: u32, vmin: u32, vmax: u32, dmin: u32, dmax: u32) -> f32 {
        ((value - vmin) * (dmax - dmin)) as f32 / ((vmax - vmin) + dmin) as f32
    }

    fn foreground(&self) -> Rgb<u8> {
        // Use last 28 bits to determine HSL values.
        let h1 = (self.source[12] as u16 & 0x0f) << 8;
        let h2 = self.source[13] as u16;

        let h = (h1 | h2) as u32;
        let s = self.source[14] as u32;
        let l = self.source[15] as u32;

        let hue = Identicon::map(h, 0, 4095, 0, 360);
        let sat = Identicon::map(s, 0, 255, 0, 20);
        let lum = Identicon::map(l, 0, 255, 0, 20);

        HSL::new(hue, 65.0 - sat, 75.0 - lum).rgb()
    }

    fn rect(image: &mut RgbImage, x0: u32, y0: u32, x1: u32, y1: u32, color: Rgb<u8>) {
        for x in (x0..x1) {
            for y in (y0..y1) {
                image.put_pixel(x, y, color);
            }
        }
    }

    pub fn image(&self) -> RgbImage {
        let pixel_size = 70;
        let sprite_size = 5;
        let inner_size = sprite_size * pixel_size;

        let background = Rgb([240, 240, 240]);
        let foreground = self.foreground();

        let mut image: RgbImage = ImageBuffer::from_pixel(self.size, self.size, background);

        let half_axis = (sprite_size - 1) / 2;
        let margin = pixel_size / 2;

        let mut nibbles = Nibbler::new(self.source);
        let mut x = half_axis * pixel_size;

        while x >= 0 {
            let mut y = 0;
            while y < inner_size {
                if nibbles.next().unwrap() % 2 == 0 {
                    Identicon::rect(&mut image,
                        (x + margin) as u32,
                        (y + margin) as u32,
                        (x + pixel_size + margin) as u32,
                        (y + pixel_size + margin) as u32,
                        foreground);

                    // Mirror blocks across axis.
                    if x != half_axis * pixel_size {
                        let x_start = 2 * half_axis * pixel_size - x;
                        Identicon::rect(&mut image,
                            (x_start + margin) as u32,
                            (y + margin) as u32,
                            (x_start + pixel_size + margin) as u32,
                            (y + pixel_size + margin) as u32,
                            foreground);
                    }
                }
                y += pixel_size;
            }
            x -= pixel_size;
        }

        image
    }
}
<commit_msg>Remove unused and deprecated Show trait.<commit_after>extern crate image;

use std::num::Float;
use std::slice::Iter;

use image::{ImageBuffer, Rgb, RgbImage};

struct HSL {
    hue: f32,
    sat: f32,
    lum: f32,
}

impl HSL {
    pub fn new(hue: f32, sat: f32, lum: f32) -> HSL {
        HSL { hue: hue, sat: sat, lum: lum }
    }

    // http://www.w3.org/TR/css3-color/#hsl-color
    pub fn rgb(&self) -> Rgb<u8> {
        let hue = self.hue / 360.0;
        let sat = self.sat / 100.0;
        let lum = self.lum / 100.0;

        let b =
            if lum <= 0.5 {
                lum * (sat + 1.0)
            } else {
                lum + sat - lum * sat
            };
        let a = lum * 2.0 - b;

        let r = HSL::hue_to_rgb(a, b, hue + 1.0/3.0);
        let g = HSL::hue_to_rgb(a, b, hue);
        let b = HSL::hue_to_rgb(a, b, hue - 1.0/3.0);

        Rgb([
            (r * 255.0).round() as u8,
            (g * 255.0).round() as u8,
            (b * 255.0).round() as u8])
    }

    fn hue_to_rgb(a: f32, b: f32, hue: f32) -> f32 {
        let h =
            if hue < 0.0 {
                hue + 1.0
            } else if hue > 1.0 {
                hue - 1.0
            } else {
                hue
            };
        if h < 1.0/6.0 { return a + (b - a) * 6.0 * h; }
        if h < 1.0/2.0 { return b; }
        if h < 2.0/3.0 { return a + (b - a) * (2.0/3.0 - h) * 6.0; }
        a
    }
}

struct Nibbler<'a> {
    byte: Option<u8>,
    bytes: Iter<'a, u8>,
}

impl<'a> Nibbler<'a> {
    pub fn new(bytes: &[u8]) -> Nibbler {
        Nibbler { bytes: bytes.iter(), byte: None }
    }
}

impl<'a> Iterator for Nibbler<'a> {
    type Item = u8;
    fn next(&mut self) -> Option<u8> {
        match self.byte {
            Some(value) => {
                self.byte = None;
                Some(value)
            },
            None => {
                match self.bytes.next() {
                    Some(value) => {
                        let hi = *value & 0xf0;
                        let lo = *value & 0x0f;
                        self.byte = Some(lo);
                        Some(hi >> 4)
                    },
                    None => None
                }
            },
        }
    }
}

pub struct Identicon<'a> {
    source: &'a[u8],
    size: u32,
}

impl<'a> Identicon<'a> {
    pub fn new(source: &[u8]) -> Identicon {
        Identicon { source: source, size: 420 }
    }

    // https://processing.org/reference/map_.html
    fn map(value: u32, vmin: u32, vmax: u32, dmin: u32, dmax: u32) -> f32 {
        ((value - vmin) * (dmax - dmin)) as f32 / ((vmax - vmin) + dmin) as f32
    }

    fn foreground(&self) -> Rgb<u8> {
        // Use last 28 bits to determine HSL values.
        let h1 = (self.source[12] as u16 & 0x0f) << 8;
        let h2 = self.source[13] as u16;

        let h = (h1 | h2) as u32;
        let s = self.source[14] as u32;
        let l = self.source[15] as u32;

        let hue = Identicon::map(h, 0, 4095, 0, 360);
        let sat = Identicon::map(s, 0, 255, 0, 20);
        let lum = Identicon::map(l, 0, 255, 0, 20);

        HSL::new(hue, 65.0 - sat, 75.0 - lum).rgb()
    }

    fn rect(image: &mut RgbImage, x0: u32, y0: u32, x1: u32, y1: u32, color: Rgb<u8>) {
        for x in (x0..x1) {
            for y in (y0..y1) {
                image.put_pixel(x, y, color);
            }
        }
    }

    pub fn image(&self) -> RgbImage {
        let pixel_size = 70;
        let sprite_size = 5;
        let inner_size = sprite_size * pixel_size;

        let background = Rgb([240, 240, 240]);
        let foreground = self.foreground();

        let mut image: RgbImage = ImageBuffer::from_pixel(self.size, self.size, background);

        let half_axis = (sprite_size - 1) / 2;
        let margin = pixel_size / 2;

        let mut nibbles = Nibbler::new(self.source);
        let mut x = half_axis * pixel_size;

        while x >= 0 {
            let mut y = 0;
            while y < inner_size {
                if nibbles.next().unwrap() % 2 == 0 {
                    Identicon::rect(&mut image,
                        (x + margin) as u32,
                        (y + margin) as u32,
                        (x + pixel_size + margin) as u32,
                        (y + pixel_size + margin) as u32,
                        foreground);

                    // Mirror blocks across axis.
                    if x != half_axis * pixel_size {
                        let x_start = 2 * half_axis * pixel_size - x;
                        Identicon::rect(&mut image,
                            (x_start + margin) as u32,
                            (y + margin) as u32,
                            (x_start + pixel_size + margin) as u32,
                            (y + pixel_size + margin) as u32,
                            foreground);
                    }
                }
                y += pixel_size;
            }
            x -= pixel_size;
        }

        image
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2018, 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>

#![allow(deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
#![cfg_attr(feature = "cargo-clippy", allow(transmute_int_to_char))]
#![cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ptr))]
#![cfg_attr(feature = "cargo-clippy", allow(trivially_copy_pass_by_ref))]

extern crate glib_sys as glib_ffi;
extern crate gdk_sys as ffi;
extern crate gdk_pixbuf;
extern crate gio;
#[macro_use]
extern crate glib;
extern crate gobject_sys as gobject_ffi;
extern crate cairo;
extern crate cairo_sys as cairo_ffi;
extern crate pango;
extern crate libc;
#[macro_use]
extern crate bitflags;

#[macro_use]
mod rt;
#[macro_use]
mod event;

#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
#[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
#[cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]
mod auto;

pub mod prelude;

pub use prelude::*;
pub use auto::*;
pub use self::auto::functions::*;

pub mod enums;

mod atom;
mod cairo_interaction;
mod device;
mod device_manager;
mod drag_context;
mod event_button;
mod event_configure;
mod event_crossing;
mod event_dnd;
mod event_expose;
mod event_focus;
mod event_grab_broken;
mod event_key;
mod event_motion;
mod event_owner_change;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod event_pad_axis;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod event_pad_button;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod event_pad_group_mode;
mod event_property;
mod event_proximity;
mod event_scroll;
mod event_selection;
mod event_setting;
mod event_touch;
mod event_touchpad_pinch;
mod event_touchpad_swipe;
mod event_visibility;
mod event_window_state;
#[cfg(any(feature = "v3_8", feature = "dox"))]
mod frame_clock;
mod functions;
mod geometry;
mod keys;
mod screen;
mod rectangle;
mod rgba;
mod visual;
mod window;

pub use ffi::GdkColor as Color;
pub use glib::Error;

pub use self::rt::{
    init,
    set_initialized,
};

pub use atom::Atom;
pub use atom::NONE as ATOM_NONE;
pub use atom::SELECTION_PRIMARY;
pub use atom::SELECTION_SECONDARY;
pub use atom::SELECTION_CLIPBOARD;
pub use atom::TARGET_BITMAP;
pub use atom::TARGET_COLORMAP;
pub use atom::TARGET_DRAWABLE;
pub use atom::TARGET_PIXMAP;
pub use atom::TARGET_STRING;
pub use atom::SELECTION_TYPE_ATOM;
pub use atom::SELECTION_TYPE_BITMAP;
pub use atom::SELECTION_TYPE_COLORMAP;
pub use atom::SELECTION_TYPE_DRAWABLE;
pub use atom::SELECTION_TYPE_INTEGER;
pub use atom::SELECTION_TYPE_PIXMAP;
pub use atom::SELECTION_TYPE_WINDOW;
pub use atom::SELECTION_TYPE_STRING;
pub use event::Event;
pub use event_button::EventButton;
pub use event_configure::EventConfigure;
pub use event_crossing::EventCrossing;
pub use event_dnd::EventDND;
pub use event_expose::EventExpose;
pub use event_focus::EventFocus;
pub use event_grab_broken::EventGrabBroken;
pub use event_key::EventKey;
pub use event_motion::EventMotion;
pub use event_owner_change::EventOwnerChange;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use event_pad_axis::EventPadAxis;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use event_pad_button::EventPadButton;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use event_pad_group_mode::EventPadGroupMode;
pub use event_property::EventProperty;
pub use event_proximity::EventProximity;
pub use event_scroll::EventScroll;
pub use event_selection::EventSelection;
pub use event_setting::EventSetting;
pub use event_touch::EventTouch;
pub use event_touchpad_pinch::EventTouchpadPinch;
pub use event_touchpad_swipe::EventTouchpadSwipe;
pub use event_visibility::EventVisibility;
pub use event_window_state::EventWindowState;
pub use functions::*;
pub use geometry::Geometry;
pub use rectangle::Rectangle;
pub use rgba::{RGBA, RgbaParseError};
pub use window::WindowAttr;

#[allow(non_camel_case_types)]
pub type key = i32;

pub use self::keys::{
    keyval_name,
    keyval_to_unicode
};
<commit_msg>Some version fixes<commit_after>// Copyright 2013-2018, 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>

#![allow(deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
#![cfg_attr(feature = "cargo-clippy", allow(transmute_int_to_char))]
#![cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ptr))]
#![cfg_attr(feature = "cargo-clippy", allow(trivially_copy_pass_by_ref))]

extern crate glib_sys as glib_ffi;
extern crate gdk_sys as ffi;
extern crate gdk_pixbuf;
extern crate gio;
#[macro_use]
extern crate glib;
extern crate gobject_sys as gobject_ffi;
extern crate cairo;
extern crate cairo_sys as cairo_ffi;
extern crate pango;
extern crate libc;
#[macro_use]
extern crate bitflags;

#[macro_use]
mod rt;
#[macro_use]
mod event;

#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
#[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
#[cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]
mod auto;

pub mod prelude;

pub use prelude::*;
pub use auto::*;
pub use self::auto::functions::*;

pub mod enums;

mod atom;
mod cairo_interaction;
mod device;
mod device_manager;
mod drag_context;
mod event_button;
mod event_configure;
mod event_crossing;
mod event_dnd;
mod event_expose;
mod event_focus;
mod event_grab_broken;
mod event_key;
mod event_motion;
mod event_owner_change;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod event_pad_axis;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod event_pad_button;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod event_pad_group_mode;
mod event_property;
mod event_proximity;
mod event_scroll;
mod event_selection;
mod event_setting;
#[cfg(any(feature = "v3_4", feature = "dox"))]
mod event_touch;
#[cfg(any(feature = "v3_18", feature = "dox"))]
mod event_touchpad_pinch;
#[cfg(any(feature = "v3_18", feature = "dox"))]
mod event_touchpad_swipe;
mod event_visibility;
mod event_window_state;
#[cfg(any(feature = "v3_8", feature = "dox"))]
mod frame_clock;
mod functions;
mod geometry;
mod keys;
mod screen;
mod rectangle;
mod rgba;
mod visual;
mod window;

pub use ffi::GdkColor as Color;
pub use glib::Error;

pub use self::rt::{
    init,
    set_initialized,
};

pub use atom::Atom;
pub use atom::NONE as ATOM_NONE;
pub use atom::SELECTION_PRIMARY;
pub use atom::SELECTION_SECONDARY;
pub use atom::SELECTION_CLIPBOARD;
pub use atom::TARGET_BITMAP;
pub use atom::TARGET_COLORMAP;
pub use atom::TARGET_DRAWABLE;
pub use atom::TARGET_PIXMAP;
pub use atom::TARGET_STRING;
pub use atom::SELECTION_TYPE_ATOM;
pub use atom::SELECTION_TYPE_BITMAP;
pub use atom::SELECTION_TYPE_COLORMAP;
pub use atom::SELECTION_TYPE_DRAWABLE;
pub use atom::SELECTION_TYPE_INTEGER;
pub use atom::SELECTION_TYPE_PIXMAP;
pub use atom::SELECTION_TYPE_WINDOW;
pub use atom::SELECTION_TYPE_STRING;
pub use event::Event;
pub use event_button::EventButton;
pub use event_configure::EventConfigure;
pub use event_crossing::EventCrossing;
pub use event_dnd::EventDND;
pub use event_expose::EventExpose;
pub use event_focus::EventFocus;
pub use event_grab_broken::EventGrabBroken;
pub use event_key::EventKey;
pub use event_motion::EventMotion;
pub use event_owner_change::EventOwnerChange;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use event_pad_axis::EventPadAxis;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use event_pad_button::EventPadButton;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use event_pad_group_mode::EventPadGroupMode;
pub use event_property::EventProperty;
pub use event_proximity::EventProximity;
pub use event_scroll::EventScroll;
pub use event_selection::EventSelection;
pub use event_setting::EventSetting;
#[cfg(any(feature = "v3_4", feature = "dox"))]
pub use event_touch::EventTouch;
#[cfg(any(feature = "v3_18", feature = "dox"))]
pub use event_touchpad_pinch::EventTouchpadPinch;
#[cfg(any(feature = "v3_18", feature = "dox"))]
pub use event_touchpad_swipe::EventTouchpadSwipe;
pub use event_visibility::EventVisibility;
pub use event_window_state::EventWindowState;
pub use functions::*;
pub use geometry::Geometry;
pub use rectangle::Rectangle;
pub use rgba::{RGBA, RgbaParseError};
pub use window::WindowAttr;

#[allow(non_camel_case_types)]
pub type key = i32;

pub use self::keys::{
    keyval_name,
    keyval_to_unicode
};
<|endoftext|>


<commit_before>//! Maman is a Rust Web Crawler saving pages on Redis.
//!
//! # Default environment variables
//!
//! * `MAMAN_ENV`=development
//! * `REDIS_URL`="redis://127.0.0.1/"
#![deny(warnings)]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

#![crate_name = "maman"]

#[macro_use]
extern crate string_cache;
#[macro_use]
extern crate log;
extern crate html5ever;
#[macro_use]
extern crate html5ever_atoms;
extern crate tendril;
extern crate url;
extern crate url_serde;
extern crate reqwest;
extern crate serde;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate robotparser;
extern crate sidekiq;
extern crate encoding;

#[macro_export]
macro_rules! maman_name {
    () => ( "Maman" )
}
#[macro_export]
macro_rules! maman_version {
    () => ( env!("CARGO_PKG_VERSION") )
}
#[macro_export]
macro_rules! maman_version_string {
    () => ( concat!(maman_name!(), " v", maman_version!()) )
}
#[macro_export]
macro_rules! maman_user_agent {
    () => ( concat!(maman_version_string!(), " (https://crates.io/crates/maman)") )
}

pub use maman::{Spider, Page};
pub mod maman;
<commit_msg>Remove unused macro use on string_cache<commit_after>//! Maman is a Rust Web Crawler saving pages on Redis.
//!
//! # Default environment variables
//!
//! * `MAMAN_ENV`=development
//! * `REDIS_URL`="redis://127.0.0.1/"
#![deny(warnings)]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

#![crate_name = "maman"]

extern crate string_cache;
#[macro_use]
extern crate log;
extern crate html5ever;
#[macro_use]
extern crate html5ever_atoms;
extern crate tendril;
extern crate url;
extern crate url_serde;
extern crate reqwest;
extern crate serde;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate robotparser;
extern crate sidekiq;
extern crate encoding;

#[macro_export]
macro_rules! maman_name {
    () => ( "Maman" )
}
#[macro_export]
macro_rules! maman_version {
    () => ( env!("CARGO_PKG_VERSION") )
}
#[macro_export]
macro_rules! maman_version_string {
    () => ( concat!(maman_name!(), " v", maman_version!()) )
}
#[macro_export]
macro_rules! maman_user_agent {
    () => ( concat!(maman_version_string!(), " (https://crates.io/crates/maman)") )
}

pub use maman::{Spider, Page};
pub mod maman;
<|endoftext|>


<commit_before>use std::str::FromStr;
use std::fmt::{self, Display};

mod read;
pub use read::{Error, Parser};

mod write;
pub use write::Writer;

/// A unit of time for the `$timescale` command
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TimescaleUnit {
    S, MS, US, NS, PS, FS,
}

impl FromStr for TimescaleUnit {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use self::TimescaleUnit::*;
        match s {
            "s"  => Ok(S),
            "ms" => Ok(MS),
            "us" => Ok(US),
            "ns" => Ok(NS),
            "ps" => Ok(PS),
            "fs" => Ok(FS),
            _ => Err(Error::Parse("Invalid timescale unit"))
        }
    }
}

impl Display for TimescaleUnit {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::TimescaleUnit::*;
        write!(f, "{}", match *self {
            S  => "s",
            MS => "ms",
            US => "us",
            NS => "ns",
            PS => "ps",
            FS => "fs",
        })
    }
}

/// A VCD scalar value
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Value {
    /// Logic high (prefixed with `V` to make a valid Rust identifier
    V0,

    /// Logic low (prefixed with `V` to make a valid Rust identifier
    V1,

    /// An uninitialized or unknown value
    X,

    /// The "high-impedance" value
    Z,
}

impl Value {
    fn parse(v: u8) -> Result<Value, Error> {
        use Value::*;
        match v {
            b'0' => Ok(V0),
            b'1' => Ok(V1),
            b'x' | b'X' => Ok(X),
            b'z' | b'Z' => Ok(Z),
            _ => Err(Error::Parse("Invalid wire value"))
        }
    }
}

impl FromStr for Value {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Value::parse(*s.as_bytes().get(0).unwrap_or(&b' '))
    }
}

impl Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Value::*;
        write!(f, "{}", match *self {
            V0  => "0",
            V1 => "1",
            X => "x",
            Z => "z",
        })
    }
}

/// A type of scope, as used in the `$scope` command
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum ScopeType {
    Module,
    Task,
    Function,
    Begin,
    Fork,
}

impl FromStr for ScopeType {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use self::ScopeType::*;
        match s {
            "module" => Ok(Module),
            "task" => Ok(Task),
            "function" => Ok(Function),
            "begin" => Ok(Begin),
            "fork" => Ok(Fork),
            _ => Err(Error::Parse("Invalid scope type"))
        }
    }
}

impl Display for ScopeType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::ScopeType::*;
        write!(f, "{}", match *self {
            Module => "module",
            Task  => "task",
            Function => "function",
            Begin  => "begin",
            Fork  => "fork",
        })
    }
}

/// A type of variable, as used in the `$var` command
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum VarType {
    //Event,
    //Integer,
    //Parameter,
    Real,
    Reg,
    //Supply0,
    //Supply1,
    //Time,
    //Tri,
    //Triant,
    //Trior,
    //Trireg,
    //Tri0,
    //Tri1,
    //Wand,
    Wire,
    //Wor,
}

impl FromStr for VarType {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use self::VarType::*;
        match s {
            "wire" => Ok(Wire),
            "reg" => Ok(Reg),
            "real" => Ok(Real),
            _ => Err(Error::Parse("Invalid var type"))
        }
    }
}

impl Display for VarType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::VarType::*;
        write!(f, "{}", match *self {
            Wire => "wire",
            Reg => "reg",
            Real => "real",
        })
    }
}

/// An ID used within the file to refer to a particular variable.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct IdCode(u32);

const ID_CHAR_MIN: u8 = b'!';
const ID_CHAR_MAX: u8 = b'~';
const NUM_ID_CHARS: u32 = (ID_CHAR_MAX - ID_CHAR_MIN + 1) as u32;

impl IdCode {
    fn new(v: &[u8]) -> Result<IdCode, Error> {
        let mut result = 0u32;
        for &i in v {
            if i < ID_CHAR_MIN || i > ID_CHAR_MAX { return Err(Error::Parse("Invalid ID character")) }
            result = result * NUM_ID_CHARS + ((i - ID_CHAR_MIN) as u32);
        }
        Ok(IdCode(result))
    }
}

impl FromStr for IdCode {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        IdCode::new(s.as_bytes())
    }
}

impl From<u32> for IdCode {
    fn from(i: u32) -> IdCode { IdCode(i) }
}

impl Display for IdCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut i = self.0;
        loop {
            try!(write!(f, "{}", ((i % NUM_ID_CHARS) as u8 + ID_CHAR_MIN) as char));
            i = i / NUM_ID_CHARS;
            if i == 0 { break; }
        }
        Ok(())
    }
}

/// Information on a VCD scope as represented by a `$scope` command and its children
#[derive(Debug, Clone)]
pub struct Scope {
    pub scope_type: ScopeType,
    pub identifier: String,
    pub children: Vec<ScopeItem>
}

impl Default for Scope {
    fn default() -> Scope {
        Scope { scope_type: ScopeType::Module, identifier: "".to_string(), children: Vec::new() }
    }
}

/// Information on a VCD variable as represented by a `$var` command.
#[derive(Debug, Clone)]
pub struct Var {
    pub var_type: VarType,
    pub size: u32,
    pub code: IdCode,
    pub reference: String,
}

/// An item in a scope -- either a child scope or a variable
#[derive(Debug, Clone)]
pub enum ScopeItem {
    Scope(Scope),
    Var(Var),
}

/// An element in a VCD file
#[derive(Debug, PartialEq, Clone)]
pub enum Command {
    /// A `$comment` command
    Comment(String),

    /// A `$date` command
    Date(String),

    /// A `$version` command
    Version(String),

    /// A `$timescale` command
    Timescale(u32, TimescaleUnit),

    /// A `$scope` command
    ScopeDef(ScopeType, String),

    /// An `$upscope` command
    Upscope,

    /// A `$var` command
    VarDef(VarType, u32, IdCode, String),

    /// An `$enddefinitions` command
    Enddefinitions,

    /// A `#xxx` timestamp
    Timestamp(u64),

    /// A `0a` change to a scalar variable
    ChangeScalar(IdCode, Value),

    /// A `b0000 a` change to a vector variable
    ChangeVector(IdCode, Vec<Value>),

    /// A `r1.234 a` change to a real variable
    ChangeReal(IdCode, f64),

    /// A `sSTART a` change to a (real?) variable
    ChangeString(IdCode, String),

    /// A beginning of a simulation command. Unlike header commands, which are parsed atomically,
    /// simulation commands emit a Begin, followed by the data changes within them, followed by
    /// End.
    Begin(SimulationCommand),

    /// An end of a simulation command.
    End(SimulationCommand)
}

/// A simulation command type, used in Command::Begin and Command::End
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum SimulationCommand {
    Dumpall,
    Dumpoff,
    Dumpon,
    Dumpvars,
}

impl Display for SimulationCommand {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::SimulationCommand::*;
        write!(f, "{}", match *self {
            Dumpall  => "dumpall",
            Dumpoff  => "dumpoff",
            Dumpon   => "dumpon",
            Dumpvars => "dumpvars",
        })
    }
}

/// Structure containing the data from the header of a VCD file
#[derive(Debug, Default)]
pub struct Header {
    pub comment: Option<String>,
    pub date: Option<String>,
    pub version: Option<String>,
    pub timescale: Option<(u32, TimescaleUnit)>,
    pub scope: Scope,
}
<commit_msg>Add TimescaleUnit conversions<commit_after>use std::str::FromStr;
use std::fmt::{self, Display};

mod read;
pub use read::{Error, Parser};

mod write;
pub use write::Writer;

/// A unit of time for the `$timescale` command
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TimescaleUnit {
    S, MS, US, NS, PS, FS,
}

impl FromStr for TimescaleUnit {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use self::TimescaleUnit::*;
        match s {
            "s"  => Ok(S),
            "ms" => Ok(MS),
            "us" => Ok(US),
            "ns" => Ok(NS),
            "ps" => Ok(PS),
            "fs" => Ok(FS),
            _ => Err(Error::Parse("Invalid timescale unit"))
        }
    }
}

impl Display for TimescaleUnit {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::TimescaleUnit::*;
        write!(f, "{}", match *self {
            S  => "s",
            MS => "ms",
            US => "us",
            NS => "ns",
            PS => "ps",
            FS => "fs",
        })
    }
}

impl TimescaleUnit {
    pub fn divisor(&self) -> u64 {
        use self::TimescaleUnit::*;
        match *self {
            S  => 1,
            MS => 1_000,
            US => 1_000_000,
            NS => 1_000_000_000,
            PS => 1_000_000_000_000,
            FS => 1_000_000_000_000_000,
        }
    }

    pub fn fraction(&self) -> f64 {
        1.0 / (self.divisor() as f64)
    }
 }

/// A VCD scalar value
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Value {
    /// Logic high (prefixed with `V` to make a valid Rust identifier
    V0,

    /// Logic low (prefixed with `V` to make a valid Rust identifier
    V1,

    /// An uninitialized or unknown value
    X,

    /// The "high-impedance" value
    Z,
}

impl Value {
    fn parse(v: u8) -> Result<Value, Error> {
        use Value::*;
        match v {
            b'0' => Ok(V0),
            b'1' => Ok(V1),
            b'x' | b'X' => Ok(X),
            b'z' | b'Z' => Ok(Z),
            _ => Err(Error::Parse("Invalid wire value"))
        }
    }
}

impl FromStr for Value {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Value::parse(*s.as_bytes().get(0).unwrap_or(&b' '))
    }
}

impl Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Value::*;
        write!(f, "{}", match *self {
            V0  => "0",
            V1 => "1",
            X => "x",
            Z => "z",
        })
    }
}

/// A type of scope, as used in the `$scope` command
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum ScopeType {
    Module,
    Task,
    Function,
    Begin,
    Fork,
}

impl FromStr for ScopeType {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use self::ScopeType::*;
        match s {
            "module" => Ok(Module),
            "task" => Ok(Task),
            "function" => Ok(Function),
            "begin" => Ok(Begin),
            "fork" => Ok(Fork),
            _ => Err(Error::Parse("Invalid scope type"))
        }
    }
}

impl Display for ScopeType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::ScopeType::*;
        write!(f, "{}", match *self {
            Module => "module",
            Task  => "task",
            Function => "function",
            Begin  => "begin",
            Fork  => "fork",
        })
    }
}

/// A type of variable, as used in the `$var` command
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum VarType {
    //Event,
    //Integer,
    //Parameter,
    Real,
    Reg,
    //Supply0,
    //Supply1,
    //Time,
    //Tri,
    //Triant,
    //Trior,
    //Trireg,
    //Tri0,
    //Tri1,
    //Wand,
    Wire,
    //Wor,
}

impl FromStr for VarType {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use self::VarType::*;
        match s {
            "wire" => Ok(Wire),
            "reg" => Ok(Reg),
            "real" => Ok(Real),
            _ => Err(Error::Parse("Invalid var type"))
        }
    }
}

impl Display for VarType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::VarType::*;
        write!(f, "{}", match *self {
            Wire => "wire",
            Reg => "reg",
            Real => "real",
        })
    }
}

/// An ID used within the file to refer to a particular variable.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct IdCode(u32);

const ID_CHAR_MIN: u8 = b'!';
const ID_CHAR_MAX: u8 = b'~';
const NUM_ID_CHARS: u32 = (ID_CHAR_MAX - ID_CHAR_MIN + 1) as u32;

impl IdCode {
    fn new(v: &[u8]) -> Result<IdCode, Error> {
        let mut result = 0u32;
        for &i in v {
            if i < ID_CHAR_MIN || i > ID_CHAR_MAX { return Err(Error::Parse("Invalid ID character")) }
            result = result * NUM_ID_CHARS + ((i - ID_CHAR_MIN) as u32);
        }
        Ok(IdCode(result))
    }
}

impl FromStr for IdCode {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        IdCode::new(s.as_bytes())
    }
}

impl From<u32> for IdCode {
    fn from(i: u32) -> IdCode { IdCode(i) }
}

impl Display for IdCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut i = self.0;
        loop {
            try!(write!(f, "{}", ((i % NUM_ID_CHARS) as u8 + ID_CHAR_MIN) as char));
            i = i / NUM_ID_CHARS;
            if i == 0 { break; }
        }
        Ok(())
    }
}

/// Information on a VCD scope as represented by a `$scope` command and its children
#[derive(Debug, Clone)]
pub struct Scope {
    pub scope_type: ScopeType,
    pub identifier: String,
    pub children: Vec<ScopeItem>
}

impl Default for Scope {
    fn default() -> Scope {
        Scope { scope_type: ScopeType::Module, identifier: "".to_string(), children: Vec::new() }
    }
}

/// Information on a VCD variable as represented by a `$var` command.
#[derive(Debug, Clone)]
pub struct Var {
    pub var_type: VarType,
    pub size: u32,
    pub code: IdCode,
    pub reference: String,
}

/// An item in a scope -- either a child scope or a variable
#[derive(Debug, Clone)]
pub enum ScopeItem {
    Scope(Scope),
    Var(Var),
}

/// An element in a VCD file
#[derive(Debug, PartialEq, Clone)]
pub enum Command {
    /// A `$comment` command
    Comment(String),

    /// A `$date` command
    Date(String),

    /// A `$version` command
    Version(String),

    /// A `$timescale` command
    Timescale(u32, TimescaleUnit),

    /// A `$scope` command
    ScopeDef(ScopeType, String),

    /// An `$upscope` command
    Upscope,

    /// A `$var` command
    VarDef(VarType, u32, IdCode, String),

    /// An `$enddefinitions` command
    Enddefinitions,

    /// A `#xxx` timestamp
    Timestamp(u64),

    /// A `0a` change to a scalar variable
    ChangeScalar(IdCode, Value),

    /// A `b0000 a` change to a vector variable
    ChangeVector(IdCode, Vec<Value>),

    /// A `r1.234 a` change to a real variable
    ChangeReal(IdCode, f64),

    /// A `sSTART a` change to a (real?) variable
    ChangeString(IdCode, String),

    /// A beginning of a simulation command. Unlike header commands, which are parsed atomically,
    /// simulation commands emit a Begin, followed by the data changes within them, followed by
    /// End.
    Begin(SimulationCommand),

    /// An end of a simulation command.
    End(SimulationCommand)
}

/// A simulation command type, used in Command::Begin and Command::End
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum SimulationCommand {
    Dumpall,
    Dumpoff,
    Dumpon,
    Dumpvars,
}

impl Display for SimulationCommand {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::SimulationCommand::*;
        write!(f, "{}", match *self {
            Dumpall  => "dumpall",
            Dumpoff  => "dumpoff",
            Dumpon   => "dumpon",
            Dumpvars => "dumpvars",
        })
    }
}

/// Structure containing the data from the header of a VCD file
#[derive(Debug, Default)]
pub struct Header {
    pub comment: Option<String>,
    pub date: Option<String>,
    pub version: Option<String>,
    pub timescale: Option<(u32, TimescaleUnit)>,
    pub scope: Scope,
}
<|endoftext|>


<commit_before>pub fn quicksort<T: PartialOrd>(vec: &mut [T]) {
    if vec.len() <= 1 {
        return;
    }
    let pivot: usize = 0;
    let mut first_opened = Vec::new();
    let mut last_closed: usize = 0;

    for i in 1..vec.len() {
        first_opened.push(i);
        if vec[i] < vec[pivot] {
            let to = first_opened.remove(0);
            vec.swap(i, to);
            last_closed = to;
        }
    }

    vec.swap(pivot, last_closed);
    quicksort(&mut vec[0..last_closed]);
    quicksort(&mut vec[last_closed+1..]);
}

#[cfg(test)]
extern crate rand;

#[cfg(test)]
mod tests {
    use rand::{self, Rng};
    use super::*;

    #[test]
    fn test_vec_of_u64() {
        let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
        let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
        quicksort(&mut vector);

        assert_eq!(vector, presorted.as_slice());
    }

    #[test]
    fn test_vec_of_u8() {
        let presorted = "        Tabcdeeefghhijklmnoooopqrrstuuvwxyz".to_string().into_bytes();
        let mut vector = "The quick brown fox jumps over the lazy dog".to_string().into_bytes();
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_array_of_u8() {
        let presorted: [u8; 10] = [1, 2, 3, 4, 5, 5, 5, 7, 9, 10];
        let mut vector: [u8; 10] = [7, 5, 3, 2, 5, 1, 4, 5, 9, 10];
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_random() {
        let mut rng = rand::thread_rng();

        for _ in 0u64 .. 10_000u64 {
            let len: usize = rng.gen();
            let mut vector = rng.gen_iter()
                                .take((len % 64) + 1)
                                .collect::<Vec<usize>>();
            quicksort(&mut vector);

            for i in 0 .. vector.len() - 1 {
                assert!(vector[i] <= vector[i + 1])
            }
        }
    }
}
<commit_msg>Add doc comments<commit_after>//! # quicksort
//!
//! Quicksort is an efficient in-line sorting algorithm created by Tony Hoare.

/// In-line sorting of a slice of T.
///
/// ```rust
/// # use ironsort::quicksort;
/// let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
/// let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
/// quicksort(&mut vector);
///
/// assert_eq!(vector, presorted.as_slice());
/// ```

pub fn quicksort<T: PartialOrd>(vec: &mut [T]) {
    if vec.len() <= 1 {
        return;
    }
    let pivot: usize = 0;
    let mut first_opened = Vec::new();
    let mut last_closed: usize = 0;

    for i in 1..vec.len() {
        first_opened.push(i);
        if vec[i] < vec[pivot] {
            let to = first_opened.remove(0);
            vec.swap(i, to);
            last_closed = to;
        }
    }

    vec.swap(pivot, last_closed);
    quicksort(&mut vec[0..last_closed]);
    quicksort(&mut vec[last_closed+1..]);
}

#[cfg(test)]
extern crate rand;

#[cfg(test)]
mod tests {
    use rand::{self, Rng};
    use super::*;

    #[test]
    fn test_vec_of_u64() {
        let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
        let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
        quicksort(&mut vector);

        assert_eq!(vector, presorted.as_slice());
    }

    #[test]
    fn test_vec_of_u8() {
        let presorted = "        Tabcdeeefghhijklmnoooopqrrstuuvwxyz".to_string().into_bytes();
        let mut vector = "The quick brown fox jumps over the lazy dog".to_string().into_bytes();
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_array_of_u8() {
        let presorted: [u8; 10] = [1, 2, 3, 4, 5, 5, 5, 7, 9, 10];
        let mut vector: [u8; 10] = [7, 5, 3, 2, 5, 1, 4, 5, 9, 10];
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_random() {
        let mut rng = rand::thread_rng();

        for _ in 0u64 .. 10_000u64 {
            let len: usize = rng.gen();
            let mut vector = rng.gen_iter()
                                .take((len % 64) + 1)
                                .collect::<Vec<usize>>();
            quicksort(&mut vector);

            for i in 0 .. vector.len() - 1 {
                assert!(vector[i] <= vector[i + 1])
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate regex;

use std::collections::HashMap;

use hyper::method::Method;
use hyper::server::{Handler, Request, Response};
use hyper::status::StatusCode;
use regex::{Regex, RegexSet};

use error::RouterError;

pub type Captures = Option<Vec<String>>;
pub type NotFoundFn = fn(Request, Response);

#[derive(PartialEq, Eq, Hash)]
pub struct RouteInfo {
    route: String,
    verb: Method
}

/// The Router struct contains the information for your app to route requests
/// properly based on their HTTP method and matching route. It allows the use
/// of a custom 404 handler if desired but provides a default as well.
///
/// Under the hood a Router uses a RegexSet to match URI's that come in to the
/// instance of the hyper server. Because of this, it has the potential to match
/// multiple patterns that you provide. It will call the first handler that it
/// matches against so the order in which you add routes matters.
pub struct Router {
    /// A custom 404 handler that you can provide.
    pub not_found: Option<NotFoundFn>,

    routes: Option<RegexSet>,
    route_list: Vec<String>,
    compiled_list: Vec<Regex>,
    route_map: HashMap<RouteInfo, Box<Fn(Request, Response, Captures)>>
}

// These are needed to satisfy the Handler trait while using Fn to accept closures.
unsafe impl Send for Router { }
unsafe impl Sync for Router { }

impl Handler for Router {
    // The handle method for the router simply tries to match the URI against
    // the first pattern that it can which in turn calls its associated handle
    // function passing the hyper Request and Response structures.
    fn handle(&self, req: Request, res: Response) {
        let uri = format!("{}", req.uri);
        let matches = self.routes.as_ref().unwrap().matches(&uri);
        let index = matches.iter().next();
        match index {
            Some(i) => {
                let route = &self.route_list[i];
                let route_info = RouteInfo{route: route.clone(), verb: req.method.clone()};
                let handler = self.route_map.get(&route_info);
                match handler {
                    Some(h) => {
                        let compiled_pattern = &self.compiled_list[i];
                        let captures = get_captures(compiled_pattern, &uri);
                        h(req, res, captures);
                    }
                    None => {
                        not_allowed(req, res);
                    }
                }
            },
            None => self.not_found.unwrap()(req, res)
        }
    }
}

impl Router {
    /// Construct a new Router to maintain the routes and their handler
    /// functions.
    pub fn new() -> Router {
        Router {
            not_found: None,
            routes: None,
            route_list: Vec::new(),
            compiled_list: Vec::new(),
            route_map: HashMap::new(),
        }
    }

    /// Add a route to the router and give it a function to call when the route
    /// is matched against. You can call this explicitly or use the convenience
    /// methods defined below.
    pub fn add_route<H>(&mut self, verb: Method, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        let route_info = RouteInfo{route: route.to_owned(), verb: verb};
        let pattern = Regex::new(route);
        match pattern {
            Ok(p) => { self.compiled_list.push(p); },
            Err(e) => { println!("Not adding this route due to error: {}", e); }
        }
        self.route_list.push(route.to_owned());
        self.route_map.insert(route_info, Box::new(handler));
    }

    /// A convenience method for OPTIONS requests.
    pub fn options<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Options, route, handler);
    }

    /// A convenience method for GET requests.
    pub fn get<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Get, route, handler);
    }

    /// A convenience method for POST requests.
    pub fn post<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Post, route, handler);
    }

    /// A convenience method for PUT requests.
    pub fn put<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Put, route, handler);
    }

    /// A convenience method for DELETE requests.
    pub fn delete<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Delete, route, handler);
    }

    /// A convenience method for PATCH requests.
    pub fn patch<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Patch, route, handler);
    }

    /// This function ensures that a valid `RegexSet` could be made from the route
    /// vector that was built while using the functions that add routes. It
    /// requires that there exist at least one route so that the RegexSet can be
    /// successfully constructed.
    ///
    /// It will also ensure that there is a handler for routes that do not match
    /// any available in the set.
    pub fn finalize(&mut self) -> Result<(), RouterError> {
        if self.route_list.len() == 0  {
            return Err(RouterError::TooFewRoutes);
        }

        // Check if the user added a 404 handler, else use the default.
        match self.not_found {
            Some(_) => {},
            None => { self.not_found = Some(default_not_found); }
        }

        let re_routes = RegexSet::new(self.route_list.iter());
        match re_routes {
            Ok(r) => {
                self.routes = Some(r);
                Ok(())
            }
            Err(_) => {
                Err(RouterError::BadSet)
            }
        }
    }

    /// Add a function to handle routes that get no matches.
    pub fn add_not_found(&mut self, not_found: NotFoundFn) {
        self.not_found = Some(not_found)
    }
}

// The default 404 handler.
fn default_not_found(req: Request, mut res: Response) {
    let message = format!("No route handler found for {}", req.uri);
    *res.status_mut() = StatusCode::NotFound;
    res.send(message.as_bytes()).unwrap();
}

// This handler will get fired when a URI matches a route but contains the wrong method.
fn not_allowed(_: Request, mut res: Response) {
    *res.status_mut() = StatusCode::MethodNotAllowed;
    let res = res.start().unwrap();
    res.end().unwrap();
}

// Return that captures from a pattern that was matched.
fn get_captures(pattern: &Regex, uri: &str) -> Captures {
    // We know this compiles because it was part of the set.
    let caps = pattern.captures(uri);
    match caps {
        Some(caps) => {
            let mut v = vec![];
            for c in caps.iter() {
                v.push(c.unwrap().to_owned());
            }
            Some(v)
        },
        None => None
    }
}

mod error;

#[test]
fn no_routes() {
    let mut router = Router::new();
    let e = router.finalize();
    assert_eq!(e.err(), Some(RouterError::TooFewRoutes));
}

#[test]
fn bad_regular_expression() {
    fn test_handler(_: Request, _: Response, _: Captures) {}
    let mut router = Router::new();
    router.add_route(Method::Get, r"/[", test_handler);
    let e = router.finalize();
    assert_eq!(e.err(), Some(RouterError::BadSet));
}
<commit_msg>Publicly export RouterError for use outside crate<commit_after>extern crate hyper;
extern crate regex;

use std::collections::HashMap;

use hyper::method::Method;
use hyper::server::{Handler, Request, Response};
use hyper::status::StatusCode;
use regex::{Regex, RegexSet};

pub use error::RouterError;

pub type Captures = Option<Vec<String>>;
pub type NotFoundFn = fn(Request, Response);

#[derive(PartialEq, Eq, Hash)]
pub struct RouteInfo {
    route: String,
    verb: Method
}

/// The Router struct contains the information for your app to route requests
/// properly based on their HTTP method and matching route. It allows the use
/// of a custom 404 handler if desired but provides a default as well.
///
/// Under the hood a Router uses a RegexSet to match URI's that come in to the
/// instance of the hyper server. Because of this, it has the potential to match
/// multiple patterns that you provide. It will call the first handler that it
/// matches against so the order in which you add routes matters.
pub struct Router {
    /// A custom 404 handler that you can provide.
    pub not_found: Option<NotFoundFn>,

    routes: Option<RegexSet>,
    route_list: Vec<String>,
    compiled_list: Vec<Regex>,
    route_map: HashMap<RouteInfo, Box<Fn(Request, Response, Captures)>>
}

// These are needed to satisfy the Handler trait while using Fn to accept closures.
unsafe impl Send for Router { }
unsafe impl Sync for Router { }

impl Handler for Router {
    // The handle method for the router simply tries to match the URI against
    // the first pattern that it can which in turn calls its associated handle
    // function passing the hyper Request and Response structures.
    fn handle(&self, req: Request, res: Response) {
        let uri = format!("{}", req.uri);
        let matches = self.routes.as_ref().unwrap().matches(&uri);
        let index = matches.iter().next();
        match index {
            Some(i) => {
                let route = &self.route_list[i];
                let route_info = RouteInfo{route: route.clone(), verb: req.method.clone()};
                let handler = self.route_map.get(&route_info);
                match handler {
                    Some(h) => {
                        let compiled_pattern = &self.compiled_list[i];
                        let captures = get_captures(compiled_pattern, &uri);
                        h(req, res, captures);
                    }
                    None => {
                        not_allowed(req, res);
                    }
                }
            },
            None => self.not_found.unwrap()(req, res)
        }
    }
}

impl Router {
    /// Construct a new Router to maintain the routes and their handler
    /// functions.
    pub fn new() -> Router {
        Router {
            not_found: None,
            routes: None,
            route_list: Vec::new(),
            compiled_list: Vec::new(),
            route_map: HashMap::new(),
        }
    }

    /// Add a route to the router and give it a function to call when the route
    /// is matched against. You can call this explicitly or use the convenience
    /// methods defined below.
    pub fn add_route<H>(&mut self, verb: Method, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        let route_info = RouteInfo{route: route.to_owned(), verb: verb};
        let pattern = Regex::new(route);
        match pattern {
            Ok(p) => { self.compiled_list.push(p); },
            Err(e) => { println!("Not adding this route due to error: {}", e); }
        }
        self.route_list.push(route.to_owned());
        self.route_map.insert(route_info, Box::new(handler));
    }

    /// A convenience method for OPTIONS requests.
    pub fn options<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Options, route, handler);
    }

    /// A convenience method for GET requests.
    pub fn get<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Get, route, handler);
    }

    /// A convenience method for POST requests.
    pub fn post<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Post, route, handler);
    }

    /// A convenience method for PUT requests.
    pub fn put<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Put, route, handler);
    }

    /// A convenience method for DELETE requests.
    pub fn delete<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Delete, route, handler);
    }

    /// A convenience method for PATCH requests.
    pub fn patch<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Patch, route, handler);
    }

    /// This function ensures that a valid `RegexSet` could be made from the route
    /// vector that was built while using the functions that add routes. It
    /// requires that there exist at least one route so that the RegexSet can be
    /// successfully constructed.
    ///
    /// It will also ensure that there is a handler for routes that do not match
    /// any available in the set.
    pub fn finalize(&mut self) -> Result<(), RouterError> {
        if self.route_list.len() == 0  {
            return Err(RouterError::TooFewRoutes);
        }

        // Check if the user added a 404 handler, else use the default.
        match self.not_found {
            Some(_) => {},
            None => { self.not_found = Some(default_not_found); }
        }

        let re_routes = RegexSet::new(self.route_list.iter());
        match re_routes {
            Ok(r) => {
                self.routes = Some(r);
                Ok(())
            }
            Err(_) => {
                Err(RouterError::BadSet)
            }
        }
    }

    /// Add a function to handle routes that get no matches.
    pub fn add_not_found(&mut self, not_found: NotFoundFn) {
        self.not_found = Some(not_found)
    }
}

// The default 404 handler.
fn default_not_found(req: Request, mut res: Response) {
    let message = format!("No route handler found for {}", req.uri);
    *res.status_mut() = StatusCode::NotFound;
    res.send(message.as_bytes()).unwrap();
}

// This handler will get fired when a URI matches a route but contains the wrong method.
fn not_allowed(_: Request, mut res: Response) {
    *res.status_mut() = StatusCode::MethodNotAllowed;
    let res = res.start().unwrap();
    res.end().unwrap();
}

// Return that captures from a pattern that was matched.
fn get_captures(pattern: &Regex, uri: &str) -> Captures {
    // We know this compiles because it was part of the set.
    let caps = pattern.captures(uri);
    match caps {
        Some(caps) => {
            let mut v = vec![];
            for c in caps.iter() {
                v.push(c.unwrap().to_owned());
            }
            Some(v)
        },
        None => None
    }
}

mod error;

#[test]
fn no_routes() {
    let mut router = Router::new();
    let e = router.finalize();
    assert_eq!(e.err(), Some(RouterError::TooFewRoutes));
}

#[test]
fn bad_regular_expression() {
    fn test_handler(_: Request, _: Response, _: Captures) {}
    let mut router = Router::new();
    router.add_route(Method::Get, r"/[", test_handler);
    let e = router.finalize();
    assert_eq!(e.err(), Some(RouterError::BadSet));
}
<|endoftext|>


<commit_before>//! A simple, connection pool library.
#![crate_name = "netutils"]
#![crate_type = "lib"]
#![unstable]
#![warn(missing_docs)]
#![feature(slicing_syntax,phase)]
#[cfg(feature = "ssl")] extern crate openssl;
#[phase(plugin, link)]extern crate log;

pub mod net;

<commit_msg>Update lib.rs<commit_after>//! A simple, connection pool library.
#![crate_name = "net-utils"]
#![crate_type = "lib"]
#![unstable]
#![warn(missing_docs)]
#![feature(slicing_syntax,phase)]
#[cfg(feature = "ssl")] extern crate openssl;
#[phase(plugin, link)]extern crate log;

pub mod net;

<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/twitter-stream/0.10.0-alpha.6")]

/*!
# Twitter Stream

A library for listening on Twitter Streaming API.

## Usage

Add this to your `Cargo.toml`:

```toml
[dependencies]
futures = "0.3"
tokio = { version = "0.2", features = ["macros"] }
twitter-stream = "=0.10.0-alpha.6"
```

## Overview

Here is a basic example that prints public mentions to @Twitter in JSON format:

```rust,no_run
use futures::prelude::*;
use twitter_stream::{Token, TwitterStream};

# #[tokio::main]
# async fn main() {
let token = Token::new("consumer_key", "consumer_secret", "access_key", "access_secret");

TwitterStream::track("@Twitter", &token)
    .try_flatten_stream()
    .try_for_each(|json| {
        println!("{}", json);
        future::ok(())
    })
    .await
    .unwrap();
# }
```
*/

#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(intra_doc_link_resolution_failure)]
#![warn(missing_docs)]

#[macro_use]
mod util;

pub mod builder;
pub mod error;
#[cfg(feature = "hyper")]
#[cfg_attr(docsrs, doc(cfg(feature = "hyper")))]
pub mod hyper;
pub mod service;

mod gzip;
mod token;

pub use oauth::Credentials;

pub use crate::builder::Builder;
pub use crate::error::Error;
pub use crate::token::Token;

use std::future::Future;
use std::pin::Pin;
use std::str;
use std::task::{Context, Poll};

use bytes::Bytes;
use futures_core::Stream;
use futures_util::ready;
use http::header::CONTENT_ENCODING;
use http::response::Parts;
use http::Response;
use http::StatusCode;
use http_body::Body;
use pin_project_lite::pin_project;

use crate::builder::BoundingBox;
use crate::gzip::MaybeGzip;
use crate::util::{HttpBodyAsStream, Lines};

pin_project! {
    /// A future returned by constructor methods which resolves to a [`TwitterStream`].
    pub struct FutureTwitterStream<F> {
        #[pin]
        response: F,
    }
}

pin_project! {
    /// A listener for Twitter Streaming API, yielding JSON strings returned from the API.
    pub struct TwitterStream<B: Body> {
        #[pin]
        inner: Lines<MaybeGzip<HttpBodyAsStream<B>>>,
    }
}

impl<B: Body> TwitterStream<B> {
    /// Creates a `Builder` for `TwitterStream`.
    pub fn builder<'a, C, A>(token: Token<C, A>) -> Builder<'a, Token<C, A>>
    where
        C: std::borrow::Borrow<str>,
        A: std::borrow::Borrow<str>,
    {
        Builder::new(token)
    }
}

#[cfg(feature = "hyper")]
impl crate::hyper::TwitterStream {
    /// Connect to the filter stream, yielding Tweets from the users specified by `follow` argument.
    ///
    /// This is a shorthand for `Builder::new(token).follow(follow).listen()`.
    /// For more specific configurations, use [`TwitterStream::builder`] or [`Builder::new`].
    ///
    /// # Panics
    ///
    /// This will panic if the underlying HTTPS connector failed to initialize.
    pub fn follow<C, A>(follow: &[u64], token: &Token<C, A>) -> crate::hyper::FutureTwitterStream
    where
        C: std::borrow::Borrow<str>,
        A: std::borrow::Borrow<str>,
    {
        Builder::new(token.as_ref()).follow(follow).listen()
    }

    /// Connect to the filter stream, yielding Tweets that matches the query specified by
    /// `track` argument.
    ///
    /// This is a shorthand for `Builder::new(token).track(track).listen()`.
    /// For more specific configurations, use [`TwitterStream::builder`] or [`Builder::new`].
    ///
    /// # Panics
    ///
    /// This will panic if the underlying HTTPS connector failed to initialize.
    pub fn track<C, A>(track: &str, token: &Token<C, A>) -> crate::hyper::FutureTwitterStream
    where
        C: std::borrow::Borrow<str>,
        A: std::borrow::Borrow<str>,
    {
        Builder::new(token.as_ref()).track(track).listen()
    }

    /// Connect to the filter stream, yielding geolocated Tweets falling within the specified
    /// bounding boxes.
    ///
    /// This is a shorthand for `Builder::new(token).locations(locations).listen()`.
    /// For more specific configurations, use [`TwitterStream::builder`] or [`Builder::new`].
    ///
    /// # Panics
    ///
    /// This will panic if the underlying HTTPS connector failed to initialize.
    pub fn locations<C, A>(
        locations: &[BoundingBox],
        token: &Token<C, A>,
    ) -> crate::hyper::FutureTwitterStream
    where
        C: std::borrow::Borrow<str>,
        A: std::borrow::Borrow<str>,
    {
        Builder::new(token.as_ref()).locations(locations).listen()
    }

    /// Connect to the sample stream, yielding a "small random sample" of all public Tweets.
    ///
    /// This is a shorthand for `Builder::new(token).listen()`.
    /// For more specific configurations, use [`TwitterStream::builder`] or [`Builder::new`].
    ///
    /// # Panics
    ///
    /// This will panic if the underlying HTTPS connector failed to initialize.
    pub fn sample<C, A>(token: &Token<C, A>) -> crate::hyper::FutureTwitterStream
    where
        C: std::borrow::Borrow<str>,
        A: std::borrow::Borrow<str>,
    {
        Builder::new(token.as_ref()).listen()
    }
}

impl<F, B, E> Future for FutureTwitterStream<F>
where
    F: Future<Output = Result<Response<B>, E>>,
    B: Body,
{
    type Output = Result<TwitterStream<B>, Error<E>>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let res = match ready!(self.project().response.poll(cx)) {
            Ok(res) => res,
            Err(e) => return Poll::Ready(Err(Error::Service(e))),
        };
        let (parts, body) = res.into_parts();
        let Parts {
            status, headers, ..
        } = parts;

        if StatusCode::OK != status {
            return Poll::Ready(Err(Error::Http(status)));
        }

        let use_gzip = headers
            .get_all(CONTENT_ENCODING)
            .iter()
            .any(|e| e == "gzip");
        let inner = if use_gzip {
            Lines::new(gzip::gzip(HttpBodyAsStream::new(body)))
        } else {
            Lines::new(gzip::identity(HttpBodyAsStream::new(body)))
        };

        Poll::Ready(Ok(TwitterStream { inner }))
    }
}

impl<B> Stream for TwitterStream<B>
where
    B: Body,
{
    type Item = Result<string::String<Bytes>, Error<B::Error>>;

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        let mut this = self.project();

        loop {
            let line = match ready!(this.inner.as_mut().poll_next(cx)?) {
                Some(t) => t,
                None => return std::task::Poll::Ready(None),
            };

            if line.iter().all(|&c| is_json_whitespace(c)) {
                continue;
            }

            str::from_utf8(&line).map_err(Error::Utf8)?;
            let line = unsafe {
                // Safety:
                // - We have checked above that `line` is valid as UTF-8.
                // - `Bytes` satisfies the requirements of `string::StableAsRef` trait
                // (https://github.com/carllerche/string/pull/17)
                string::String::<Bytes>::from_utf8_unchecked(line)
            };
            return Poll::Ready(Some(Ok(line)));
        }
    }
}

fn is_json_whitespace(c: u8) -> bool {
    // RFC7159 §2
    b" \t\n\r".contains(&c)
}
<commit_msg>Fix an `unused import` warning<commit_after>#![doc(html_root_url = "https://docs.rs/twitter-stream/0.10.0-alpha.6")]

/*!
# Twitter Stream

A library for listening on Twitter Streaming API.

## Usage

Add this to your `Cargo.toml`:

```toml
[dependencies]
futures = "0.3"
tokio = { version = "0.2", features = ["macros"] }
twitter-stream = "=0.10.0-alpha.6"
```

## Overview

Here is a basic example that prints public mentions to @Twitter in JSON format:

```rust,no_run
use futures::prelude::*;
use twitter_stream::{Token, TwitterStream};

# #[tokio::main]
# async fn main() {
let token = Token::new("consumer_key", "consumer_secret", "access_key", "access_secret");

TwitterStream::track("@Twitter", &token)
    .try_flatten_stream()
    .try_for_each(|json| {
        println!("{}", json);
        future::ok(())
    })
    .await
    .unwrap();
# }
```
*/

#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(intra_doc_link_resolution_failure)]
#![warn(missing_docs)]

#[macro_use]
mod util;

pub mod builder;
pub mod error;
#[cfg(feature = "hyper")]
#[cfg_attr(docsrs, doc(cfg(feature = "hyper")))]
pub mod hyper;
pub mod service;

mod gzip;
mod token;

pub use oauth::Credentials;

pub use crate::builder::Builder;
pub use crate::error::Error;
pub use crate::token::Token;

use std::future::Future;
use std::pin::Pin;
use std::str;
use std::task::{Context, Poll};

use bytes::Bytes;
use futures_core::Stream;
use futures_util::ready;
use http::header::CONTENT_ENCODING;
use http::response::Parts;
use http::Response;
use http::StatusCode;
use http_body::Body;
use pin_project_lite::pin_project;

use crate::gzip::MaybeGzip;
use crate::util::{HttpBodyAsStream, Lines};

pin_project! {
    /// A future returned by constructor methods which resolves to a [`TwitterStream`].
    pub struct FutureTwitterStream<F> {
        #[pin]
        response: F,
    }
}

pin_project! {
    /// A listener for Twitter Streaming API, yielding JSON strings returned from the API.
    pub struct TwitterStream<B: Body> {
        #[pin]
        inner: Lines<MaybeGzip<HttpBodyAsStream<B>>>,
    }
}

impl<B: Body> TwitterStream<B> {
    /// Creates a `Builder` for `TwitterStream`.
    pub fn builder<'a, C, A>(token: Token<C, A>) -> Builder<'a, Token<C, A>>
    where
        C: std::borrow::Borrow<str>,
        A: std::borrow::Borrow<str>,
    {
        Builder::new(token)
    }
}

#[cfg(feature = "hyper")]
impl crate::hyper::TwitterStream {
    /// Connect to the filter stream, yielding Tweets from the users specified by `follow` argument.
    ///
    /// This is a shorthand for `Builder::new(token).follow(follow).listen()`.
    /// For more specific configurations, use [`TwitterStream::builder`] or [`Builder::new`].
    ///
    /// # Panics
    ///
    /// This will panic if the underlying HTTPS connector failed to initialize.
    pub fn follow<C, A>(follow: &[u64], token: &Token<C, A>) -> crate::hyper::FutureTwitterStream
    where
        C: std::borrow::Borrow<str>,
        A: std::borrow::Borrow<str>,
    {
        Builder::new(token.as_ref()).follow(follow).listen()
    }

    /// Connect to the filter stream, yielding Tweets that matches the query specified by
    /// `track` argument.
    ///
    /// This is a shorthand for `Builder::new(token).track(track).listen()`.
    /// For more specific configurations, use [`TwitterStream::builder`] or [`Builder::new`].
    ///
    /// # Panics
    ///
    /// This will panic if the underlying HTTPS connector failed to initialize.
    pub fn track<C, A>(track: &str, token: &Token<C, A>) -> crate::hyper::FutureTwitterStream
    where
        C: std::borrow::Borrow<str>,
        A: std::borrow::Borrow<str>,
    {
        Builder::new(token.as_ref()).track(track).listen()
    }

    /// Connect to the filter stream, yielding geolocated Tweets falling within the specified
    /// bounding boxes.
    ///
    /// This is a shorthand for `Builder::new(token).locations(locations).listen()`.
    /// For more specific configurations, use [`TwitterStream::builder`] or [`Builder::new`].
    ///
    /// # Panics
    ///
    /// This will panic if the underlying HTTPS connector failed to initialize.
    pub fn locations<C, A>(
        locations: &[builder::BoundingBox],
        token: &Token<C, A>,
    ) -> crate::hyper::FutureTwitterStream
    where
        C: std::borrow::Borrow<str>,
        A: std::borrow::Borrow<str>,
    {
        Builder::new(token.as_ref()).locations(locations).listen()
    }

    /// Connect to the sample stream, yielding a "small random sample" of all public Tweets.
    ///
    /// This is a shorthand for `Builder::new(token).listen()`.
    /// For more specific configurations, use [`TwitterStream::builder`] or [`Builder::new`].
    ///
    /// # Panics
    ///
    /// This will panic if the underlying HTTPS connector failed to initialize.
    pub fn sample<C, A>(token: &Token<C, A>) -> crate::hyper::FutureTwitterStream
    where
        C: std::borrow::Borrow<str>,
        A: std::borrow::Borrow<str>,
    {
        Builder::new(token.as_ref()).listen()
    }
}

impl<F, B, E> Future for FutureTwitterStream<F>
where
    F: Future<Output = Result<Response<B>, E>>,
    B: Body,
{
    type Output = Result<TwitterStream<B>, Error<E>>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let res = match ready!(self.project().response.poll(cx)) {
            Ok(res) => res,
            Err(e) => return Poll::Ready(Err(Error::Service(e))),
        };
        let (parts, body) = res.into_parts();
        let Parts {
            status, headers, ..
        } = parts;

        if StatusCode::OK != status {
            return Poll::Ready(Err(Error::Http(status)));
        }

        let use_gzip = headers
            .get_all(CONTENT_ENCODING)
            .iter()
            .any(|e| e == "gzip");
        let inner = if use_gzip {
            Lines::new(gzip::gzip(HttpBodyAsStream::new(body)))
        } else {
            Lines::new(gzip::identity(HttpBodyAsStream::new(body)))
        };

        Poll::Ready(Ok(TwitterStream { inner }))
    }
}

impl<B> Stream for TwitterStream<B>
where
    B: Body,
{
    type Item = Result<string::String<Bytes>, Error<B::Error>>;

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        let mut this = self.project();

        loop {
            let line = match ready!(this.inner.as_mut().poll_next(cx)?) {
                Some(t) => t,
                None => return std::task::Poll::Ready(None),
            };

            if line.iter().all(|&c| is_json_whitespace(c)) {
                continue;
            }

            str::from_utf8(&line).map_err(Error::Utf8)?;
            let line = unsafe {
                // Safety:
                // - We have checked above that `line` is valid as UTF-8.
                // - `Bytes` satisfies the requirements of `string::StableAsRef` trait
                // (https://github.com/carllerche/string/pull/17)
                string::String::<Bytes>::from_utf8_unchecked(line)
            };
            return Poll::Ready(Some(Ok(line)));
        }
    }
}

fn is_json_whitespace(c: u8) -> bool {
    // RFC7159 §2
    b" \t\n\r".contains(&c)
}
<|endoftext|>