<commit_before>//
// Copyright 2014-2016 the slack-rs authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Slack realtime messaging client: https://api.slack.com/bot-users
//!
//! See [CHANGELOG.md](https://github.com/slack-rs/slack-rs/blob/master/CHANGELOG.md) for latest
//! release notes.

extern crate reqwest;
pub extern crate slack_api as api;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tungstenite;
#[macro_use]
extern crate log;

pub mod error;
pub use error::Error;

pub use api::{Channel, Group, Im, Team, User, Message};

mod events;
pub use events::Event;

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{self, channel};
use events::{MessageSent, MessageError};

/// Implement this trait in your code to handle message events
pub trait EventHandler {
    /// When a message is received this will be called with self, the slack client,
    /// and the `Event` received.
    fn on_event(&mut self, cli: &RtmClient, event: Event);

    /// Called when the connection is closed for any reason.
    fn on_close(&mut self, cli: &RtmClient);

    /// Called when the connection is opened.
    fn on_connect(&mut self, cli: &RtmClient);
}

/// Used for passing websocket messages in channels
#[derive(Debug)]
enum WsMessage {
    Close,
    Text(String),
}

/// The actual messaging client.
pub struct RtmClient {
    start_response: api::rtm::StartResponse,
    sender: Sender,
    rx: mpsc::Receiver<WsMessage>,
}

/// Thread-safe API for sending messages asynchronously
#[derive(Clone)]
pub struct Sender {
    tx: mpsc::Sender<WsMessage>,
    msg_num: Arc<AtomicUsize>,
}

impl Sender {
    /// Get the next message id
    ///
    /// A value returned from this method *must* be included in the JSON payload
    /// (the `id` field) when constructing your own message.
    pub fn get_msg_uid(&self) -> usize {
        self.msg_num.fetch_add(1, Ordering::SeqCst)
    }

    /// Send a raw message
    ///
    /// Must set `message.id` using result of `get_msg_id()`.
    ///
    /// Success from this API does not guarantee the message is delivered
    /// successfully since that runs on a separate task.
    pub fn send(&self, raw: &str) -> Result<(), Error> {
        self.tx
            .send(WsMessage::Text(raw.to_string()))
            .map_err(|err| Error::Internal(format!("{}", err)))?;
        Ok(())
    }

    /// Send a message to the specified channel id
    ///
    /// Success from this API does not guarantee the message is delivered
    /// successfully since that runs on a separate task.
    ///
    /// `channel_id` is the slack channel id, e.g. `UXYZ1234`, *not* `#general`.
    ///
    /// Only valid after `RtmClient::run`.
    pub fn send_message(&self, channel_id: &str, msg: &str) -> Result<usize, Error> {
        let n = self.get_msg_uid();
        let msg_json = serde_json::to_string(&msg)?;
        let mstr = format!(r#"{{"id": {},"type": "message", "channel": "{}","text": "{}"}}"#,
                           n,
                           channel_id,
                           &msg_json[1..msg_json.len() - 1]);

        self.send(&mstr[..])
            .map_err(|err| Error::Internal(format!("{}", err)))?;

        Ok(n)
    }

    /// Marks connected client as being typing to a channel
    /// This is mostly used to signal to other peers that a message
    /// is being typed. Will have the server send a "user_typing" message to all the
    /// peers.
    /// Slack doc can be found at https://api.slack.com/rtm under "Typing Indicators"
    ///
    /// `channel_id` is the slack channel id, e.g. `UXYZ1234`, not `#general`.
    pub fn send_typing(&self, channel_id: &str) -> Result<usize, Error> {
        let n = self.get_msg_uid();
        let mstr = format!(r#"{{"id": {}, "type": "typing", "channel": "{}"}}"#,
                           n,
                           channel_id);

        self.send(&mstr)
            .map_err(|err| Error::Internal(format!("{:?}", err)))?;
        Ok(n)
    }

    /// Subscribes to presence updates for the given users
    /// This is due to the update in presence events detailed here:
    /// https://api.slack.com/changelog/2017-10-making-rtm-presence-subscription-only
    ///
    /// `user_list` is a slice of the list of users to subscrib, e.g. `W839208`, not @xyz.
    /// The full list of users to subscribe to must be sent each time the subscription should
    /// change
    /// Slack doc can be found at https://api.slack.com/docs/presence-and-status under "Determining
    /// user presence"
    pub fn subscribe_presence(&self, user_list: &[&str]) -> Result<usize, Error> {
        let n = self.get_msg_uid();
        let mstr = format!(r#"{{"type": "presence_sub", "ids": "{:?}"}}"#,
                           user_list);

        self.send(&mstr)
            .map_err(|err| Error::Internal(format!("{:?}", err)))?;
        Ok(n)
    }

    /// Shutdown `RtmClient`
    pub fn shutdown(&self) -> Result<(), Error> {
        self.tx
            .send(WsMessage::Close)
            .map_err(|_| Error::Internal("Error sending shutdown message".into()))
    }
}

impl RtmClient {
    /// Logs in to slack. Call this before calling `run`.
    /// Alternatively use `login_and_run`.
    pub fn login(token: &str) -> Result<RtmClient, Error> {
        let client = reqwest::Client::new();
        let start_response = api::rtm::start(&client, token, &Default::default())?;

        // setup channels for passing messages
        let (tx, rx) = channel::<WsMessage>();
        let sender = Sender {
            tx: tx,
            msg_num: Arc::new(AtomicUsize::new(0)),
        };

        Ok(RtmClient {
               start_response: start_response,
               sender: sender,
               rx: rx,
           })
    }

    /// Runs the message receive loop
    pub fn run<T: EventHandler>(&self, handler: &mut T) -> Result<(), Error> {
        let start_url = self.start_response
            .url
            .as_ref()
            .ok_or(Error::Api("Slack did not provide a URL".into()))?;
        println!("start_url returned is \"{:?}\"", start_url);

        let wss_url = reqwest::Url::parse(&start_url)?;
        let (mut websocket, _resp) = tungstenite::client::connect(wss_url)?;

        // Slack can leave us hanging
        {
            let socket = match *websocket.get_mut() {
                tungstenite::stream::Stream::Plain(ref s) => s,
                tungstenite::stream::Stream::Tls(ref mut t) => t.get_mut()
            };
            socket.set_read_timeout(Some(std::time::Duration::from_secs(30)))?;
            socket.set_write_timeout(Some(std::time::Duration::from_secs(25)))?;
        }

        handler.on_connect(self);

        let mut prev_ = ::std::time::Instant::now();

        // receive loop
        loop {
            // try to write out pending messages (if any)
            loop {
                match self.rx.try_recv() {
                    Ok(msg) => {
                        match msg {
                            WsMessage::Text(text) => {
                                websocket
                                    .write_message(tungstenite::Message::Text(text))?
                            }
                            WsMessage::Close => {
                                handler.on_close(self);
                                return websocket.close(None).map_err(|e| e.into());
                            }
                        }
                    }
                    Err(mpsc::TryRecvError::Disconnected) => {
                        handler.on_close(self);
                        return Err(Error::Internal("rx disconnected".into()));
                    }
                    Err(mpsc::TryRecvError::Empty) => break,
                }
            }

            // blocks until a message is received or websocket errors
            let message = match websocket.read_message() {
                Err(e) => {
                    debug!("{:?}", e);
                    // read failed, try send ping to check still alive
                    websocket.write_message(tungstenite::Message::Ping(vec![]))?;
                    continue;
                }
                Ok(m) => m
            };

            let received = ::std::time::Instant::now(); {
                let print_recieved = |var: &str| {
                    debug!("RTM WS {} recieved {:?} since last msg", var, received - prev_);
                };
                // handle the message
                match message {
                    tungstenite::Message::Text(text) => {
                        match Event::from_json(&text[..]) {
                            Ok(event) => handler.on_event(self, event),
                            Err(err) => {
                                info!("Unable to deserialize slack message, error: {}: json: {}",
                                      err,
                                      text);
                            }
                        }
                    }
                    tungstenite::Message::Binary(_) => print_recieved("Binary"),
                    tungstenite::Message::Ping(_) => print_recieved("Ping"),
                    tungstenite::Message::Pong(_) => print_recieved("Pong"),
                }
            }
            prev_ = received;
        }
    }

    /// Runs the main loop for the client after logging in to slack.
    ///
    /// Returns an error if the process fails at any point, or an Ok(()) on successful
    /// close.
    ///
    /// Takes an `EventHandler` implemented by the user which will be called when `Event`s are
    /// received.
    pub fn login_and_run<T: EventHandler>(token: &str, handler: &mut T) -> Result<(), Error> {
        let client = RtmClient::login(token)?;
        client.run(handler)
    }

    /// Get a reference thread-safe cloneable message `Sender`
    pub fn sender(&self) -> &Sender {
        &self.sender
    }

    /// Returns a reference to the `StartResponse`.
    pub fn start_response(&self) -> &api::rtm::StartResponse {
        &self.start_response
    }
}

impl Event {
    /// Try to deserialize an `Event` from a json-encoded `&str`
    fn from_json(s: &str) -> Result<Event, Error> {
        match serde_json::from_str::<Event>(s) {
            Ok(ev) => Ok(ev),
            Err(e) => {
                // try for the MessageSent / MessageError variants that don't expose type
                if let Ok(ev) = serde_json::from_str::<MessageSent>(s) {
                    Ok(Event::MessageSent(ev))
                } else if let Ok(ev) = serde_json::from_str::<MessageError>(s) {
                    Ok(Event::MessageError(ev))
                } else {
                    Err(e.into())
                }
            }
        }
    }
}
<commit_msg>add query param to start url<commit_after>//
// Copyright 2014-2016 the slack-rs authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Slack realtime messaging client: https://api.slack.com/bot-users
//!
//! See [CHANGELOG.md](https://github.com/slack-rs/slack-rs/blob/master/CHANGELOG.md) for latest
//! release notes.

extern crate reqwest;
pub extern crate slack_api as api;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tungstenite;
#[macro_use]
extern crate log;

pub mod error;
pub use error::Error;

pub use api::{Channel, Group, Im, Team, User, Message};

mod events;
pub use events::Event;

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{self, channel};
use events::{MessageSent, MessageError};

/// Implement this trait in your code to handle message events
pub trait EventHandler {
    /// When a message is received this will be called with self, the slack client,
    /// and the `Event` received.
    fn on_event(&mut self, cli: &RtmClient, event: Event);

    /// Called when the connection is closed for any reason.
    fn on_close(&mut self, cli: &RtmClient);

    /// Called when the connection is opened.
    fn on_connect(&mut self, cli: &RtmClient);
}

/// Used for passing websocket messages in channels
#[derive(Debug)]
enum WsMessage {
    Close,
    Text(String),
}

/// The actual messaging client.
pub struct RtmClient {
    start_response: api::rtm::StartResponse,
    sender: Sender,
    rx: mpsc::Receiver<WsMessage>,
}

/// Thread-safe API for sending messages asynchronously
#[derive(Clone)]
pub struct Sender {
    tx: mpsc::Sender<WsMessage>,
    msg_num: Arc<AtomicUsize>,
}

impl Sender {
    /// Get the next message id
    ///
    /// A value returned from this method *must* be included in the JSON payload
    /// (the `id` field) when constructing your own message.
    pub fn get_msg_uid(&self) -> usize {
        self.msg_num.fetch_add(1, Ordering::SeqCst)
    }

    /// Send a raw message
    ///
    /// Must set `message.id` using result of `get_msg_id()`.
    ///
    /// Success from this API does not guarantee the message is delivered
    /// successfully since that runs on a separate task.
    pub fn send(&self, raw: &str) -> Result<(), Error> {
        self.tx
            .send(WsMessage::Text(raw.to_string()))
            .map_err(|err| Error::Internal(format!("{}", err)))?;
        Ok(())
    }

    /// Send a message to the specified channel id
    ///
    /// Success from this API does not guarantee the message is delivered
    /// successfully since that runs on a separate task.
    ///
    /// `channel_id` is the slack channel id, e.g. `UXYZ1234`, *not* `#general`.
    ///
    /// Only valid after `RtmClient::run`.
    pub fn send_message(&self, channel_id: &str, msg: &str) -> Result<usize, Error> {
        let n = self.get_msg_uid();
        let msg_json = serde_json::to_string(&msg)?;
        let mstr = format!(r#"{{"id": {},"type": "message", "channel": "{}","text": "{}"}}"#,
                           n,
                           channel_id,
                           &msg_json[1..msg_json.len() - 1]);

        self.send(&mstr[..])
            .map_err(|err| Error::Internal(format!("{}", err)))?;

        Ok(n)
    }

    /// Marks connected client as being typing to a channel
    /// This is mostly used to signal to other peers that a message
    /// is being typed. Will have the server send a "user_typing" message to all the
    /// peers.
    /// Slack doc can be found at https://api.slack.com/rtm under "Typing Indicators"
    ///
    /// `channel_id` is the slack channel id, e.g. `UXYZ1234`, not `#general`.
    pub fn send_typing(&self, channel_id: &str) -> Result<usize, Error> {
        let n = self.get_msg_uid();
        let mstr = format!(r#"{{"id": {}, "type": "typing", "channel": "{}"}}"#,
                           n,
                           channel_id);

        self.send(&mstr)
            .map_err(|err| Error::Internal(format!("{:?}", err)))?;
        Ok(n)
    }

    /// Subscribes to presence updates for the given users
    /// This is due to the update in presence events detailed here:
    /// https://api.slack.com/changelog/2017-10-making-rtm-presence-subscription-only
    ///
    /// `user_list` is a slice of the list of users to subscrib, e.g. `W839208`, not @xyz.
    /// The full list of users to subscribe to must be sent each time the subscription should
    /// change
    /// Slack doc can be found at https://api.slack.com/docs/presence-and-status under "Determining
    /// user presence"
    pub fn subscribe_presence(&self, user_list: &[&str]) -> Result<usize, Error> {
        let n = self.get_msg_uid();
        let mstr = format!(r#"{{"type": "presence_sub", "ids": "{:?}"}}"#,
                           user_list);

        self.send(&mstr)
            .map_err(|err| Error::Internal(format!("{:?}", err)))?;
        Ok(n)
    }

    /// Shutdown `RtmClient`
    pub fn shutdown(&self) -> Result<(), Error> {
        self.tx
            .send(WsMessage::Close)
            .map_err(|_| Error::Internal("Error sending shutdown message".into()))
    }
}

impl RtmClient {
    /// Logs in to slack. Call this before calling `run`.
    /// Alternatively use `login_and_run`.
    pub fn login(token: &str) -> Result<RtmClient, Error> {
        let client = reqwest::Client::new();
        let start_response = api::rtm::start(&client, token, &Default::default())?;

        // setup channels for passing messages
        let (tx, rx) = channel::<WsMessage>();
        let sender = Sender {
            tx: tx,
            msg_num: Arc::new(AtomicUsize::new(0)),
        };

        Ok(RtmClient {
               start_response: start_response,
               sender: sender,
               rx: rx,
           })
    }

    /// Runs the message receive loop
    pub fn run<T: EventHandler>(&self, handler: &mut T) -> Result<(), Error> {
        let start_url = self.start_response
            .url
            .as_ref()
            .ok_or(Error::Api("Slack did not provide a URL".into()))?;
        let mut start_url_qp = start_url.clone();
        start_url_qp.push_str(&("?batch_presence_aware=1".to_string()));
        println!("start_url returned is \"{:?}\"", start_url_qp);
        let wss_url = reqwest::Url::parse(&start_url_qp)?;
        let (mut websocket, _resp) = tungstenite::client::connect(wss_url)?;

        // Slack can leave us hanging
        {
            let socket = match *websocket.get_mut() {
                tungstenite::stream::Stream::Plain(ref s) => s,
                tungstenite::stream::Stream::Tls(ref mut t) => t.get_mut()
            };
            socket.set_read_timeout(Some(std::time::Duration::from_secs(30)))?;
            socket.set_write_timeout(Some(std::time::Duration::from_secs(25)))?;
        }

        handler.on_connect(self);

        let mut prev_ = ::std::time::Instant::now();

        // receive loop
        loop {
            // try to write out pending messages (if any)
            loop {
                match self.rx.try_recv() {
                    Ok(msg) => {
                        match msg {
                            WsMessage::Text(text) => {
                                websocket
                                    .write_message(tungstenite::Message::Text(text))?
                            }
                            WsMessage::Close => {
                                handler.on_close(self);
                                return websocket.close(None).map_err(|e| e.into());
                            }
                        }
                    }
                    Err(mpsc::TryRecvError::Disconnected) => {
                        handler.on_close(self);
                        return Err(Error::Internal("rx disconnected".into()));
                    }
                    Err(mpsc::TryRecvError::Empty) => break,
                }
            }

            // blocks until a message is received or websocket errors
            let message = match websocket.read_message() {
                Err(e) => {
                    debug!("{:?}", e);
                    // read failed, try send ping to check still alive
                    websocket.write_message(tungstenite::Message::Ping(vec![]))?;
                    continue;
                }
                Ok(m) => m
            };

            let received = ::std::time::Instant::now(); {
                let print_recieved = |var: &str| {
                    debug!("RTM WS {} recieved {:?} since last msg", var, received - prev_);
                };
                // handle the message
                match message {
                    tungstenite::Message::Text(text) => {
                        match Event::from_json(&text[..]) {
                            Ok(event) => handler.on_event(self, event),
                            Err(err) => {
                                info!("Unable to deserialize slack message, error: {}: json: {}",
                                      err,
                                      text);
                            }
                        }
                    }
                    tungstenite::Message::Binary(_) => print_recieved("Binary"),
                    tungstenite::Message::Ping(_) => print_recieved("Ping"),
                    tungstenite::Message::Pong(_) => print_recieved("Pong"),
                }
            }
            prev_ = received;
        }
    }

    /// Runs the main loop for the client after logging in to slack.
    ///
    /// Returns an error if the process fails at any point, or an Ok(()) on successful
    /// close.
    ///
    /// Takes an `EventHandler` implemented by the user which will be called when `Event`s are
    /// received.
    pub fn login_and_run<T: EventHandler>(token: &str, handler: &mut T) -> Result<(), Error> {
        let client = RtmClient::login(token)?;
        client.run(handler)
    }

    /// Get a reference thread-safe cloneable message `Sender`
    pub fn sender(&self) -> &Sender {
        &self.sender
    }

    /// Returns a reference to the `StartResponse`.
    pub fn start_response(&self) -> &api::rtm::StartResponse {
        &self.start_response
    }
}

impl Event {
    /// Try to deserialize an `Event` from a json-encoded `&str`
    fn from_json(s: &str) -> Result<Event, Error> {
        match serde_json::from_str::<Event>(s) {
            Ok(ev) => Ok(ev),
            Err(e) => {
                // try for the MessageSent / MessageError variants that don't expose type
                if let Ok(ev) = serde_json::from_str::<MessageSent>(s) {
                    Ok(Event::MessageSent(ev))
                } else if let Ok(ev) = serde_json::from_str::<MessageError>(s) {
                    Ok(Event::MessageError(ev))
                } else {
                    Err(e.into())
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>#![deny(unused_must_use)]
#[macro_export]
macro_rules! FSM {
    (@inner next $new_state:ident{$($new_el:ident:$new_el_val:expr),*}) => (
        $new_state{$($new_el:$new_el_val),*}
    );
    (@inner next $new_state:ident) => (
        $new_state{}
    );

    (@inner command $cur:ident;$callback:block;$new_state:ident$({$($new_el:ident:$new_el_val:expr),*})*) => (
        {
            $callback;
            Some(States::$new_state{context: FSM!(@inner next $new_state$({$($new_el:$new_el_val),*})*)})
        }
    );

    (@inner command $cur:ident;$callback:block;) => (
        {
            $callback;
            Some(States::__SameState__)
        }
    );

    (@inner command $cur:ident; ;$new_state:ident$({$($new_el:ident:$new_el_val:expr),*})*) => (
        {
            Some(States::$new_state{context: FSM!(@inner next $new_state$({$($new_el:$new_el_val),*})*)})
        }
    );

    (@inner command $cur:ident ; ;) => (
        Some(States::__SameState__)
    );

    (@inner context $ss:ident $sel:ident)=>(let $sel = $ss;);
    (@inner context $ss:ident )=>();

    (@inner >> $($sel:ident)* $income:block) => (
            fn enter(&mut self) -> Result<(), ()> {
                FSM!(@inner context self $($sel)*);
                $income
                Ok(())
            }
    );
    (@inner << $($sel:ident)* $outcome:block) => (
            fn leave(&mut self) -> Result<(), ()> {
                FSM!(@inner context self $($sel)*);
                $outcome
                Ok(())
            }
    );
    (@inner >> $($sel:ident)*) => (
            fn enter(&mut self) -> Result<(), ()> {
                Ok(())
            }
    );
    (@inner << $($sel:ident)*) => (
            fn leave(&mut self) -> Result<(), ()> {
                Ok(())
            }
    );

    (@inner params $state:ident {$($el:ident:$typ:ty);*}) => (
        #[derive(Debug)]
        #[derive(PartialEq)]
        #[derive(Copy)]
        #[derive(Clone)]
        pub struct $state {pub $($el:$typ),*}
    );
    (@inner params $state:ident) => (
        #[derive(Debug)]
        #[derive(PartialEq)]
        #[derive(Copy)]
        #[derive(Clone)]
        pub struct $state {}
    );
    (@inner initial $initial:ident{$($init_field:ident:$init_val:expr),*}) => ($initial{$($init_field: $init_val),*});
    (@inner initial $initial:ident) => ($initial{});

(
    $machine:ident ($initial:ident$({$($init_field:ident:$init_val:expr),*})*)
    states[$($states:ident),*]
    commands[$($commands:ident),*]

    $(($state:ident $($sel:ident)*$({$($el:ident:$typ:ty);*})*:
        $(>> $income:block)*
        $(<< $outcome:block)*
        $($cmd:ident $($callback:block)* => $($new_state:ident$({$($new_el:ident:$new_el_val:expr),*})*)*;)*
    ))*
) => (
    #[allow(non_snake_case)]
    #[allow(unused_imports)]
    #[allow(dead_code)]
    #[allow(unused_variables)]
    mod $machine {
        use super::*;
        trait CanDoJob {
            fn do_job(&mut self, cmd: &Commands) -> Option<States>;
            fn leave(&mut self) -> Result<(), ()>;
            fn enter(&mut self) -> Result<(), ()>;
        }

        $(
        FSM!(@inner params $state $({$($el:$typ);*})*);

        impl CanDoJob for $state {
            fn do_job(&mut self, cmd: & Commands) -> Option<States> {
                FSM!(@inner context self $($sel)*);
                match *cmd {
                    $(Commands::$cmd => {FSM!(@inner command self;$($callback)*;$($new_state$({$($new_el:$new_el_val),*})*)*)})*
                    _ => None
                }
            }

            FSM!(@inner >> $($sel)* $($income)*);
            FSM!(@inner << $($sel)* $($outcome)*);
        }
        )*

        #[derive(Debug)]
        #[derive(PartialEq)]
        #[derive(Copy)]
        #[derive(Clone)]
        pub enum States {
            __SameState__,
            $($states {context: $states}),*
        }

        #[derive(Debug)]
        #[derive(PartialEq)]
        pub enum Commands {
            $($commands),*
        }

        pub struct Machine {
            state: States
        }
        pub fn new() -> Machine {
            let mut context = FSM!(@inner initial $initial $({$($init_field: $init_val),*})*);
            context.enter().unwrap();
            Machine{state: States::$initial{context: context}}
        }

        impl Machine {
            pub fn execute(&mut self, cmd: & Commands) -> Result<(),()>{
                match {
                    match self.state {
                        States::__SameState__ => None,
                        $(States::$state{ ref mut context } => context.do_job(cmd)),*
                    }
                } {
                    Some(x) => {
                        match x {
                            States::__SameState__ => {},
                            _ => {
                                self.change_state(x)
                            }
                        };Ok(())
                    },
                    None => {println!("Wrong operation {:?} for {:?} state!", cmd, self.state); Err(())}
                }
            }
            fn change_state(&mut self, new_state: States) {
                match self.state {
                    States::__SameState__ => Ok(()),
                    $(States::$state{ ref mut context } => context.leave()),*
                }.unwrap();
                self.state = new_state;
                match self.state {
                    States::__SameState__ => Ok(()),
                    $(States::$state{ ref mut context } => context.enter()),*
                }.unwrap();
            }
            pub fn state(&self) -> States {
                self.state.clone()
            }
        }
    }
)
}

#[cfg(test)]
mod tests {
    fn tes(x:i16) {
        println!("x:{}",x);
    }

    FSM!(
    Mach1 (New{x:0})

    states[New,InConfig,Operational]
    commands[Configure, ConfigureDone, Drop]

    ( New context{x: i16}:
        >> {println!("Enter {:?}", context)}
        << {println!("Leave {:?}", context)}
        Configure     {println!("In New with context val: {}", context.x);} =>     InConfig{x:context.x+1, y:0};
        ConfigureDone => New{x:0};
    )
    ( InConfig context{x:i16; y:i16}:
        >> {println!("Enter {:?}", context)}
        << {println!("Leave {:?}", context)}
        ConfigureDone {tes(context.x)}=> Operational;
    )
    ( Operational context:
        >> {println!("Enter {:?}", context)}
        << {println!("Leave {:?}", context)}
        ConfigureDone =>;
        Drop => New{x:0};
    )
    );

    FSM!(
    Mach2 (State1)

    states[State1,State2,State3]
    commands[ToState1, ToState2, ToState3]

    ( State1 :
        ToState2 => State2;
    )
    ( State2 :
        ToState3 => State3;
    )
    ( State3 :
        ToState1 => State1;
    )
    );

    #[test]
    fn test1() {
        let mut m = Mach1::new();
        m.execute(&Mach1::Commands::Configure).unwrap();
        m.execute(&Mach1::Commands::ConfigureDone).unwrap();
        m.execute(&Mach1::Commands::Drop).unwrap();
        m.execute(&Mach1::Commands::Configure).unwrap();
        m.execute(&Mach1::Commands::ConfigureDone).unwrap();
        m.execute(&Mach1::Commands::ConfigureDone).unwrap();
        m.execute(&Mach1::Commands::ConfigureDone).unwrap();
    }

    #[test]
    #[should_panic]
    fn test2() {
        let mut m = Mach2::new();
        m.execute(&Mach2::Commands::ToState2).unwrap();
        m.execute(&Mach2::Commands::ToState3).unwrap();
        m.execute(&Mach2::Commands::ToState1).unwrap();
        m.execute(&Mach2::Commands::ToState3).unwrap();
    }
}
<commit_msg>Add examples to the lib.<commit_after>#![deny(unused_must_use)]
//! State machine generator
//!
//! State machine consists of:
//! Name, initial state, List of States, List of Commands, list of States Nodes.
//! Each State Node contain: Name, State Context (optional), list of Command Reactions.
//! Each Command Reaction contain: Command to react on, user-defined code of reaction (optional) and
//!     next State of machine (optional).
//!
//! Simplest state machine example:
//!
//! ```
//! #[macro_use] extern crate Rust_fsm;
//!
//! FSM!(
//!     Simple(A) // Name and initial State
//!     states[A,B] // list of States
//!     commands[Next] // list of Commands
//!     (A: // State Node
//!         Next => B; // Command Reaction. Just change state to B
//!     )
//!     (B:
//!         Next => A;
//!     )
//! );
//!
//! # fn main() {
//! use Simple::*;
//!
//! let mut machine = Simple::new();
//! assert!(match machine.state(){States::A{..}=>true,_=>false});
//! machine.execute(&Simple::Commands::Next).unwrap();
//! assert!(match machine.state(){States::B{..}=>true,_=>false});
//! machine.execute(&Simple::Commands::Next).unwrap();
//! assert!(match machine.state(){States::A{..}=>true,_=>false});
//! # }
//! ```
//!
//! You can add some intelligence to machine:
//!
//! ```
//! #[macro_use] extern crate Rust_fsm;
//!
//! FSM!(
//!     Simple(A{counter:0}) // Name and initial State with initial value
//!     states[A,B] // list of States
//!     commands[Next] // list of Commands
//!     (A context{counter:i16}: // State Node and this state context description with binding name
//!         Next {context.counter=context.counter+1}=> B{counter:context.counter}; // Command Reaction. Now on command Next we add 1 to our context. Also we change state to B and init it with our x value.
//!     )
//!     (B context{counter:i16}:
//!         Next {context.counter=context.counter+1}=> A{counter:context.counter};
//!     )
//! );
//!
//! # fn main() {
//! use Simple::*;
//!
//! let mut machine = Simple::new();
//! assert!(match machine.state(){
//!     States::A{context}=> if context.counter == 0 {true} else {false}, // We are in state A and have our initial value 0
//!     _=>false
//! });
//! machine.execute(&Simple::Commands::Next).unwrap();
//! assert!(match machine.state(){
//!     States::B{context}=> if context.counter == 1 {true} else {false}, // We are in state B and have counter == 1
//!     _=>false
//! });
//! machine.execute(&Simple::Commands::Next).unwrap();
//! assert!(match machine.state(){
//!     States::A{context}=> if context.counter == 2 {true} else {false}, // Again in state A and have counter == 2
//!     _=>false
//! });
//! # }
//! ```
//! ```
//! #[macro_use] extern crate Rust_fsm;
//!
//! FSM!(
//!     Simple(A{counter:0}) // Name and initial State with initial value
//!     states[A,B] // list of States
//!     commands[Next] // list of Commands
//!     (A context{counter:i16}: // State Node and this state context description with binding name
//!         >> {context.counter = context.counter+1;} // Execute when enter state A
//!         << {context.counter = context.counter+1;} // Execute when leave state A
//!         Next {context.counter=context.counter+1;} => B{counter:context.counter}; // Command Reaction. Now on command Next we add 1 to our context. Also we change state to B and init it with our x value.
//!     )
//!     (B context{counter:i16}:
//!         Next {context.counter=context.counter+1} => A{counter:context.counter};
//!     )
//! );
//!
//! # fn main() {
//! use Simple::*;
//!
//! let mut machine = Simple::new();
//! assert!(match machine.state(){
//!
//!     // We are in state A and have value 1. Because Enter State callback executed.
//!
//!     States::A{context}=> if context.counter == 1 {true} else {false},
//!     _=>false
//! });
//! machine.execute(&Simple::Commands::Next).unwrap();
//! assert!(match machine.state(){
//!
//!     // We are in state B and have counter == 2. Increment happen on User Code execution. Execution of Leave state callback happen after we transfer data to the next state.
//!
//!     States::B{context}=> {println!("context counter: {}", context.counter);if context.counter == 2 {true} else {false}},
//!     _=>false
//! });
//! machine.execute(&Simple::Commands::Next).unwrap();
//! assert!(match machine.state(){
//!
//!     // Again in state A and have counter == 4. Increment happen on User Code execution and on state A enter.
//!
//!     States::A{context}=> if context.counter == 4 {true} else {false},
//!     _=>false
//! });
//! # }
//! ```
//!

#[macro_export]
macro_rules! FSM {

    // Initialize state by values
    (@inner next $new_state:ident{$($new_el:ident:$new_el_val:expr),*}) => (
        $new_state{$($new_el:$new_el_val),*}
    );

    // if state have no fields to initialize. Just for remove redundant curl braces.
    (@inner next $new_state:ident) => (
        $new_state{}
    );

    // If Event have user-defined code and move machine to new state. Execute code and return new state.
    (@inner command $cur:ident;$callback:block;$new_state:ident$({$($new_el:ident:$new_el_val:expr),*})*) => (
        {
            $callback;
            Some(States::$new_state{context: FSM!(@inner next $new_state$({$($new_el:$new_el_val),*})*)})
        }
    );

    // If Event have user-defined code and don't move machine to new state. Execute code and return __SameState__ .
    (@inner command $cur:ident;$callback:block;) => (
        {
            $callback;
            Some(States::__SameState__)
        }
    );

    // If Event have no user-defined code and move machine to new state. Just return new state.
    (@inner command $cur:ident; ;$new_state:ident$({$($new_el:ident:$new_el_val:expr),*})*) => (
        {
            Some(States::$new_state{context: FSM!(@inner next $new_state$({$($new_el:$new_el_val),*})*)})
        }
    );

    // If Event have nothing to do on event. Just return __SameState__.
    (@inner command $cur:ident ; ;) => (
        Some(States::__SameState__)
    );

    (@inner context $ss:ident $sel:ident)=>(let $sel = $ss;);
    (@inner context $ss:ident )=>();

    // Enter/Leave processors with and without user-defined code.
    (@inner >> $($sel:ident)* $income:block) => (
            fn enter(&mut self) -> Result<(), ()> {
                FSM!(@inner context self $($sel)*);
                $income
                Ok(())
            }
    );
    (@inner << $($sel:ident)* $outcome:block) => (
            fn leave(&mut self) -> Result<(), ()> {
                FSM!(@inner context self $($sel)*);
                $outcome
                Ok(())
            }
    );
    (@inner >> $($sel:ident)*) => (
            fn enter(&mut self) -> Result<(), ()> {
                Ok(())
            }
    );
    (@inner << $($sel:ident)*) => (
            fn leave(&mut self) -> Result<(), ()> {
                Ok(())
            }
    );

    // This structs keep user-defined contexts for states.
    (@inner params $state:ident {$($el:ident:$typ:ty);*}) => (
        #[derive(Debug)]
        #[derive(PartialEq)]
        #[derive(Copy)]
        #[derive(Clone)]
        pub struct $state {pub $($el:$typ),*}
    );
    (@inner params $state:ident) => (
        #[derive(Debug)]
        #[derive(PartialEq)]
        #[derive(Copy)]
        #[derive(Clone)]
        pub struct $state {}
    );
    (@inner initial $initial:ident{$($init_field:ident:$init_val:expr),*}) => ($initial{$($init_field: $init_val),*});
    (@inner initial $initial:ident) => ($initial{});

// Main pattern

(
    $machine:ident ($initial:ident$({$($init_field:ident:$init_val:expr),*})*)
    states[$($states:ident),*]
    commands[$($commands:ident),*]

    $(($state:ident $($sel:ident)*$({$($el:ident:$typ:ty);*})*:
        $(>> $income:block)*
        $(<< $outcome:block)*
        $($cmd:ident $($callback:block)* => $($new_state:ident$({$($new_el:ident:$new_el_val:expr),*})*)*;)*
    ))*
) => (
    #[allow(non_snake_case)]
    #[allow(unused_imports)]
    #[allow(dead_code)]
    #[allow(unused_variables)]
    mod $machine {
        use super::*;
        trait CanDoJob {
            fn do_job(&mut self, cmd: &Commands) -> Option<States>;
            fn leave(&mut self) -> Result<(), ()>;
            fn enter(&mut self) -> Result<(), ()>;
        }

        $(
        FSM!(@inner params $state $({$($el:$typ);*})*);

        impl CanDoJob for $state {
            fn do_job(&mut self, cmd: & Commands) -> Option<States> {
                FSM!(@inner context self $($sel)*);
                match *cmd {
                    $(Commands::$cmd => {FSM!(@inner command self;$($callback)*;$($new_state$({$($new_el:$new_el_val),*})*)*)})*
                    _ => None
                }
            }

            FSM!(@inner >> $($sel)* $($income)*);
            FSM!(@inner << $($sel)* $($outcome)*);
        }
        )*

        #[derive(Debug)]
        #[derive(PartialEq)]
        #[derive(Copy)]
        #[derive(Clone)]
        pub enum States {
            __SameState__,
            $($states {context: $states}),*
        }

        #[derive(Debug)]
        #[derive(PartialEq)]
        pub enum Commands {
            $($commands),*
        }

        pub struct Machine {
            state: States
        }
        pub fn new() -> Machine {
            let mut context = FSM!(@inner initial $initial $({$($init_field: $init_val),*})*);
            context.enter().unwrap();
            Machine{state: States::$initial{context: context}}
        }

        impl Machine {
            pub fn execute(&mut self, cmd: & Commands) -> Result<(),()>{
                match {
                    match self.state {
                        States::__SameState__ => None,
                        $(States::$state{ ref mut context } => context.do_job(cmd)),*
                    }
                } {
                    Some(x) => {
                        match x {
                            States::__SameState__ => {},
                            _ => {
                                self.change_state(x)
                            }
                        };Ok(())
                    },
                    None => {println!("Wrong operation {:?} for {:?} state!", cmd, self.state); Err(())}
                }
            }
            fn change_state(&mut self, new_state: States) {
                match self.state {
                    States::__SameState__ => Ok(()),
                    $(States::$state{ ref mut context } => context.leave()),*
                }.unwrap();
                self.state = new_state;
                match self.state {
                    States::__SameState__ => Ok(()),
                    $(States::$state{ ref mut context } => context.enter()),*
                }.unwrap();
            }
            pub fn state(&self) -> States {
                self.state.clone()
            }
        }
    }
)
}

#[cfg(test)]
mod tests {
    fn tes(x:i16) {
        println!("x:{}",x);
    }

    FSM!(
    Mach1 (New{x:0})

    states[New,InConfig,Operational]
    commands[Configure, ConfigureDone, Drop]

    ( New context{x: i16}:
        >> {println!("Enter {:?}", context)}
        << {println!("Leave {:?}", context)}
        Configure     {println!("In New with context val: {}", context.x);} =>     InConfig{x:context.x+1, y:0};
        ConfigureDone => New{x:0};
    )
    ( InConfig context{x:i16; y:i16}:
        >> {println!("Enter {:?}", context)}
        << {println!("Leave {:?}", context)}
        ConfigureDone {tes(context.x)}=> Operational;
    )
    ( Operational context:
        >> {println!("Enter {:?}", context)}
        << {println!("Leave {:?}", context)}
        ConfigureDone =>;
        Drop => New{x:0};
    )
    );

    FSM!(
    Mach2 (State1)

    states[State1,State2,State3]
    commands[ToState1, ToState2, ToState3]

    ( State1 :
        ToState2 => State2;
    )
    ( State2 :
        ToState3 => State3;
    )
    ( State3 :
        ToState1 => State1;
    )
    );

    #[test]
    fn test1() {
        let mut m = Mach1::new();
        m.execute(&Mach1::Commands::Configure).unwrap();
        m.execute(&Mach1::Commands::ConfigureDone).unwrap();
        m.execute(&Mach1::Commands::Drop).unwrap();
        m.execute(&Mach1::Commands::Configure).unwrap();
        m.execute(&Mach1::Commands::ConfigureDone).unwrap();
        m.execute(&Mach1::Commands::ConfigureDone).unwrap();
        m.execute(&Mach1::Commands::ConfigureDone).unwrap();
    }

    #[test]
    #[should_panic]
    fn test2() {
        let mut m = Mach2::new();
        m.execute(&Mach2::Commands::ToState2).unwrap();
        m.execute(&Mach2::Commands::ToState3).unwrap();
        m.execute(&Mach2::Commands::ToState1).unwrap();
        m.execute(&Mach2::Commands::ToState3).unwrap();
    }
}
<|endoftext|>


<commit_before>//! The `rust-unidecode` library is a Rust port of Sean M. Burke's famous
//! [`Text::Unidecode`](http://search.cpan.org/~sburke/Text-Unidecode-1.23/lib/Text/Unidecode.pm)
//! module for Perl. It transliterates Unicode strings such as "Æneid" into pure
//! ASCII ones such as "AEneid." For a detailed explanation on the rationale
//! behind using such a library, you can refer to both the documentation of the
//! original module and
//! [this article](http://interglacial.com/~sburke/tpj/as_html/tpj22.html)
//! written by Burke in 2001.
//!
//! The data set used to translate the Unicode was ported directly from the
//! `Text::Unidecode` module using a Perl script, so `rust-unidecode` should
//! produce identical output.
//!
//! Examples
//! --------
//! ```ignore
//! extern crate unidecode;
//! use unidecode::unidecode;
//!
//! assert_eq!(unidecode("Æneid"), "AEneid");
//! assert_eq!(unidecode("étude"), "etude");
//! assert_eq!(unidecode("北亰"), "Bei Jing");
//! assert_eq!(unidecode("ᔕᓇᓇ"), "shanana");
//! assert_eq!(unidecode("げんまい茶"), "genmaiCha ");
//! ```

mod data;
use data::MAPPING;

/// This function takes any Unicode string and returns an ASCII transliteration
/// of that string.
///
/// # Guarantees
///
/// * The `String` returned will be valid ASCII; the decimal representation of
///   every `char` in the string will be between 0 and 127, inclusive.
/// * Every ASCII character (0x0000 - 0x007F) is mapped to itself.
/// * All Unicode characters will translate to a string containing newlines
///   (`"\n"`) or ASCII characters in the range 0x0020 - 0x007E. So for example,
///   no Unicode character will translate to `\u{01}`. The exception is if the
///   ASCII character itself is passed in, in which case it will be mapped to
///   itself. (So `'\u{01}'` will be mapped to `"\u{01}"`.)
///
/// # Warnings
///
/// * As stated, some transliterations do produce `\n` characters.
/// * Some Unicode characters transliterate to an empty string, either on
///   purpose or because `rust-unidecode` does not know about the character.
/// * Some Unicode characters are unknown and transliterate to `"[?]"`.
/// * Many Unicode characters transliterate to multi-character strings. For
///   example, 北 is transliterated as "Bei ".
///
/// These guarantees/warnings are paraphrased from the original
/// `Text::Unidecode` documentation.
pub fn unidecode(s: &str) -> String {
    s.chars().map(|ch| unidecode_char(ch)).collect()
}

/// This function takes a single Unicode character and returns an ASCII
/// transliteration.
///
/// The warnings and guarantees of `unidecode()` apply to this function as well.
#[inline]
pub fn unidecode_char(ch: char) -> &'static str {
    MAPPING.get(ch as usize).map(|&s| s).unwrap_or("")
}
<commit_msg>added examples for unidecode_char<commit_after>//! The `rust-unidecode` library is a Rust port of Sean M. Burke's famous
//! [`Text::Unidecode`](http://search.cpan.org/~sburke/Text-Unidecode-1.23/lib/Text/Unidecode.pm)
//! module for Perl. It transliterates Unicode strings such as "Æneid" into pure
//! ASCII ones such as "AEneid." For a detailed explanation on the rationale
//! behind using such a library, you can refer to both the documentation of the
//! original module and
//! [this article](http://interglacial.com/~sburke/tpj/as_html/tpj22.html)
//! written by Burke in 2001.
//!
//! The data set used to translate the Unicode was ported directly from the
//! `Text::Unidecode` module using a Perl script, so `rust-unidecode` should
//! produce identical output.
//!
//! Examples
//! --------
//! ```ignore
//! extern crate unidecode;
//! use unidecode::unidecode;
//!
//! assert_eq!(unidecode("Æneid"), "AEneid");
//! assert_eq!(unidecode("étude"), "etude");
//! assert_eq!(unidecode("北亰"), "Bei Jing");
//! assert_eq!(unidecode("ᔕᓇᓇ"), "shanana");
//! assert_eq!(unidecode("げんまい茶"), "genmaiCha ");
//! ```

mod data;
use data::MAPPING;

/// This function takes any Unicode string and returns an ASCII transliteration
/// of that string.
///
/// # Guarantees
///
/// * The `String` returned will be valid ASCII; the decimal representation of
///   every `char` in the string will be between 0 and 127, inclusive.
/// * Every ASCII character (0x0000 - 0x007F) is mapped to itself.
/// * All Unicode characters will translate to a string containing newlines
///   (`"\n"`) or ASCII characters in the range 0x0020 - 0x007E. So for example,
///   no Unicode character will translate to `\u{01}`. The exception is if the
///   ASCII character itself is passed in, in which case it will be mapped to
///   itself. (So `'\u{01}'` will be mapped to `"\u{01}"`.)
///
/// # Warnings
///
/// * As stated, some transliterations do produce `\n` characters.
/// * Some Unicode characters transliterate to an empty string, either on
///   purpose or because `rust-unidecode` does not know about the character.
/// * Some Unicode characters are unknown and transliterate to `"[?]"`.
/// * Many Unicode characters transliterate to multi-character strings. For
///   example, 北 is transliterated as "Bei ".
///
/// These guarantees/warnings are paraphrased from the original
/// `Text::Unidecode` documentation.
pub fn unidecode(s: &str) -> String {
    s.chars().map(|ch| unidecode_char(ch)).collect()
}

/// This function takes a single Unicode character and returns an ASCII
/// transliteration.
///
/// The warnings and guarantees of `unidecode()` apply to this function as well.
///
/// Examples
/// --------
/// ```ignore
/// assert_eq!(unidecode_char('Æ'), "AE");
/// assert_eq!(unidecode_char('北'), "Bei ");
/// ```
#[inline]
pub fn unidecode_char(ch: char) -> &'static str {
    MAPPING.get(ch as usize).map(|&s| s).unwrap_or("")
}
<|endoftext|>


<commit_before>//! Multi-producer multi-consumer channels for message passing.
//!
//! Channels are concurrent FIFO queues used for passing messages between threads.
//!
//! Crossbeam's channels are an alternative to the [`std::sync::mpsc`] channels provided by the
//! standard library. They are an improvement in pretty much all aspects: ergonomics, flexibility,
//! features, performance.
//!
//! # Types of channels
//!
//! A channel can be constructed by calling functions [`unbounded`] and [`bounded`]. The former
//! creates a channel of unbounded capacity (i.e. it can contain an arbitrary number of messages),
//! while the latter creates a channel of bounded capacity (i.e. there is a limit to how many
//! messages it can hold at a time).
//!
//! Both constructors returns a pair of two values: a sender and a receiver. Senders and receivers
//! represent two opposite sides of a channel. Messages are sent using senders and received using
//! receivers.
//!
//! Creating an unbounded channel:
//!
//! ```
//! use crossbeam_channel::unbounded;
//!
//! // Create an unbounded channel.
//! let (tx, rx) = unbounded();
//!
//! // Can send an arbitrarily large number of messages.
//! for i in 0..1000 {
//!     tx.try_send(i).unwrap();
//! }
//! ```
//!
//! Creating a bounded channel:
//!
//! ```
//! use crossbeam_channel::bounded;
//!
//! // Create a channel that can hold at most 5 messages at a time.
//! let (tx, rx) = bounded(5);
//!
//! // Can send only 5 messages.
//! for i in 0..5 {
//!     tx.try_send(i).unwrap();
//! }
//!
//! // An attempt to send one more message will fail.
//! assert!(tx.try_send(5).is_err());
//! ```
//!
//! An interesting special case is a bounded, zero-capacity channel. This kind of channel cannot
//! hold any messages at all! In order to send a message through the channel, another thread must
//! be waiting at the other end of it at the same time:
//!
//! ```
//! use crossbeam_channel::bounded;
//!
//! use std::thread;
//!
//! // Create a zero-capacity channel.
//! let (tx, rx) = bounded(0);
//!
//! // Spawn a thread that sends a message into the channel.
//! thread::spawn(move || tx.send("Hi!").unwrap());
//!
//! // Receive the message.
//! assert_eq!(rx.recv(), Ok("Hi!"));
//! ```
//!
//! # Sharing channels
//!
//! Senders and receivers can be either shared by reference or cloned and then sent to other
//! threads. Feel free to use any of these two approaches as you like.
//!
//! Sharing by reference:
//!
//! ```
//! extern crate crossbeam_channel;
//! extern crate crossbeam_utils;
//! # fn main() {
//!
//! use crossbeam_channel::unbounded;
//!
//! let (tx, rx) = unbounded();
//!
//! crossbeam_utils::scoped::scope(|s| {
//!     // Spawn a thread that sends one message and then receives one.
//!     s.spawn(|| {
//!         tx.send(1).unwrap();
//!         rx.recv().unwrap();
//!     });
//!
//!     // Spawn another thread that does the same thing.
//!     // Both closures capture `tx` and `rx` by reference.
//!     s.spawn(|| {
//!         tx.send(2).unwrap();
//!         rx.recv().unwrap();
//!     });
//! });
//!
//! # }
//! ```
//!
//! Sharing by sending:
//!
//! ```
//! use std::thread;
//! use crossbeam_channel::unbounded;
//!
//! let (tx, rx) = unbounded();
//! let (tx2, rx2) = (tx.clone(), rx.clone());
//!
//! // Spawn a thread that sends one message and then receives one.
//! // Here, `tx` and `rx` are moved into the closure (sent into the thread).
//! thread::spawn(move || {
//!     tx.send(1).unwrap();
//!     rx.recv().unwrap();
//! });
//!
//! // Spawn another thread that does the same thing.
//! // Here, `tx2` and `rx2` are moved into the closure (sent into the thread).
//! thread::spawn(move || {
//!     tx2.send(2).unwrap();
//!     rx2.recv().unwrap();
//! });
//! ```
//!
//! # Disconnection
//!
//! As soon as all senders or all receivers associated with a channel are dropped, it becomes
//! disconnected. Messages cannot be sent into a disconnected channel anymore, but the remaining
//! messages can still be received.
//!
//! ```
//! use crossbeam_channel::{unbounded, TrySendError};
//!
//! let (tx, rx) = unbounded();
//!
//! // The only receiver is dropped, disconnecting the channel.
//! drop(rx);
//!
//! // Attempting to send a message will result in an error.
//! assert_eq!(tx.try_send("hello"), Err(TrySendError::Disconnected("hello")));
//! ```
//!
//! ```
//! use crossbeam_channel::{unbounded, TryRecvError};
//!
//! let (tx, rx) = unbounded();
//! tx.try_send(1).unwrap();
//! tx.try_send(2).unwrap();
//! tx.try_send(3).unwrap();
//!
//! // The only sender is dropped, disconnecting the channel.
//! drop(tx);
//!
//! // The remaining messages can be received.
//! assert_eq!(rx.try_recv(), Ok(1));
//! assert_eq!(rx.try_recv(), Ok(2));
//! assert_eq!(rx.try_recv(), Ok(3));
//!
//! // However, attempting to receive another message will result in an error.
//! assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
//! ```
//!
//! # Blocking and non-blocking operations
//!
//! Send and receive operations come in three variants:
//!
//! 1. Non-blocking: [`try_send`] and [`try_recv`].
//! 2. Blocking: [`try_send`] and [`try_recv`].
//! 3. Blocking with a timeout: [`send_timeout`] and [`recv_timeout`].
//!
//! The non-blocking variant attempts to perform the operation, but doesn't block the current
//! thread on failure (e.g. if receiving a message from an empty channel).
//!
//! The blocking variant will wait until the operation can be performed or the channel becomes
//! disconnected.
//!
//! Blocking with a timeout does the same thing, but blocks the current thread only for a limited
//! amount time.
//!
//! # Iteration
//!
//! Receivers can be turned into iterators. For example, calling [`iter`] creates an iterator that
//! returns messages until the channel is disconnected. Note that iteration may block while waiting
//! for the next message.
//!
//! ```
//! use crossbeam_channel::unbounded;
//!
//! let (tx, rx) = unbounded();
//! tx.send(1).unwrap();
//! tx.send(2).unwrap();
//! tx.send(3).unwrap();
//!
//! // Drop the sender in order to disconnect the channel.
//! drop(tx);
//!
//! // Receive all remaining messages.
//! let v: Vec<_> = rx.iter().collect();
//! assert_eq!(v, [1, 2, 3]);
//! ```
//!
//! By calling [`try_iter`] it is also possible to create an iterator that returns messages until
//! the channel is empty. This iterator will never block the current thread.
//!
//! ```
//! use crossbeam_channel::unbounded;
//!
//! let (tx, rx) = unbounded();
//! tx.send(1).unwrap();
//! tx.send(2).unwrap();
//! tx.send(3).unwrap();
//! // No need to drop the sender.
//!
//! // Receive all messages currently in the channel.
//! let v: Vec<_> = rx.try_iter().collect();
//! assert_eq!(v, [1, 2, 3]);
//! ```
//!
//! Finally, there is the [`into_iter`] method, which is equivalent to [`iter`], except it takes
//! ownership of the receiver instead of borrowing it.
//!
//! # Selection
//!
//! Selection allows you to declare a set of operations on channels and perform exactly one of
//! them, whichever becomes ready first, possibly blocking until that happens.
//!
//! For example, selection can be used to receive a message from one of the two channels, blocking
//! until a message appears on either of them:
//!
//! ```
//! # #[macro_use]
//! # extern crate crossbeam_channel;
//! # fn main() {
//!
//! use std::thread;
//! use crossbeam_channel::unbounded;
//!
//! let (tx1, rx1) = unbounded();
//! let (tx2, rx2) = unbounded();
//!
//! thread::spawn(move || tx1.send("foo").unwrap());
//! thread::spawn(move || tx2.send("bar").unwrap());
//!
//! select_loop! {
//!     recv(rx1, msg) => {
//!         println!("Received a message from the first channel: {}", msg);
//!     }
//!     recv(rx2, msg) => {
//!         println!("Received a message from the second channel: {}", msg);
//!     }
//! }
//!
//! # }
//! ```
//!
//! The syntax of [`select_loop!`] is very similar to the one used by `match`.
//!
//! Here is another, more complicated example of selection. Here we are selecting over two
//! operations on the opposite ends of the same channel: a send and a receive operation.
//!
//! ```
//! # #[macro_use]
//! # extern crate crossbeam_channel;
//! # fn main() {
//!
//! use crossbeam_channel::{bounded, Sender, Receiver, Select};
//! use std::thread;
//!
//! // Either send my name into the channel or receive someone else's, whatever happens first.
//! fn seek<'a>(name: &'a str, tx: Sender<&'a str>, rx: Receiver<&'a str>) {
//!     select_loop! {
//!         recv(rx, peer) => println!("{} received a message from {}.", name, peer),
//!         send(tx, name) => {},
//!     }
//! }
//!
//! let (tx, rx) = bounded(1); // Make room for one unmatched send.
//!
//! // Pair up five people by exchanging messages over the channel.
//! // Since there is an odd number of them, one person won't have its match.
//! ["Anna", "Bob", "Cody", "Dave", "Eva"].iter()
//!     .map(|name| {
//!         let tx = tx.clone();
//!         let rx = rx.clone();
//!         thread::spawn(move || seek(name, tx, rx))
//!     })
//!     .collect::<Vec<_>>()
//!     .into_iter()
//!     .for_each(|t| t.join().unwrap());
//!
//! // Let's send a message to the remaining person who doesn't have a match.
//! if let Ok(name) = rx.try_recv() {
//!     println!("No one received {}’s message.", name);
//! }
//!
//! # }
//! ```
//!
//! For more details, take a look at the documentation of [`select_loop!`].
//!
//! If you need a more powerful interface that allows selecting over a dynamic set of channel
//! operations, use [`Select`].
//!
//! [`std::sync::mpsc`]: https://doc.rust-lang.org/std/sync/mpsc/index.html
//! [`unbounded`]: fn.unbounded.html
//! [`bounded`]: fn.bounded.html
//! [`try_send`]: struct.Sender.html#method.try_send
//! [`send`]: struct.Sender.html#method.send
//! [`send_timeout`]: struct.Sender.html#method.send_timeout
//! [`try_recv`]: struct.Receiver.html#method.try_recv
//! [`recv`]: struct.Receiver.html#method.recv
//! [`recv_timeout`]: struct.Receiver.html#method.recv_timeout
//! [`iter`]: struct.Receiver.html#method.iter
//! [`try_iter`]: struct.Receiver.html#method.try_iter
//! [`into_iter`]: struct.Receiver.html#method.into_iter
//! [`select_loop!`]: macro.select_loop.html
//! [`Select`]: struct.Select.html

#![cfg_attr(feature = "nightly", feature(hint_core_should_pause))]

extern crate crossbeam_epoch;
extern crate crossbeam_utils;
extern crate parking_lot;
extern crate rand;

mod channel;
mod err;
mod exchanger;
mod flavors;
mod monitor;
mod select;
mod util;

pub use channel::{bounded, unbounded};
pub use channel::{Receiver, Sender};
pub use channel::{IntoIter, Iter, TryIter};
pub use err::{RecvError, RecvTimeoutError, TryRecvError};
pub use err::{SendError, SendTimeoutError, TrySendError};
pub use err::{SelectRecvError, SelectSendError};
pub use select::Select;
<commit_msg>util -> utils<commit_after>//! Multi-producer multi-consumer channels for message passing.
//!
//! Channels are concurrent FIFO queues used for passing messages between threads.
//!
//! Crossbeam's channels are an alternative to the [`std::sync::mpsc`] channels provided by the
//! standard library. They are an improvement in pretty much all aspects: ergonomics, flexibility,
//! features, performance.
//!
//! # Types of channels
//!
//! A channel can be constructed by calling functions [`unbounded`] and [`bounded`]. The former
//! creates a channel of unbounded capacity (i.e. it can contain an arbitrary number of messages),
//! while the latter creates a channel of bounded capacity (i.e. there is a limit to how many
//! messages it can hold at a time).
//!
//! Both constructors returns a pair of two values: a sender and a receiver. Senders and receivers
//! represent two opposite sides of a channel. Messages are sent using senders and received using
//! receivers.
//!
//! Creating an unbounded channel:
//!
//! ```
//! use crossbeam_channel::unbounded;
//!
//! // Create an unbounded channel.
//! let (tx, rx) = unbounded();
//!
//! // Can send an arbitrarily large number of messages.
//! for i in 0..1000 {
//!     tx.try_send(i).unwrap();
//! }
//! ```
//!
//! Creating a bounded channel:
//!
//! ```
//! use crossbeam_channel::bounded;
//!
//! // Create a channel that can hold at most 5 messages at a time.
//! let (tx, rx) = bounded(5);
//!
//! // Can send only 5 messages.
//! for i in 0..5 {
//!     tx.try_send(i).unwrap();
//! }
//!
//! // An attempt to send one more message will fail.
//! assert!(tx.try_send(5).is_err());
//! ```
//!
//! An interesting special case is a bounded, zero-capacity channel. This kind of channel cannot
//! hold any messages at all! In order to send a message through the channel, another thread must
//! be waiting at the other end of it at the same time:
//!
//! ```
//! use crossbeam_channel::bounded;
//!
//! use std::thread;
//!
//! // Create a zero-capacity channel.
//! let (tx, rx) = bounded(0);
//!
//! // Spawn a thread that sends a message into the channel.
//! thread::spawn(move || tx.send("Hi!").unwrap());
//!
//! // Receive the message.
//! assert_eq!(rx.recv(), Ok("Hi!"));
//! ```
//!
//! # Sharing channels
//!
//! Senders and receivers can be either shared by reference or cloned and then sent to other
//! threads. Feel free to use any of these two approaches as you like.
//!
//! Sharing by reference:
//!
//! ```
//! extern crate crossbeam_channel;
//! extern crate crossbeam_utils;
//! # fn main() {
//!
//! use crossbeam_channel::unbounded;
//!
//! let (tx, rx) = unbounded();
//!
//! crossbeam_utils::scoped::scope(|s| {
//!     // Spawn a thread that sends one message and then receives one.
//!     s.spawn(|| {
//!         tx.send(1).unwrap();
//!         rx.recv().unwrap();
//!     });
//!
//!     // Spawn another thread that does the same thing.
//!     // Both closures capture `tx` and `rx` by reference.
//!     s.spawn(|| {
//!         tx.send(2).unwrap();
//!         rx.recv().unwrap();
//!     });
//! });
//!
//! # }
//! ```
//!
//! Sharing by sending:
//!
//! ```
//! use std::thread;
//! use crossbeam_channel::unbounded;
//!
//! let (tx, rx) = unbounded();
//! let (tx2, rx2) = (tx.clone(), rx.clone());
//!
//! // Spawn a thread that sends one message and then receives one.
//! // Here, `tx` and `rx` are moved into the closure (sent into the thread).
//! thread::spawn(move || {
//!     tx.send(1).unwrap();
//!     rx.recv().unwrap();
//! });
//!
//! // Spawn another thread that does the same thing.
//! // Here, `tx2` and `rx2` are moved into the closure (sent into the thread).
//! thread::spawn(move || {
//!     tx2.send(2).unwrap();
//!     rx2.recv().unwrap();
//! });
//! ```
//!
//! # Disconnection
//!
//! As soon as all senders or all receivers associated with a channel are dropped, it becomes
//! disconnected. Messages cannot be sent into a disconnected channel anymore, but the remaining
//! messages can still be received.
//!
//! ```
//! use crossbeam_channel::{unbounded, TrySendError};
//!
//! let (tx, rx) = unbounded();
//!
//! // The only receiver is dropped, disconnecting the channel.
//! drop(rx);
//!
//! // Attempting to send a message will result in an error.
//! assert_eq!(tx.try_send("hello"), Err(TrySendError::Disconnected("hello")));
//! ```
//!
//! ```
//! use crossbeam_channel::{unbounded, TryRecvError};
//!
//! let (tx, rx) = unbounded();
//! tx.try_send(1).unwrap();
//! tx.try_send(2).unwrap();
//! tx.try_send(3).unwrap();
//!
//! // The only sender is dropped, disconnecting the channel.
//! drop(tx);
//!
//! // The remaining messages can be received.
//! assert_eq!(rx.try_recv(), Ok(1));
//! assert_eq!(rx.try_recv(), Ok(2));
//! assert_eq!(rx.try_recv(), Ok(3));
//!
//! // However, attempting to receive another message will result in an error.
//! assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
//! ```
//!
//! # Blocking and non-blocking operations
//!
//! Send and receive operations come in three variants:
//!
//! 1. Non-blocking: [`try_send`] and [`try_recv`].
//! 2. Blocking: [`try_send`] and [`try_recv`].
//! 3. Blocking with a timeout: [`send_timeout`] and [`recv_timeout`].
//!
//! The non-blocking variant attempts to perform the operation, but doesn't block the current
//! thread on failure (e.g. if receiving a message from an empty channel).
//!
//! The blocking variant will wait until the operation can be performed or the channel becomes
//! disconnected.
//!
//! Blocking with a timeout does the same thing, but blocks the current thread only for a limited
//! amount time.
//!
//! # Iteration
//!
//! Receivers can be turned into iterators. For example, calling [`iter`] creates an iterator that
//! returns messages until the channel is disconnected. Note that iteration may block while waiting
//! for the next message.
//!
//! ```
//! use crossbeam_channel::unbounded;
//!
//! let (tx, rx) = unbounded();
//! tx.send(1).unwrap();
//! tx.send(2).unwrap();
//! tx.send(3).unwrap();
//!
//! // Drop the sender in order to disconnect the channel.
//! drop(tx);
//!
//! // Receive all remaining messages.
//! let v: Vec<_> = rx.iter().collect();
//! assert_eq!(v, [1, 2, 3]);
//! ```
//!
//! By calling [`try_iter`] it is also possible to create an iterator that returns messages until
//! the channel is empty. This iterator will never block the current thread.
//!
//! ```
//! use crossbeam_channel::unbounded;
//!
//! let (tx, rx) = unbounded();
//! tx.send(1).unwrap();
//! tx.send(2).unwrap();
//! tx.send(3).unwrap();
//! // No need to drop the sender.
//!
//! // Receive all messages currently in the channel.
//! let v: Vec<_> = rx.try_iter().collect();
//! assert_eq!(v, [1, 2, 3]);
//! ```
//!
//! Finally, there is the [`into_iter`] method, which is equivalent to [`iter`], except it takes
//! ownership of the receiver instead of borrowing it.
//!
//! # Selection
//!
//! Selection allows you to declare a set of operations on channels and perform exactly one of
//! them, whichever becomes ready first, possibly blocking until that happens.
//!
//! For example, selection can be used to receive a message from one of the two channels, blocking
//! until a message appears on either of them:
//!
//! ```
//! # #[macro_use]
//! # extern crate crossbeam_channel;
//! # fn main() {
//!
//! use std::thread;
//! use crossbeam_channel::unbounded;
//!
//! let (tx1, rx1) = unbounded();
//! let (tx2, rx2) = unbounded();
//!
//! thread::spawn(move || tx1.send("foo").unwrap());
//! thread::spawn(move || tx2.send("bar").unwrap());
//!
//! select_loop! {
//!     recv(rx1, msg) => {
//!         println!("Received a message from the first channel: {}", msg);
//!     }
//!     recv(rx2, msg) => {
//!         println!("Received a message from the second channel: {}", msg);
//!     }
//! }
//!
//! # }
//! ```
//!
//! The syntax of [`select_loop!`] is very similar to the one used by `match`.
//!
//! Here is another, more complicated example of selection. Here we are selecting over two
//! operations on the opposite ends of the same channel: a send and a receive operation.
//!
//! ```
//! # #[macro_use]
//! # extern crate crossbeam_channel;
//! # fn main() {
//!
//! use crossbeam_channel::{bounded, Sender, Receiver, Select};
//! use std::thread;
//!
//! // Either send my name into the channel or receive someone else's, whatever happens first.
//! fn seek<'a>(name: &'a str, tx: Sender<&'a str>, rx: Receiver<&'a str>) {
//!     select_loop! {
//!         recv(rx, peer) => println!("{} received a message from {}.", name, peer),
//!         send(tx, name) => {},
//!     }
//! }
//!
//! let (tx, rx) = bounded(1); // Make room for one unmatched send.
//!
//! // Pair up five people by exchanging messages over the channel.
//! // Since there is an odd number of them, one person won't have its match.
//! ["Anna", "Bob", "Cody", "Dave", "Eva"].iter()
//!     .map(|name| {
//!         let tx = tx.clone();
//!         let rx = rx.clone();
//!         thread::spawn(move || seek(name, tx, rx))
//!     })
//!     .collect::<Vec<_>>()
//!     .into_iter()
//!     .for_each(|t| t.join().unwrap());
//!
//! // Let's send a message to the remaining person who doesn't have a match.
//! if let Ok(name) = rx.try_recv() {
//!     println!("No one received {}’s message.", name);
//! }
//!
//! # }
//! ```
//!
//! For more details, take a look at the documentation of [`select_loop!`].
//!
//! If you need a more powerful interface that allows selecting over a dynamic set of channel
//! operations, use [`Select`].
//!
//! [`std::sync::mpsc`]: https://doc.rust-lang.org/std/sync/mpsc/index.html
//! [`unbounded`]: fn.unbounded.html
//! [`bounded`]: fn.bounded.html
//! [`try_send`]: struct.Sender.html#method.try_send
//! [`send`]: struct.Sender.html#method.send
//! [`send_timeout`]: struct.Sender.html#method.send_timeout
//! [`try_recv`]: struct.Receiver.html#method.try_recv
//! [`recv`]: struct.Receiver.html#method.recv
//! [`recv_timeout`]: struct.Receiver.html#method.recv_timeout
//! [`iter`]: struct.Receiver.html#method.iter
//! [`try_iter`]: struct.Receiver.html#method.try_iter
//! [`into_iter`]: struct.Receiver.html#method.into_iter
//! [`select_loop!`]: macro.select_loop.html
//! [`Select`]: struct.Select.html

#![cfg_attr(feature = "nightly", feature(hint_core_should_pause))]

extern crate crossbeam_epoch;
extern crate crossbeam_utils;
extern crate parking_lot;
extern crate rand;

mod channel;
mod err;
mod exchanger;
mod flavors;
mod monitor;
mod select;
mod utils;

pub use channel::{bounded, unbounded};
pub use channel::{Receiver, Sender};
pub use channel::{IntoIter, Iter, TryIter};
pub use err::{RecvError, RecvTimeoutError, TryRecvError};
pub use err::{SendError, SendTimeoutError, TrySendError};
pub use err::{SelectRecvError, SelectSendError};
pub use select::Select;
<|endoftext|>


<commit_before>#![feature(slice_splits, core)]
#![cfg_attr(test, feature(test))]
extern crate core;
extern crate itertools;
extern crate rand;

use core::ptr;
use itertools::partition;
use std::cmp::Ordering::{self, Less};
use std::mem;

#[derive(Debug, Clone)]
pub struct LazySort<T> {
    inner: LazySortInternal<T>,
}

impl<T: Ord> Iterator for LazySort<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.inner.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }
}

#[derive(Debug, Clone)]
enum LazySortInternal<T> {
    Base(Vec<T>),
    Recursive(Recursive<T>),
}

impl<T: Ord> LazySortInternal<T> {
    fn new(mut v: Vec<T>) -> LazySortInternal<T> {
        if v.len() <= 32 {
            insertion_sort(&mut v, |a, b| b.cmp(a));
            LazySortInternal::Base(v)
        } else {
            LazySortInternal::Recursive(Recursive::new(v))
        }
    }
}

impl<T: Ord> Iterator for LazySortInternal<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        match *self {
            LazySortInternal::Base(ref mut v) => v.pop(),
            LazySortInternal::Recursive(ref mut r) => r.next(),
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        match *self {
            LazySortInternal::Base(ref v) => (v.len(), Some(v.len())),
            LazySortInternal::Recursive(ref r) => r.size_hint(),
        }
    }
}

#[derive(Clone, Debug)]
struct Recursive<T> {
    greater: Vec<T>,
    less: Option<Box<LazySortInternal<T>>>,
}

impl<T: Ord> Recursive<T> {
    fn new(v: Vec<T>) -> Recursive<T> {
        Recursive {
            greater: v,
            less: None,
        }
    }

    fn split_greater(&mut self) -> Option<T> {
        match self.greater.len() {
            0 => None,
            1 => self.greater.pop(),
            _ => {
                let pivot_idx = self.greater.len() - 1;
                let split_idx = {
                    let mid_idx = self.greater.len() / 2;
                    // I've chosen the element in the middle of the vec as the pivot.
                    // However, we first swap the pivot with the last element so that there is
                    // a contiguous space in memory to be partitioned.
                    self.greater.swap(pivot_idx, mid_idx);
                    let (pivot, rest) = self.greater.split_last_mut().unwrap();
                    // partition all but the last element, which is the pivot. This makes the vec
                    // look like [greater, greater, ..., greater, less, less, ..., less, pivot]
                    partition(rest, |el| el > pivot)
                };
                // Swapping the pivot with the first less element allows us to split off
                // vec[split_idx + 1..] to create a new vec with all the elements less than pivot.
                self.greater.swap(pivot_idx, split_idx);
                let split_off_idx = split_idx + 1;
                if split_off_idx < self.greater.len() {
                    let mut less = Box::new(LazySortInternal::new(self.greater
                                                                      .split_off(split_off_idx)));
                    // Recursively compute the next element from the LazySortInternal struct containing
                    // the elements less than the pivot.
                    let next = less.next();
                    self.less = Some(less);
                    next
                } else {
                    // If there were no elements less than the pivot, then return the pivot.
                    self.greater.pop()
                }
            }
        }
    }
}

impl<T: Ord> Iterator for Recursive<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        let next = if let Some(ref mut less) = self.less {
            less.next()
        } else {
            return self.split_greater();
        };
        if next.is_some() {
            next
        } else {
            self.less = None;
            // The pivot is always the last element in the vec, and it's the first element
            // to be returned once all of the elements less than it have been returned.
            self.greater.pop()
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        match self.less {
            None => (self.greater.len(), Some(self.greater.len())),
            Some(ref less) => {
                let (lower, upper) = less.size_hint();
                (lower + self.greater.len(),
                 upper.map(|upper| upper + self.greater.len()))
            }
        }
    }
}

pub trait LazySortIterator: Iterator
    where Self: Sized,
          Self::Item: Ord
{
    fn lazy_sort(self) -> LazySort<Self::Item> {
        LazySort { inner: LazySortInternal::new(self.collect()) }
    }
}

impl<T> LazySortIterator for T
    where T: Iterator,
          T::Item: Ord { }

// This is copied from libcollections/slice.rs
fn insertion_sort<T, F>(v: &mut [T], mut compare: F)
    where F: FnMut(&T, &T) -> Ordering
{
    let len = v.len() as isize;
    let buf_v = v.as_mut_ptr();

    // 1 <= i < len;
    for i in 1..len {
        // j satisfies: 0 <= j <= i;
        let mut j = i;
        unsafe {
            // `i` is in bounds.
            let read_ptr = buf_v.offset(i) as *const T;

            // find where to insert, we need to do strict <,
            // rather than <=, to maintain stability.

            // 0 <= j - 1 < len, so .offset(j - 1) is in bounds.
            while j > 0 && compare(&*read_ptr, &*buf_v.offset(j - 1)) == Less {
                j -= 1;
            }

            // shift everything to the right, to make space to
            // insert this value.

            // j + 1 could be `len` (for the last `i`), but in
            // that case, `i == j` so we don't copy. The
            // `.offset(j)` is always in bounds.

            if i != j {
                let tmp = ptr::read(read_ptr);
                ptr::copy(&*buf_v.offset(j), buf_v.offset(j + 1), (i - j) as usize);
                ptr::copy_nonoverlapping(&tmp, buf_v.offset(j), 1);
                mem::forget(tmp);
            }
        }
    }
}

#[test]
fn test_sort() {
    let mut v = vec![2, 4, 2, 5, 8, 4, 3, 4, 6];
    let v2: Vec<_> = v.iter().cloned().lazy_sort().collect();
    v.sort();
    assert_eq!(v, v2);
}

#[test]
fn test_empty() {
    let v: Vec<u64> = vec![];
    let v2: Vec<_> = v.iter().cloned().lazy_sort().collect();
    assert_eq!(v, v2);
}

#[test]
fn test_size_hint() {
    let v = vec![2, 4, 2, 5, 8, 4, 3, 4, 6];
    let mut sort_iter = v.iter().cloned().lazy_sort();
    for i in 0..v.len() {
        let (lower, upper) = sort_iter.size_hint();
        assert_eq!(v.len() - i, lower);
        assert_eq!(Some(v.len() - i), upper);
        sort_iter.next();
    }
}

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

    use self::test::Bencher;
    use rand::{thread_rng, Rng};
    use super::LazySortIterator;

    #[bench]
    fn take_1000_lazy(b: &mut Bencher) {
        let mut rng = thread_rng();
        let v: Vec<u32> = rng.gen_iter().take(50_000).collect();
        b.iter(|| v.iter().cloned().lazy_sort().take(1000).collect::<Vec<_>>());
    }

    #[bench]
    fn take_1000_eager(b: &mut Bencher) {
        let mut rng = thread_rng();
        let v: Vec<u32> = rng.gen_iter().take(50_000).collect();
        b.iter(|| {
            let mut v = v.clone();
            v.sort();
            v.iter().cloned().take(1000).collect::<Vec<_>>();
        });
    }

    #[bench]
    fn take_10_000_lazy(b: &mut Bencher) {
        let mut rng = thread_rng();
        let v: Vec<u32> = rng.gen_iter().take(50_000).collect();
        b.iter(|| v.iter().cloned().lazy_sort().take(10_000).collect::<Vec<_>>());
    }

    #[bench]
    fn take_10_000_eager(b: &mut Bencher) {
        let mut rng = thread_rng();
        let v: Vec<u32> = rng.gen_iter().take(50_000).collect();
        b.iter(|| {
            let mut v = v.clone();
            v.sort();
            v.iter().cloned().take(10_000).collect::<Vec<_>>();
        });
    }

    #[bench]
    fn take_50_000_lazy(b: &mut Bencher) {
        let mut rng = thread_rng();
        let v: Vec<u32> = rng.gen_iter().take(50_000).collect();
        b.iter(|| v.iter().cloned().lazy_sort().take(50_000).collect::<Vec<_>>());
    }

    #[bench]
    fn take_50_000_eager(b: &mut Bencher) {
        let mut rng = thread_rng();
        let v: Vec<u32> = rng.gen_iter().take(50_000).collect();
        b.iter(|| {
            let mut v = v.clone();
            v.sort();
            v.iter().cloned().take(50_000).collect::<Vec<_>>();
        });
    }
}
<commit_msg>Add benches: take_10_(lazy|eager)<commit_after>#![feature(slice_splits, core)]
#![cfg_attr(test, feature(test))]
extern crate core;
extern crate itertools;
extern crate rand;

use core::ptr;
use itertools::partition;
use std::cmp::Ordering::{self, Less};
use std::mem;

#[derive(Debug, Clone)]
pub struct LazySort<T> {
    inner: LazySortInternal<T>,
}

impl<T: Ord> Iterator for LazySort<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.inner.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }
}

#[derive(Debug, Clone)]
enum LazySortInternal<T> {
    Base(Vec<T>),
    Recursive(Recursive<T>),
}

impl<T: Ord> LazySortInternal<T> {
    fn new(mut v: Vec<T>) -> LazySortInternal<T> {
        if v.len() <= 32 {
            insertion_sort(&mut v, |a, b| b.cmp(a));
            LazySortInternal::Base(v)
        } else {
            LazySortInternal::Recursive(Recursive::new(v))
        }
    }
}

impl<T: Ord> Iterator for LazySortInternal<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        match *self {
            LazySortInternal::Base(ref mut v) => v.pop(),
            LazySortInternal::Recursive(ref mut r) => r.next(),
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        match *self {
            LazySortInternal::Base(ref v) => (v.len(), Some(v.len())),
            LazySortInternal::Recursive(ref r) => r.size_hint(),
        }
    }
}

#[derive(Clone, Debug)]
struct Recursive<T> {
    greater: Vec<T>,
    less: Option<Box<LazySortInternal<T>>>,
}

impl<T: Ord> Recursive<T> {
    fn new(v: Vec<T>) -> Recursive<T> {
        Recursive {
            greater: v,
            less: None,
        }
    }

    fn split_greater(&mut self) -> Option<T> {
        match self.greater.len() {
            0 => None,
            1 => self.greater.pop(),
            _ => {
                let pivot_idx = self.greater.len() - 1;
                let split_idx = {
                    let mid_idx = self.greater.len() / 2;
                    // I've chosen the element in the middle of the vec as the pivot.
                    // However, we first swap the pivot with the last element so that there is
                    // a contiguous space in memory to be partitioned.
                    self.greater.swap(pivot_idx, mid_idx);
                    let (pivot, rest) = self.greater.split_last_mut().unwrap();
                    // partition all but the last element, which is the pivot. This makes the vec
                    // look like [greater, greater, ..., greater, less, less, ..., less, pivot]
                    partition(rest, |el| el > pivot)
                };
                // Swapping the pivot with the first less element allows us to split off
                // vec[split_idx + 1..] to create a new vec with all the elements less than pivot.
                self.greater.swap(pivot_idx, split_idx);
                let split_off_idx = split_idx + 1;
                if split_off_idx < self.greater.len() {
                    let mut less = Box::new(LazySortInternal::new(self.greater
                                                                      .split_off(split_off_idx)));
                    // Recursively compute the next element from the LazySortInternal struct containing
                    // the elements less than the pivot.
                    let next = less.next();
                    self.less = Some(less);
                    next
                } else {
                    // If there were no elements less than the pivot, then return the pivot.
                    self.greater.pop()
                }
            }
        }
    }
}

impl<T: Ord> Iterator for Recursive<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        let next = if let Some(ref mut less) = self.less {
            less.next()
        } else {
            return self.split_greater();
        };
        if next.is_some() {
            next
        } else {
            self.less = None;
            // The pivot is always the last element in the vec, and it's the first element
            // to be returned once all of the elements less than it have been returned.
            self.greater.pop()
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        match self.less {
            None => (self.greater.len(), Some(self.greater.len())),
            Some(ref less) => {
                let (lower, upper) = less.size_hint();
                (lower + self.greater.len(),
                 upper.map(|upper| upper + self.greater.len()))
            }
        }
    }
}

pub trait LazySortIterator: Iterator
    where Self: Sized,
          Self::Item: Ord
{
    fn lazy_sort(self) -> LazySort<Self::Item> {
        LazySort { inner: LazySortInternal::new(self.collect()) }
    }
}

impl<T> LazySortIterator for T
    where T: Iterator,
          T::Item: Ord { }

// This is copied from libcollections/slice.rs
fn insertion_sort<T, F>(v: &mut [T], mut compare: F)
    where F: FnMut(&T, &T) -> Ordering
{
    let len = v.len() as isize;
    let buf_v = v.as_mut_ptr();

    // 1 <= i < len;
    for i in 1..len {
        // j satisfies: 0 <= j <= i;
        let mut j = i;
        unsafe {
            // `i` is in bounds.
            let read_ptr = buf_v.offset(i) as *const T;

            // find where to insert, we need to do strict <,
            // rather than <=, to maintain stability.

            // 0 <= j - 1 < len, so .offset(j - 1) is in bounds.
            while j > 0 && compare(&*read_ptr, &*buf_v.offset(j - 1)) == Less {
                j -= 1;
            }

            // shift everything to the right, to make space to
            // insert this value.

            // j + 1 could be `len` (for the last `i`), but in
            // that case, `i == j` so we don't copy. The
            // `.offset(j)` is always in bounds.

            if i != j {
                let tmp = ptr::read(read_ptr);
                ptr::copy(&*buf_v.offset(j), buf_v.offset(j + 1), (i - j) as usize);
                ptr::copy_nonoverlapping(&tmp, buf_v.offset(j), 1);
                mem::forget(tmp);
            }
        }
    }
}

#[test]
fn test_sort() {
    let mut v = vec![2, 4, 2, 5, 8, 4, 3, 4, 6];
    let v2: Vec<_> = v.iter().cloned().lazy_sort().collect();
    v.sort();
    assert_eq!(v, v2);
}

#[test]
fn test_empty() {
    let v: Vec<u64> = vec![];
    let v2: Vec<_> = v.iter().cloned().lazy_sort().collect();
    assert_eq!(v, v2);
}

#[test]
fn test_size_hint() {
    let v = vec![2, 4, 2, 5, 8, 4, 3, 4, 6];
    let mut sort_iter = v.iter().cloned().lazy_sort();
    for i in 0..v.len() {
        let (lower, upper) = sort_iter.size_hint();
        assert_eq!(v.len() - i, lower);
        assert_eq!(Some(v.len() - i), upper);
        sort_iter.next();
    }
}

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

    use self::test::Bencher;
    use rand::{thread_rng, Rng};
    use super::LazySortIterator;

    fn take_lazy(b: &mut Bencher, k: usize) {
        let mut rng = thread_rng();
        let v: Vec<u32> = rng.gen_iter().take(50_000).collect();
        b.iter(|| v.iter().cloned().lazy_sort().take(k).collect::<Vec<_>>());
    }

    fn take_eager(b: &mut Bencher, k: usize) {
        let mut rng = thread_rng();
        let v: Vec<u32> = rng.gen_iter().take(50_000).collect();
        b.iter(|| {
            let mut v = v.clone();
            v.sort();
            v.iter().cloned().take(k).collect::<Vec<_>>();
        });
    }

    #[bench]
    fn take_10_lazy(b: &mut Bencher) {
        take_lazy(b, 10);
    }

    #[bench]
    fn take_10_eager(b: &mut Bencher) {
        take_eager(b, 10);
    }

    #[bench]
    fn take_1000_lazy(b: &mut Bencher) {
        take_lazy(b, 1000)
    }

    #[bench]
    fn take_1000_eager(b: &mut Bencher) {
        take_eager(b, 1000);
    }

    #[bench]
    fn take_10_000_lazy(b: &mut Bencher) {
        take_lazy(b, 10_000);
    }

    #[bench]
    fn take_10_000_eager(b: &mut Bencher) {
        take_eager(b, 10_000);
    }

    #[bench]
    fn take_50_000_lazy(b: &mut Bencher) {
        take_lazy(b, 50_000);
    }

    #[bench]
    fn take_50_000_eager(b: &mut Bencher) {
        take_eager(b, 50_000);
    }
}
<|endoftext|>