<commit_before>//! A batteries included runtime for applications using Tokio.
//!
//! Applications using Tokio require some runtime support in order to work:
//!
//! * A [reactor] to drive I/O resources.
//! * An [executor] to execute tasks that use these I/O resources.
//!
//! While it is possible to setup each component manually, this involves a bunch
//! of boilerplate.
//!
//! [`Runtime`] bundles all of these various runtime components into a single
//! handle that can be started and shutdown together, eliminating the necessary
//! boilerplate to run a Tokio application.
//!
//! Most applications wont need to use [`Runtime`] directly. Instead, they will
//! use the [`run`] function, which uses [`Runtime`] under the hood.
//!
//! Creating a [`Runtime`] does the following:
//!
//! * Spawn a background thread running a [`Reactor`] instance.
//! * Start a [`ThreadPool`] for executing futures.
//!
//! The thread pool uses a work-stealing strategy and is configured to start a
//! worker thread for each CPU core available on the system. This tends to be
//! the ideal setup for Tokio applications.
//!
//! # Usage
//!
//! Most applications will use the [`run`] function. This takes a future to
//! "seed" the application, blocking the thread until the runtime becomes
//! [idle].
//!
//! ```rust
//! # extern crate tokio;
//! # extern crate futures;
//! # use futures::{Future, Stream};
//! use tokio::net::TcpListener;
//!
//! # fn process<T>(_: T) -> Box<Future<Item = (), Error = ()> + Send> {
//! # unimplemented!();
//! # }
//! # fn dox() {
//! # let addr = "127.0.0.1:8080".parse().unwrap();
//! let listener = TcpListener::bind(&addr).unwrap();
//!
//! let server = listener.incoming()
//!     .map_err(|e| println!("error = {:?}", e))
//!     .for_each(|socket| {
//!         tokio::spawn(process(socket))
//!     });
//!
//! tokio::run(server);
//! # }
//! # pub fn main() {}
//! ```
//!
//! In this function, the `run` function blocks until the runtime becomes idle.
//! See [`shutdown_on_idle`][idle] for more shutdown details.
//!
//! From within the context of the runtime, additional tasks are spawned using
//! the [`tokio::spawn`] function. Futures spawned using this function will be
//! executed on the same thread pool used by the [`Runtime`].
//!
//! A [`Runtime`] instance can also be used directly.
//!
//! ```rust
//! # extern crate tokio;
//! # extern crate futures;
//! # use futures::{Future, Stream};
//! use tokio::runtime::Runtime;
//! use tokio::net::TcpListener;
//!
//! # fn process<T>(_: T) -> Box<Future<Item = (), Error = ()> + Send> {
//! # unimplemented!();
//! # }
//! # fn dox() {
//! # let addr = "127.0.0.1:8080".parse().unwrap();
//! let listener = TcpListener::bind(&addr).unwrap();
//!
//! let server = listener.incoming()
//!     .map_err(|e| println!("error = {:?}", e))
//!     .for_each(|socket| {
//!         tokio::spawn(process(socket))
//!     });
//!
//! // Create the runtime
//! let mut rt = Runtime::new().unwrap();
//!
//! // Spawn the server task
//! rt.spawn(server);
//!
//! // Wait until the runtime becomes idle and shut it down.
//! rt.shutdown_on_idle()
//!     .wait().unwrap();
//! # }
//! # pub fn main() {}
//! ```
//!
//! [reactor]: ../reactor/struct.Reactor.html
//! [executor]: https://tokio.rs/docs/getting-started/runtime-model/#executors
//! [`Runtime`]: struct.Runtime.html
//! [`ThreadPool`]: ../executor/thread_pool/struct.ThreadPool.html
//! [`run`]: fn.run.html
//! [idle]: struct.Runtime.html#method.shutdown_on_idle
//! [`tokio::spawn`]: ../executor/fn.spawn.html

use reactor::{Reactor, Handle, Background};

use tokio_threadpool::{self as threadpool, ThreadPool, Sender};
use futures::Poll;
use futures::future::{self, Future};

use std::{fmt, io};

/// Handle to the Tokio runtime.
///
/// The Tokio runtime includes a reactor as well as an executor for running
/// tasks.
///
/// See [module level][mod] documentation for more details.
///
/// [mod]: index.html
#[derive(Debug)]
pub struct Runtime {
    inner: Option<Inner>,
}

/// Executes futures on the runtime
///
/// All futures spawned using this executor will be submitted to the associated
/// Runtime's executor. This executor is usually a thread pool.
///
/// For more details, see the [module level](index.html) documentation.
#[derive(Debug, Clone)]
pub struct TaskExecutor {
    inner: Sender,
}

/// A future that resolves when the Tokio `Runtime` is shut down.
pub struct Shutdown {
    inner: Box<Future<Item = (), Error = ()> + Send>,
}

#[derive(Debug)]
struct Inner {
    /// Reactor running on a background thread.
    reactor: Background,

    /// Task execution pool.
    pool: ThreadPool,
}

// ===== impl Runtime =====

/// Start the Tokio runtime using the supplied future to bootstrap execution.
///
/// This function is used to bootstrap the execution of a Tokio application. It
/// does the following:
///
/// * Start the Tokio runtime using a default configuration.
/// * Spawn the given future onto the thread pool.
/// * Block the çurrent thread until the runtime shuts down.
///
/// Note that the function will not return immediately once `future` has
/// completed. Instead it waits for the entire runtime to become idle.
///
/// See [module level][mod] documentation for more details.
///
/// # Examples
///
/// ```rust
/// # extern crate tokio;
/// # extern crate futures;
/// # use futures::{Future, Stream};
/// use tokio::net::TcpListener;
///
/// # fn process<T>(_: T) -> Box<Future<Item = (), Error = ()> + Send> {
/// # unimplemented!();
/// # }
/// # fn dox() {
/// # let addr = "127.0.0.1:8080".parse().unwrap();
/// let listener = TcpListener::bind(&addr).unwrap();
///
/// let server = listener.incoming()
///     .map_err(|e| println!("error = {:?}", e))
///     .for_each(|socket| {
///         tokio::spawn(process(socket))
///     });
///
/// tokio::run(server);
/// # }
/// # pub fn main() {}
/// ```
///
/// # Panics
///
/// This function panics if called from the context of an executor.
///
/// [mod]: ../index.html
pub fn run<F>(future: F)
where F: Future<Item = (), Error = ()> + Send + 'static,
{
    let mut runtime = Runtime::new().unwrap();
    runtime.spawn(future);
    runtime.shutdown_on_idle().wait().unwrap();
}

impl Runtime {
    /// Create a new runtime instance with default configuration values.
    ///
    /// See [module level][mod] documentation for more details.
    ///
    /// [mod]: index.html
    pub fn new() -> io::Result<Self> {
        // Spawn a reactor on a background thread.
        let reactor = Reactor::new()?.background()?;

        // Get a handle to the reactor.
        let handle = reactor.handle().clone();

        let pool = threadpool::Builder::new()
            .around_worker(move |w, enter| {
                ::tokio_reactor::with_default(&handle, enter, |_| {
                    w.run();
                });
            })
            .build();

        Ok(Runtime {
            inner: Some(Inner {
                reactor,
                pool,
            }),
        })
    }

    /// Return a reference to the reactor handle for this runtime instance.
    pub fn handle(&self) -> &Handle {
        self.inner().reactor.handle()
    }

    /// Return a handle to the runtime's executor.
    pub fn executor(&self) -> TaskExecutor {
        let inner = self.inner().pool.sender().clone();
        TaskExecutor { inner }
    }

    /// Spawn a future onto the Tokio runtime.
    ///
    /// This spawns the given future onto the runtime's executor, usually a
    /// thread pool. The thread pool is then responsible for polling the future
    /// until it completes.
    ///
    /// See [module level][mod] documentation for more details.
    ///
    /// [mod]: index.html
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate tokio;
    /// # extern crate futures;
    /// # use futures::{future, Future, Stream};
    /// use tokio::runtime::Runtime;
    ///
    /// # fn dox() {
    /// // Create the runtime
    /// let mut rt = Runtime::new().unwrap();
    ///
    /// // Spawn a future onto the runtime
    /// rt.spawn(future::lazy(|| {
    ///     println!("now running on a worker thread");
    ///     Ok(())
    /// }));
    /// # }
    /// # pub fn main() {}
    /// ```
    ///
    /// # Panics
    ///
    /// This function panics if the spawn fails. Failure occurs if the executor
    /// is currently at capacity and is unable to spawn a new future.
    pub fn spawn<F>(&mut self, future: F) -> &mut Self
    where F: Future<Item = (), Error = ()> + Send + 'static,
    {
        self.inner_mut().pool.sender().spawn(future).unwrap();
        self
    }

    /// Signals the runtime to shutdown once it becomes idle.
    ///
    /// Returns a future that completes once the shutdown operation has
    /// completed.
    ///
    /// This function can be used to perform a graceful shutdown of the runtime.
    ///
    /// The runtime enters an idle state once **all** of the following occur.
    ///
    /// * The thread pool has no tasks to execute, i.e., all tasks that were
    ///   spawned have completed.
    /// * The reactor is not managing any I/O resources.
    ///
    /// See [module level][mod] documentation for more details.
    ///
    /// [mod]: index.html
    pub fn shutdown_on_idle(mut self) -> Shutdown {
        let inner = self.inner.take().unwrap();

        let inner = Box::new({
            let pool = inner.pool;
            let reactor = inner.reactor;

            pool.shutdown_on_idle().and_then(|_| {
                reactor.shutdown_on_idle()
            })
        });

        Shutdown { inner }
    }

    /// Signals the runtime to shutdown immediately.
    ///
    /// Returns a future that completes once the shutdown operation has
    /// completed.
    ///
    /// This function will forcibly shutdown the runtime, causing any
    /// in-progress work to become canceled. The shutdown steps are:
    ///
    /// * Drain any scheduled work queues.
    /// * Drop any futures that have not yet completed.
    /// * Drop the reactor.
    ///
    /// Once the reactor has dropped, any outstanding I/O resources bound to
    /// that reactor will no longer function. Calling any method on them will
    /// result in an error.
    ///
    /// See [module level][mod] documentation for more details.
    ///
    /// [mod]: index.html
    pub fn shutdown_now(mut self) -> Shutdown {
        let inner = self.inner.take().unwrap();

        let inner = Box::new({
            let pool = inner.pool;
            let reactor = inner.reactor;

            pool.shutdown_now().and_then(|_| {
                reactor.shutdown_now()
            })
        });

        Shutdown { inner }
    }

    fn inner(&self) -> &Inner {
        self.inner.as_ref().unwrap()
    }

    fn inner_mut(&mut self) -> &mut Inner {
        self.inner.as_mut().unwrap()
    }
}

// ===== impl TaskExecutor =====

impl<T> future::Executor<T> for TaskExecutor
where T: Future<Item = (), Error = ()> + Send + 'static,
{
    fn execute(&self, future: T) -> Result<(), future::ExecuteError<T>> {
        self.inner.execute(future)
    }
}

impl ::executor::Executor for TaskExecutor {
    fn spawn(&mut self, future: Box<Future<Item = (), Error = ()> + Send>)
        -> Result<(), ::executor::SpawnError>
    {
        self.inner.spawn(future)
    }
}

// ===== impl Shutdown =====

impl Future for Shutdown {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        try_ready!(self.inner.poll());
        Ok(().into())
    }
}

impl fmt::Debug for Shutdown {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Shutdown")
            .field("inner", &"Box<Future<Item = (), Error = ()>>")
            .finish()
    }
}
<commit_msg>Remove premature French translation of "current" (#197)<commit_after>//! A batteries included runtime for applications using Tokio.
//!
//! Applications using Tokio require some runtime support in order to work:
//!
//! * A [reactor] to drive I/O resources.
//! * An [executor] to execute tasks that use these I/O resources.
//!
//! While it is possible to setup each component manually, this involves a bunch
//! of boilerplate.
//!
//! [`Runtime`] bundles all of these various runtime components into a single
//! handle that can be started and shutdown together, eliminating the necessary
//! boilerplate to run a Tokio application.
//!
//! Most applications wont need to use [`Runtime`] directly. Instead, they will
//! use the [`run`] function, which uses [`Runtime`] under the hood.
//!
//! Creating a [`Runtime`] does the following:
//!
//! * Spawn a background thread running a [`Reactor`] instance.
//! * Start a [`ThreadPool`] for executing futures.
//!
//! The thread pool uses a work-stealing strategy and is configured to start a
//! worker thread for each CPU core available on the system. This tends to be
//! the ideal setup for Tokio applications.
//!
//! # Usage
//!
//! Most applications will use the [`run`] function. This takes a future to
//! "seed" the application, blocking the thread until the runtime becomes
//! [idle].
//!
//! ```rust
//! # extern crate tokio;
//! # extern crate futures;
//! # use futures::{Future, Stream};
//! use tokio::net::TcpListener;
//!
//! # fn process<T>(_: T) -> Box<Future<Item = (), Error = ()> + Send> {
//! # unimplemented!();
//! # }
//! # fn dox() {
//! # let addr = "127.0.0.1:8080".parse().unwrap();
//! let listener = TcpListener::bind(&addr).unwrap();
//!
//! let server = listener.incoming()
//!     .map_err(|e| println!("error = {:?}", e))
//!     .for_each(|socket| {
//!         tokio::spawn(process(socket))
//!     });
//!
//! tokio::run(server);
//! # }
//! # pub fn main() {}
//! ```
//!
//! In this function, the `run` function blocks until the runtime becomes idle.
//! See [`shutdown_on_idle`][idle] for more shutdown details.
//!
//! From within the context of the runtime, additional tasks are spawned using
//! the [`tokio::spawn`] function. Futures spawned using this function will be
//! executed on the same thread pool used by the [`Runtime`].
//!
//! A [`Runtime`] instance can also be used directly.
//!
//! ```rust
//! # extern crate tokio;
//! # extern crate futures;
//! # use futures::{Future, Stream};
//! use tokio::runtime::Runtime;
//! use tokio::net::TcpListener;
//!
//! # fn process<T>(_: T) -> Box<Future<Item = (), Error = ()> + Send> {
//! # unimplemented!();
//! # }
//! # fn dox() {
//! # let addr = "127.0.0.1:8080".parse().unwrap();
//! let listener = TcpListener::bind(&addr).unwrap();
//!
//! let server = listener.incoming()
//!     .map_err(|e| println!("error = {:?}", e))
//!     .for_each(|socket| {
//!         tokio::spawn(process(socket))
//!     });
//!
//! // Create the runtime
//! let mut rt = Runtime::new().unwrap();
//!
//! // Spawn the server task
//! rt.spawn(server);
//!
//! // Wait until the runtime becomes idle and shut it down.
//! rt.shutdown_on_idle()
//!     .wait().unwrap();
//! # }
//! # pub fn main() {}
//! ```
//!
//! [reactor]: ../reactor/struct.Reactor.html
//! [executor]: https://tokio.rs/docs/getting-started/runtime-model/#executors
//! [`Runtime`]: struct.Runtime.html
//! [`ThreadPool`]: ../executor/thread_pool/struct.ThreadPool.html
//! [`run`]: fn.run.html
//! [idle]: struct.Runtime.html#method.shutdown_on_idle
//! [`tokio::spawn`]: ../executor/fn.spawn.html

use reactor::{Reactor, Handle, Background};

use tokio_threadpool::{self as threadpool, ThreadPool, Sender};
use futures::Poll;
use futures::future::{self, Future};

use std::{fmt, io};

/// Handle to the Tokio runtime.
///
/// The Tokio runtime includes a reactor as well as an executor for running
/// tasks.
///
/// See [module level][mod] documentation for more details.
///
/// [mod]: index.html
#[derive(Debug)]
pub struct Runtime {
    inner: Option<Inner>,
}

/// Executes futures on the runtime
///
/// All futures spawned using this executor will be submitted to the associated
/// Runtime's executor. This executor is usually a thread pool.
///
/// For more details, see the [module level](index.html) documentation.
#[derive(Debug, Clone)]
pub struct TaskExecutor {
    inner: Sender,
}

/// A future that resolves when the Tokio `Runtime` is shut down.
pub struct Shutdown {
    inner: Box<Future<Item = (), Error = ()> + Send>,
}

#[derive(Debug)]
struct Inner {
    /// Reactor running on a background thread.
    reactor: Background,

    /// Task execution pool.
    pool: ThreadPool,
}

// ===== impl Runtime =====

/// Start the Tokio runtime using the supplied future to bootstrap execution.
///
/// This function is used to bootstrap the execution of a Tokio application. It
/// does the following:
///
/// * Start the Tokio runtime using a default configuration.
/// * Spawn the given future onto the thread pool.
/// * Block the current thread until the runtime shuts down.
///
/// Note that the function will not return immediately once `future` has
/// completed. Instead it waits for the entire runtime to become idle.
///
/// See the [module level][mod] documentation for more details.
///
/// # Examples
///
/// ```rust
/// # extern crate tokio;
/// # extern crate futures;
/// # use futures::{Future, Stream};
/// use tokio::net::TcpListener;
///
/// # fn process<T>(_: T) -> Box<Future<Item = (), Error = ()> + Send> {
/// # unimplemented!();
/// # }
/// # fn dox() {
/// # let addr = "127.0.0.1:8080".parse().unwrap();
/// let listener = TcpListener::bind(&addr).unwrap();
///
/// let server = listener.incoming()
///     .map_err(|e| println!("error = {:?}", e))
///     .for_each(|socket| {
///         tokio::spawn(process(socket))
///     });
///
/// tokio::run(server);
/// # }
/// # pub fn main() {}
/// ```
///
/// # Panics
///
/// This function panics if called from the context of an executor.
///
/// [mod]: ../index.html
pub fn run<F>(future: F)
where F: Future<Item = (), Error = ()> + Send + 'static,
{
    let mut runtime = Runtime::new().unwrap();
    runtime.spawn(future);
    runtime.shutdown_on_idle().wait().unwrap();
}

impl Runtime {
    /// Create a new runtime instance with default configuration values.
    ///
    /// See [module level][mod] documentation for more details.
    ///
    /// [mod]: index.html
    pub fn new() -> io::Result<Self> {
        // Spawn a reactor on a background thread.
        let reactor = Reactor::new()?.background()?;

        // Get a handle to the reactor.
        let handle = reactor.handle().clone();

        let pool = threadpool::Builder::new()
            .around_worker(move |w, enter| {
                ::tokio_reactor::with_default(&handle, enter, |_| {
                    w.run();
                });
            })
            .build();

        Ok(Runtime {
            inner: Some(Inner {
                reactor,
                pool,
            }),
        })
    }

    /// Return a reference to the reactor handle for this runtime instance.
    pub fn handle(&self) -> &Handle {
        self.inner().reactor.handle()
    }

    /// Return a handle to the runtime's executor.
    pub fn executor(&self) -> TaskExecutor {
        let inner = self.inner().pool.sender().clone();
        TaskExecutor { inner }
    }

    /// Spawn a future onto the Tokio runtime.
    ///
    /// This spawns the given future onto the runtime's executor, usually a
    /// thread pool. The thread pool is then responsible for polling the future
    /// until it completes.
    ///
    /// See [module level][mod] documentation for more details.
    ///
    /// [mod]: index.html
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate tokio;
    /// # extern crate futures;
    /// # use futures::{future, Future, Stream};
    /// use tokio::runtime::Runtime;
    ///
    /// # fn dox() {
    /// // Create the runtime
    /// let mut rt = Runtime::new().unwrap();
    ///
    /// // Spawn a future onto the runtime
    /// rt.spawn(future::lazy(|| {
    ///     println!("now running on a worker thread");
    ///     Ok(())
    /// }));
    /// # }
    /// # pub fn main() {}
    /// ```
    ///
    /// # Panics
    ///
    /// This function panics if the spawn fails. Failure occurs if the executor
    /// is currently at capacity and is unable to spawn a new future.
    pub fn spawn<F>(&mut self, future: F) -> &mut Self
    where F: Future<Item = (), Error = ()> + Send + 'static,
    {
        self.inner_mut().pool.sender().spawn(future).unwrap();
        self
    }

    /// Signals the runtime to shutdown once it becomes idle.
    ///
    /// Returns a future that completes once the shutdown operation has
    /// completed.
    ///
    /// This function can be used to perform a graceful shutdown of the runtime.
    ///
    /// The runtime enters an idle state once **all** of the following occur.
    ///
    /// * The thread pool has no tasks to execute, i.e., all tasks that were
    ///   spawned have completed.
    /// * The reactor is not managing any I/O resources.
    ///
    /// See [module level][mod] documentation for more details.
    ///
    /// [mod]: index.html
    pub fn shutdown_on_idle(mut self) -> Shutdown {
        let inner = self.inner.take().unwrap();

        let inner = Box::new({
            let pool = inner.pool;
            let reactor = inner.reactor;

            pool.shutdown_on_idle().and_then(|_| {
                reactor.shutdown_on_idle()
            })
        });

        Shutdown { inner }
    }

    /// Signals the runtime to shutdown immediately.
    ///
    /// Returns a future that completes once the shutdown operation has
    /// completed.
    ///
    /// This function will forcibly shutdown the runtime, causing any
    /// in-progress work to become canceled. The shutdown steps are:
    ///
    /// * Drain any scheduled work queues.
    /// * Drop any futures that have not yet completed.
    /// * Drop the reactor.
    ///
    /// Once the reactor has dropped, any outstanding I/O resources bound to
    /// that reactor will no longer function. Calling any method on them will
    /// result in an error.
    ///
    /// See [module level][mod] documentation for more details.
    ///
    /// [mod]: index.html
    pub fn shutdown_now(mut self) -> Shutdown {
        let inner = self.inner.take().unwrap();

        let inner = Box::new({
            let pool = inner.pool;
            let reactor = inner.reactor;

            pool.shutdown_now().and_then(|_| {
                reactor.shutdown_now()
            })
        });

        Shutdown { inner }
    }

    fn inner(&self) -> &Inner {
        self.inner.as_ref().unwrap()
    }

    fn inner_mut(&mut self) -> &mut Inner {
        self.inner.as_mut().unwrap()
    }
}

// ===== impl TaskExecutor =====

impl<T> future::Executor<T> for TaskExecutor
where T: Future<Item = (), Error = ()> + Send + 'static,
{
    fn execute(&self, future: T) -> Result<(), future::ExecuteError<T>> {
        self.inner.execute(future)
    }
}

impl ::executor::Executor for TaskExecutor {
    fn spawn(&mut self, future: Box<Future<Item = (), Error = ()> + Send>)
        -> Result<(), ::executor::SpawnError>
    {
        self.inner.spawn(future)
    }
}

// ===== impl Shutdown =====

impl Future for Shutdown {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        try_ready!(self.inner.poll());
        Ok(().into())
    }
}

impl fmt::Debug for Shutdown {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Shutdown")
            .field("inner", &"Box<Future<Item = (), Error = ()>>")
            .finish()
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::sync::{Arc, Mutex};
use std::sync::atomic::AtomicUsize;

use futures::{future, Future, BoxFuture, Stream};
use tokio_proto::streaming::{Message, Body};
use tokio_service::Service;

use bytes::{BufMut, BytesMut};

use admin;
use codec::PacketHeader;
use packet::PacketMagic;
use queues::SharedJobStorage;
use worker::{SharedWorkers, Worker, Wake};
use constants::*;

pub type GearmanBody = Body<BytesMut, io::Error>;
pub type GearmanMessage = Message<PacketHeader, GearmanBody>;

pub struct GearmanService {
    pub conn_id: usize,
    pub queues: SharedJobStorage,
    pub workers: SharedWorkers,
    pub worker: Arc<Mutex<Worker>>,
    pub job_count: Arc<Mutex<AtomicUsize>>,
}

impl GearmanService {
    /// Things that don't require a body should use this
    fn response_from_header(&self,
                            header: &PacketHeader)
                            -> Message<PacketHeader, Body<BytesMut, io::Error>> {
        match header.ptype {
            ADMIN_VERSION => {
                let resp_str = "OK some-rustygear-version\n";
                let mut resp_body = BytesMut::with_capacity(resp_str.len());
                resp_body.put(&resp_str[..]);
                let resp_body = Body::from(resp_body);
                Message::WithBody(PacketHeader {
                                      magic: PacketMagic::TEXT,
                                      ptype: header.ptype,
                                      psize: resp_str.len() as u32,
                                  },
                                  resp_body)
            }
            ADMIN_STATUS => admin::admin_command_status(self.queues.clone(), self.workers.clone()),
            _ => {
                panic!("response_from_header called with invalid ptype: {}",
                       header.ptype)
            }
        }
    }

    pub fn new(conn_id: usize,
               queues: SharedJobStorage,
               workers: SharedWorkers,
               job_count: Arc<Mutex<AtomicUsize>>)
               -> GearmanService {
        GearmanService {
            conn_id: conn_id,
            queues: queues.clone(),
            worker: Arc::new(Mutex::new((Worker::new()))),
            workers: workers.clone(),
            job_count: job_count.clone(),
        }
    }

    fn handle_can_do(&self, body: GearmanBody) -> BoxFuture<GearmanMessage, io::Error> {
        let worker = self.worker.clone();
        let workers = self.workers.clone();
        let conn_id = self.conn_id;
        body.for_each(move |chunk| {
                let fname = chunk.freeze();
                debug!("CAN_DO fname = {:?}", fname);
                let mut worker = worker.lock().unwrap();
                worker.can_do(fname);
                workers.clone().wakeup(&mut worker, conn_id);
                Ok(())
            })
            .and_then(|_| {
                future::finished(Message::WithBody(PacketHeader::noop(),
                                                   Body::from(BytesMut::new())))
            })
            .boxed()
    }
}

impl Service for GearmanService {
    type Request = GearmanMessage;
    type Response = GearmanMessage;
    type Error = io::Error;
    type Future = BoxFuture<Self::Response, Self::Error>;

    fn call(&self, req: Self::Request) -> Self::Future {
        debug!("Got a req {:?}", req);
        match req {
            Message::WithoutBody(header) => {
                match header.ptype {
                    ADMIN_VERSION | ADMIN_STATUS => {
                        future::ok(self.response_from_header(&header)).boxed()
                    }

                    _ => {
                        future::err(io::Error::new(io::ErrorKind::Other,
                                                   format!("Bodyless packet type = {}",
                                                           header.ptype)))
                            .boxed()
                    }
                }
            }
            Message::WithBody(header, body) => {
                match header.ptype {
                    /*
                    SUBMIT_JOB => self.handle_submit_job(PRIORITY_NORMAL, false),
                    SUBMIT_JOB_HIGH => self.handle_submit_job(PRIORITY_HIGH, false),
                    SUBMIT_JOB_LOW => self.handle_submit_job(PRIORITY_LOW, false),
                    SUBMIT_JOB_BG => self.handle_submit_job(PRIORITY_NORMAL, true),
                    SUBMIT_JOB_HIGH_BG => self.handle_submit_job(PRIORITY_HIGH, true),
                    SUBMIT_JOB_LOW_BG => self.handle_submit_job(PRIORITY_LOW, true),
                    PRE_SLEEP => self.handle_pre_sleep(),
                    */
                    CAN_DO => self.handle_can_do(body),/*
                    CANT_DO => self.handle_cant_do(),
                    GRAB_JOB => self.handle_grab_job(),
                    GRAB_JOB_UNIQ => self.handle_grab_job_uniq(),
                    GRAB_JOB_ALL => self.handle_grab_job_all(),
                    WORK_COMPLETE => self.handle_work_complete(),
                    WORK_STATUS | WORK_DATA | WORK_WARNING => self.handle_work_update(),
                    ECHO_REQ => self.handle_echo_req(&req),*/
                    _ => {
                        error!("Unimplemented: {:?} processing packet", header);
                        future::err(io::Error::new(io::ErrorKind::Other,
                                                   format!("Invalid packet type {}", header.ptype)))
                            .boxed()
                    }
                }
            }
        }
    }
}
<commit_msg>Handle chunks properly<commit_after>use std::io;
use std::sync::{Arc, Mutex};
use std::sync::atomic::AtomicUsize;

use futures::{future, Future, BoxFuture, Stream};
use tokio_proto::streaming::{Message, Body};
use tokio_service::Service;

use bytes::{BufMut, BytesMut};

use admin;
use codec::PacketHeader;
use packet::PacketMagic;
use queues::SharedJobStorage;
use worker::{SharedWorkers, Worker, Wake};
use constants::*;

pub type GearmanBody = Body<BytesMut, io::Error>;
pub type GearmanMessage = Message<PacketHeader, GearmanBody>;

pub struct GearmanService {
    pub conn_id: usize,
    pub queues: SharedJobStorage,
    pub workers: SharedWorkers,
    pub worker: Arc<Mutex<Worker>>,
    pub job_count: Arc<Mutex<AtomicUsize>>,
}

impl GearmanService {
    /// Things that don't require a body should use this
    fn response_from_header(&self,
                            header: &PacketHeader)
                            -> Message<PacketHeader, Body<BytesMut, io::Error>> {
        match header.ptype {
            ADMIN_VERSION => {
                let resp_str = "OK some-rustygear-version\n";
                let mut resp_body = BytesMut::with_capacity(resp_str.len());
                resp_body.put(&resp_str[..]);
                let resp_body = Body::from(resp_body);
                Message::WithBody(PacketHeader {
                                      magic: PacketMagic::TEXT,
                                      ptype: header.ptype,
                                      psize: resp_str.len() as u32,
                                  },
                                  resp_body)
            }
            ADMIN_STATUS => admin::admin_command_status(self.queues.clone(), self.workers.clone()),
            _ => {
                panic!("response_from_header called with invalid ptype: {}",
                       header.ptype)
            }
        }
    }

    pub fn new(conn_id: usize,
               queues: SharedJobStorage,
               workers: SharedWorkers,
               job_count: Arc<Mutex<AtomicUsize>>)
               -> GearmanService {
        GearmanService {
            conn_id: conn_id,
            queues: queues.clone(),
            worker: Arc::new(Mutex::new((Worker::new()))),
            workers: workers.clone(),
            job_count: job_count.clone(),
        }
    }

    fn handle_can_do(&self, body: GearmanBody) -> BoxFuture<GearmanMessage, io::Error> {
        let worker = self.worker.clone();
        let workers = self.workers.clone();
        let conn_id = self.conn_id;
        body.concat2()
            .and_then(
                move |fname| {
                    let fname = fname.freeze();
                    debug!("CAN_DO fname = {:?}", fname);
                    let mut worker = worker.lock().unwrap();
                    worker.can_do(fname);
                    workers.clone().wakeup(&mut worker, conn_id);
                    future::finished(Message::WithBody(PacketHeader::noop(),
                                                   Body::from(BytesMut::new())))
            })
            .boxed()
    }
}

impl Service for GearmanService {
    type Request = GearmanMessage;
    type Response = GearmanMessage;
    type Error = io::Error;
    type Future = BoxFuture<Self::Response, Self::Error>;

    fn call(&self, req: Self::Request) -> Self::Future {
        debug!("Got a req {:?}", req);
        match req {
            Message::WithoutBody(header) => {
                match header.ptype {
                    ADMIN_VERSION | ADMIN_STATUS => {
                        future::ok(self.response_from_header(&header)).boxed()
                    }

                    _ => {
                        future::err(io::Error::new(io::ErrorKind::Other,
                                                   format!("Bodyless packet type = {}",
                                                           header.ptype)))
                            .boxed()
                    }
                }
            }
            Message::WithBody(header, body) => {
                match header.ptype {
                    /*
                    SUBMIT_JOB => self.handle_submit_job(PRIORITY_NORMAL, false),
                    SUBMIT_JOB_HIGH => self.handle_submit_job(PRIORITY_HIGH, false),
                    SUBMIT_JOB_LOW => self.handle_submit_job(PRIORITY_LOW, false),
                    SUBMIT_JOB_BG => self.handle_submit_job(PRIORITY_NORMAL, true),
                    SUBMIT_JOB_HIGH_BG => self.handle_submit_job(PRIORITY_HIGH, true),
                    SUBMIT_JOB_LOW_BG => self.handle_submit_job(PRIORITY_LOW, true),
                    PRE_SLEEP => self.handle_pre_sleep(),
                    */
                    CAN_DO => self.handle_can_do(body),/*
                    CANT_DO => self.handle_cant_do(),
                    GRAB_JOB => self.handle_grab_job(),
                    GRAB_JOB_UNIQ => self.handle_grab_job_uniq(),
                    GRAB_JOB_ALL => self.handle_grab_job_all(),
                    WORK_COMPLETE => self.handle_work_complete(),
                    WORK_STATUS | WORK_DATA | WORK_WARNING => self.handle_work_update(),
                    ECHO_REQ => self.handle_echo_req(&req),*/
                    _ => {
                        error!("Unimplemented: {:?} processing packet", header);
                        future::err(io::Error::new(io::ErrorKind::Other,
                                                   format!("Invalid packet type {}", header.ptype)))
                            .boxed()
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 University of Glasgow
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::io::Result;
use std::net::SocketAddr;
use std::time::{Duration, Instant};

pub struct Inactive;
pub struct Active;
pub struct Leaving;

pub trait IoTimer {
  fn send_datagram(&self, buf : &[u8], addr : SocketAddr) -> Result<usize>;
  fn   start_timer(&self, id : u32, timeout : Duration);
  fn  cancel_timer(&self, id : u32);
}

pub struct Session<'a, State> {
    iotimer : &'a IoTimer,
    state   : State,
    ssrc    : u32
}

// ================================================================================================

impl <'a> Session<'a, Inactive> {
    pub fn new(iotimer : &'a IoTimer) -> Session<'a, Inactive> {
        unimplemented!();
    }

    pub fn join(self) -> Session<'a, Active> {
        unimplemented!();
    }
}

// ================================================================================================

impl <'a> Session<'a, Active> {
    pub fn leave(self) -> Session<'a, Leaving> {
        unimplemented!();
    }

    fn recv_datagram(&self, now : Instant, buf : &[u8], addr : SocketAddr) {
        unimplemented!();
    }

    fn timeout(&self, now : Instant, timer : u32) {
        unimplemented!();
    }
}

// ================================================================================================

impl <'a> Session<'a, Leaving> {
    fn recv_datagram(&self, now : Instant, buf : &[u8], addr : SocketAddr) {
        unimplemented!();
    }

    fn timeout(&self, now : Instant, timer : u32) {
        unimplemented!();
    }
}

// ================================================================================================
<commit_msg>Split IoTimer into SendDatagram and Timers traits<commit_after>// Copyright (c) 2016 University of Glasgow
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::io::Result;
use std::net::SocketAddr;
use std::time::{Duration, Instant};

pub struct Inactive;
pub struct Active;
pub struct Leaving;

pub trait SendDatagram {
  fn send_datagram(&self, buf : &[u8], addr : SocketAddr) -> Result<usize>;
}

pub trait Timers {
  fn   start(&self, id : u32, timeout : Duration);
  fn  cancel(&self, id : u32);
}

pub struct Session<'a, State> {
    network : &'a SendDatagram,
    timers  : &'a Timers,
    state   : State,
    ssrc    : u32
}

// ================================================================================================

impl <'a> Session<'a, Inactive> {
    pub fn new(network: &'a SendDatagram, timers: &'a Timers) -> Session<'a, Inactive> {
        Session {
            network : network,
            timers  : timers,
            state   : Inactive,
            ssrc    : 0             // FIXME
        }
    }

    pub fn join(self) -> Session<'a, Active> {
        unimplemented!();
    }
}

// ================================================================================================

impl <'a> Session<'a, Active> {
    pub fn leave(self) -> Session<'a, Leaving> {
        unimplemented!();
    }

    fn recv_datagram(&self, now : Instant, buf : &[u8], addr : SocketAddr) {
        unimplemented!();
    }

    fn timeout(&self, now : Instant, timer : u32) {
        unimplemented!();
    }
}

// ================================================================================================

impl <'a> Session<'a, Leaving> {
    fn recv_datagram(&self, now : Instant, buf : &[u8], addr : SocketAddr) {
        unimplemented!();
    }

    fn timeout(&self, now : Instant, timer : u32) {
        unimplemented!();
    }
}

// ================================================================================================
<|endoftext|>


<commit_before>extern crate byteorder;

use std;
use std::io::Write;
use self::byteorder::NativeEndian;
use self::byteorder::WriteBytesExt;

/// Represents a value in the scalar set.
/// The values must be able to store booking information
/// for managing the contents of the set. These requirements
/// are captured in this trait.
pub trait Value
{
    /// Gets the index of the bucket for this value.
    fn get_bucket_index(
        &self,
        buckets: &Self,
    ) -> usize;

    /// Gets a zero.
    fn zero() -> Self;

    /// Gets the integer value as a size.
    fn as_index( &self ) -> usize;

    /// Converts the number of buckets into the value type.i
    fn from_bucket_count( bucket_count: &usize ) -> Self;

    /// Converts the number of set members into the value type.
    fn from_member_count( member_count: usize ) -> Self;

    /// Converts the given index into the value type.
    fn from_index( index: usize ) -> Self;

    /// Decrements the value by one.
    fn decrement( &self ) -> Self;

    /// Provides total ordering for elements.
    fn cmp(
        &self,
        other: &Self,
    ) -> std::cmp::Ordering;

    /// Serializes the value.
    fn serialize(
        &self,
        &mut Write,
    ) -> Result<(), std::io::Error>;
}

/// Implements Value trait for i32
impl Value for i32
{
    /// Gets the index of the bucket for this value.
    fn get_bucket_index(
        &self,
        buckets: &i32,
    ) -> usize
    {
        return ( self.clone() as usize ) % ( buckets.clone() as usize );
    }

    /// Gets a zero.
    fn zero() -> i32
    {
        return 0;
    }

    /// Gets the integer value as a size.
    fn as_index( &self ) -> usize
    {
        return self.clone() as usize;
    }

    /// Converts the specified value to a value that can be stored in the container.
    fn from_bucket_count( bucket_count: &usize ) -> i32
    {
        return bucket_count.clone() as i32;
    }

    /// Converts the number of set members into the value type.
    fn from_member_count( member_count: usize ) -> i32
    {
        return member_count as i32;
    }

    /// Converts the given value to index.
    fn from_index( index: usize ) -> i32
    {
        return index as i32;
    }

    /// Decrements the value by one.
    fn decrement( &self ) -> i32
    {
        return self - 1;
    }

    /// Provides total ordering for elements.
    fn cmp(
        &self,
        other: &i32,
    ) -> std::cmp::Ordering
    {
        std::cmp::Ord::cmp( self, other )
    }

    /// Serializes the value.
    fn serialize(
        &self,
        writer: &mut Write,
    ) -> Result<(), std::io::Error>
    {
        writer.write_i32::<NativeEndian>( *self )?;
        Ok( () )
    }
}

/// Implements Value trait for f32
/// * The largest permissible value is 2^24.
/// * Mainly implemented to provide an easy to use interface for sending the structure to GPU.
#[cfg(any(feature = "floats", test))]
impl Value for f32
{
    /// Gets the index of the bucket for this value.
    fn get_bucket_index(
        &self,
        buckets: &f32,
    ) -> usize
    {
        return ( self.clone() as usize ) % ( buckets.clone() as usize );
    }

    /// Gets a zero.
    fn zero() -> f32
    {
        return 0.0;
    }

    /// Gets the integer value as a size.
    fn as_index( &self ) -> usize
    {
        return self.clone() as usize;
    }

    /// Converts the specified value to a value that can be stored in the container.
    fn from_bucket_count( bucket_count: &usize ) -> f32
    {
        return bucket_count.clone() as f32;
    }

    /// Converts the number of set members into the value type.
    fn from_member_count( member_count: usize ) -> f32
    {
        return member_count as f32;
    }

    /// Converts the given value to index.
    fn from_index( index: usize ) -> f32
    {
        return index as f32;
    }

    /// Decrements the value by one.
    fn decrement( &self ) -> f32
    {
        return self - 1.0;
    }

    /// Provides total ordering for elements.
    fn cmp(
        &self,
        other: &f32,
    ) -> std::cmp::Ordering
    {
        let me = self.clone() as i32;
        let other = other.clone() as i32;
        std::cmp::Ord::cmp( &me, &other )
    }

    /// Serializes the value.
    fn serialize(
        &self,
        writer: &mut Write,
    ) -> Result<(), std::io::Error>
    {
        writer.write_f32::<NativeEndian>( *self )?;
        Ok( () )
    }
}

/// The index of the number of members in the set.
const SIZE_INDEX: usize = 1;

/// The index of the first bucket.
const FIRST_BUCKET_INDEX: usize = 2;

/// Defines how the data is stored in the scalar set.
enum Storage<'a, TA, TB>
where
    TB: 'a,
{
    /// The data is stored as a vector.
    Vector
    { data: Vec<TA> },

    /// The data is stored as a slice.
    Slice
    { data: &'a [TB] },
}

/// Scalar set cabable of storing values with Value trait.
pub struct RoScalarSet<'a, T>
where
    T: std::clone::Clone + Value + 'a,
{
    _storage: Storage<'a, T, T>,
}

impl<'a, T> Clone for RoScalarSet<'a, T>
where
    T: std::clone::Clone + Value + 'a,
{
    /// Returns a copy of the value.
    fn clone( &self ) -> Self
    {
        RoScalarSet::new( self.borrow_values() )
    }

    /// Performs copy-assignment from source.
    fn clone_from(
        &mut self,
        source: &Self,
    )
    {
        let storage = RoScalarSet::create_storage( source.borrow_values() );
        self._storage = storage;
    }
}

impl<'a, T> RoScalarSet<'a, T>
where
    T: std::clone::Clone + Value + 'a,
{
    /// Returns a new integer hash set holding the specified values.
    ///
    /// # ArgumentRoScalarSets
    ///
    /// * 'values' Holds the values stored in the hash set.
    pub fn new<'b, 'c>( values: &'c [T] ) -> RoScalarSet<'b, T>
    {
        let storage = RoScalarSet::create_storage( values );
        return RoScalarSet { _storage: storage };
    }

    /// Attaches an integer hash set to a slice holding the values.
    ///
    /// # ArgumentRoScalarSets
    ///
    /// * 'values' Holds the values stored in the hash set.
    pub fn attach<'b>( buffer: &'b [T] ) -> Result<( RoScalarSet<'b, T>, &'b [T] ), &str>
    {
        // Determine the length of this scalar set.
        if buffer.len() < 4
        {
            return Err( "The buffer is to small" );
        }
        let buckets = buffer[0].as_index();
        let values = buffer[SIZE_INDEX].as_index();
        let total_size = FIRST_BUCKET_INDEX + ( buckets + 1 ) + values;

        // Attach.
        let ( set, remainder ) = buffer.split_at( total_size );
        let storage: Storage<T, T> = Storage::Slice { data: set };
        return Ok( ( RoScalarSet { _storage: storage }, remainder ) );
    }

    /// Checks if any the sets have anything in common.
    pub fn any(
        &self,
        other: &RoScalarSet<T>,
    ) -> bool
    {
        // Determine the smaller set.
        let small;
        let large;
        if other.size() < self.size()
        {
            small = other;
            large = self;
        }
        else
        {
            small = self;
            large = other;
        }

        // For better performance we iterate the smaller set.
        for s in small.borrow_values()
        {
            if large.contains( s )
            {
                return true;
            }
        }

        // Values was not found.
        return false;
    }

    /// Checks whether the given value exists in the set or not.
    pub fn contains(
        &self,
        value: &T,
    ) -> bool
    {
        // Get the bucket associated with the value.
        let bucket = self.get_bucket( &value );

        // Locate the value.
        match bucket.binary_search_by( |probe| probe.cmp( &value ) )
        {
            Ok( _ ) => return true,
            Err( _ ) => return false,
        }
    }

    /// Gets the number of members in the set.
    pub fn size( &self ) -> usize
    {
        let storage = self.borrow_storage();
        return storage[SIZE_INDEX].as_index();
    }

    /// Gets the number of buckets.
    pub fn bucket_count( &self ) -> usize
    {
        let storage = self.borrow_storage();
        return storage[0].as_index();
    }

    /// Serializes the scalar set into the given writer.
    pub fn serialize<W>(
        &self,
        writer: &mut W,
    ) -> Result<(), std::io::Error>
    where
        W: Write,
    {
        // Write our intern
        let storage = self.borrow_storage();
        for v in storage
        {
            v.serialize( writer )?;
        }
        Ok( () )
    }

    /// Gets a read-only slice containing the values of a bucket.
    fn get_bucket(
        &self,
        value: &T,
    ) -> &[T]
    {
        // Determine the bucket.
        let storage = self.borrow_storage();
        let bucket_id: usize = value.get_bucket_index( &storage[0] );
        let bucket_index = bucket_id + FIRST_BUCKET_INDEX;
        let begin: usize = storage[bucket_index].as_index();
        let end: usize = storage[( bucket_index + 1 )].as_index();
        let ( _, remainder ) = storage.split_at( begin );
        let ( bucket, _ ) = remainder.split_at( end - begin );
        return bucket;
    }

    /// Borrows the values of the set.
    fn borrow_values( &'a self ) -> &'a [T]
    {
        // Split the value part from the storage.
        let start = FIRST_BUCKET_INDEX + self.bucket_count() + 1;
        let ( _, values ) = self.borrow_storage().split_at( start );
        return values;
    }

    /// Borrows the storage fo<TA, TB>r accessing the values.
    fn borrow_storage( &'a self ) -> &'a [T]
    {
        let s: &'a [T] = match &self._storage
        {
            &Storage::Vector { ref data } => data.as_slice(),
            &Storage::Slice { ref data } => data,
        };
        return s;
    }

    /// Creates a new storage buffer from the given values.
    fn create_storage( values: &[T] ) -> Storage<'a, T, T>
    {
        // Determine the number of buckets. We introduce a 5% overhead.
        let bucket_count: usize = ( values.len() as f64 * 0.05 ).ceil() as usize;
        let mut storage: Vec<T> = vec![T::zero(); ( FIRST_BUCKET_INDEX + bucket_count + 1 + values.len() )];

        // Store the number of buckets.
        let buckets = T::from_bucket_count( &bucket_count );
        storage[0] = buckets.clone();

        // Store the number of members.
        storage[SIZE_INDEX] = T::from_member_count( values.len() );

        // Count the values required for each bucket.
        let mut values_in_buckets: Vec<i32> = vec![0; bucket_count];
        for v in values
        {
            let bucket = v.get_bucket_index( &buckets );
            values_in_buckets[bucket] += 1;
        }

        // Set bucket pointers to point the end of each bucket.
        // They will be decrements one-by-one when the buckets are filled.
        let first_bucket: usize = FIRST_BUCKET_INDEX;
        let data_start: usize = FIRST_BUCKET_INDEX + bucket_count + 1;
        let mut previous_bucket_end = data_start;
        for b in 0..bucket_count
        {
            // The end of the previous bucket is the start of the previous bucket.
            let index = previous_bucket_end + values_in_buckets[b].as_index();
            storage[b + first_bucket] = T::from_index( index );
            previous_bucket_end = index;
        }

        // Fix the end of the last bucket.
        storage[first_bucket + bucket_count] = T::from_index( storage.len() );

        // Put values into buckets.
        for v in values
        {
            // Determine bucket for the value.
            let bucket_id = v.get_bucket_index( &buckets );

            // Make room for the new value.
            storage[bucket_id + first_bucket] = storage[bucket_id + first_bucket].decrement();
            let value_index: usize = storage[bucket_id + first_bucket].as_index();
            storage[value_index] = v.clone();
        }

        // Sort each bucket to enable binary search.
        for b in 0..bucket_count
        {
            // Determine the location of the bucket.
            let begin: usize = storage[b + first_bucket].as_index();
            let end: usize = storage[b + first_bucket + 1].as_index();
            if end < begin
            {
                panic!( "Invalid bucket: {}", b );
            }

            // Get a splice for sorting.
            let ( _, remainder ) = storage.split_at_mut( begin );
            let ( bucket, _ ) = remainder.split_at_mut( end - begin );
            bucket.sort_by( |a, b| a.cmp( b ) );
        }

        let storage: Storage<'a, T, T> = Storage::Vector { data: storage };
        storage
    }
}
<commit_msg>Slight clarifications to the comments<commit_after>extern crate byteorder;

use std;
use std::io::Write;
use self::byteorder::NativeEndian;
use self::byteorder::WriteBytesExt;

/// Represents a value in the scalar set.
/// The values must be able to store booking information
/// for managing the contents of the set. These requirements
/// are captured in this trait.
pub trait Value
{
    /// Gets the index of the bucket for this value.
    fn get_bucket_index(
        &self,
        buckets: &Self,
    ) -> usize;

    /// Gets a zero.
    fn zero() -> Self;

    /// Gets the integer value as a size.
    fn as_index( &self ) -> usize;

    /// Converts the number of buckets into the value type.i
    fn from_bucket_count( bucket_count: &usize ) -> Self;

    /// Converts the number of set members into the value type.
    fn from_member_count( member_count: usize ) -> Self;

    /// Converts the given index into the value type.
    fn from_index( index: usize ) -> Self;

    /// Decrements the value by one.
    fn decrement( &self ) -> Self;

    /// Provides total ordering for elements.
    fn cmp(
        &self,
        other: &Self,
    ) -> std::cmp::Ordering;

    /// Serializes the value.
    fn serialize(
        &self,
        &mut Write,
    ) -> Result<(), std::io::Error>;
}

/// Implements Value trait for i32
impl Value for i32
{
    /// Gets the index of the bucket for this value.
    fn get_bucket_index(
        &self,
        buckets: &i32,
    ) -> usize
    {
        return ( self.clone() as usize ) % ( buckets.clone() as usize );
    }

    /// Gets a zero.
    fn zero() -> i32
    {
        return 0;
    }

    /// Gets the integer value as a size.
    fn as_index( &self ) -> usize
    {
        return self.clone() as usize;
    }

    /// Converts the specified value to a value that can be stored in the container.
    fn from_bucket_count( bucket_count: &usize ) -> i32
    {
        return bucket_count.clone() as i32;
    }

    /// Converts the number of set members into the value type.
    fn from_member_count( member_count: usize ) -> i32
    {
        return member_count as i32;
    }

    /// Converts the given value to index.
    fn from_index( index: usize ) -> i32
    {
        return index as i32;
    }

    /// Decrements the value by one.
    fn decrement( &self ) -> i32
    {
        return self - 1;
    }

    /// Provides total ordering for elements.
    fn cmp(
        &self,
        other: &i32,
    ) -> std::cmp::Ordering
    {
        std::cmp::Ord::cmp( self, other )
    }

    /// Serializes the value.
    fn serialize(
        &self,
        writer: &mut Write,
    ) -> Result<(), std::io::Error>
    {
        writer.write_i32::<NativeEndian>( *self )?;
        Ok( () )
    }
}

/// Implements Value trait for f32
/// * The largest permissible value is 2^24.
/// * Mainly implemented to provide an easy to use interface for sending the structure to GPU.
#[cfg(any(feature = "floats", test))]
impl Value for f32
{
    /// Gets the index of the bucket for this value.
    fn get_bucket_index(
        &self,
        buckets: &f32,
    ) -> usize
    {
        return ( self.clone() as usize ) % ( buckets.clone() as usize );
    }

    /// Gets a zero.
    fn zero() -> f32
    {
        return 0.0;
    }

    /// Gets the integer value as a size.
    fn as_index( &self ) -> usize
    {
        return self.clone() as usize;
    }

    /// Converts the specified value to a value that can be stored in the container.
    fn from_bucket_count( bucket_count: &usize ) -> f32
    {
        return bucket_count.clone() as f32;
    }

    /// Converts the number of set members into the value type.
    fn from_member_count( member_count: usize ) -> f32
    {
        return member_count as f32;
    }

    /// Converts the given value to index.
    fn from_index( index: usize ) -> f32
    {
        return index as f32;
    }

    /// Decrements the value by one.
    fn decrement( &self ) -> f32
    {
        return self - 1.0;
    }

    /// Provides total ordering for Value elements.
    fn cmp(
        &self,
        other: &f32,
    ) -> std::cmp::Ordering
    {
        let me = self.clone() as i32;
        let other = other.clone() as i32;
        std::cmp::Ord::cmp( &me, &other )
    }

    /// Serializes the value.
    fn serialize(
        &self,
        writer: &mut Write,
    ) -> Result<(), std::io::Error>
    {
        writer.write_f32::<NativeEndian>( *self )?;
        Ok( () )
    }
}

/// The index or position in the array that holds the number of members in the set.
const SIZE_INDEX: usize = 1;

/// The index or position in the array that holds the index to the first value of the first bucket.
const FIRST_BUCKET_INDEX: usize = 2;

/// Defines how the data is stored in the scalar set.
enum Storage<'a, TA, TB>
where
    TB: 'a,
{
    /// The data is stored as a vector.
    Vector
    { data: Vec<TA> },

    /// The data is stored in a slice. Not owned by the scalar set.
    Slice
    { data: &'a [TB] },
}

/// Scalar set cabable of storing values with Value trait.
pub struct RoScalarSet<'a, T>
where
    T: std::clone::Clone + Value + 'a,
{
    _storage: Storage<'a, T, T>,
}

impl<'a, T> Clone for RoScalarSet<'a, T>
where
    T: std::clone::Clone + Value + 'a,
{
    /// Returns a copy of the set.
    fn clone( &self ) -> Self
    {
        RoScalarSet::new( self.borrow_values() )
    }

    /// Copies the content from the given set.alloc
    fn clone_from(
        &mut self,
        source: &Self,
    )
    {
        let storage = RoScalarSet::create_storage( source.borrow_values() );
        self._storage = storage;
    }
}

impl<'a, T> RoScalarSet<'a, T>
where
    T: std::clone::Clone + Value + 'a,
{
    /// Returns a new integer hash set holding the specified values.
    ///
    /// # ArgumentRoScalarSets
    ///
    /// * 'values' Holds the values stored in the hash set.
    pub fn new<'b, 'c>( values: &'c [T] ) -> RoScalarSet<'b, T>
    {
        let storage = RoScalarSet::create_storage( values );
        return RoScalarSet { _storage: storage };
    }

    /// Attaches an integer hash set to a slice holding the values.
    ///
    /// # ArgumentRoScalarSets
    ///
    /// * 'values' Slice that holds the values stored in the hash set.
    pub fn attach<'b>( buffer: &'b [T] ) -> Result<( RoScalarSet<'b, T>, &'b [T] ), &str>
    {
        // Determine the length of this scalar set.
        if buffer.len() < 4
        {
            return Err( "The buffer is to small" );
        }
        let buckets = buffer[0].as_index();
        let values = buffer[SIZE_INDEX].as_index();
        let total_size = FIRST_BUCKET_INDEX + ( buckets + 1 ) + values;

        // Attach.
        let ( set, remainder ) = buffer.split_at( total_size );
        let storage: Storage<T, T> = Storage::Slice { data: set };
        return Ok( ( RoScalarSet { _storage: storage }, remainder ) );
    }

    /// Checks if any the sets have anything in common.
    pub fn any(
        &self,
        other: &RoScalarSet<T>,
    ) -> bool
    {
        // Determine the smaller set.
        let small;
        let large;
        if other.size() < self.size()
        {
            small = other;
            large = self;
        }
        else
        {
            small = self;
            large = other;
        }

        // For better performance we iterate the smaller set.
        for s in small.borrow_values()
        {
            if large.contains( s )
            {
                return true;
            }
        }

        // Values was not found.
        return false;
    }

    /// Checks whether the given value exists in the set or not.
    pub fn contains(
        &self,
        value: &T,
    ) -> bool
    {
        // Get the bucket associated with the value.
        let bucket = self.get_bucket( &value );

        // Locate the value.
        match bucket.binary_search_by( |probe| probe.cmp( &value ) )
        {
            Ok( _ ) => return true,
            Err( _ ) => return false,
        }
    }

    /// Gets the number of members in the set.
    pub fn size( &self ) -> usize
    {
        let storage = self.borrow_storage();
        return storage[SIZE_INDEX].as_index();
    }

    /// Gets the number of buckets.
    pub fn bucket_count( &self ) -> usize
    {
        let storage = self.borrow_storage();
        return storage[0].as_index();
    }

    /// Serializes the scalar set into the given writer.
    pub fn serialize<W>(
        &self,
        writer: &mut W,
    ) -> Result<(), std::io::Error>
    where
        W: Write,
    {
        // Write our intern
        let storage = self.borrow_storage();
        for v in storage
        {
            v.serialize( writer )?;
        }
        Ok( () )
    }

    /// Gets a read-only slice containing the values of a bucket that holdes the given value.
    fn get_bucket(
        &self,
        value: &T,
    ) -> &[T]
    {
        // Determine the bucket.
        let storage = self.borrow_storage();
        let bucket_id: usize = value.get_bucket_index( &storage[0] );
        let bucket_index = bucket_id + FIRST_BUCKET_INDEX;
        let begin: usize = storage[bucket_index].as_index();
        let end: usize = storage[( bucket_index + 1 )].as_index();
        let ( _, remainder ) = storage.split_at( begin );
        let ( bucket, _ ) = remainder.split_at( end - begin );
        return bucket;
    }

    /// Borrows the values of the set.
    fn borrow_values( &'a self ) -> &'a [T]
    {
        // Split the value part from the storage.
        let start = FIRST_BUCKET_INDEX + self.bucket_count() + 1;
        let ( _, values ) = self.borrow_storage().split_at( start );
        return values;
    }

    /// Borrows the storage for accessing the values.
    fn borrow_storage( &'a self ) -> &'a [T]
    {
        let s: &'a [T] = match &self._storage
        {
            &Storage::Vector { ref data } => data.as_slice(),
            &Storage::Slice { ref data } => data,
        };
        return s;
    }

    /// Creates a new storage buffer from the given values.
    fn create_storage( values: &[T] ) -> Storage<'a, T, T>
    {
        // Determine the number of buckets. We introduce a 5% overhead.
        let bucket_count: usize = ( values.len() as f64 * 0.05 ).ceil() as usize;
        let mut storage: Vec<T> = vec![T::zero(); ( FIRST_BUCKET_INDEX + bucket_count + 1 + values.len() )];

        // Store the number of buckets.
        let buckets = T::from_bucket_count( &bucket_count );
        storage[0] = buckets.clone();

        // Store the number of members.
        storage[SIZE_INDEX] = T::from_member_count( values.len() );

        // Count the values required for each bucket.
        let mut values_in_buckets: Vec<i32> = vec![0; bucket_count];
        for v in values
        {
            let bucket = v.get_bucket_index( &buckets );
            values_in_buckets[bucket] += 1;
        }

        // Set bucket pointers to point the end of each bucket.
        // This way we can use the bucket pointers to track the next empty position when
        // distributing the values into the buckets.
        let first_bucket: usize = FIRST_BUCKET_INDEX;
        let data_start: usize = FIRST_BUCKET_INDEX + bucket_count + 1;
        let mut previous_bucket_end = data_start;
        for b in 0..bucket_count
        {
            // The end of the previous bucket is the start of the previous bucket.
            let index = previous_bucket_end + values_in_buckets[b].as_index();
            storage[b + first_bucket] = T::from_index( index );
            previous_bucket_end = index;
        }

        // Fix the end of the last bucket.
        storage[first_bucket + bucket_count] = T::from_index( storage.len() );

        // Put values into buckets.
        for v in values
        {
            // Determine bucket for the value.
            let bucket_id = v.get_bucket_index( &buckets );

            // Make room for the new value.
            storage[bucket_id + first_bucket] = storage[bucket_id + first_bucket].decrement();
            let value_index: usize = storage[bucket_id + first_bucket].as_index();

            // And finally store the value.
            storage[value_index] = v.clone();
        }

        // Sort each bucket to enable binary search.
        for b in 0..bucket_count
        {
            // Determine the location of the bucket.
            let begin: usize = storage[b + first_bucket].as_index();
            let end: usize = storage[b + first_bucket + 1].as_index();
            if end < begin
            {
                panic!( "Invalid bucket: {}", b );
            }

            // Get a splice that represents the bucket and sort it.
            let ( _, remainder ) = storage.split_at_mut( begin );
            let ( bucket, _ ) = remainder.split_at_mut( end - begin );
            bucket.sort_by( |a, b| a.cmp( b ) );
        }

        let storage: Storage<'a, T, T> = Storage::Vector { data: storage };
        storage
    }
}
<|endoftext|>


<commit_before>//! Iterators that are sources (produce elements from parameters,
//! not from another iterator).

use std::mem;

/// See [`repeat_call`](../fn.repeat_call.html) for more information.
pub struct RepeatCall<F> {
    f: F,
}

/// An iterator source that produces elements indefinitely by calling
/// a given closure.
///
/// Iterator element type is the return type of the closure.
///
/// ```
/// use itertools::repeat_call;
/// use itertools::Itertools;
/// use std::collections::BinaryHeap;
///
/// let mut heap = BinaryHeap::from(vec![2, 5, 3, 7, 8]);
///
/// // extract each element in sorted order
/// for element in repeat_call(|| heap.pop()).while_some() {
///     print!("{}", element);
/// }
///
/// itertools::assert_equal(
///     repeat_call(|| 1).take(5),
///     vec![1, 1, 1, 1, 1]
/// );
/// ```
pub fn repeat_call<F>(function: F) -> RepeatCall<F> {
    RepeatCall { f: function }
}

impl Iterator for RepeatCall<F>
    where F: FnMut() -> A
{
    type Item = A;

    #[inline]
    fn next(&mut self) -> Option {
        Some((self.f)())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (usize::max_value(), None)
    }
}

/// Creates a new unfold source with the specified closure as the "iterator
/// function" and an initial state to eventually pass to the closure
///
/// `unfold` is a general iterator builder: it has a mutable state value,
/// and a closure with access to the state that produces the next value.
///
/// This more or less equivalent to a regular struct with an `Iterator`
/// implementation, and is useful for one-off iterators.
///
/// ```
/// // an iterator that yields sequential Fibonacci numbers,
/// // and stops at the maximum representable value.
///
/// use itertools::unfold;
///
/// let mut fibonacci = unfold((1_u32, 1_u32), |state| {
///     let (ref mut x1, ref mut x2) = *state;
///
///     // Attempt to get the next Fibonacci number
///     let next = x1.saturating_add(*x2);
///
///     // Shift left: ret <- x1 <- x2 <- next
///     let ret = *x1;
///     *x1 = *x2;
///     *x2 = next;
///
///     // If addition has saturated at the maximum, we are finished
///     if ret == *x1 && ret > 1 {
///         return None;
///     }
///
///     Some(ret)
/// });
///
/// itertools::assert_equal(fibonacci.by_ref().take(8),
///                         vec![1, 1, 2, 3, 5, 8, 13, 21]);
/// assert_eq!(fibonacci.last(), Some(2_971_215_073))
/// ```
pub fn unfold(initial_state: St, f: F) -> Unfold<St, F>
    where F: FnMut(&mut St) -> Option
{
    Unfold {
        f: f,
        state: initial_state,
    }
}

/// See [`unfold`](../fn.unfold.html) for more information.
#[derive(Clone)]
pub struct Unfold<St, F> {
    f: F,
    /// Internal state that will be passed to the closure on the next iteration
    pub state: St,
}

impl Iterator for Unfold<St, F>
    where F: FnMut(&mut St) -> Option
{
    type Item = A;

    #[inline]
    fn next(&mut self) -> Option {
        (self.f)(&mut self.state)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        // no possible known bounds at this point
        (0, None)
    }
}

/// An iterator that infinitely applies function to state and yields results.
///
/// This `struct` is created by the [`iterate()`] function. See its documentation for more.
///
/// [`iterate()`]: ../fn.iterate.html
#[derive(Clone)]
pub struct Iterate<St, F> {
    state: St,
    f: F,
}

impl<St, F> Iterator for Iterate<St, F>
    where F: FnMut(&St) -> St
{
    type Item = St;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        let next_state = (self.f)(&self.state);
        Some(mem::replace(&mut self.state, next_state))
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (usize::max_value(), None)
    }
}

/// Creates a new iterator that infinitely applies function to state and yields results.
///
/// ```
/// use itertools::iterate;
///
/// itertools::assert_equal(iterate(1, |&i| i * 3).take(5), vec![1, 3, 9, 27, 81]);
/// ```
pub fn iterate<St, F>(initial_state: St, f: F) -> Iterate<St, F>
    where F: FnMut(&St) -> St
{
    Iterate {
        state: initial_state,
        f: f,
    }
}
<commit_msg>Fix description regarding "state" and argument name<commit_after>//! Iterators that are sources (produce elements from parameters,
//! not from another iterator).

use std::mem;

/// See [`repeat_call`](../fn.repeat_call.html) for more information.
pub struct RepeatCall<F> {
    f: F,
}

/// An iterator source that produces elements indefinitely by calling
/// a given closure.
///
/// Iterator element type is the return type of the closure.
///
/// ```
/// use itertools::repeat_call;
/// use itertools::Itertools;
/// use std::collections::BinaryHeap;
///
/// let mut heap = BinaryHeap::from(vec![2, 5, 3, 7, 8]);
///
/// // extract each element in sorted order
/// for element in repeat_call(|| heap.pop()).while_some() {
///     print!("{}", element);
/// }
///
/// itertools::assert_equal(
///     repeat_call(|| 1).take(5),
///     vec![1, 1, 1, 1, 1]
/// );
/// ```
pub fn repeat_call<F>(function: F) -> RepeatCall<F> {
    RepeatCall { f: function }
}

impl Iterator for RepeatCall<F>
    where F: FnMut() -> A
{
    type Item = A;

    #[inline]
    fn next(&mut self) -> Option {
        Some((self.f)())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (usize::max_value(), None)
    }
}

/// Creates a new unfold source with the specified closure as the "iterator
/// function" and an initial state to eventually pass to the closure
///
/// `unfold` is a general iterator builder: it has a mutable state value,
/// and a closure with access to the state that produces the next value.
///
/// This more or less equivalent to a regular struct with an `Iterator`
/// implementation, and is useful for one-off iterators.
///
/// ```
/// // an iterator that yields sequential Fibonacci numbers,
/// // and stops at the maximum representable value.
///
/// use itertools::unfold;
///
/// let mut fibonacci = unfold((1_u32, 1_u32), |state| {
///     let (ref mut x1, ref mut x2) = *state;
///
///     // Attempt to get the next Fibonacci number
///     let next = x1.saturating_add(*x2);
///
///     // Shift left: ret <- x1 <- x2 <- next
///     let ret = *x1;
///     *x1 = *x2;
///     *x2 = next;
///
///     // If addition has saturated at the maximum, we are finished
///     if ret == *x1 && ret > 1 {
///         return None;
///     }
///
///     Some(ret)
/// });
///
/// itertools::assert_equal(fibonacci.by_ref().take(8),
///                         vec![1, 1, 2, 3, 5, 8, 13, 21]);
/// assert_eq!(fibonacci.last(), Some(2_971_215_073))
/// ```
pub fn unfold(initial_state: St, f: F) -> Unfold<St, F>
    where F: FnMut(&mut St) -> Option
{
    Unfold {
        f: f,
        state: initial_state,
    }
}

/// See [`unfold`](../fn.unfold.html) for more information.
#[derive(Clone)]
pub struct Unfold<St, F> {
    f: F,
    /// Internal state that will be passed to the closure on the next iteration
    pub state: St,
}

impl Iterator for Unfold<St, F>
    where F: FnMut(&mut St) -> Option
{
    type Item = A;

    #[inline]
    fn next(&mut self) -> Option {
        (self.f)(&mut self.state)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        // no possible known bounds at this point
        (0, None)
    }
}

/// An iterator that infinitely applies function to value and yields results.
///
/// This `struct` is created by the [`iterate()`] function. See its documentation for more.
///
/// [`iterate()`]: ../fn.iterate.html
#[derive(Clone)]
pub struct Iterate<St, F> {
    state: St,
    f: F,
}

impl<St, F> Iterator for Iterate<St, F>
    where F: FnMut(&St) -> St
{
    type Item = St;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        let next_state = (self.f)(&self.state);
        Some(mem::replace(&mut self.state, next_state))
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (usize::max_value(), None)
    }
}

/// Creates a new iterator that infinitely applies function to value and yields results.
///
/// ```
/// use itertools::iterate;
///
/// itertools::assert_equal(iterate(1, |&i| i * 3).take(5), vec![1, 3, 9, 27, 81]);
/// ```
pub fn iterate<St, F>(initial_value: St, f: F) -> Iterate<St, F>
    where F: FnMut(&St) -> St
{
    Iterate {
        state: initial_value,
        f: f,
    }
}
<|endoftext|>


<commit_before>use winapi;
use secur32;
use std::io;
use std::mem;
use std::ptr;

use Inner;

lazy_static! {
    static ref UNISP_NAME: Vec<u8> = winapi::UNISP_NAME.bytes().chain(Some(0)).collect();
}

#[derive(Copy, Debug, Clone, PartialEq, Eq)]
pub enum Direction {
    Inbound,
    Outbound,
}

/// https://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
pub enum Algorithm {
    /// Advanced Encryption Standard (AES).
    Aes = winapi::CALG_AES,
    /// 128 bit AES.
    Aes128 = winapi::CALG_AES_128,
    /// 192 bit AES.
    Aes192 = winapi::CALG_AES_192,
    /// 256 bit AES.
    Aes256 = winapi::CALG_AES_256,
    /// Temporary algorithm identifier for handles of Diffie-Hellman–agreed keys.
    AgreedkeyAny = winapi::CALG_AGREEDKEY_ANY,
    /// An algorithm to create a 40-bit DES key that has parity bits and zeroed key bits to make
    /// its key length 64 bits.
    CylinkMek = winapi::CALG_CYLINK_MEK,
    /// DES encryption algorithm.
    Des = winapi::CALG_DES,
    /// DESX encryption algorithm.
    Desx = winapi::CALG_DESX,
    /// Diffie-Hellman ephemeral key exchange algorithm.
    DhEphem = winapi::CALG_DH_EPHEM,
    /// Diffie-Hellman store and forward key exchange algorithm.
    DhSf = winapi::CALG_DH_SF,
    /// DSA public key signature algorithm.
    DssSign = winapi::CALG_DSS_SIGN,
    /// Elliptic curve Diffie-Hellman key exchange algorithm.
    Ecdh = winapi::CALG_ECDH,
    // https://github.com/retep998/winapi-rs/issues/287
    // /// Ephemeral elliptic curve Diffie-Hellman key exchange algorithm.
    // EcdhEphem = winapi::CALG_ECDH_EPHEM,
    /// Elliptic curve digital signature algorithm.
    Ecdsa = winapi::CALG_ECDSA,
    /// One way function hashing algorithm.
    HashReplaceOwf = winapi::CALG_HASH_REPLACE_OWF,
    /// Hughes MD5 hashing algorithm.
    HughesMd5 = winapi::CALG_HUGHES_MD5,
    /// HMAC keyed hash algorithm.
    Hmac = winapi::CALG_HMAC,
    /// MAC keyed hash algorithm.
    Mac = winapi::CALG_MAC,
    /// MD2 hashing algorithm.
    Md2 = winapi::CALG_MD2,
    /// MD4 hashing algorithm.
    Md4 = winapi::CALG_MD4,
    /// MD5 hashing algorithm.
    Md5 = winapi::CALG_MD5,
    /// No signature algorithm..
    NoSign = winapi::CALG_NO_SIGN,
    /// RC2 block encryption algorithm.
    Rc2 = winapi::CALG_RC2,
    /// RC4 stream encryption algorithm.
    Rc4 = winapi::CALG_RC4,
    /// RC5 block encryption algorithm.
    Rc5 = winapi::CALG_RC5,
    /// RSA public key exchange algorithm.
    RsaKeyx = winapi::CALG_RSA_KEYX,
    /// RSA public key signature algorithm.
    RsaSign = winapi::CALG_RSA_SIGN,
    /// SHA hashing algorithm.
    Sha1 = winapi::CALG_SHA1,
    /// 256 bit SHA hashing algorithm.
    Sha256 = winapi::CALG_SHA_256,
    /// 384 bit SHA hashing algorithm.
    Sha384 = winapi::CALG_SHA_384,
    /// 512 bit SHA hashing algorithm.
    Sha512 = winapi::CALG_SHA_512,
    /// Triple DES encryption algorithm.
    TripleDes = winapi::CALG_3DES,
    /// Two-key triple DES encryption with effective key length equal to 112 bits.
    TripleDes112 = winapi::CALG_3DES_112,
    #[doc(hidden)]
    __ForExtensibility,
}

#[derive(Debug, Copy, Clone)]
pub enum Protocol {
    /// Secure Sockets Layer 3.0
    Ssl3,
    /// Transport Layer Security 1.0
    Tls10,
    /// Transport Layer Security 1.1
    Tls11,
    /// Transport Layer Security 1.2
    Tls12,
    #[doc(hidden)]
    __ForExtensibility,
}

impl Protocol {
    fn dword(self, direction: Direction) -> winapi::DWORD {
        match (self, direction) {
            (Protocol::Ssl3, Direction::Inbound) => winapi::SP_PROT_SSL3_SERVER,
            (Protocol::Tls10, Direction::Inbound) => winapi::SP_PROT_TLS1_0_SERVER,
            (Protocol::Tls11, Direction::Inbound) => winapi::SP_PROT_TLS1_1_SERVER,
            (Protocol::Tls12, Direction::Inbound) => winapi::SP_PROT_TLS1_2_SERVER,
            (Protocol::Ssl3, Direction::Outbound) => winapi::SP_PROT_SSL3_CLIENT,
            (Protocol::Tls10, Direction::Outbound) => winapi::SP_PROT_TLS1_0_CLIENT,
            (Protocol::Tls11, Direction::Outbound) => winapi::SP_PROT_TLS1_1_CLIENT,
            (Protocol::Tls12, Direction::Outbound) => winapi::SP_PROT_TLS1_2_CLIENT,
            (Protocol::__ForExtensibility, _) => unreachable!(),
        }
    }
}

pub struct SchannelCredBuilder {
    supported_algorithms: Option<Vec<Algorithm>>,
    enabled_protocols: Option<Vec<Protocol>>,
}

impl SchannelCredBuilder {
    /// Sets the algorithms supported for sessions created from this builder.
    pub fn supported_algorithms(mut self,
                                supported_algorithms: &[Algorithm])
                                -> SchannelCredBuilder {
        self.supported_algorithms = Some(supported_algorithms.to_owned());
        self
    }

    /// Sets the protocols enabled for sessions created from this builder.
    pub fn enabled_protocols(mut self, enabled_protocols: &[Protocol]) -> SchannelCredBuilder {
        self.enabled_protocols = Some(enabled_protocols.to_owned());
        self
    }

    pub fn acquire(&self, direction: Direction) -> io::Result<SchannelCred> {
        unsafe {
            let mut handle = mem::uninitialized();
            let mut cred_data: winapi::SCHANNEL_CRED = mem::zeroed();
            cred_data.dwVersion = winapi::SCHANNEL_CRED_VERSION;
            cred_data.dwFlags = winapi::SCH_USE_STRONG_CRYPTO;
            if let Some(ref supported_algorithms) = self.supported_algorithms {
                cred_data.cSupportedAlgs = supported_algorithms.len() as winapi::DWORD;
                cred_data.palgSupportedAlgs = supported_algorithms.as_ptr() as *mut _;
            }
            if let Some(ref enabled_protocols) = self.enabled_protocols {
                cred_data.grbitEnabledProtocols = enabled_protocols.iter()
                                                                   .map(|p| p.dword(direction))
                                                                   .fold(0, |acc, p| acc | p);
            }

            let direction = match direction {
                Direction::Inbound => winapi::SECPKG_CRED_INBOUND,
                Direction::Outbound => winapi::SECPKG_CRED_OUTBOUND,
            };

            match secur32::AcquireCredentialsHandleA(ptr::null_mut(),
                                                     UNISP_NAME.as_ptr() as *const _ as *mut _,
                                                     direction,
                                                     ptr::null_mut(),
                                                     &mut cred_data as *mut _ as *mut _,
                                                     None,
                                                     ptr::null_mut(),
                                                     &mut handle,
                                                     ptr::null_mut()) {
                winapi::SEC_E_OK => Ok(SchannelCred(handle)),
                err => Err(io::Error::from_raw_os_error(err as i32)),
            }
        }
    }
}

pub struct SchannelCred(winapi::CredHandle);

impl Drop for SchannelCred {
    fn drop(&mut self) {
        unsafe {
            secur32::FreeCredentialsHandle(&mut self.0);
        }
    }
}

impl Inner<winapi::CredHandle> for SchannelCred {
    unsafe fn from_inner(inner: winapi::CredHandle) -> SchannelCred {
        SchannelCred(inner)
    }

    fn as_inner(&self) -> winapi::CredHandle {
        self.0
    }

    fn get_mut(&mut self) -> &mut winapi::CredHandle {
        &mut self.0
    }
}

impl SchannelCred {
    pub fn builder() -> SchannelCredBuilder {
        SchannelCredBuilder {
            supported_algorithms: None,
            enabled_protocols: None,
        }
    }
}<commit_msg>Rename builder<commit_after>use winapi;
use secur32;
use std::io;
use std::mem;
use std::ptr;

use Inner;

lazy_static! {
    static ref UNISP_NAME: Vec<u8> = winapi::UNISP_NAME.bytes().chain(Some(0)).collect();
}

#[derive(Copy, Debug, Clone, PartialEq, Eq)]
pub enum Direction {
    Inbound,
    Outbound,
}

/// https://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
pub enum Algorithm {
    /// Advanced Encryption Standard (AES).
    Aes = winapi::CALG_AES,
    /// 128 bit AES.
    Aes128 = winapi::CALG_AES_128,
    /// 192 bit AES.
    Aes192 = winapi::CALG_AES_192,
    /// 256 bit AES.
    Aes256 = winapi::CALG_AES_256,
    /// Temporary algorithm identifier for handles of Diffie-Hellman–agreed keys.
    AgreedkeyAny = winapi::CALG_AGREEDKEY_ANY,
    /// An algorithm to create a 40-bit DES key that has parity bits and zeroed key bits to make
    /// its key length 64 bits.
    CylinkMek = winapi::CALG_CYLINK_MEK,
    /// DES encryption algorithm.
    Des = winapi::CALG_DES,
    /// DESX encryption algorithm.
    Desx = winapi::CALG_DESX,
    /// Diffie-Hellman ephemeral key exchange algorithm.
    DhEphem = winapi::CALG_DH_EPHEM,
    /// Diffie-Hellman store and forward key exchange algorithm.
    DhSf = winapi::CALG_DH_SF,
    /// DSA public key signature algorithm.
    DssSign = winapi::CALG_DSS_SIGN,
    /// Elliptic curve Diffie-Hellman key exchange algorithm.
    Ecdh = winapi::CALG_ECDH,
    // https://github.com/retep998/winapi-rs/issues/287
    // /// Ephemeral elliptic curve Diffie-Hellman key exchange algorithm.
    // EcdhEphem = winapi::CALG_ECDH_EPHEM,
    /// Elliptic curve digital signature algorithm.
    Ecdsa = winapi::CALG_ECDSA,
    /// One way function hashing algorithm.
    HashReplaceOwf = winapi::CALG_HASH_REPLACE_OWF,
    /// Hughes MD5 hashing algorithm.
    HughesMd5 = winapi::CALG_HUGHES_MD5,
    /// HMAC keyed hash algorithm.
    Hmac = winapi::CALG_HMAC,
    /// MAC keyed hash algorithm.
    Mac = winapi::CALG_MAC,
    /// MD2 hashing algorithm.
    Md2 = winapi::CALG_MD2,
    /// MD4 hashing algorithm.
    Md4 = winapi::CALG_MD4,
    /// MD5 hashing algorithm.
    Md5 = winapi::CALG_MD5,
    /// No signature algorithm..
    NoSign = winapi::CALG_NO_SIGN,
    /// RC2 block encryption algorithm.
    Rc2 = winapi::CALG_RC2,
    /// RC4 stream encryption algorithm.
    Rc4 = winapi::CALG_RC4,
    /// RC5 block encryption algorithm.
    Rc5 = winapi::CALG_RC5,
    /// RSA public key exchange algorithm.
    RsaKeyx = winapi::CALG_RSA_KEYX,
    /// RSA public key signature algorithm.
    RsaSign = winapi::CALG_RSA_SIGN,
    /// SHA hashing algorithm.
    Sha1 = winapi::CALG_SHA1,
    /// 256 bit SHA hashing algorithm.
    Sha256 = winapi::CALG_SHA_256,
    /// 384 bit SHA hashing algorithm.
    Sha384 = winapi::CALG_SHA_384,
    /// 512 bit SHA hashing algorithm.
    Sha512 = winapi::CALG_SHA_512,
    /// Triple DES encryption algorithm.
    TripleDes = winapi::CALG_3DES,
    /// Two-key triple DES encryption with effective key length equal to 112 bits.
    TripleDes112 = winapi::CALG_3DES_112,
    #[doc(hidden)]
    __ForExtensibility,
}

#[derive(Debug, Copy, Clone)]
pub enum Protocol {
    /// Secure Sockets Layer 3.0
    Ssl3,
    /// Transport Layer Security 1.0
    Tls10,
    /// Transport Layer Security 1.1
    Tls11,
    /// Transport Layer Security 1.2
    Tls12,
    #[doc(hidden)]
    __ForExtensibility,
}

impl Protocol {
    fn dword(self, direction: Direction) -> winapi::DWORD {
        match (self, direction) {
            (Protocol::Ssl3, Direction::Inbound) => winapi::SP_PROT_SSL3_SERVER,
            (Protocol::Tls10, Direction::Inbound) => winapi::SP_PROT_TLS1_0_SERVER,
            (Protocol::Tls11, Direction::Inbound) => winapi::SP_PROT_TLS1_1_SERVER,
            (Protocol::Tls12, Direction::Inbound) => winapi::SP_PROT_TLS1_2_SERVER,
            (Protocol::Ssl3, Direction::Outbound) => winapi::SP_PROT_SSL3_CLIENT,
            (Protocol::Tls10, Direction::Outbound) => winapi::SP_PROT_TLS1_0_CLIENT,
            (Protocol::Tls11, Direction::Outbound) => winapi::SP_PROT_TLS1_1_CLIENT,
            (Protocol::Tls12, Direction::Outbound) => winapi::SP_PROT_TLS1_2_CLIENT,
            (Protocol::__ForExtensibility, _) => unreachable!(),
        }
    }
}

pub struct Builder {
    supported_algorithms: Option<Vec<Algorithm>>,
    enabled_protocols: Option<Vec<Protocol>>,
}

impl Builder {
    /// Sets the algorithms supported for sessions created from this builder.
    pub fn supported_algorithms(mut self,
                                supported_algorithms: &[Algorithm])
                                -> Builder {
        self.supported_algorithms = Some(supported_algorithms.to_owned());
        self
    }

    /// Sets the protocols enabled for sessions created from this builder.
    pub fn enabled_protocols(mut self, enabled_protocols: &[Protocol]) -> Builder {
        self.enabled_protocols = Some(enabled_protocols.to_owned());
        self
    }

    pub fn acquire(&self, direction: Direction) -> io::Result<SchannelCred> {
        unsafe {
            let mut handle = mem::uninitialized();
            let mut cred_data: winapi::SCHANNEL_CRED = mem::zeroed();
            cred_data.dwVersion = winapi::SCHANNEL_CRED_VERSION;
            cred_data.dwFlags = winapi::SCH_USE_STRONG_CRYPTO;
            if let Some(ref supported_algorithms) = self.supported_algorithms {
                cred_data.cSupportedAlgs = supported_algorithms.len() as winapi::DWORD;
                cred_data.palgSupportedAlgs = supported_algorithms.as_ptr() as *mut _;
            }
            if let Some(ref enabled_protocols) = self.enabled_protocols {
                cred_data.grbitEnabledProtocols = enabled_protocols.iter()
                                                                   .map(|p| p.dword(direction))
                                                                   .fold(0, |acc, p| acc | p);
            }

            let direction = match direction {
                Direction::Inbound => winapi::SECPKG_CRED_INBOUND,
                Direction::Outbound => winapi::SECPKG_CRED_OUTBOUND,
            };

            match secur32::AcquireCredentialsHandleA(ptr::null_mut(),
                                                     UNISP_NAME.as_ptr() as *const _ as *mut _,
                                                     direction,
                                                     ptr::null_mut(),
                                                     &mut cred_data as *mut _ as *mut _,
                                                     None,
                                                     ptr::null_mut(),
                                                     &mut handle,
                                                     ptr::null_mut()) {
                winapi::SEC_E_OK => Ok(SchannelCred(handle)),
                err => Err(io::Error::from_raw_os_error(err as i32)),
            }
        }
    }
}

pub struct SchannelCred(winapi::CredHandle);

impl Drop for SchannelCred {
    fn drop(&mut self) {
        unsafe {
            secur32::FreeCredentialsHandle(&mut self.0);
        }
    }
}

impl Inner<winapi::CredHandle> for SchannelCred {
    unsafe fn from_inner(inner: winapi::CredHandle) -> SchannelCred {
        SchannelCred(inner)
    }

    fn as_inner(&self) -> winapi::CredHandle {
        self.0
    }

    fn get_mut(&mut self) -> &mut winapi::CredHandle {
        &mut self.0
    }
}

impl SchannelCred {
    pub fn builder() -> Builder {
        Builder {
            supported_algorithms: None,
            enabled_protocols: None,
        }
    }
}<|endoftext|>