<commit_before>//! Abstractions for asynchronous programming.
//!
//! This crate provides a number of core abstractions for writing asynchronous
//! code:
//!
//! - [Futures](crate::future::Future) are single eventual values produced by
//!   asychronous computations. Some programming languages (e.g. JavaScript)
//!   call this concept "promise".
//! - [Streams](crate::stream::Stream) represent a series of values
//!   produced asynchronously.
//! - [Sinks](crate::sink::Sink) provide support for asynchronous writing of
//!   data.
//! - [Executors](crate::executor) are responsible for running asynchronous
//!   tasks.
//!
//! The crate also contains abstractions for [asynchronous I/O](crate::io) and
//! [cross-task communication](crate::channel).
//!
//! Underlying all of this is the *task system*, which is a form of lightweight
//! threading. Large asynchronous computations are built up using futures,
//! streams and sinks, and then spawned as independent tasks that are run to
//! completion, but *do not block* the thread running them.

#![feature(futures_api)]

#![cfg_attr(not(feature = "std"), no_std)]

#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]

#![doc(html_root_url = "https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.12/futures")]

#[doc(hidden)] pub use futures_util::core_reexport;

#[doc(hidden)] pub use futures_core::future::Future;
#[doc(hidden)] pub use futures_core::future::TryFuture;
#[doc(hidden)] pub use futures_util::future::FutureExt;
#[doc(hidden)] pub use futures_util::try_future::TryFutureExt;

#[doc(hidden)] pub use futures_core::stream::Stream;
#[doc(hidden)] pub use futures_core::stream::TryStream;
#[doc(hidden)] pub use futures_util::stream::StreamExt;
#[doc(hidden)] pub use futures_util::try_stream::TryStreamExt;

#[doc(hidden)] pub use futures_sink::Sink;
#[doc(hidden)] pub use futures_util::sink::SinkExt;

#[doc(hidden)] pub use futures_core::task::Poll;

// Macro reexports
pub use futures_util::{
    // Error/readiness propagation
    try_ready, try_poll, ready,
};
#[cfg(feature = "std")]
pub use futures_util::{
    // Async-await
    join, try_join, pending, poll,
};

#[cfg(feature = "std")]
pub mod channel {
    //! Cross-task communication.
    //!
    //! Like threads, concurrent tasks sometimes need to communicate with each
    //! other. This module contains two basic abstractions for doing so:
    //!
    //! - [oneshot](crate::channel::oneshot), a way of sending a single value
    //!   from one task to another.
    //! - [mpsc](crate::channel::mpsc), a multi-producer, single-consumer
    //!   channel for sending values between tasks, analogous to the
    //!   similarly-named structure in the standard library.

    pub use futures_channel::{oneshot, mpsc};
}

#[cfg(feature = "compat")]
pub mod compat {
    //! Interop between `futures` 0.1 and 0.3.

    pub use futures_util::compat::{
        Compat,
        Compat01As03,
        Executor01Future,
        Executor01As03,
        Executor01CompatExt,
        Future01CompatExt,
        Stream01CompatExt,
    };
}

#[cfg(feature = "std")]
pub mod executor {
    //! Task execution.
    //!
    //! All asynchronous computation occurs within an executor, which is
    //! capable of spawning futures as tasks. This module provides several
    //! built-in executors, as well as tools for building your own.
    //!
    //! # Using a thread pool (M:N task scheduling)
    //!
    //! Most of the time tasks should be executed on a [thread
    //! pool](crate::executor::ThreadPool). A small set of worker threads can
    //! handle a very large set of spawned tasks (which are much lighter weight
    //! than threads).
    //!
    //! The simplest way to use a thread pool is to
    //! [`run`](crate::executor::ThreadPool::run) an initial task on it, which
    //! can then spawn further tasks back onto the pool to complete its work:
    //!
    //! ```
    //! #![feature(futures_api)]
    //! use futures::executor::ThreadPool;
    //! # use futures::future::{Future, lazy};
    //! # let my_app = lazy(|_| 42);
    //!
    //! // assuming `my_app: Future`
    //! ThreadPool::new().expect("Failed to create threadpool").run(my_app);
    //! ```
    //!
    //! The call to [`run`](crate::executor::ThreadPool::run) will block the
    //! current thread until the future defined by `my_app` completes, and will
    //! return the result of that future.
    //!
    //! # Spawning additional tasks
    //!
    //! Tasks can be spawned onto a spawner by calling its
    //! [`spawn_obj`](crate::task::Spawn::spawn_obj) method directly.
    //! In the case of `!Send` futures,
    //! [`spawn_local_obj`](crate::task::LocalSpawn::spawn_local_obj)
    //! can be used instead.
    //!
    //! # Single-threaded execution
    //!
    //! In addition to thread pools, it's possible to run a task (and the tasks
    //! it spawns) entirely within a single thread via the
    //! [`LocalPool`](crate::executor::LocalPool) executor. Aside from cutting
    //! down on synchronization costs, this executor also makes it possible to
    //! spawn non-`Send` tasks, via
    //! [`spawn_local_obj`](crate::executor::LocalSpawn::spawn_local_obj).
    //! The `LocalPool` is best suited for running I/O-bound tasks that do
    //! relatively little work between I/O operations.
    //!
    //! There is also a convenience function,
    //! [`block_on`](crate::executor::block_on), for simply running a future to
    //! completion on the current thread, while routing any spawned tasks
    //! to a global thread pool.

    pub use futures_executor::{
        BlockingStream,
        Enter, EnterError,
        LocalSpawner, LocalPool,
        ThreadPool, ThreadPoolBuilder,
        block_on, block_on_stream, enter,
    };
}

pub mod future {
    //! Asynchronous values.
    //!
    //! This module contains:
    //!
    //! - The [`Future` trait](crate::future::Future).
    //! - The [`FutureExt`](crate::future::FutureExt) trait, which provides
    //!   adapters for chaining and composing futures.
    //! - Top-level future combinators like [`lazy`](crate::future::lazy) which
    //!   creates a future from a closure that defines its return value, and
    //!   [`ready`](crate::future::ready), which constructs a future with an
    //!   immediate defined value.

    pub use futures_core::future::{
        Future, TryFuture, FusedFuture,
        FutureObj, LocalFutureObj, UnsafeFutureObj,
    };

    pub use futures_util::future::{
        empty, Empty,
        lazy, Lazy,
        maybe_done, MaybeDone,
        poll_fn, PollFn,
        ready, ok, err, Ready,

        OptionFuture,

        FutureExt,
        FlattenStream, Flatten, Fuse, Inspect, IntoStream, Join, Join3, Join4,
        Join5, Map, Then,
    };

    #[cfg(feature = "std")]
    pub use futures_util::future::{
        abortable, Abortable, AbortHandle, AbortRegistration, Aborted,
        Remote, RemoteHandle,
        // For FutureExt:
        CatchUnwind, Shared,

        join_all, JoinAll,

        // ToDo: SelectAll, SelectOk, select_all, select_ok
    };

    pub use futures_util::try_future::{
        TryFutureExt,
        AndThen, ErrInto, FlattenSink, IntoFuture, MapErr, MapOk, OrElse,
        UnwrapOrElse,
        TryJoin, TryJoin3, TryJoin4, TryJoin5,
        try_join_all, TryJoinAll,
    };
}

#[cfg(feature = "std")]
pub mod io {
    //! Asynchronous I/O.
    //!
    //! This module is the asynchronous version of `std::io`. It defines two
    //! traits, [`AsyncRead`](crate::io::AsyncRead) and
    //! [`AsyncWrite`](crate::io::AsyncWrite), which mirror the `Read` and
    //! `Write` traits of the standard library. However, these traits integrate
    //! with the asynchronous task system, so that if an I/O object isn't ready
    //! for reading (or writing), the thread is not blocked, and instead the
    //! current task is queued to be woken when I/O is ready.
    //!
    //! In addition, the [`AsyncReadExt`](crate::io::AsyncReadExt) and
    //! [`AsyncWriteExt`](crate::io::AsyncWriteExt) extension traits offer a
    //! variety of useful combinators for operating with asynchronous I/O
    //! objects, including ways to work with them using futures, streams and
    //! sinks.

    pub use futures_io::{
        Error, Initializer, IoVec, ErrorKind, AsyncRead, AsyncWrite, Result
    };
    pub use futures_util::io::{
        AsyncReadExt, AsyncWriteExt, AllowStdIo, Close, CopyInto, Flush,
        Read, ReadExact, ReadHalf, ReadToEnd, Window, WriteAll, WriteHalf,
    };
}

#[cfg(feature = "std")]
pub mod lock {
    //! Futures-powered synchronization primitives.
    pub use futures_util::lock::{Mutex, MutexLockFuture, MutexGuard};
}

pub mod prelude {
    //! A "prelude" for crates using the `futures` crate.
    //!
    //! This prelude is similar to the standard library's prelude in that you'll
    //! almost always want to import its entire contents, but unlike the
    //! standard library's prelude you'll have to do so manually:
    //!
    //! ```
    //! use futures::prelude::*;
    //! ```
    //!
    //! The prelude may grow over time as additional items see ubiquitous use.

    pub use crate::future::{self, Future, TryFuture, FutureExt, TryFutureExt};
    pub use crate::stream::{self, Stream, TryStream, StreamExt, TryStreamExt};
    pub use crate::sink::{self, Sink, SinkExt};

    #[cfg(feature = "std")]
    pub use crate::io::{ AsyncRead, AsyncWrite, AsyncReadExt, AsyncWriteExt };
}

pub mod sink {
    //! Asynchronous sinks.
    //!
    //! This module contains:
    //!
    //! - The [`Sink` trait](crate::sink::Sink), which allows you to
    //!   asynchronously write data.
    //! - The [`SinkExt`](crate::sink::SinkExt) trait, which provides adapters
    //!   for chaining and composing sinks.

    pub use futures_sink::Sink;

    pub use futures_util::sink::{
        Close, Flush, Send, SendAll, SinkErrInto, SinkMapErr, With,
        SinkExt, Fanout, Drain, DrainError, drain,
        // WithFlatMap,
    };

    #[cfg(feature = "std")]
    pub use futures_util::sink::Buffer;
}

pub mod stream {
    //! Asynchronous streams.
    //!
    //! This module contains:
    //!
    //! - The [`Stream` trait](crate::stream::Stream), for objects that can
    //!   asynchronously produce a sequence of values.
    //! - The [`StreamExt`](crate::stream::StreamExt) trait, which provides
    //!   adapters for chaining and composing streams.
    //! - Top-level stream contructors like [`iter_ok`](crate::stream::iter)
    //!   which creates a stream from an iterator, and
    //!   [`futures_unordered`](crate::stream::futures_unordered()), which
    //!   constructs a stream from a collection of futures.

    pub use futures_core::stream::{
        Stream, TryStream, FusedStream,
        StreamObj, LocalStreamObj, UnsafeStreamObj,
    };

    pub use futures_util::stream::{
        iter, Iter,
        repeat, Repeat,
        empty, Empty,
        once, Once,
        poll_fn, PollFn,
        unfold, Unfold,

        StreamExt,
        Chain, Concat, Filter, FilterMap, Flatten, Fold, Forward, ForEach, Fuse,
        StreamFuture, Inspect, Map, Next, Peekable, Select, Skip, SkipWhile,
        Take, TakeWhile, Then, Zip
    };

    #[cfg(feature = "std")]
    pub use futures_util::stream::{
        futures_ordered, FuturesOrdered,
        futures_unordered, FuturesUnordered,

        // For StreamExt:
        BufferUnordered, Buffered, CatchUnwind, Chunks, Collect, SplitStream,
        SplitSink, ReuniteError,

        select_all, SelectAll,
    };

    pub use futures_util::try_stream::{
        TryStreamExt,
        TryNext, TryForEach, ErrInto,
        TryFold, TrySkipWhile,
        IntoStream,
        // ToDo: AndThen, ErrInto, InspectErr, MapErr, OrElse
    };

    #[cfg(feature = "std")]
    pub use futures_util::try_stream::{
        // For TryStreamExt:
        TryCollect, TryBufferUnordered,
        // ToDo: AndThen, InspectErr, MapErr, OrElse
    };
}

pub mod task {
    //! Tools for working with tasks.
    //!
    //! This module contains:
    //!
    //! - [`Spawn`](crate::task::Spawn), a trait for spawning new tasks.
    //! - [`Waker`](crate::task::Waker), a handle for waking up a task.
    //!
    //! The remaining types and traits in the module are used for implementing
    //! executors or dealing with synchronization issues around task wakeup.

    pub use futures_core::task::{
        Poll, Spawn, LocalSpawn, SpawnError,
        Waker, LocalWaker, UnsafeWake,
    };

    #[cfg(feature = "std")]
    pub use futures_core::task::{
        Wake, local_waker, local_waker_from_nonlocal
    };

    #[cfg(feature = "std")]
    pub use futures_util::task::{
        LocalWakerRef, local_waker_ref, local_waker_ref_from_nonlocal,
        SpawnExt, LocalSpawnExt,
    };

    pub use futures_util::task::{
        noop_local_waker, noop_local_waker_ref,
    };

    #[cfg_attr(
        feature = "nightly",
        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
    )]
    pub use futures_util::task::AtomicWaker;
}

// `select!` re-export --------------------------------------

#[cfg(feature = "std")]
#[doc(hidden)]
pub use futures_util::rand_reexport;

#[cfg(feature = "std")]
#[doc(hidden)]
pub mod inner_select {
    pub use futures_util::select;
}

#[cfg(feature = "std")]
futures_util::document_select_macro! {
    #[macro_export]
    macro_rules! select { // replace `::futures_util` with `::futures` as the crate path
        ($($tokens:tt)*) => {
            $crate::inner_select::select! {
                futures_crate_path ( ::futures )
                $( $tokens )*
            }
        }
    }
}
<commit_msg>Fix missed feature usage<commit_after>//! Abstractions for asynchronous programming.
//!
//! This crate provides a number of core abstractions for writing asynchronous
//! code:
//!
//! - [Futures](crate::future::Future) are single eventual values produced by
//!   asychronous computations. Some programming languages (e.g. JavaScript)
//!   call this concept "promise".
//! - [Streams](crate::stream::Stream) represent a series of values
//!   produced asynchronously.
//! - [Sinks](crate::sink::Sink) provide support for asynchronous writing of
//!   data.
//! - [Executors](crate::executor) are responsible for running asynchronous
//!   tasks.
//!
//! The crate also contains abstractions for [asynchronous I/O](crate::io) and
//! [cross-task communication](crate::channel).
//!
//! Underlying all of this is the *task system*, which is a form of lightweight
//! threading. Large asynchronous computations are built up using futures,
//! streams and sinks, and then spawned as independent tasks that are run to
//! completion, but *do not block* the thread running them.

#![feature(futures_api)]
#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))]

#![cfg_attr(not(feature = "std"), no_std)]

#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]

#![doc(html_root_url = "https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.12/futures")]

#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "nightly")))]
compile_error!("The `cfg-target-has-atomic` feature requires the `nightly` feature as an explicit opt-in to unstable features");

#[doc(hidden)] pub use futures_util::core_reexport;

#[doc(hidden)] pub use futures_core::future::Future;
#[doc(hidden)] pub use futures_core::future::TryFuture;
#[doc(hidden)] pub use futures_util::future::FutureExt;
#[doc(hidden)] pub use futures_util::try_future::TryFutureExt;

#[doc(hidden)] pub use futures_core::stream::Stream;
#[doc(hidden)] pub use futures_core::stream::TryStream;
#[doc(hidden)] pub use futures_util::stream::StreamExt;
#[doc(hidden)] pub use futures_util::try_stream::TryStreamExt;

#[doc(hidden)] pub use futures_sink::Sink;
#[doc(hidden)] pub use futures_util::sink::SinkExt;

#[doc(hidden)] pub use futures_core::task::Poll;

// Macro reexports
pub use futures_util::{
    // Error/readiness propagation
    try_ready, try_poll, ready,
};
#[cfg(feature = "std")]
pub use futures_util::{
    // Async-await
    join, try_join, pending, poll,
};

#[cfg(feature = "std")]
pub mod channel {
    //! Cross-task communication.
    //!
    //! Like threads, concurrent tasks sometimes need to communicate with each
    //! other. This module contains two basic abstractions for doing so:
    //!
    //! - [oneshot](crate::channel::oneshot), a way of sending a single value
    //!   from one task to another.
    //! - [mpsc](crate::channel::mpsc), a multi-producer, single-consumer
    //!   channel for sending values between tasks, analogous to the
    //!   similarly-named structure in the standard library.

    pub use futures_channel::{oneshot, mpsc};
}

#[cfg(feature = "compat")]
pub mod compat {
    //! Interop between `futures` 0.1 and 0.3.

    pub use futures_util::compat::{
        Compat,
        Compat01As03,
        Executor01Future,
        Executor01As03,
        Executor01CompatExt,
        Future01CompatExt,
        Stream01CompatExt,
    };
}

#[cfg(feature = "std")]
pub mod executor {
    //! Task execution.
    //!
    //! All asynchronous computation occurs within an executor, which is
    //! capable of spawning futures as tasks. This module provides several
    //! built-in executors, as well as tools for building your own.
    //!
    //! # Using a thread pool (M:N task scheduling)
    //!
    //! Most of the time tasks should be executed on a [thread
    //! pool](crate::executor::ThreadPool). A small set of worker threads can
    //! handle a very large set of spawned tasks (which are much lighter weight
    //! than threads).
    //!
    //! The simplest way to use a thread pool is to
    //! [`run`](crate::executor::ThreadPool::run) an initial task on it, which
    //! can then spawn further tasks back onto the pool to complete its work:
    //!
    //! ```
    //! #![feature(futures_api)]
    //! use futures::executor::ThreadPool;
    //! # use futures::future::{Future, lazy};
    //! # let my_app = lazy(|_| 42);
    //!
    //! // assuming `my_app: Future`
    //! ThreadPool::new().expect("Failed to create threadpool").run(my_app);
    //! ```
    //!
    //! The call to [`run`](crate::executor::ThreadPool::run) will block the
    //! current thread until the future defined by `my_app` completes, and will
    //! return the result of that future.
    //!
    //! # Spawning additional tasks
    //!
    //! Tasks can be spawned onto a spawner by calling its
    //! [`spawn_obj`](crate::task::Spawn::spawn_obj) method directly.
    //! In the case of `!Send` futures,
    //! [`spawn_local_obj`](crate::task::LocalSpawn::spawn_local_obj)
    //! can be used instead.
    //!
    //! # Single-threaded execution
    //!
    //! In addition to thread pools, it's possible to run a task (and the tasks
    //! it spawns) entirely within a single thread via the
    //! [`LocalPool`](crate::executor::LocalPool) executor. Aside from cutting
    //! down on synchronization costs, this executor also makes it possible to
    //! spawn non-`Send` tasks, via
    //! [`spawn_local_obj`](crate::executor::LocalSpawn::spawn_local_obj).
    //! The `LocalPool` is best suited for running I/O-bound tasks that do
    //! relatively little work between I/O operations.
    //!
    //! There is also a convenience function,
    //! [`block_on`](crate::executor::block_on), for simply running a future to
    //! completion on the current thread, while routing any spawned tasks
    //! to a global thread pool.

    pub use futures_executor::{
        BlockingStream,
        Enter, EnterError,
        LocalSpawner, LocalPool,
        ThreadPool, ThreadPoolBuilder,
        block_on, block_on_stream, enter,
    };
}

pub mod future {
    //! Asynchronous values.
    //!
    //! This module contains:
    //!
    //! - The [`Future` trait](crate::future::Future).
    //! - The [`FutureExt`](crate::future::FutureExt) trait, which provides
    //!   adapters for chaining and composing futures.
    //! - Top-level future combinators like [`lazy`](crate::future::lazy) which
    //!   creates a future from a closure that defines its return value, and
    //!   [`ready`](crate::future::ready), which constructs a future with an
    //!   immediate defined value.

    pub use futures_core::future::{
        Future, TryFuture, FusedFuture,
        FutureObj, LocalFutureObj, UnsafeFutureObj,
    };

    pub use futures_util::future::{
        empty, Empty,
        lazy, Lazy,
        maybe_done, MaybeDone,
        poll_fn, PollFn,
        ready, ok, err, Ready,

        OptionFuture,

        FutureExt,
        FlattenStream, Flatten, Fuse, Inspect, IntoStream, Join, Join3, Join4,
        Join5, Map, Then,
    };

    #[cfg(feature = "std")]
    pub use futures_util::future::{
        abortable, Abortable, AbortHandle, AbortRegistration, Aborted,
        Remote, RemoteHandle,
        // For FutureExt:
        CatchUnwind, Shared,

        join_all, JoinAll,

        // ToDo: SelectAll, SelectOk, select_all, select_ok
    };

    pub use futures_util::try_future::{
        TryFutureExt,
        AndThen, ErrInto, FlattenSink, IntoFuture, MapErr, MapOk, OrElse,
        UnwrapOrElse,
        TryJoin, TryJoin3, TryJoin4, TryJoin5,
        try_join_all, TryJoinAll,
    };
}

#[cfg(feature = "std")]
pub mod io {
    //! Asynchronous I/O.
    //!
    //! This module is the asynchronous version of `std::io`. It defines two
    //! traits, [`AsyncRead`](crate::io::AsyncRead) and
    //! [`AsyncWrite`](crate::io::AsyncWrite), which mirror the `Read` and
    //! `Write` traits of the standard library. However, these traits integrate
    //! with the asynchronous task system, so that if an I/O object isn't ready
    //! for reading (or writing), the thread is not blocked, and instead the
    //! current task is queued to be woken when I/O is ready.
    //!
    //! In addition, the [`AsyncReadExt`](crate::io::AsyncReadExt) and
    //! [`AsyncWriteExt`](crate::io::AsyncWriteExt) extension traits offer a
    //! variety of useful combinators for operating with asynchronous I/O
    //! objects, including ways to work with them using futures, streams and
    //! sinks.

    pub use futures_io::{
        Error, Initializer, IoVec, ErrorKind, AsyncRead, AsyncWrite, Result
    };
    pub use futures_util::io::{
        AsyncReadExt, AsyncWriteExt, AllowStdIo, Close, CopyInto, Flush,
        Read, ReadExact, ReadHalf, ReadToEnd, Window, WriteAll, WriteHalf,
    };
}

#[cfg(feature = "std")]
pub mod lock {
    //! Futures-powered synchronization primitives.
    pub use futures_util::lock::{Mutex, MutexLockFuture, MutexGuard};
}

pub mod prelude {
    //! A "prelude" for crates using the `futures` crate.
    //!
    //! This prelude is similar to the standard library's prelude in that you'll
    //! almost always want to import its entire contents, but unlike the
    //! standard library's prelude you'll have to do so manually:
    //!
    //! ```
    //! use futures::prelude::*;
    //! ```
    //!
    //! The prelude may grow over time as additional items see ubiquitous use.

    pub use crate::future::{self, Future, TryFuture, FutureExt, TryFutureExt};
    pub use crate::stream::{self, Stream, TryStream, StreamExt, TryStreamExt};
    pub use crate::sink::{self, Sink, SinkExt};

    #[cfg(feature = "std")]
    pub use crate::io::{ AsyncRead, AsyncWrite, AsyncReadExt, AsyncWriteExt };
}

pub mod sink {
    //! Asynchronous sinks.
    //!
    //! This module contains:
    //!
    //! - The [`Sink` trait](crate::sink::Sink), which allows you to
    //!   asynchronously write data.
    //! - The [`SinkExt`](crate::sink::SinkExt) trait, which provides adapters
    //!   for chaining and composing sinks.

    pub use futures_sink::Sink;

    pub use futures_util::sink::{
        Close, Flush, Send, SendAll, SinkErrInto, SinkMapErr, With,
        SinkExt, Fanout, Drain, DrainError, drain,
        // WithFlatMap,
    };

    #[cfg(feature = "std")]
    pub use futures_util::sink::Buffer;
}

pub mod stream {
    //! Asynchronous streams.
    //!
    //! This module contains:
    //!
    //! - The [`Stream` trait](crate::stream::Stream), for objects that can
    //!   asynchronously produce a sequence of values.
    //! - The [`StreamExt`](crate::stream::StreamExt) trait, which provides
    //!   adapters for chaining and composing streams.
    //! - Top-level stream contructors like [`iter_ok`](crate::stream::iter)
    //!   which creates a stream from an iterator, and
    //!   [`futures_unordered`](crate::stream::futures_unordered()), which
    //!   constructs a stream from a collection of futures.

    pub use futures_core::stream::{
        Stream, TryStream, FusedStream,
        StreamObj, LocalStreamObj, UnsafeStreamObj,
    };

    pub use futures_util::stream::{
        iter, Iter,
        repeat, Repeat,
        empty, Empty,
        once, Once,
        poll_fn, PollFn,
        unfold, Unfold,

        StreamExt,
        Chain, Concat, Filter, FilterMap, Flatten, Fold, Forward, ForEach, Fuse,
        StreamFuture, Inspect, Map, Next, Peekable, Select, Skip, SkipWhile,
        Take, TakeWhile, Then, Zip
    };

    #[cfg(feature = "std")]
    pub use futures_util::stream::{
        futures_ordered, FuturesOrdered,
        futures_unordered, FuturesUnordered,

        // For StreamExt:
        BufferUnordered, Buffered, CatchUnwind, Chunks, Collect, SplitStream,
        SplitSink, ReuniteError,

        select_all, SelectAll,
    };

    pub use futures_util::try_stream::{
        TryStreamExt,
        TryNext, TryForEach, ErrInto,
        TryFold, TrySkipWhile,
        IntoStream,
        // ToDo: AndThen, ErrInto, InspectErr, MapErr, OrElse
    };

    #[cfg(feature = "std")]
    pub use futures_util::try_stream::{
        // For TryStreamExt:
        TryCollect, TryBufferUnordered,
        // ToDo: AndThen, InspectErr, MapErr, OrElse
    };
}

pub mod task {
    //! Tools for working with tasks.
    //!
    //! This module contains:
    //!
    //! - [`Spawn`](crate::task::Spawn), a trait for spawning new tasks.
    //! - [`Waker`](crate::task::Waker), a handle for waking up a task.
    //!
    //! The remaining types and traits in the module are used for implementing
    //! executors or dealing with synchronization issues around task wakeup.

    pub use futures_core::task::{
        Poll, Spawn, LocalSpawn, SpawnError,
        Waker, LocalWaker, UnsafeWake,
    };

    #[cfg(feature = "std")]
    pub use futures_core::task::{
        Wake, local_waker, local_waker_from_nonlocal
    };

    #[cfg(feature = "std")]
    pub use futures_util::task::{
        LocalWakerRef, local_waker_ref, local_waker_ref_from_nonlocal,
        SpawnExt, LocalSpawnExt,
    };

    pub use futures_util::task::{
        noop_local_waker, noop_local_waker_ref,
    };

    #[cfg_attr(
        feature = "target-has-atomic",
        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
    )]
    pub use futures_util::task::AtomicWaker;
}

// `select!` re-export --------------------------------------

#[cfg(feature = "std")]
#[doc(hidden)]
pub use futures_util::rand_reexport;

#[cfg(feature = "std")]
#[doc(hidden)]
pub mod inner_select {
    pub use futures_util::select;
}

#[cfg(feature = "std")]
futures_util::document_select_macro! {
    #[macro_export]
    macro_rules! select { // replace `::futures_util` with `::futures` as the crate path
        ($($tokens:tt)*) => {
            $crate::inner_select::select! {
                futures_crate_path ( ::futures )
                $( $tokens )*
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::convert::TryFrom;
use std::str::FromStr;

#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum Version {
    V26,
    V27,
    V28,
    V29,
    V29a,
    V30,
    V30a,
    V31,
    V31a,
    V31b,
}

impl FromStr for Version {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use Version::*;
        let v = match s {
            "2.6" => V26,
            "2.7" => V27,
            "2.8" => V28,
            "2.9" => V29,
            "2.9a" => V29a,
            "3.0" => V30,
            "3.0a" => V30a,
            "3.1" => V31,
            "3.1a" => V31a,
            "3.1b" => V31b,
            _ => return Err(()),
        };
        Ok(v)
    }
}

impl AsRef<str> for Version {
    fn as_ref(&self) -> &'static str {
        use Version::*;
        match *self {
            V26 => "2.6",
            V27 => "2.7",
            V28 => "2.8",
            V29 => "2.9",
            V29a => "2.9a",
            V30 => "3.0",
            V30a => "3.0a",
            V31 => "3.1",
            V31a => "3.1a",
            V31b => "3.1b",
        }
    }
}

#[derive(Debug)]
pub enum ParseVersionError {
    BadVersionOutput(String),
    UnsupportedVersion(String),
}

impl Version {
    // Try parse `tmux -v` result
    pub fn try_from_version_output(version_output: &str) -> Result<Self, ParseVersionError> {
        let version_number = version_output
            .trim()
            .split(" ")
            .nth(1)
            .ok_or_else(|| ParseVersionError::BadVersionOutput(version_output.to_string()))?;
        Self::try_from(version_number)
    }

    pub fn as_str(&self) -> &str {
        self.as_ref()
    }
}

impl TryFrom<&str> for Version {
    type Error = ParseVersionError;

    fn try_from(value: &str) -> Result<Self, Self::Error> {
        Self::from_str(value).map_err(|_| ParseVersionError::UnsupportedVersion(value.to_owned()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_version() {
        let tmux_output = "tmux 3.1b";

        let actual = Version::try_from_version_output(tmux_output);
        assert!(matches!(actual, Ok(Version::V31b)));
    }
}
<commit_msg>Add tmux 3.1c<commit_after>use std::convert::TryFrom;
use std::str::FromStr;

#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum Version {
    V26,
    V27,
    V28,
    V29,
    V29a,
    V30,
    V30a,
    V31,
    V31a,
    V31b,
    V31c,
}

impl FromStr for Version {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use Version::*;
        let v = match s {
            "2.6" => V26,
            "2.7" => V27,
            "2.8" => V28,
            "2.9" => V29,
            "2.9a" => V29a,
            "3.0" => V30,
            "3.0a" => V30a,
            "3.1" => V31,
            "3.1a" => V31a,
            "3.1b" => V31b,
            "3.1c" => V31c,
            _ => return Err(()),
        };
        Ok(v)
    }
}

impl AsRef<str> for Version {
    fn as_ref(&self) -> &'static str {
        use Version::*;
        match *self {
            V26 => "2.6",
            V27 => "2.7",
            V28 => "2.8",
            V29 => "2.9",
            V29a => "2.9a",
            V30 => "3.0",
            V30a => "3.0a",
            V31 => "3.1",
            V31a => "3.1a",
            V31b => "3.1b",
            V31c => "3.1c",
        }
    }
}

#[derive(Debug)]
pub enum ParseVersionError {
    BadVersionOutput(String),
    UnsupportedVersion(String),
}

impl Version {
    // Try parse `tmux -v` result
    pub fn try_from_version_output(version_output: &str) -> Result<Self, ParseVersionError> {
        let version_number = version_output
            .trim()
            .split(" ")
            .nth(1)
            .ok_or_else(|| ParseVersionError::BadVersionOutput(version_output.to_string()))?;
        Self::try_from(version_number)
    }

    pub fn as_str(&self) -> &str {
        self.as_ref()
    }
}

impl TryFrom<&str> for Version {
    type Error = ParseVersionError;

    fn try_from(value: &str) -> Result<Self, Self::Error> {
        Self::from_str(value).map_err(|_| ParseVersionError::UnsupportedVersion(value.to_owned()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_version() {
        let tmux_output = "tmux 3.1b";

        let actual = Version::try_from_version_output(tmux_output);
        assert!(matches!(actual, Ok(Version::V31b)));
    }
}
<|endoftext|>


<commit_before>extern crate cc;

use std::{env, fs};
use std::path::PathBuf;

fn main() {
    let mut compiler = cc::Build::new();
    compiler
        .file("liblz4/lib/lz4.c")
        .file("liblz4/lib/lz4frame.c")
        .file("liblz4/lib/lz4hc.c")
        .file("liblz4/lib/xxhash.c")
        // We always compile the C with optimization, because otherwise it is 20x slower.
        .opt_level(3);
    match env::var("TARGET").unwrap().as_str()
    {
      "i686-pc-windows-gnu" => {
        compiler
            .flag("-fno-tree-vectorize");
      },
      _ => {}
    }
    compiler.compile("liblz4.a");

    let src = env::current_dir().unwrap().join("liblz4").join("lib");
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let include = dst.join("include");
    fs::create_dir_all(&include).unwrap();
    for e in fs::read_dir(&src).unwrap() {
        let e = e.unwrap();
        if e.file_name().into_string().unwrap().ends_with(".h") {
            fs::copy(e.path(), include.join(e.file_name())).unwrap();
        }
    }
    println!("cargo:root={}", dst.display());
}
<commit_msg>Don't panic in lz4-sys build script<commit_after>extern crate cc;

use std::{env, fs, process};
use std::error::Error;
use std::path::PathBuf;

fn main() {
    match run() {
        Ok(()) => (),
        Err(err) => {
            eprintln!("{}", err);
            process::exit(1);
        }
    }
}

fn run() -> Result<(), Box<dyn Error>> {
    let mut compiler = cc::Build::new();
    compiler
        .file("liblz4/lib/lz4.c")
        .file("liblz4/lib/lz4frame.c")
        .file("liblz4/lib/lz4hc.c")
        .file("liblz4/lib/xxhash.c")
        // We always compile the C with optimization, because otherwise it is 20x slower.
        .opt_level(3);
    match env::var("TARGET")
        .map_err(|err| format!("reading TARGET environment variable: {}", err))?
        .as_str()
    {
      "i686-pc-windows-gnu" => {
        compiler
            .flag("-fno-tree-vectorize");
      },
      _ => {}
    }
    compiler.compile("liblz4.a");

    let src = env::current_dir()?.join("liblz4").join("lib");
    let dst = PathBuf::from(env::var_os("OUT_DIR").ok_or("missing OUT_DIR environment variable")?);
    let include = dst.join("include");
    fs::create_dir_all(&include)
        .map_err(|err| format!("creating directory {}: {}", include.display(), err))?;
    for e in fs::read_dir(&src)? {
        let e = e?;
        let utf8_file_name = e.file_name().into_string()
            .map_err(|_| format!("unable to convert file name {:?} to UTF-8", e.file_name()))?;
        if utf8_file_name.ends_with(".h") {
            let from = e.path();
            let to = include.join(e.file_name());
            fs::copy(&from, &to)
                .map_err(|err| format!("copying {} to {}: {}", from.display(), to.display(), err))?;
        }
    }
    println!("cargo:root={}", dst.display());

    Ok(())
}
<|endoftext|>


<commit_before>use crate::grammar::ast::{BinaryExpression, BinaryOp, Expression};
use crate::grammar::model::{Fragment, HasFragment};
use crate::grammar::parsers::expression::binary_expression::operators::{
    Associativity, OperatorInfo,
};
use crate::grammar::parsers::expression::ToExpression;
use crate::grammar::parsers::whitespace::token_delimiter;
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::combinator::{map, value};
use nom::error::ErrorKind;
use nom::sequence::delimited;
use nom::Err::Error;
use nom::IResult;

fn binary_operator(input: Fragment) -> IResult<Fragment, BinaryOp> {
    use BinaryOp::*;
    let get_token = |op: BinaryOp| op.get_info().token;
    let value_tag = |op:BinaryOp| value(op, get_token(op));
    alt((
        // some of these are sequentially important; AndAnd needs to go before And
        // to avoid under-parsing.
        value_tag(OrOr),
        value_tag(Or),
        value_tag(AndAnd),
        value_tag(And),
        value_tag(Ge),
        value_tag(Gt),
        value_tag(Le),
        value_tag(Lt),
        value_tag(Xor),
        value_tag(NotEq),
        value_tag(EqEq),
        value_tag(DotDot),
        value_tag(Add),
        value_tag(Sub),
        value_tag(Mul),
        value_tag(Div),
        value_tag(Mod),
    ))(input)
}

fn build_binary_expr<'s>(a: Expression<'s>, op: OperatorInfo, b: Expression<'s>) -> Expression<'s> {
    BinaryExpression::new(
        Fragment::merge(a.get_fragment(), b.get_fragment()).expect("Fragments must be contiguous"),
        a,
        op.id,
        b,
    )
    .create_expr()
}

/// Shunting yard algorithm for structuring binary expressions. Takes
pub fn shunting_yard<'s>(input: Fragment<'s>) -> IResult<Fragment<'s>, BinaryExpression<'s>> {
    let mut exprs = Vec::new();
    let mut ops = Vec::<OperatorInfo>::new();
    // expose remaining input at top-level
    let mut rem = input;
    // parse the first operand
    if let Ok((rem1, operand)) = BinaryExpression::primary(rem) {
        rem = rem1;
        exprs.push(operand);
        // parse the operator chain
        while let Ok((rem1, operator)) = binary_operator(rem) {
            // shunt operators of greater precedence over
            while let Some(top) = ops.pop() {
                use Associativity::Left;
                if top.prec > operator.prec || (top.prec == operator.prec && operator.assoc == Left)
                {
                    // build BinaryExpression and push onto exprs
                    let b = exprs.pop().expect("(b1) exprs stack must be len >= 2");
                    let a = exprs.pop().expect("(a1) exprs stack must be len >= 2");
                    exprs.push(build_binary_expr(a, top, b));
                } else {
                    // repush popped operator, not shunting
                    ops.push(top);
                    break;
                }
            }
            if let Ok((rem1, operand)) = BinaryExpression::primary(rem1) {
                // commit consuming the source of (operator + second operand)
                rem = rem1;
                ops.push(operator);
                exprs.push(operand);
            } else {
                // don't comsume the source of (operator)
                break;
            }
        }
    }
    // shunt over remaining operators
    while let Some(op) = ops.pop() {
        let b = exprs.pop().expect("(b2) exprs stack must be len >= 2");
        let a = exprs.pop().expect("(a2) exprs stack must be len >= 2");
        exprs.push(build_binary_expr(a, op, b));
    }
    if let Some(Expression::BinaryExpression(expr)) = exprs.pop() {
        Ok((rem, expr))
    } else {
        Err(Error((input, ErrorKind::SeparatedNonEmptyList)))
    }
}
<commit_msg>add delimiter<commit_after>use crate::grammar::ast::{BinaryExpression, BinaryOp, Expression};
use crate::grammar::model::{Fragment, HasFragment};
use crate::grammar::parsers::expression::binary_expression::operators::{
    Associativity, OperatorInfo,
};
use crate::grammar::parsers::expression::ToExpression;
use crate::grammar::parsers::whitespace::token_delimiter;
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::combinator::{map, value};
use nom::error::ErrorKind;
use nom::sequence::delimited;
use nom::Err::Error;
use nom::IResult;

fn binary_operator(input: Fragment) -> IResult<Fragment, BinaryOp> {
    use BinaryOp::*;
    let get_token = |op: BinaryOp| op.get_info().token;
    let value_tag = |op:BinaryOp| value(op, tag(get_token(op)));
    delimited(
        token_delimiter,
        alt((
            // some of these are sequentially important; AndAnd needs to go before And
            // to avoid under-parsing.
            value_tag(OrOr),
            value_tag(Or),
            value_tag(AndAnd),
            value_tag(And),
            value_tag(Ge),
            value_tag(Gt),
            value_tag(Le),
            value_tag(Lt),
            value_tag(Xor),
            value_tag(NotEq),
            value_tag(EqEq),
            value_tag(DotDot),
            value_tag(Add),
            value_tag(Sub),
            value_tag(Mul),
            value_tag(Div),
            value_tag(Mod),
        )),
        token_delimiter
    )(input)
}

fn build_binary_expr<'s>(a: Expression<'s>, op: OperatorInfo, b: Expression<'s>) -> Expression<'s> {
    BinaryExpression::new(
        Fragment::merge(a.get_fragment(), b.get_fragment()).expect("Fragments must be contiguous"),
        a,
        op.id,
        b,
    )
    .create_expr()
}

/// Shunting yard algorithm for structuring binary expressions. Takes
pub fn shunting_yard<'s>(input: Fragment<'s>) -> IResult<Fragment<'s>, BinaryExpression<'s>> {
    let mut exprs = Vec::new();
    let mut ops = Vec::<OperatorInfo>::new();
    // expose remaining input at top-level
    let mut rem = input;
    // parse the first operand
    if let Ok((rem1, operand)) = BinaryExpression::primary(rem) {
        rem = rem1;
        exprs.push(operand);
        // parse the operator chain
        while let Ok((rem1, operator)) = binary_operator(rem) {
            // shunt operators of greater precedence over
            while let Some(top) = ops.pop() {
                use Associativity::Left;
                if top.prec > operator.prec || (top.prec == operator.prec && operator.assoc == Left)
                {
                    // build BinaryExpression and push onto exprs
                    let b = exprs.pop().expect("(b1) exprs stack must be len >= 2");
                    let a = exprs.pop().expect("(a1) exprs stack must be len >= 2");
                    exprs.push(build_binary_expr(a, top, b));
                } else {
                    // repush popped operator, not shunting
                    ops.push(top);
                    break;
                }
            }
            if let Ok((rem1, operand)) = BinaryExpression::primary(rem1) {
                // commit consuming the source of (operator + second operand)
                rem = rem1;
                ops.push(operator);
                exprs.push(operand);
            } else {
                // don't comsume the source of (operator)
                break;
            }
        }
    }
    // shunt over remaining operators
    while let Some(op) = ops.pop() {
        let b = exprs.pop().expect("(b2) exprs stack must be len >= 2");
        let a = exprs.pop().expect("(a2) exprs stack must be len >= 2");
        exprs.push(build_binary_expr(a, op, b));
    }
    if let Some(Expression::BinaryExpression(expr)) = exprs.pop() {
        Ok((rem, expr))
    } else {
        Err(Error((input, ErrorKind::SeparatedNonEmptyList)))
    }
}
<|endoftext|>


<commit_before>extern crate gcc;
#[macro_use] extern crate lazy_static;
extern crate regex;
extern crate semver;

use regex::Regex;
use semver::Version;
use std::env;
use std::ffi::OsStr;
use std::io::{self, ErrorKind};
use std::path::PathBuf;
use std::process::Command;

lazy_static!{
    /// LLVM version used by this version of the crate.
    static ref CRATE_VERSION: Version = {
        let crate_version = Version::parse(env!("CARGO_PKG_VERSION"))
            .expect("Crate version is somehow not valid semver");
        Version {
            major: crate_version.major / 10,
            minor: crate_version.major % 10,
            .. crate_version
        }
    };

    /// Filesystem path to an llvm-config binary for the correct version.
    static ref LLVM_CONFIG_PATH: PathBuf = {
        // Try llvm-config via PATH first.
        if let Some(name) = locate_system_llvm_config() {
            return name.into();
        } else {
            println!("Didn't find usable system-wide LLVM.");
        }

        // Did the user give us a binary path to use? If yes, try
        // to use that and fail if it doesn't work.
        let binary_prefix_var = format!("LLVM_SYS_{}_PREFIX",
                                        env!("CARGO_PKG_VERSION_MAJOR"));
        if let Some(path) = env::var_os(&binary_prefix_var) {
            let mut pb: PathBuf = path.into();
            pb.push("bin");
            pb.push("llvm-config");

            let ver = llvm_version(&pb)
                .expect(&format!("Failed to execute {:?}", &pb));
            if is_compatible_llvm(&ver) {
                return pb;
            } else {
                panic!("LLVM binaries specified by {} are the wrong version.
                        (Found {}, need {}.)", binary_prefix_var, ver, *CRATE_VERSION);
            }
        } else {
            println!("{} not set, not using precompiled binaries", binary_prefix_var);
        }

        // No binaries. Offer to download and compile a blessed version,
        // but only with positive confirmation. It's a fairly large download,
        // takes a while and could get wiped out by a `cargo clean` so it's
        // useful if doing an install but is in general not recommended.
        let autobuild_var = format!("LLVM_SYS_{}_AUTOBUILD",
                                    env!("CARGO_PKG_VERSION_MAJOR"));
        match env::var_os(&autobuild_var) {
            Some(ref x) => {
                if x == "YES" {
                    unimplemented!();
                } else {
                    println!("{} must be exactly \"YES\" to enable autobuild (is {:?})",
                             autobuild_var, x);
                }
            }
            None => {
                println!("{} not set, will not automatically compile LLVM",
                         autobuild_var);
            }
        }

        panic!("Could not find a compatible version of LLVM");
    };
}

/// Try to find a system-wide version of llvm-config that is compatible with
/// this crate.
///
/// Returns None on failure.
fn locate_system_llvm_config() -> Option<&'static str> {
    match llvm_version("llvm-config") {
        Ok(ref version) if is_compatible_llvm(version) => {
            // Compatible version found. Nice.
            return Some("llvm-config");
        },
        Ok(version) => {
            // Version mismatch. Will try further searches, but warn that
            // we're not using the system one.
            println!("Found LLVM version {} on PATH, but need {}.",
                     version, *CRATE_VERSION);
        },
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            // Looks like we failed to execute any llvm-config. Keep
            // searching.
        },
        // Some other error, probably a weird failure. Give up.
        Err(e) => panic!("Failed to search PATH for llvm-config: {}", e),
    }

    None
}

/// Check whether the given version of LLVM is blacklisted,
/// returning `Some(reason)` if it is.
fn is_blacklisted_llvm(llvm_version: &Version) -> Option<&'static str> {
    static BLACKLIST: &'static [(u64, u64, u64, &'static str)] = &[];

    let blacklist_var = format!("LLVM_SYS_{}_IGNORE_BLACKLIST",
                                env!("CARGO_PKG_VERSION_MAJOR"));
    if let Some(x) = env::var_os(&blacklist_var) {
        if &x == "YES" {
            println!("cargo:warning=Ignoring blacklist entry for LLVM {}", llvm_version);
            return None;
        } else {
            println!("cargo:warning={} is set but not exactly \"YES\"; blacklist is still honored.",
                     &blacklist_var);
        }
    }

    for &(major, minor, patch, reason) in BLACKLIST.iter() {
        let bad_version = Version {
            major: major, minor: minor, patch: patch,
            pre: vec![], build: vec![],
        };

        if &bad_version == llvm_version {
            return Some(reason);
        }
    }
    None
}

/// Check whether the given LLVM version is compatible with this version of
/// the crate.
fn is_compatible_llvm(llvm_version: &Version) -> bool {
    if let Some(reason) = is_blacklisted_llvm(llvm_version) {
        println!("Found LLVM {}, which is blacklisted: {}", llvm_version, reason);
        return false;
    }

    let strict = env::var_os(format!("LLVM_SYS_{}_STRICT_VERSIONING",
                                     env!("CARGO_PKG_VERSION_MAJOR"))).is_some()
        || cfg!(feature="strict-versioning");
    if strict {
        llvm_version.major == CRATE_VERSION.major &&
            llvm_version.minor == CRATE_VERSION.minor
    } else {
        llvm_version.major >= CRATE_VERSION.major ||
            (llvm_version.major == CRATE_VERSION.major &&
             llvm_version.minor >= CRATE_VERSION.minor)
    }
}

/// Get the output from running `llvm-config` with the given argument.
///
/// Lazily searches for or compiles LLVM as configured by the environment
/// variables.
fn llvm_config(arg: &str) -> String {
    llvm_config_ex(&*LLVM_CONFIG_PATH, arg)
        .expect("Surprising failure from llvm-config")
}

/// Invoke the specified binary as llvm-config.
///
/// Explicit version of the `llvm_config` function that bubbles errors
/// up.
fn llvm_config_ex<S: AsRef<OsStr>>(binary: S, arg: &str)
        -> io::Result<String> {
    Command::new(binary)
        .arg(arg)
        .arg("--link-static")   // Don't use dylib for >= 3.9
        .output()
        .map(|output| String::from_utf8(output.stdout)
            .expect("Output from llvm-config was not valid UTF-8"))
}

/// Get the LLVM version using llvm-config.
fn llvm_version<S: AsRef<OsStr>>(binary: S) -> io::Result<Version> {
    let version_str = try!(llvm_config_ex(binary.as_ref(), "--version"));

    // LLVM isn't really semver and uses version suffixes to build
    // version strings like '3.8.0svn', so limit what we try to parse
    // to only the numeric bits.
    let re = Regex::new(r"^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)")
        .unwrap();
    let m = re.find(&version_str)
        .expect("Could not determine LLVM version from llvm-config.");

    Ok(Version::parse(&version_str[m.start()..m.end()]).unwrap())
}

/// Get the names of the dylibs required by LLVM, including the C++ standard
/// library.
fn get_system_libraries() -> Vec<String> {
    llvm_config("--system-libs")
        .split(&[' ', '\n'] as &[char])
        .filter(|s| !s.is_empty())
        .map(|flag| {
            if cfg!(target_env = "msvc") {
                // Same as --libnames, foo.lib
                assert!(flag.ends_with(".lib"));
                &flag[..flag.len() - 4]
            } else {
                // Linker flags style, -lfoo
                assert!(flag.starts_with("-l"));
                &flag[2..]
            }
        })
        .chain(get_system_libcpp())
        .map(str::to_owned)
        .collect::<Vec<String>>()
}

/// Get the library that must be linked for C++, if any.
fn get_system_libcpp() -> Option<&'static str> {
    if cfg!(target_env = "msvc") {
        // MSVC doesn't need an explicit one.
        None
    } else if cfg!(target_os = "macos") {
        // On OS X 10.9 and later, LLVM's libc++ is the default. On earlier
        // releases GCC's libstdc++ is default. Unfortunately we can't
        // reasonably detect which one we need (on older ones libc++ is
        // available and can be selected with -stdlib=lib++), so assume the
        // latest, at the cost of breaking the build on older OS releases
        // when LLVM was built against libstdc++.
        Some("c++")
    } else {
        // Otherwise assume GCC's libstdc++.
        // This assumption is probably wrong on some platforms, but would need
        // testing on them.
        Some("stdc++")
    }
}

/// Get the names of libraries to link against.
fn get_link_libraries() -> Vec<String> {
    // Using --libnames in conjunction with --libdir is particularly important
    // for MSVC when LLVM is in a path with spaces, but it is generally less of
    // a hack than parsing linker flags output from --libs and --ldflags.
    llvm_config("--libnames")
        .split(&[' ', '\n'] as &[char])
        .filter(|s| !s.is_empty())
        .map(|name| {
            // --libnames gives library filenames. Extract only the name that
            // we need to pass to the linker.
            if cfg!(target_env = "msvc") {
                // LLVMfoo.lib
                assert!(name.ends_with(".lib"));
                &name[..name.len() - 4]
            } else {
                // libLLVMfoo.a
                assert!(name.starts_with("lib") && name.ends_with(".a"));
                &name[3..name.len() - 2]
            }
        })
        .map(str::to_owned)
        .collect::<Vec<String>>()
}

fn main() {
    let libdir = llvm_config("--libdir");

    // Export information to other crates
    println!("cargo:config_path={}", LLVM_CONFIG_PATH.display()); // will be DEP_LLVM_CONFIG_PATH
    println!("cargo:libdir={}", libdir); // DEP_LLVM_LIBDIR

    // Link LLVM libraries
    println!("cargo:rustc-link-search=native={}", libdir);
    for name in get_link_libraries() {
        println!("cargo:rustc-link-lib=static={}", name);
    }

    // Link system libraries
    for name in get_system_libraries() {
        println!("cargo:rustc-link-lib=dylib={}", name);
    }

    // Link libffi if the user requested this workaround.
    // See https://bitbucket.org/tari/llvm-sys.rs/issues/12/
    let force_ffi = env::var_os(format!("LLVM_SYS_{}_FFI_WORKAROUND",
                                        env!("CARGO_PKG_VERSION_MAJOR")))
        .is_some();
    if force_ffi {
        println!("cargo:rustc-link-lib=dylib={}", "ffi");
    }

    // Build the extra wrapper functions.
    std::env::set_var("CFLAGS", llvm_config("--cflags").trim());
    gcc::compile_library("libtargetwrappers.a", &["wrappers/target.c"]);
}
<commit_msg>Clean -W... flags from LLVM CFLAGS at build time.<commit_after>extern crate gcc;
#[macro_use] extern crate lazy_static;
extern crate regex;
extern crate semver;

use regex::Regex;
use semver::Version;
use std::env;
use std::ffi::OsStr;
use std::io::{self, ErrorKind};
use std::path::PathBuf;
use std::process::Command;

lazy_static!{
    /// LLVM version used by this version of the crate.
    static ref CRATE_VERSION: Version = {
        let crate_version = Version::parse(env!("CARGO_PKG_VERSION"))
            .expect("Crate version is somehow not valid semver");
        Version {
            major: crate_version.major / 10,
            minor: crate_version.major % 10,
            .. crate_version
        }
    };

    /// Filesystem path to an llvm-config binary for the correct version.
    static ref LLVM_CONFIG_PATH: PathBuf = {
        // Try llvm-config via PATH first.
        if let Some(name) = locate_system_llvm_config() {
            return name.into();
        } else {
            println!("Didn't find usable system-wide LLVM.");
        }

        // Did the user give us a binary path to use? If yes, try
        // to use that and fail if it doesn't work.
        let binary_prefix_var = format!("LLVM_SYS_{}_PREFIX",
                                        env!("CARGO_PKG_VERSION_MAJOR"));
        if let Some(path) = env::var_os(&binary_prefix_var) {
            let mut pb: PathBuf = path.into();
            pb.push("bin");
            pb.push("llvm-config");

            let ver = llvm_version(&pb)
                .expect(&format!("Failed to execute {:?}", &pb));
            if is_compatible_llvm(&ver) {
                return pb;
            } else {
                panic!("LLVM binaries specified by {} are the wrong version.
                        (Found {}, need {}.)", binary_prefix_var, ver, *CRATE_VERSION);
            }
        } else {
            println!("{} not set, not using precompiled binaries", binary_prefix_var);
        }

        // No binaries. Offer to download and compile a blessed version,
        // but only with positive confirmation. It's a fairly large download,
        // takes a while and could get wiped out by a `cargo clean` so it's
        // useful if doing an install but is in general not recommended.
        let autobuild_var = format!("LLVM_SYS_{}_AUTOBUILD",
                                    env!("CARGO_PKG_VERSION_MAJOR"));
        match env::var_os(&autobuild_var) {
            Some(ref x) => {
                if x == "YES" {
                    unimplemented!();
                } else {
                    println!("{} must be exactly \"YES\" to enable autobuild (is {:?})",
                             autobuild_var, x);
                }
            }
            None => {
                println!("{} not set, will not automatically compile LLVM",
                         autobuild_var);
            }
        }

        panic!("Could not find a compatible version of LLVM");
    };
}

/// Try to find a system-wide version of llvm-config that is compatible with
/// this crate.
///
/// Returns None on failure.
fn locate_system_llvm_config() -> Option<&'static str> {
    match llvm_version("llvm-config") {
        Ok(ref version) if is_compatible_llvm(version) => {
            // Compatible version found. Nice.
            return Some("llvm-config");
        },
        Ok(version) => {
            // Version mismatch. Will try further searches, but warn that
            // we're not using the system one.
            println!("Found LLVM version {} on PATH, but need {}.",
                     version, *CRATE_VERSION);
        },
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            // Looks like we failed to execute any llvm-config. Keep
            // searching.
        },
        // Some other error, probably a weird failure. Give up.
        Err(e) => panic!("Failed to search PATH for llvm-config: {}", e),
    }

    None
}

/// Check whether the given version of LLVM is blacklisted,
/// returning `Some(reason)` if it is.
fn is_blacklisted_llvm(llvm_version: &Version) -> Option<&'static str> {
    static BLACKLIST: &'static [(u64, u64, u64, &'static str)] = &[];

    let blacklist_var = format!("LLVM_SYS_{}_IGNORE_BLACKLIST",
                                env!("CARGO_PKG_VERSION_MAJOR"));
    if let Some(x) = env::var_os(&blacklist_var) {
        if &x == "YES" {
            println!("cargo:warning=Ignoring blacklist entry for LLVM {}", llvm_version);
            return None;
        } else {
            println!("cargo:warning={} is set but not exactly \"YES\"; blacklist is still honored.",
                     &blacklist_var);
        }
    }

    for &(major, minor, patch, reason) in BLACKLIST.iter() {
        let bad_version = Version {
            major: major, minor: minor, patch: patch,
            pre: vec![], build: vec![],
        };

        if &bad_version == llvm_version {
            return Some(reason);
        }
    }
    None
}

/// Check whether the given LLVM version is compatible with this version of
/// the crate.
fn is_compatible_llvm(llvm_version: &Version) -> bool {
    if let Some(reason) = is_blacklisted_llvm(llvm_version) {
        println!("Found LLVM {}, which is blacklisted: {}", llvm_version, reason);
        return false;
    }

    let strict = env::var_os(format!("LLVM_SYS_{}_STRICT_VERSIONING",
                                     env!("CARGO_PKG_VERSION_MAJOR"))).is_some()
        || cfg!(feature="strict-versioning");
    if strict {
        llvm_version.major == CRATE_VERSION.major &&
            llvm_version.minor == CRATE_VERSION.minor
    } else {
        llvm_version.major >= CRATE_VERSION.major ||
            (llvm_version.major == CRATE_VERSION.major &&
             llvm_version.minor >= CRATE_VERSION.minor)
    }
}

/// Get the output from running `llvm-config` with the given argument.
///
/// Lazily searches for or compiles LLVM as configured by the environment
/// variables.
fn llvm_config(arg: &str) -> String {
    llvm_config_ex(&*LLVM_CONFIG_PATH, arg)
        .expect("Surprising failure from llvm-config")
}

/// Invoke the specified binary as llvm-config.
///
/// Explicit version of the `llvm_config` function that bubbles errors
/// up.
fn llvm_config_ex<S: AsRef<OsStr>>(binary: S, arg: &str)
        -> io::Result<String> {
    Command::new(binary)
        .arg(arg)
        .arg("--link-static")   // Don't use dylib for >= 3.9
        .output()
        .map(|output| String::from_utf8(output.stdout)
            .expect("Output from llvm-config was not valid UTF-8"))
}

/// Get the LLVM version using llvm-config.
fn llvm_version<S: AsRef<OsStr>>(binary: S) -> io::Result<Version> {
    let version_str = try!(llvm_config_ex(binary.as_ref(), "--version"));

    // LLVM isn't really semver and uses version suffixes to build
    // version strings like '3.8.0svn', so limit what we try to parse
    // to only the numeric bits.
    let re = Regex::new(r"^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)")
        .unwrap();
    let m = re.find(&version_str)
        .expect("Could not determine LLVM version from llvm-config.");

    Ok(Version::parse(&version_str[m.start()..m.end()]).unwrap())
}

/// Get the names of the dylibs required by LLVM, including the C++ standard
/// library.
fn get_system_libraries() -> Vec<String> {
    llvm_config("--system-libs")
        .split(&[' ', '\n'] as &[char])
        .filter(|s| !s.is_empty())
        .map(|flag| {
            if cfg!(target_env = "msvc") {
                // Same as --libnames, foo.lib
                assert!(flag.ends_with(".lib"));
                &flag[..flag.len() - 4]
            } else {
                // Linker flags style, -lfoo
                assert!(flag.starts_with("-l"));
                &flag[2..]
            }
        })
        .chain(get_system_libcpp())
        .map(str::to_owned)
        .collect::<Vec<String>>()
}

/// Get the library that must be linked for C++, if any.
fn get_system_libcpp() -> Option<&'static str> {
    if cfg!(target_env = "msvc") {
        // MSVC doesn't need an explicit one.
        None
    } else if cfg!(target_os = "macos") {
        // On OS X 10.9 and later, LLVM's libc++ is the default. On earlier
        // releases GCC's libstdc++ is default. Unfortunately we can't
        // reasonably detect which one we need (on older ones libc++ is
        // available and can be selected with -stdlib=lib++), so assume the
        // latest, at the cost of breaking the build on older OS releases
        // when LLVM was built against libstdc++.
        Some("c++")
    } else {
        // Otherwise assume GCC's libstdc++.
        // This assumption is probably wrong on some platforms, but would need
        // testing on them.
        Some("stdc++")
    }
}

/// Get the names of libraries to link against.
fn get_link_libraries() -> Vec<String> {
    // Using --libnames in conjunction with --libdir is particularly important
    // for MSVC when LLVM is in a path with spaces, but it is generally less of
    // a hack than parsing linker flags output from --libs and --ldflags.
    llvm_config("--libnames")
        .split(&[' ', '\n'] as &[char])
        .filter(|s| !s.is_empty())
        .map(|name| {
            // --libnames gives library filenames. Extract only the name that
            // we need to pass to the linker.
            if cfg!(target_env = "msvc") {
                // LLVMfoo.lib
                assert!(name.ends_with(".lib"));
                &name[..name.len() - 4]
            } else {
                // libLLVMfoo.a
                assert!(name.starts_with("lib") && name.ends_with(".a"));
                &name[3..name.len() - 2]
            }
        })
        .map(str::to_owned)
        .collect::<Vec<String>>()
}

fn get_llvm_cflags() -> String {
    let output = llvm_config("--cflags");

    // llvm-config includes cflags from its own compilation with --cflags that
    // may not be relevant to us. In particularly annoying cases, these might
    // include flags that aren't understood by the default compiler we're
    // using. Unless requested otherwise, clean CFLAGS of options that are
    // known to be possibly-harmful.
    let no_clean = env::var_os(format!("LLVM_SYS_{}_NO_CLEAN_CFLAGS",
                                       env!("CARGO_PKG_VERSION_MAJOR"))).is_some();
    if no_clean || cfg!(target_env = "msvc") {
        // MSVC doesn't accept -W... options, so don't try to strip them and
        // possibly strip something that should be retained. Also do nothing if
        // the user requests it.
        return output;
    }

    llvm_config("--cflags").split(&[' ', '\n'][..])
        .filter(|word| !word.starts_with("-W"))
        .collect::<Vec<_>>()
        .join(" ")
}

fn main() {
    let libdir = llvm_config("--libdir");

    // Export information to other crates
    println!("cargo:config_path={}", LLVM_CONFIG_PATH.display()); // will be DEP_LLVM_CONFIG_PATH
    println!("cargo:libdir={}", libdir); // DEP_LLVM_LIBDIR

    // Link LLVM libraries
    println!("cargo:rustc-link-search=native={}", libdir);
    for name in get_link_libraries() {
        println!("cargo:rustc-link-lib=static={}", name);
    }

    // Link system libraries
    for name in get_system_libraries() {
        println!("cargo:rustc-link-lib=dylib={}", name);
    }

    // Link libffi if the user requested this workaround.
    // See https://bitbucket.org/tari/llvm-sys.rs/issues/12/
    let force_ffi = env::var_os(format!("LLVM_SYS_{}_FFI_WORKAROUND",
                                        env!("CARGO_PKG_VERSION_MAJOR")))
        .is_some();
    if force_ffi {
        println!("cargo:rustc-link-lib=dylib={}", "ffi");
    }

    // Build the extra wrapper functions.
    std::env::set_var("CFLAGS", get_llvm_cflags());
    gcc::compile_library("libtargetwrappers.a", &["wrappers/target.c"]);
}
<|endoftext|>


<commit_before>extern crate cmake;
extern crate bindgen;

use std::env;
use std::path::PathBuf;
use cmake::Config;

fn main() {
    let bindings = bindgen::Builder::default()
        .clang_arg("-Ivendor/enet/include/")
        .header("wrapper.h")
        .generate()
        .expect("Unable to generate bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");

    let dst = Config::new("vendor/enet")
                .build_target("enet")
                .build();

    eprintln!("LUL: {}", dst.display());

    println!("cargo:rustc-link-search=native={}/build", dst.display());
    println!("cargo:rustc-link-lib=static=enet");
}<commit_msg>set bindgen builder option derive debug to false<commit_after>extern crate cmake;
extern crate bindgen;

use std::env;
use std::path::PathBuf;
use cmake::Config;

fn main() {
    let bindings = bindgen::Builder::default()
        .clang_arg("-Ivendor/enet/include/")
        .header("wrapper.h")
        .derive_debug(false)
        .generate()
        .expect("Unable to generate bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");

    let dst = Config::new("vendor/enet")
                .build_target("enet")
                .build();

    eprintln!("LUL: {}", dst.display());

    println!("cargo:rustc-link-search=native={}/build", dst.display());
    println!("cargo:rustc-link-lib=static=enet");
}
<|endoftext|>


<commit_before>use value::{Value};
use std::str::FromStr;
use std::f64;

#[derive(Clone, Debug, Copy)]
pub enum Primitive {
    LT,
    LTE,
    NEQ,
    Add,
    Subtract,
    Multiply,
    Remainder,
    Round,
    Split,
    Concat,
    ParseFloat,
    Count,
    Contains,
    Sum,
    Mean,
    StandardDeviation,
    Empty,
}

pub fn resolve_as_scalar<'a>(mut ix: usize, constants: &'a [Value], outer: &'a [Value]) -> &'a Value {
    if ix < constants.len() {
        return &constants[ix];
    } else {
        ix = ix - constants.len()
    }
    return &outer[ix];
}

pub fn resolve_as_vector<'a>(mut ix: usize, constants: &'a [Value], outer: &'a [Value], inner: &'a [Vec<Value>]) -> Vec<&'a Value> {
    if ix < constants.len() {
        return vec![&constants[ix]; inner.len()];
    } else {
        ix = ix - constants.len()
    }
    if ix < outer.len() {
        return vec![&outer[ix]; inner.len()];
    } else {
        ix = ix - outer.len()
    }
    return inner.iter().map(|values| &values[ix]).collect();
}

impl Primitive {
    pub fn eval_from_join<'a>(&self, input_bindings: &[(usize, usize)], inputs: &[Value]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        let values = input_bindings.iter().enumerate().map(|(ix, &(field_ix, variable_ix))| {
            assert_eq!(ix, field_ix);
            &inputs[variable_ix]
        }).collect::<Vec<_>>();
        match (*self, &values[..]) {
            // NOTE be aware that arguments will be in alphabetical order by field id
            (LT, [ref a, ref b]) => if a < b {vec![vec![]]} else {vec![]},
            (LTE, [ref a, ref b]) => if a <= b {vec![vec![]]} else {vec![]},
            (NEQ, [ref a, ref b]) => if a != b {vec![vec![]]} else {vec![]},
            (Add, [&Float(a), &Float(b)]) => vec![vec![Float(a+b)]],
            (Subtract, [&Float(a), &Float(b)]) => vec![vec![Float(a-b)]],
            (Multiply, [&Float(a), &Float(b)]) => vec![vec![Float(a*b)]],
            (Remainder, [&Float(a), &Float(b)]) => vec![vec![Float(a%b)]], // akin to C-like languages, the % operator is remainder,
            (Round, [&Float(a), &Float(b)]) => vec![vec![Float((a*10f64.powf(b)).round()/10f64.powf(b))]],
            (Contains, [&String(ref inner), &String(ref outer)]) => {
              let inner_lower = &inner.to_lowercase();
              let outer_lower = &outer.to_lowercase();
              vec![vec![Bool(outer_lower.contains(inner_lower))]]
            },
            (Split, [&String(ref split), &String(ref string)]) => {
                string.split(split).enumerate().map(|(ix, segment)| vec![Float(ix as f64), String(segment.to_owned())]).collect()
            },
            (Concat, [&String(ref a), &String(ref b)]) => vec![vec![String(a.to_owned() + b)]],
            (Concat, [&String(ref a), &Float(ref b)]) => vec![vec![String(a.to_owned() + &format!("{}", b))]],
            (Concat, [&Float(ref a), &String(ref b)]) => vec![vec![String(format!("{}", a) + b)]],
            (ParseFloat, [&String(ref a)]) => {
                match f64::from_str(&a) {
                    Ok(v) => vec![vec![Float(v), Bool(true)]],
                    _ => vec![vec![Float(f64::MAX), Bool(false)]]
                }
            },
            (Count, [&Column(ref column)]) => vec![vec![Float(column.len() as f64)]],
            (Sum, [&Column(ref column)]) => {
                let sum = column.iter().fold(0f64, |sum, value|
                    match *value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, column),
                    });
                vec![vec![Float(sum)]]
            }
            (Mean, [&Column(ref column)]) => {
                let sum = column.iter().fold(0f64, |sum, value|
                    match *value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, column),
                    });
                let mean = sum / (column.len() as f64);
                vec![vec![Float(mean)]]
            },
            (StandardDeviation, [&Column(ref column)]) => {
                let sum = column.iter().fold(0f64, |sum, value|
                    match *value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, column),
                    });
                let sum_squares = column.iter().fold(0f64, |sum, value|
                    match *value {
                        Float(float) => sum + float.powi(2),
                        _ => panic!("Type error while calling: {:?} {:?}", self, column),
                    });
                let standard_deviation = ((sum_squares - sum.powi(2)) / (column.len() as f64)).sqrt();
                vec![vec![Float(standard_deviation)]]
            }
            (Empty, [&Column(ref column)]) => vec![vec![Bool(column.len() == 0)]],
            _ => panic!("Type error while calling: {:?} {:?}", self, values)
        }
    }

    pub fn eval_from_aggregate<'a>(&self, arguments: &[usize], constants: &[Value], outer: &[Value], inner: &[Vec<Value>]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        match (*self, arguments) {
            // NOTE be aware that arguments will be in alphabetical order by field id
            (LT, _) => panic!("Cannot use {:?} in an aggregate", self),
            (LTE, _) => panic!("Cannot use {:?} in an aggregate", self),
            (NEQ, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Add, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Subtract, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Multiply, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Remainder, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Round, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Contains, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Split, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Concat, _) => panic!("Cannot use {:?} in an aggregate", self),
            (ParseFloat, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Count, [_]) => {
                vec![vec![Float(inner.len() as f64)]]
            },
            (Sum, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                vec![vec![Float(sum)]]
            },
            (Mean, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                let mean = sum / (in_values.len() as f64);
                vec![vec![Float(mean)]]
            },
            (StandardDeviation, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                let sum_squares = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float.powi(2),
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                let standard_deviation = ((sum_squares - sum.powi(2)) / (in_values.len() as f64)).sqrt();
                vec![vec![Float(standard_deviation)]]
            },
            (Empty, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                vec![vec![Bool(in_values.len() == 0)]]
            },
            _ => panic!("Wrong number of arguments while calling: {:?} {:?}", self, arguments),
        }
    }

    pub fn from_str(string: &str) -> Self {
        match string {
            "<" => Primitive::LT,
            "<=" => Primitive::LTE,
            "!=" => Primitive::NEQ,
            "add" => Primitive::Add,
            "subtract" => Primitive::Subtract,
            "multiply" => Primitive::Multiply,
            "remainder" => Primitive::Remainder,
            "round" => Primitive::Round,
            "contains" => Primitive::Contains,
            "split" => Primitive::Split,
            "concat" => Primitive::Concat,
            "parse float" => Primitive::ParseFloat,
            "count" => Primitive::Count,
            "sum" => Primitive::Sum,
            "mean" => Primitive::Mean,
            "standard deviation" => Primitive::StandardDeviation,
            "empty" => Primitive::Empty,
            _ => panic!("Unknown primitive: {:?}", string),
        }
    }
}

pub fn primitives() -> Vec<(&'static str, Vec<&'static str>, Vec<&'static str>, Vec<&'static str>)> {
    vec![
        ("<", vec!["in A", "in B"], vec![], vec![]),
        ("<=", vec!["in A", "in B"], vec![], vec![]),
        ("!=", vec!["in A", "in B"], vec![], vec![]),
        ("add", vec!["in A", "in B"], vec![], vec!["out"]),
        ("subtract", vec!["in A", "in B"], vec![], vec!["out"]),
        ("multiply", vec!["in A", "in B"], vec![], vec!["out"]),
        ("remainder", vec!["in A", "in B"], vec![], vec!["out"]),
        ("round", vec!["in A", "in B"], vec![], vec!["out"]),
        ("contains", vec!["inner", "outer"], vec![], vec!["out"]),
        ("split", vec!["split", "string"], vec![], vec!["ix", "segment"]),
        ("concat", vec!["a", "b"], vec![], vec!["out"]),
        ("parse float", vec!["a"], vec![], vec!["out", "valid"]),
        ("count", vec![], vec!["in"], vec!["out"]),
        ("sum", vec![], vec!["in"], vec!["out"]),
        ("mean", vec![], vec!["in"], vec!["out"]),
        ("standard deviation", vec![], vec!["in"], vec!["out"]),
        ("empty", vec![], vec!["in"], vec!["out"]),
    ]
}
<commit_msg>Disable empty, since it no longer makes sense<commit_after>use value::{Value};
use std::str::FromStr;
use std::f64;

#[derive(Clone, Debug, Copy)]
pub enum Primitive {
    LT,
    LTE,
    NEQ,
    Add,
    Subtract,
    Multiply,
    Remainder,
    Round,
    Split,
    Concat,
    ParseFloat,
    Count,
    Contains,
    Sum,
    Mean,
    StandardDeviation,
    Empty,
}

pub fn resolve_as_scalar<'a>(mut ix: usize, constants: &'a [Value], outer: &'a [Value]) -> &'a Value {
    if ix < constants.len() {
        return &constants[ix];
    } else {
        ix = ix - constants.len()
    }
    return &outer[ix];
}

pub fn resolve_as_vector<'a>(mut ix: usize, constants: &'a [Value], outer: &'a [Value], inner: &'a [Vec<Value>]) -> Vec<&'a Value> {
    if ix < constants.len() {
        return vec![&constants[ix]; inner.len()];
    } else {
        ix = ix - constants.len()
    }
    if ix < outer.len() {
        return vec![&outer[ix]; inner.len()];
    } else {
        ix = ix - outer.len()
    }
    return inner.iter().map(|values| &values[ix]).collect();
}

impl Primitive {
    pub fn eval_from_join<'a>(&self, input_bindings: &[(usize, usize)], inputs: &[Value]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        let values = input_bindings.iter().enumerate().map(|(ix, &(field_ix, variable_ix))| {
            assert_eq!(ix, field_ix);
            &inputs[variable_ix]
        }).collect::<Vec<_>>();
        match (*self, &values[..]) {
            // NOTE be aware that arguments will be in alphabetical order by field id
            (LT, [ref a, ref b]) => if a < b {vec![vec![]]} else {vec![]},
            (LTE, [ref a, ref b]) => if a <= b {vec![vec![]]} else {vec![]},
            (NEQ, [ref a, ref b]) => if a != b {vec![vec![]]} else {vec![]},
            (Add, [&Float(a), &Float(b)]) => vec![vec![Float(a+b)]],
            (Subtract, [&Float(a), &Float(b)]) => vec![vec![Float(a-b)]],
            (Multiply, [&Float(a), &Float(b)]) => vec![vec![Float(a*b)]],
            (Remainder, [&Float(a), &Float(b)]) => vec![vec![Float(a%b)]], // akin to C-like languages, the % operator is remainder,
            (Round, [&Float(a), &Float(b)]) => vec![vec![Float((a*10f64.powf(b)).round()/10f64.powf(b))]],
            (Contains, [&String(ref inner), &String(ref outer)]) => {
              let inner_lower = &inner.to_lowercase();
              let outer_lower = &outer.to_lowercase();
              vec![vec![Bool(outer_lower.contains(inner_lower))]]
            },
            (Split, [&String(ref split), &String(ref string)]) => {
                string.split(split).enumerate().map(|(ix, segment)| vec![Float(ix as f64), String(segment.to_owned())]).collect()
            },
            (Concat, [&String(ref a), &String(ref b)]) => vec![vec![String(a.to_owned() + b)]],
            (Concat, [&String(ref a), &Float(ref b)]) => vec![vec![String(a.to_owned() + &format!("{}", b))]],
            (Concat, [&Float(ref a), &String(ref b)]) => vec![vec![String(format!("{}", a) + b)]],
            (ParseFloat, [&String(ref a)]) => {
                match f64::from_str(&a) {
                    Ok(v) => vec![vec![Float(v), Bool(true)]],
                    _ => vec![vec![Float(f64::MAX), Bool(false)]]
                }
            },
            (Count, [&Column(ref column)]) => vec![vec![Float(column.len() as f64)]],
            (Sum, [&Column(ref column)]) => {
                let sum = column.iter().fold(0f64, |sum, value|
                    match *value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, column),
                    });
                vec![vec![Float(sum)]]
            }
            (Mean, [&Column(ref column)]) => {
                let sum = column.iter().fold(0f64, |sum, value|
                    match *value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, column),
                    });
                let mean = sum / (column.len() as f64);
                vec![vec![Float(mean)]]
            },
            (StandardDeviation, [&Column(ref column)]) => {
                let sum = column.iter().fold(0f64, |sum, value|
                    match *value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, column),
                    });
                let sum_squares = column.iter().fold(0f64, |sum, value|
                    match *value {
                        Float(float) => sum + float.powi(2),
                        _ => panic!("Type error while calling: {:?} {:?}", self, column),
                    });
                let standard_deviation = ((sum_squares - sum.powi(2)) / (column.len() as f64)).sqrt();
                vec![vec![Float(standard_deviation)]]
            }
            (Empty, _) => vec![vec![Bool(false)]], // TODO empty doesn't make sense with non-outer joins
            _ => panic!("Type error while calling: {:?} {:?}", self, values)
        }
    }

    pub fn eval_from_aggregate<'a>(&self, arguments: &[usize], constants: &[Value], outer: &[Value], inner: &[Vec<Value>]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        match (*self, arguments) {
            // NOTE be aware that arguments will be in alphabetical order by field id
            (LT, _) => panic!("Cannot use {:?} in an aggregate", self),
            (LTE, _) => panic!("Cannot use {:?} in an aggregate", self),
            (NEQ, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Add, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Subtract, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Multiply, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Remainder, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Round, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Contains, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Split, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Concat, _) => panic!("Cannot use {:?} in an aggregate", self),
            (ParseFloat, _) => panic!("Cannot use {:?} in an aggregate", self),
            (Count, [_]) => {
                vec![vec![Float(inner.len() as f64)]]
            },
            (Sum, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                vec![vec![Float(sum)]]
            },
            (Mean, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                let mean = sum / (in_values.len() as f64);
                vec![vec![Float(mean)]]
            },
            (StandardDeviation, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                let sum = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float,
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                let sum_squares = in_values.iter().fold(0f64, |sum, value|
                    match **value {
                        Float(float) => sum + float.powi(2),
                        _ => panic!("Type error while calling: {:?} {:?}", self, in_values),
                    });
                let standard_deviation = ((sum_squares - sum.powi(2)) / (in_values.len() as f64)).sqrt();
                vec![vec![Float(standard_deviation)]]
            },
            (Empty, [in_ix]) => {
                let in_values = resolve_as_vector(in_ix, constants, outer, inner);
                vec![vec![Bool(in_values.len() == 0)]]
            },
            _ => panic!("Wrong number of arguments while calling: {:?} {:?}", self, arguments),
        }
    }

    pub fn from_str(string: &str) -> Self {
        match string {
            "<" => Primitive::LT,
            "<=" => Primitive::LTE,
            "!=" => Primitive::NEQ,
            "add" => Primitive::Add,
            "subtract" => Primitive::Subtract,
            "multiply" => Primitive::Multiply,
            "remainder" => Primitive::Remainder,
            "round" => Primitive::Round,
            "contains" => Primitive::Contains,
            "split" => Primitive::Split,
            "concat" => Primitive::Concat,
            "parse float" => Primitive::ParseFloat,
            "count" => Primitive::Count,
            "sum" => Primitive::Sum,
            "mean" => Primitive::Mean,
            "standard deviation" => Primitive::StandardDeviation,
            "empty" => Primitive::Empty,
            _ => panic!("Unknown primitive: {:?}", string),
        }
    }
}

pub fn primitives() -> Vec<(&'static str, Vec<&'static str>, Vec<&'static str>, Vec<&'static str>)> {
    vec![
        ("<", vec!["in A", "in B"], vec![], vec![]),
        ("<=", vec!["in A", "in B"], vec![], vec![]),
        ("!=", vec!["in A", "in B"], vec![], vec![]),
        ("add", vec!["in A", "in B"], vec![], vec!["out"]),
        ("subtract", vec!["in A", "in B"], vec![], vec!["out"]),
        ("multiply", vec!["in A", "in B"], vec![], vec!["out"]),
        ("remainder", vec!["in A", "in B"], vec![], vec!["out"]),
        ("round", vec!["in A", "in B"], vec![], vec!["out"]),
        ("contains", vec!["inner", "outer"], vec![], vec!["out"]),
        ("split", vec!["split", "string"], vec![], vec!["ix", "segment"]),
        ("concat", vec!["a", "b"], vec![], vec!["out"]),
        ("parse float", vec!["a"], vec![], vec!["out", "valid"]),
        ("count", vec![], vec!["in"], vec!["out"]),
        ("sum", vec![], vec!["in"], vec!["out"]),
        ("mean", vec![], vec!["in"], vec!["out"]),
        ("standard deviation", vec![], vec!["in"], vec!["out"]),
        ("empty", vec![], vec!["in"], vec!["out"]),
    ]
}
<|endoftext|>