<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()))?;
        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())
                }
            }
        }
    }
}
<commit_msg>removed debug print statement<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()));
        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>//! `textwrap` provides functions for word wrapping and filling text.

extern crate unicode_width;

use unicode_width::UnicodeWidthStr;

/// A Wrapper holds settings for wrapping text.
pub struct Wrapper {
    width: usize,
}

impl Wrapper {
    /// Create a new Wrapper for wrapping at the specified width.
    pub fn new(width: usize) -> Wrapper {
        Wrapper { width: width }
    }

    /// Fill a line of text at `self.width` characters. Strings are
    /// wrapped based on their displayed width, not their size in
    /// bytes.
    ///
    /// The result is a string with newlines between each line. Use
    /// the `wrap` method if you need access to the individual lines.
    ///
    /// ```
    /// use textwrap::Wrapper;
    ///
    /// let wrapper = Wrapper::new(15);
    /// assert_eq!(wrapper.fill("Memory safety without garbage collection."),
    ///            "Memory safety\nwithout garbage\ncollection.");
    /// ```
    pub fn fill(&self, s: &str) -> String {
        self.wrap(&s).join("\n")
    }

    /// Wrap  a line of  text at `self.width` characters.  Strings are
    ///  wrapped based  on their  displayed width,  not their  size in
    /// bytes.
    ///
    /// ```
    /// use textwrap::Wrapper;
    ///
    /// let wrap15 = Wrapper::new(15);
    /// assert_eq!(wrap15.wrap("Concurrency without data races."),
    ///            vec!["Concurrency",
    ///                 "without data",
    ///                 "races."]);
    ///
    /// let wrap20 = Wrapper::new(20);
    /// assert_eq!(wrap20.wrap("Concurrency without data races."),
    ///            vec!["Concurrency without",
    ///                 "data races."]);
    /// ```
    pub fn wrap(&self, s: &str) -> Vec<String> {
        let mut result = Vec::new();
        let mut line = Vec::new();
        let mut line_width = 0;

        for mut word in s.split_whitespace() {
            while !word.is_empty() {
                let splits = self.split_word(&word);
                let (smallest, hyphen, longest) = splits[0];
                let min_width = smallest.width() + hyphen.len();

                // Add a new line if even the smallest split doesn't
                // fit.
                if !line.is_empty() && line_width + line.len() + min_width > self.width {
                    result.push(line.join(" "));
                    line = Vec::new();
                    line_width = 0;
                }

                // Find a split that fits on the current line.
                for &(head, hyphen, tail) in splits.iter().rev() {
                    if line_width + line.len() + head.width() + hyphen.len() <= self.width {
                        line.push(String::from(head) + hyphen);
                        line_width += head.width();
                        word = tail;
                        break;
                    }
                }

                // If nothing got added, we forcibly add the smallest
                // split and continue with the longest tail.
                if line_width == 0 {
                    result.push(String::from(smallest) + hyphen);
                    line_width = 0;
                    word = longest;
                }
            }
        }
        if !line.is_empty() {
            result.push(line.join(" "));
        }
        return result;
    }

    /// Split word into all possible parts (head, tail). Word must be
    /// non-empty. The returned vector will always be non-empty.
    fn split_word<'b>(&self, word: &'b str) -> Vec<(&'b str, &'b str, &'b str)> {
        let mut result = Vec::new();

        // Split on hyphens, smallest split first.
        for (n, _) in word.match_indices('-') {
            let (head, tail) = word.split_at(n + 1);
            result.push((head, "", tail));
        }

        // Finally option is no split at all.
        result.push((word, "", ""));

        return result;
    }
}

/// Fill a line of text at `width` characters. Strings are wrapped
/// based on their displayed width, not their size in bytes.
///
/// The result is a string with newlines between each line. Use `wrap`
/// if you need access to the individual lines.
///
/// ```
/// use textwrap::fill;
///
/// assert_eq!(fill("Memory safety without garbage collection.", 15),
///            "Memory safety\nwithout garbage\ncollection.");
/// ```
///
/// This function creates a Wrapper on the fly. If you need to wrap
/// many strings, it can be more efficient to create a single Wrapper
/// and call its [`fill` method](struct.Wrapper.html#method.fill).
pub fn fill(s: &str, width: usize) -> String {
    wrap(s, width).join("\n")
}

/// Wrap a line of text at `width` characters. Strings are wrapped
/// based on their displayed width, not their size in bytes.
///
/// ```
/// use textwrap::wrap;
///
/// assert_eq!(wrap("Concurrency without data races.", 15),
///            vec!["Concurrency",
///                 "without data",
///                 "races."]);
///
/// assert_eq!(wrap("Concurrency without data races.", 20),
///            vec!["Concurrency without",
///                 "data races."]);
/// ```
///
/// This function creates a Wrapper on the fly. If you need to wrap
/// many strings, it can be more efficient to create a single Wrapper
/// and call its [`wrap` method](struct.Wrapper.html#method.wrap).
pub fn wrap(s: &str, width: usize) -> Vec<String> {
    Wrapper::new(width).wrap(s)
}

/// Add prefix to each non-empty line.
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("Foo\nBar\n", "  "), "  Foo\n  Bar\n");
/// ```
///
/// Empty lines (lines consisting only of whitespace) are not indented
/// and the whitespace is replaced by a single newline (`\n`):
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("Foo\n\nBar\n  \t  \nBaz\n", "  "),
///            "  Foo\n\n  Bar\n\n  Baz\n");
/// ```
///
/// Leading and trailing whitespace on non-empty lines is kept
/// unchanged:
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent(" \t  Foo   ", "  "), "   \t  Foo   \n");
/// ```
pub fn indent(s: &str, prefix: &str) -> String {
    let mut result = String::new();
    for line in s.lines() {
        if line.chars().any(|c| !c.is_whitespace()) {
            result.push_str(prefix);
            result.push_str(line);
        }
        result.push('\n');
    }
    return result;
}

/// Removes common leading whitespace from each line.
///
/// This will look at each non-empty line and determine the maximum
/// amount of whitespace that can be removed from the line.
///
/// ```
/// use textwrap::dedent;
///
/// assert_eq!(dedent("  1st line\n  2nd line\n"),
///            "1st line\n2nd line\n");
/// ```
pub fn dedent(s: &str) -> String {
    let mut prefix = String::new();
    let mut lines = s.lines();

    // We first search for a non-empty line to find a prefix.
    for line in &mut lines {
        let whitespace = line.chars()
            .take_while(|c| c.is_whitespace())
            .collect::<String>();
        // Check if the line had anything but whitespace
        if whitespace.len() < line.len() {
            prefix = whitespace;
            break;
        }
    }

    // We then continue looking through the remaining lines to
    // possibly shorten the prefix.
    for line in &mut lines {
        let whitespace = line.chars()
            .zip(prefix.chars())
            .take_while(|&(a, b)| a == b)
            .map(|(_, b)| b)
            .collect::<String>();
        // Check if we have found a shorter prefix
        if whitespace.len() < prefix.len() {
            prefix = whitespace;
        }
    }

    // We now go over the lines a second time to build the result.
    let mut result = String::new();
    for line in s.lines() {
        if line.starts_with(&prefix) && line.chars().any(|c| !c.is_whitespace()) {
            let (_, tail) = line.split_at(prefix.len());
            result.push_str(tail);
        }
        result.push('\n');
    }
    return result;
}

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

    /// Add newlines. Ensures that the final line in the vector also
    /// has a newline.
    fn add_nl(lines: &Vec<&str>) -> String {
        lines.join("\n") + "\n"
    }

    #[test]
    fn no_wrap() {
        assert_eq!(wrap("foo", 10), vec!["foo"]);
    }

    #[test]
    fn simple() {
        assert_eq!(wrap("foo bar baz", 5), vec!["foo", "bar", "baz"]);
    }

    #[test]
    fn multi_word_on_line() {
        assert_eq!(wrap("foo bar baz", 10), vec!["foo bar", "baz"]);
    }

    #[test]
    fn long_word() {
        assert_eq!(wrap("foo", 0), vec!["foo"]);
    }

    #[test]
    fn long_words() {
        assert_eq!(wrap("foo bar", 0), vec!["foo", "bar"]);
    }

    #[test]
    fn whitespace_is_squeezed() {
        assert_eq!(wrap(" foo \t  bar  ", 10), vec!["foo bar"]);
    }

    #[test]
    fn wide_character_handling() {
        assert_eq!(wrap("Hello, World!", 15), vec!["Hello, World!"]);
        assert_eq!(wrap("Ｈｅｌｌｏ, Ｗｏｒｌｄ!", 15),
                   vec!["Ｈｅｌｌｏ,", "Ｗｏｒｌｄ!"]);
    }

    #[test]
    fn hyphens() {
        assert_eq!(wrap("foo-bar", 5), vec!["foo-", "bar"]);
    }

    #[test]
    fn trailing_hyphen() {
        assert_eq!(wrap("foobar-", 5), vec!["foobar-"]);
    }

    #[test]
    fn multiple_hyphens() {
        assert_eq!(wrap("foo-bar-baz", 5), vec!["foo-", "bar-", "baz"]);
    }

    #[test]
    fn multiple_splits() {
        assert_eq!(wrap("foo-bar-baz", 9), vec!["foo-bar-", "baz"]);
    }

    #[test]
    fn forced_split() {
        assert_eq!(wrap("foobar-baz", 5), vec!["foobar-", "baz"]);
    }

    #[test]
    fn test_fill() {
        assert_eq!(fill("foo bar baz", 10), "foo bar\nbaz");
    }

    #[test]
    fn test_indent_empty() {
        assert_eq!(indent("\n", "  "), "\n");
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_indent_nonempty() {
        let x = vec!["  foo",
                     "bar",
                     "  baz"];
        let y = vec!["//  foo",
                     "//bar",
                     "//  baz"];
        assert_eq!(indent(&add_nl(&x), "//"), add_nl(&y));
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_indent_empty_line() {
        let x = vec!["  foo",
                     "bar",
                     "",
                     "  baz"];
        let y = vec!["//  foo",
                     "//bar",
                     "",
                     "//  baz"];
        assert_eq!(indent(&add_nl(&x), "//"), add_nl(&y));
    }

    #[test]
    fn test_dedent_empty() {
        assert_eq!(dedent(""), "");
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_dedent_multi_line() {
        let x = vec!["    foo",
                     "  bar",
                     "    baz"];
        let y = vec!["  foo",
                     "bar",
                     "  baz"];
        assert_eq!(dedent(&add_nl(&x)), add_nl(&y));
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_dedent_empty_line() {
        let x = vec!["    foo",
                     "  bar",
                     "   ",
                     "    baz"];
        let y = vec!["  foo",
                     "bar",
                     "",
                     "  baz"];
        assert_eq!(dedent(&add_nl(&x)), add_nl(&y));
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_dedent_mixed_whitespace() {
        let x = vec!["\tfoo",
                     "  bar"];
        let y = vec!["\tfoo",
                     "  bar"];
        assert_eq!(dedent(&add_nl(&x)), add_nl(&y));
    }
}
<commit_msg>wrap: let the current line be a String again<commit_after>//! `textwrap` provides functions for word wrapping and filling text.

extern crate unicode_width;

use unicode_width::UnicodeWidthStr;

/// A Wrapper holds settings for wrapping text.
pub struct Wrapper {
    width: usize,
}

impl Wrapper {
    /// Create a new Wrapper for wrapping at the specified width.
    pub fn new(width: usize) -> Wrapper {
        Wrapper { width: width }
    }

    /// Fill a line of text at `self.width` characters. Strings are
    /// wrapped based on their displayed width, not their size in
    /// bytes.
    ///
    /// The result is a string with newlines between each line. Use
    /// the `wrap` method if you need access to the individual lines.
    ///
    /// ```
    /// use textwrap::Wrapper;
    ///
    /// let wrapper = Wrapper::new(15);
    /// assert_eq!(wrapper.fill("Memory safety without garbage collection."),
    ///            "Memory safety\nwithout garbage\ncollection.");
    /// ```
    pub fn fill(&self, s: &str) -> String {
        self.wrap(&s).join("\n")
    }

    /// Wrap  a line of  text at `self.width` characters.  Strings are
    ///  wrapped based  on their  displayed width,  not their  size in
    /// bytes.
    ///
    /// ```
    /// use textwrap::Wrapper;
    ///
    /// let wrap15 = Wrapper::new(15);
    /// assert_eq!(wrap15.wrap("Concurrency without data races."),
    ///            vec!["Concurrency",
    ///                 "without data",
    ///                 "races."]);
    ///
    /// let wrap20 = Wrapper::new(20);
    /// assert_eq!(wrap20.wrap("Concurrency without data races."),
    ///            vec!["Concurrency without",
    ///                 "data races."]);
    /// ```
    pub fn wrap(&self, s: &str) -> Vec<String> {
        let mut result = Vec::new();
        let mut line = String::new();
        let mut line_width = 0;

        for mut word in s.split_whitespace() {
            while !word.is_empty() {
                let splits = self.split_word(&word);
                let (smallest, hyphen, longest) = splits[0];
                let min_width = smallest.width() + hyphen.len();

                // Add a new line if even the smallest split doesn't
                // fit.
                if !line.is_empty() && line_width + 1 + min_width > self.width {
                    result.push(line);
                    line = String::new();
                    line_width = 0;
                }

                let space = if line_width > 0 { 1 } else { 0 };

                // Find a split that fits on the current line.
                for &(head, hyphen, tail) in splits.iter().rev() {
                    if line_width + space + head.width() + hyphen.len() <= self.width {
                        if line_width > 0 {
                            line.push(' ');
                        }
                        line.push_str(head);
                        line.push_str(hyphen);
                        line_width += space + head.width() + hyphen.len();
                        word = tail;
                        break;
                    }
                }

                // If nothing got added, we forcibly add the smallest
                // split and continue with the longest tail.
                if line_width == 0 {
                    result.push(String::from(smallest) + hyphen);
                    line_width = 0;
                    word = longest;
                }
            }
        }
        if !line.is_empty() {
            result.push(line);
        }
        return result;
    }

    /// Split word into all possible parts (head, tail). Word must be
    /// non-empty. The returned vector will always be non-empty.
    fn split_word<'b>(&self, word: &'b str) -> Vec<(&'b str, &'b str, &'b str)> {
        let mut result = Vec::new();

        // Split on hyphens, smallest split first.
        for (n, _) in word.match_indices('-') {
            let (head, tail) = word.split_at(n + 1);
            result.push((head, "", tail));
        }

        // Finally option is no split at all.
        result.push((word, "", ""));

        return result;
    }
}

/// Fill a line of text at `width` characters. Strings are wrapped
/// based on their displayed width, not their size in bytes.
///
/// The result is a string with newlines between each line. Use `wrap`
/// if you need access to the individual lines.
///
/// ```
/// use textwrap::fill;
///
/// assert_eq!(fill("Memory safety without garbage collection.", 15),
///            "Memory safety\nwithout garbage\ncollection.");
/// ```
///
/// This function creates a Wrapper on the fly. If you need to wrap
/// many strings, it can be more efficient to create a single Wrapper
/// and call its [`fill` method](struct.Wrapper.html#method.fill).
pub fn fill(s: &str, width: usize) -> String {
    wrap(s, width).join("\n")
}

/// Wrap a line of text at `width` characters. Strings are wrapped
/// based on their displayed width, not their size in bytes.
///
/// ```
/// use textwrap::wrap;
///
/// assert_eq!(wrap("Concurrency without data races.", 15),
///            vec!["Concurrency",
///                 "without data",
///                 "races."]);
///
/// assert_eq!(wrap("Concurrency without data races.", 20),
///            vec!["Concurrency without",
///                 "data races."]);
/// ```
///
/// This function creates a Wrapper on the fly. If you need to wrap
/// many strings, it can be more efficient to create a single Wrapper
/// and call its [`wrap` method](struct.Wrapper.html#method.wrap).
pub fn wrap(s: &str, width: usize) -> Vec<String> {
    Wrapper::new(width).wrap(s)
}

/// Add prefix to each non-empty line.
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("Foo\nBar\n", "  "), "  Foo\n  Bar\n");
/// ```
///
/// Empty lines (lines consisting only of whitespace) are not indented
/// and the whitespace is replaced by a single newline (`\n`):
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("Foo\n\nBar\n  \t  \nBaz\n", "  "),
///            "  Foo\n\n  Bar\n\n  Baz\n");
/// ```
///
/// Leading and trailing whitespace on non-empty lines is kept
/// unchanged:
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent(" \t  Foo   ", "  "), "   \t  Foo   \n");
/// ```
pub fn indent(s: &str, prefix: &str) -> String {
    let mut result = String::new();
    for line in s.lines() {
        if line.chars().any(|c| !c.is_whitespace()) {
            result.push_str(prefix);
            result.push_str(line);
        }
        result.push('\n');
    }
    return result;
}

/// Removes common leading whitespace from each line.
///
/// This will look at each non-empty line and determine the maximum
/// amount of whitespace that can be removed from the line.
///
/// ```
/// use textwrap::dedent;
///
/// assert_eq!(dedent("  1st line\n  2nd line\n"),
///            "1st line\n2nd line\n");
/// ```
pub fn dedent(s: &str) -> String {
    let mut prefix = String::new();
    let mut lines = s.lines();

    // We first search for a non-empty line to find a prefix.
    for line in &mut lines {
        let whitespace = line.chars()
            .take_while(|c| c.is_whitespace())
            .collect::<String>();
        // Check if the line had anything but whitespace
        if whitespace.len() < line.len() {
            prefix = whitespace;
            break;
        }
    }

    // We then continue looking through the remaining lines to
    // possibly shorten the prefix.
    for line in &mut lines {
        let whitespace = line.chars()
            .zip(prefix.chars())
            .take_while(|&(a, b)| a == b)
            .map(|(_, b)| b)
            .collect::<String>();
        // Check if we have found a shorter prefix
        if whitespace.len() < prefix.len() {
            prefix = whitespace;
        }
    }

    // We now go over the lines a second time to build the result.
    let mut result = String::new();
    for line in s.lines() {
        if line.starts_with(&prefix) && line.chars().any(|c| !c.is_whitespace()) {
            let (_, tail) = line.split_at(prefix.len());
            result.push_str(tail);
        }
        result.push('\n');
    }
    return result;
}

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

    /// Add newlines. Ensures that the final line in the vector also
    /// has a newline.
    fn add_nl(lines: &Vec<&str>) -> String {
        lines.join("\n") + "\n"
    }

    #[test]
    fn no_wrap() {
        assert_eq!(wrap("foo", 10), vec!["foo"]);
    }

    #[test]
    fn simple() {
        assert_eq!(wrap("foo bar baz", 5), vec!["foo", "bar", "baz"]);
    }

    #[test]
    fn multi_word_on_line() {
        assert_eq!(wrap("foo bar baz", 10), vec!["foo bar", "baz"]);
    }

    #[test]
    fn long_word() {
        assert_eq!(wrap("foo", 0), vec!["foo"]);
    }

    #[test]
    fn long_words() {
        assert_eq!(wrap("foo bar", 0), vec!["foo", "bar"]);
    }

    #[test]
    fn whitespace_is_squeezed() {
        assert_eq!(wrap(" foo \t  bar  ", 10), vec!["foo bar"]);
    }

    #[test]
    fn wide_character_handling() {
        assert_eq!(wrap("Hello, World!", 15), vec!["Hello, World!"]);
        assert_eq!(wrap("Ｈｅｌｌｏ, Ｗｏｒｌｄ!", 15),
                   vec!["Ｈｅｌｌｏ,", "Ｗｏｒｌｄ!"]);
    }

    #[test]
    fn hyphens() {
        assert_eq!(wrap("foo-bar", 5), vec!["foo-", "bar"]);
    }

    #[test]
    fn trailing_hyphen() {
        assert_eq!(wrap("foobar-", 5), vec!["foobar-"]);
    }

    #[test]
    fn multiple_hyphens() {
        assert_eq!(wrap("foo-bar-baz", 5), vec!["foo-", "bar-", "baz"]);
    }

    #[test]
    fn multiple_splits() {
        assert_eq!(wrap("foo-bar-baz", 9), vec!["foo-bar-", "baz"]);
    }

    #[test]
    fn forced_split() {
        assert_eq!(wrap("foobar-baz", 5), vec!["foobar-", "baz"]);
    }

    #[test]
    fn test_fill() {
        assert_eq!(fill("foo bar baz", 10), "foo bar\nbaz");
    }

    #[test]
    fn test_indent_empty() {
        assert_eq!(indent("\n", "  "), "\n");
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_indent_nonempty() {
        let x = vec!["  foo",
                     "bar",
                     "  baz"];
        let y = vec!["//  foo",
                     "//bar",
                     "//  baz"];
        assert_eq!(indent(&add_nl(&x), "//"), add_nl(&y));
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_indent_empty_line() {
        let x = vec!["  foo",
                     "bar",
                     "",
                     "  baz"];
        let y = vec!["//  foo",
                     "//bar",
                     "",
                     "//  baz"];
        assert_eq!(indent(&add_nl(&x), "//"), add_nl(&y));
    }

    #[test]
    fn test_dedent_empty() {
        assert_eq!(dedent(""), "");
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_dedent_multi_line() {
        let x = vec!["    foo",
                     "  bar",
                     "    baz"];
        let y = vec!["  foo",
                     "bar",
                     "  baz"];
        assert_eq!(dedent(&add_nl(&x)), add_nl(&y));
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_dedent_empty_line() {
        let x = vec!["    foo",
                     "  bar",
                     "   ",
                     "    baz"];
        let y = vec!["  foo",
                     "bar",
                     "",
                     "  baz"];
        assert_eq!(dedent(&add_nl(&x)), add_nl(&y));
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_dedent_mixed_whitespace() {
        let x = vec!["\tfoo",
                     "  bar"];
        let y = vec!["\tfoo",
                     "  bar"];
        assert_eq!(dedent(&add_nl(&x)), add_nl(&y));
    }
}
<|endoftext|>


<commit_before>// TODO: deny missing docs
#![allow(missing_docs)]

extern crate futures;
extern crate tokio_core;
extern crate trust_dns;

use futures::Future;
use futures::future::join_all;
use std::net::{Ipv4Addr, SocketAddr};
use std::str::FromStr;
use tokio_core::reactor::Handle;
use trust_dns::client::{ClientFuture, ClientHandle};
use trust_dns::rr::domain;
use trust_dns::rr::{DNSClass, RData, RecordType};
use trust_dns::udp::UdpClientStream;

pub fn lookup<T: Into<SocketAddr>>(
    loop_handle: &Handle,
    domain_name: &str,
    server: T,
) -> Box<Future<Item = Option<Ipv4Addr>, Error = ()>> {
    let socket_address = server.into();
    let (stream, sender) = UdpClientStream::new(socket_address, loop_handle);
    let mut client = ClientFuture::new(stream, sender, &loop_handle, None);
    let domain_name = domain::Name::from_str(domain_name).unwrap();

    Box::new(
        client
            .query(domain_name, DNSClass::IN, RecordType::A)
            .map(move |response| {
                let record = &response.answers()[0];
                if let &RData::A(address) = record.rdata() {
                    Some(address)
                } else {
                    None
                }
            })
            .map_err(move |_| ()),
    )
}

pub fn multiple_lookup<T: Into<SocketAddr>>(
    loop_handle: &Handle,
    domain_name: &str,
    servers: Vec<T>,
) -> Box<Future<Item = Vec<Option<Ipv4Addr>>, Error = ()>> {
    let futures: Vec<_> = servers
        .into_iter()
        .map(|server| lookup(loop_handle, domain_name, server))
        .collect();

    Box::new(join_all(futures))
}

#[cfg(test)]
mod test {
    use super::*;
    use tokio_core::reactor::Core;

    #[test]
    fn lookup_with_google() {
        let mut io_loop = Core::new().unwrap();
        let host = "example.com";
        let server = (Ipv4Addr::from_str("8.8.8.8").unwrap(), 53);

        let lookup = lookup(&io_loop.handle(), host, server);
        let results = io_loop.run(lookup);

        assert_eq!(results.unwrap(), Some(Ipv4Addr::new(93, 184, 216, 34)));
    }

    #[test]
    fn multiple_lookup_with_google() {
        let mut io_loop = Core::new().unwrap();
        let host = "example.com";
        let servers = vec![
            (Ipv4Addr::from_str("8.8.8.8").unwrap(), 53),
            (Ipv4Addr::from_str("8.8.4.4").unwrap(), 53),
        ];

        let lookup = multiple_lookup(&io_loop.handle(), host, servers);
        let results = io_loop.run(lookup);

        assert!(results.is_ok());
        let addresses = results.unwrap();
        assert_eq!(addresses[0], Some(Ipv4Addr::new(93, 184, 216, 34)));
        assert_eq!(addresses[1], Some(Ipv4Addr::new(93, 184, 216, 34)));
    }
}
<commit_msg>Clippify<commit_after>// TODO: deny missing docs
#![allow(missing_docs)]

extern crate futures;
extern crate tokio_core;
extern crate trust_dns;

use futures::Future;
use futures::future::join_all;
use std::net::{Ipv4Addr, SocketAddr};
use std::str::FromStr;
use tokio_core::reactor::Handle;
use trust_dns::client::{ClientFuture, ClientHandle};
use trust_dns::rr::domain;
use trust_dns::rr::{DNSClass, RData, RecordType};
use trust_dns::udp::UdpClientStream;

pub fn lookup<T: Into<SocketAddr>>(
    loop_handle: &Handle,
    domain_name: &str,
    server: T,
) -> Box<Future<Item = Option<Ipv4Addr>, Error = ()>> {
    let socket_address = server.into();
    let (stream, sender) = UdpClientStream::new(socket_address, loop_handle);
    let mut client = ClientFuture::new(stream, sender, loop_handle, None);
    let domain_name = domain::Name::from_str(domain_name).unwrap();

    Box::new(
        client
            .query(domain_name, DNSClass::IN, RecordType::A)
            .map(move |response| {
                let record = &response.answers()[0];
                if let RData::A(address) = *record.rdata() {
                    Some(address)
                } else {
                    None
                }
            })
            .map_err(move |_| ()),
    )
}

pub fn multiple_lookup<T: Into<SocketAddr>>(
    loop_handle: &Handle,
    domain_name: &str,
    servers: Vec<T>,
) -> Box<Future<Item = Vec<Option<Ipv4Addr>>, Error = ()>> {
    let futures: Vec<_> = servers
        .into_iter()
        .map(|server| lookup(loop_handle, domain_name, server))
        .collect();

    Box::new(join_all(futures))
}

#[cfg(test)]
mod test {
    use super::*;
    use tokio_core::reactor::Core;

    #[test]
    fn lookup_with_google() {
        let mut io_loop = Core::new().unwrap();
        let host = "example.com";
        let server = (Ipv4Addr::from_str("8.8.8.8").unwrap(), 53);

        let lookup = lookup(&io_loop.handle(), host, server);
        let results = io_loop.run(lookup);

        assert_eq!(results.unwrap(), Some(Ipv4Addr::new(93, 184, 216, 34)));
    }

    #[test]
    fn multiple_lookup_with_google() {
        let mut io_loop = Core::new().unwrap();
        let host = "example.com";
        let servers = vec![
            (Ipv4Addr::from_str("8.8.8.8").unwrap(), 53),
            (Ipv4Addr::from_str("8.8.4.4").unwrap(), 53),
        ];

        let lookup = multiple_lookup(&io_loop.handle(), host, servers);
        let results = io_loop.run(lookup);

        assert!(results.is_ok());
        let addresses = results.unwrap();
        assert_eq!(addresses[0], Some(Ipv4Addr::new(93, 184, 216, 34)));
        assert_eq!(addresses[1], Some(Ipv4Addr::new(93, 184, 216, 34)));
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 lazy-static.rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

/*!
A macro for declaring lazily evaluated statics.

Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.
This includes anything requiring heap allocations, like vectors or hash maps,
as well as anything that requires function calls to be computed.

# Syntax

```ignore
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```

Attributes (including doc comments) are supported as well:

```rust
# #[macro_use]
# extern crate lazy_static;
# fn main() {
lazy_static! {
    /// This is an example for using doc comment attributes
    static ref EXAMPLE: u8 = 42;
}
# }
```

# Semantics

For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Attributes end up
attaching to this type.)

On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object. Note that this can lead to deadlocks
if you have multiple lazy statics that depend on each other in their initialization.

Apart from the lazy initialization, the resulting "static ref" variables
have generally the same properties as regular "static" variables:

- Any type in them needs to fulfill the `Sync` trait.
- If the type has a destructor, then it will not run when the process exits.

# Example

Using the macro:

```rust
#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}

fn times_two(n: u32) -> u32 { n * 2 }

fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```

# Implementation details

The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access. On stable Rust, the macro may need to allocate each static on the heap.

*/

#![cfg_attr(feature="nightly", feature(const_fn, allow_internal_unstable, core_intrinsics, const_unsafe_cell_new))]

#![doc(html_root_url = "https://docs.rs/lazy_static/0.2.8")]
#![no_std]

#[cfg(not(feature="nightly"))]
#[doc(hidden)]
pub mod lazy;

#[cfg(all(feature="nightly", not(feature="spin_no_std")))]
#[path="nightly_lazy.rs"]
#[doc(hidden)]
pub mod lazy;

#[cfg(all(feature="nightly", feature="spin_no_std"))]
#[path="core_lazy.rs"]
#[doc(hidden)]
pub mod lazy;

#[doc(hidden)]
pub use core::ops::Deref as __Deref;

#[macro_export]
#[cfg_attr(feature="nightly", allow_internal_unstable)]
#[doc(hidden)]
macro_rules! __lazy_static_internal {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub(in $in:path) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@PUB_IN, $in, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    (@PUB_IN, $in:path, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@MAKE TY, PUB_IN, $in, $(#[$attr])*, $N);
        __lazy_static_internal!(@TAIL, $N : $T = $e);
        __lazy_static_internal!($($t)*);
    };
    (@$VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@MAKE TY, $VIS, $(#[$attr])*, $N);
        __lazy_static_internal!(@TAIL, $N : $T = $e);
        __lazy_static_internal!($($t)*);
    };
    (@TAIL, $N:ident : $T:ty = $e:expr) => {
        impl $crate::__Deref for $N {
            type Target = $T;
            #[allow(unsafe_code)]
            fn deref(&self) -> &$T {
                unsafe {
                    #[inline(always)]
                    fn __static_ref_initialize() -> $T { $e }

                    #[inline(always)]
                    unsafe fn __stability() -> &'static $T {
                        __lazy_static_create!(LAZY, $T);
                        LAZY.get(__static_ref_initialize)
                    }
                    __stability()
                }
            }
        }
        impl $crate::LazyStatic for $N {
            fn initialize(lazy: &Self) {
                let _ = &**lazy;
            }
        }
    };
    (@MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (@MAKE TY, PUB_IN, $in:path, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub(in $in) struct $N {__private_field: ()}
        #[doc(hidden)]
        pub(in $in) static $N: $N = $N {__private_field: ()};
    };
    (@MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}

#[macro_export]
#[cfg_attr(feature="nightly", allow_internal_unstable)]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub (in $in:path) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@PUB_IN, $in, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    () => ()
}

/// Support trait for enabling a few common operation on lazy static values.
///
/// This is implemented by each defined lazy static, and
/// used by the free functions in this crate.
pub trait LazyStatic {
    #[doc(hidden)]
    fn initialize(lazy: &Self);
}

/// Takes a shared reference to a lazy static and initializes
/// it if it has not been already.
///
/// This can be used to control the initialization point of a lazy static.
///
/// Example:
///
/// ```rust
/// #[macro_use]
/// extern crate lazy_static;
///
/// lazy_static! {
///     static ref BUFFER: Vec<u8> = (0..65537).collect();
/// }
///
/// fn main() {
///     lazy_static::initialize(&BUFFER);
///
///     // ...
///     work_with_initialized_data(&BUFFER);
/// }
/// # fn work_with_initialized_data(_: &[u8]) {}
/// ```
pub fn initialize<T: LazyStatic>(lazy: &T) {
    LazyStatic::initialize(lazy);
}
<commit_msg>fix keyword error<commit_after>// Copyright 2016 lazy-static.rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

/*!
A macro for declaring lazily evaluated statics.

Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.
This includes anything requiring heap allocations, like vectors or hash maps,
as well as anything that requires function calls to be computed.

# Syntax

```ignore
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```

Attributes (including doc comments) are supported as well:

```rust
# #[macro_use]
# extern crate lazy_static;
# fn main() {
lazy_static! {
    /// This is an example for using doc comment attributes
    static ref EXAMPLE: u8 = 42;
}
# }
```

# Semantics

For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Attributes end up
attaching to this type.)

On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object. Note that this can lead to deadlocks
if you have multiple lazy statics that depend on each other in their initialization.

Apart from the lazy initialization, the resulting "static ref" variables
have generally the same properties as regular "static" variables:

- Any type in them needs to fulfill the `Sync` trait.
- If the type has a destructor, then it will not run when the process exits.

# Example

Using the macro:

```rust
#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}

fn times_two(n: u32) -> u32 { n * 2 }

fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```

# Implementation details

The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access. On stable Rust, the macro may need to allocate each static on the heap.

*/

#![cfg_attr(feature="nightly", feature(const_fn, allow_internal_unstable, core_intrinsics, const_unsafe_cell_new))]

#![doc(html_root_url = "https://docs.rs/lazy_static/0.2.8")]
#![no_std]

#[cfg(not(feature="nightly"))]
#[doc(hidden)]
pub mod lazy;

#[cfg(all(feature="nightly", not(feature="spin_no_std")))]
#[path="nightly_lazy.rs"]
#[doc(hidden)]
pub mod lazy;

#[cfg(all(feature="nightly", feature="spin_no_std"))]
#[path="core_lazy.rs"]
#[doc(hidden)]
pub mod lazy;

#[doc(hidden)]
pub use core::ops::Deref as __Deref;

#[macro_export]
#[cfg_attr(feature="nightly", allow_internal_unstable)]
#[doc(hidden)]
macro_rules! __lazy_static_internal {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub(in $pub_in:path) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@PUB_IN, $pub_in, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    (@PUB_IN, $pub_in:path, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@MAKE TY, PUB_IN, $pub_in, $(#[$attr])*, $N);
        __lazy_static_internal!(@TAIL, $N : $T = $e);
        __lazy_static_internal!($($t)*);
    };
    (@$VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@MAKE TY, $VIS, $(#[$attr])*, $N);
        __lazy_static_internal!(@TAIL, $N : $T = $e);
        __lazy_static_internal!($($t)*);
    };
    (@TAIL, $N:ident : $T:ty = $e:expr) => {
        impl $crate::__Deref for $N {
            type Target = $T;
            #[allow(unsafe_code)]
            fn deref(&self) -> &$T {
                unsafe {
                    #[inline(always)]
                    fn __static_ref_initialize() -> $T { $e }

                    #[inline(always)]
                    unsafe fn __stability() -> &'static $T {
                        __lazy_static_create!(LAZY, $T);
                        LAZY.get(__static_ref_initialize)
                    }
                    __stability()
                }
            }
        }
        impl $crate::LazyStatic for $N {
            fn initialize(lazy: &Self) {
                let _ = &**lazy;
            }
        }
    };
    (@MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (@MAKE TY, PUB_IN, $pub_in:path, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub(in $pub_in) struct $N {__private_field: ()}
        #[doc(hidden)]
        pub(in $pub_in) static $N: $N = $N {__private_field: ()};
    };
    (@MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}

#[macro_export]
#[cfg_attr(feature="nightly", allow_internal_unstable)]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub (in $pub_in:path) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@PUB_IN, $pub_in, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    () => ()
}

/// Support trait for enabling a few common operation on lazy static values.
///
/// This is implemented by each defined lazy static, and
/// used by the free functions in this crate.
pub trait LazyStatic {
    #[doc(hidden)]
    fn initialize(lazy: &Self);
}

/// Takes a shared reference to a lazy static and initializes
/// it if it has not been already.
///
/// This can be used to control the initialization point of a lazy static.
///
/// Example:
///
/// ```rust
/// #[macro_use]
/// extern crate lazy_static;
///
/// lazy_static! {
///     static ref BUFFER: Vec<u8> = (0..65537).collect();
/// }
///
/// fn main() {
///     lazy_static::initialize(&BUFFER);
///
///     // ...
///     work_with_initialized_data(&BUFFER);
/// }
/// # fn work_with_initialized_data(_: &[u8]) {}
/// ```
pub fn initialize<T: LazyStatic>(lazy: &T) {
    LazyStatic::initialize(lazy);
}
<|endoftext|>


<commit_before>#![feature(augmented_assignments,
           op_assign_traits,
           core_intrinsics)]

extern crate ramp;
extern crate ieee754;
extern crate rand;

use ramp::Int;
use std::{fmt, i64};

mod ops;

mod sign;
pub use sign::Sign;

#[derive(Copy, Clone, Debug)]
enum Style {
    NaN,
    Infinity,
    Zero,
    Normal,
    // no subnormals... awkward to handle, and, the exponent goes down
    // to -2**63 + 1, which is somewhat small.
}

#[derive(Clone)]
pub struct Float {
    prec: u32,
    sign: Sign,
    exp: i64,
    signif: Int,
    style: Style
}
impl fmt::Debug for Float {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.debug_assert_valid();
        match self.style {
            Style::NaN => write!(f, "NaN"),
            Style::Zero => write!(f, "{}0.0", self.sign),
            Style::Infinity => write!(f, "{}inf", self.sign),
            Style::Normal => write!(f, "{}{:b} * 2^({} - {})",
                                    self.sign, self.signif, self.exp, self.prec),
        }
    }
}

impl Float {
    pub fn zero(p: u32) -> Float {
        Float::zero_(p, Sign::Pos)
    }

    pub fn neg_zero(p: u32) -> Float {
        Float::zero_(p, Sign::Neg)
    }

    pub fn max(p: u32) -> Float {
        Float {
            prec: p,
            sign: Sign::Pos,
            exp: i64::MAX - 1,
            signif: (Int::from(1) << p as usize) - 1,
            style: Style::Normal
        }
    }
    pub fn min(p: u32) -> Float {
        -Float::max(p)
    }
    pub fn min_positive(p: u32) -> Float {
        Float {
            prec: p,
            sign: Sign::Pos,
            exp: i64::MIN + 1,
            signif: (Int::from(1) << (p as usize - 1)),
            style: Style::Normal,
        }
    }

    pub fn infinity(p: u32) -> Float {
        Float::inf(p, Sign::Pos)
    }

    pub fn neg_infinity(p: u32) -> Float {
        Float::inf(p, Sign::Neg)
    }

    pub fn nan(p: u32) -> Float {
        Float {
            prec: p,
            sign: Sign::Pos,
            exp: i64::MAX,
            signif: Int::zero(),
            style: Style::NaN,
        }
    }

    pub fn next_above(mut self) -> Float {
        if self.sign == Sign::Pos {
            self.add_ulp();
        } else {
            self.sub_ulp();
        }
        self
    }
    pub fn next_below(mut self) -> Float {
        if self.sign == Sign::Neg {
            self.add_ulp();
        } else {
            self.sub_ulp();
        }
        self
    }
    pub fn next_toward(self, target: &Float) -> Float {
        use std::cmp::Ordering;
        match self.partial_cmp(target) {
            None | Some(Ordering::Equal) => self,
            Some(Ordering::Less) => self.next_above(),
            Some(Ordering::Greater) => self.next_below(),
        }
    }

    /// Generate a float in [0, 1), with the same distribution as
    /// generating an integer in [0, 2**p) and dividing by
    /// 2**p. (i.e. pretty close to uniform, but the smallest bits
    /// aren't quite right).
    pub fn rand<R: rand::Rng>(r: &mut R, p: u32) -> Float {
        use ramp::RandomInt;

        let mut signif = RandomInt::gen_uint(r, p as usize);
        let bits = signif.bit_length();
        assert!(bits <= p);
        let shift = p - bits;

        let (exp, style) = if signif == 0 {
            (i64::MIN, Style::Zero)
        } else {
            signif <<= shift as usize;

            (-1 - (shift as i64), Style::Normal)
        };
        Float {
            prec: p,
            sign: Sign::Pos,
            exp: exp,
            signif: signif,
            style: style
        }
    }

    pub fn abs(mut self) -> Float {
        self.debug_assert_valid();
        self.sign = Sign::Pos;
        self
    }
    pub fn sign(&self) -> Option<Sign> {
        self.debug_assert_valid();
        if let Style::NaN = self.style {
            None
        } else {
            Some(self.sign)
        }
    }
    pub fn negate(&mut self) {
        self.sign = -self.sign;
    }
    pub fn precision(&self) -> u32 {
        self.debug_assert_valid();
        self.prec
    }
    pub fn with_precision(mut self, prec: u32) -> Float {
        self.debug_assert_valid();
        assert!(prec > 0);
        let old_prec = self.prec;
        self.prec = prec;
        match self.style {
            Style::NaN | Style::Infinity | Style::Zero => {}
            Style::Normal => {
                if prec < old_prec {
                    // less precision:
                    let trailing_zeros = self.signif.trailing_zeros();
                    let has_trailing_one = trailing_zeros < old_prec - prec - 1;
                    let half_ulp_bit = self.signif.bit(old_prec - prec - 1);
                    let ulp_bit = self.signif.bit(old_prec - prec);
                    let round = half_ulp_bit & (ulp_bit | has_trailing_one);

                    self.signif >>= (old_prec - prec) as usize;
                    if round {
                        self.add_ulp();
                    }
                } else if prec > old_prec {
                    self.signif <<= (prec - old_prec) as usize;
                }
            }
        }
        self.debug_assert_valid();
        self
    }

    // self * 2**exp
    pub fn mul_exp2(mut self, exp: i64) -> Float {
        self.debug_assert_valid();
        match self.style {
            Style::Normal => {
                self.exp = self.exp.saturating_add(exp);
                self.normalise(false);
            }
            Style::NaN | Style::Infinity | Style::Zero => {}
        }
        self
    }

    fn zero_(p: u32, sign: Sign) -> Float {
        Float {
            prec: p,
            sign: sign,
            exp: i64::MIN,
            signif: Int::zero(),
            style: Style::Zero,
        }
    }
    fn inf(p: u32, sign: Sign) -> Float {
        Float {
            prec: p,
            sign: sign,
            exp: i64::MAX,
            signif: Int::zero(),
            style: Style::Infinity
        }
    }
    fn normalise(&mut self, check_bits: bool) {
        let diff = if check_bits {
            let bits = self.signif.bit_length() as i64;
            if self.signif == 0 {
                *self = Float::zero_(self.prec, self.sign);
                return
            }
            bits - self.prec as i64
        } else {
            0
        };
        self.exp = self.exp.saturating_add(diff);
        match self.exp {
            // FIXME (#13)
            i64::MAX => *self = Float::inf(self.prec, self.sign),
            i64::MIN => *self = Float::zero_(self.prec, self.sign),
            _ => {
                use std::cmp::Ordering;
                match diff.cmp(&0) {
                    Ordering::Greater => self.signif >>= diff as usize,
                    Ordering::Equal => {},
                    Ordering::Less => self.signif <<= (-diff) as usize,
                }
            }
        }
    }

    fn add_ulp(&mut self) {
        self.debug_assert_valid();
        match self.style {
            Style::NaN => {},
            Style::Infinity => {}
            Style::Zero => {
                let s = self.sign;
                // FIXME (#13)
                *self = Float::min_positive(self.prec);
                self.sign = s;
            }
            Style::Normal => {
                self.signif += 1;
                if self.signif.bit(self.prec) {
                    self.exp += 1;
                    if self.exp == i64::MAX {
                        // FIXME (#13)
                        *self = Float::inf(self.prec, self.sign)
                    } else {
                        self.signif >>= 1;
                    }
                }
            }
        }
    }
    fn sub_ulp(&mut self) {
        self.debug_assert_valid();
        match self.style {
            Style::NaN => {},
            Style::Infinity => {
                // FIXME (#13)
                *self = Float::max(self.prec)
            }
            Style::Zero => {
                // FIXME (#13)
                *self = Float::min_positive(self.prec);
                self.sign = -self.sign;
            }
            Style::Normal => {
                self.signif -= 1;
                if !self.signif.bit(self.prec - 1) {
                    self.exp -= 1;
                    if self.exp == i64::MIN {
                        // FIXME (#13)
                        *self = Float::zero_(self.prec, self.sign);
                    } else {
                        self.signif <<= 1;
                        self.signif |= 1;
                    }
                }
            }
        }
    }

    fn is_valid(&self) -> bool {
        match self.style {
            Style::NaN => {
                // theoretically we could require self.signif != 0,
                // but that would force an allocation
                self.exp == i64::MAX
            }
            Style::Infinity => {
                self.exp == i64::MAX && self.signif == 0
            }
            Style::Zero => {
                self.exp == i64::MIN && self.signif == 0
            }
            Style::Normal => {
                i64::MIN < self.exp && self.exp < i64::MAX &&
                    self.signif.bit_length() == self.prec
            }
        }
    }
    fn debug_assert_valid(&self) {
        // FIXME: everything is debugging at the moment
        assert!(self.is_valid());
    }
}

fn add_overflow(x: i64, y: i64) -> (i64, bool) {
    unsafe {
        std::intrinsics::add_with_overflow(x, y)
    }
}
fn sub_overflow(x: i64, y: i64) -> (i64, bool) {
    unsafe {
        std::intrinsics::sub_with_overflow(x, y)
    }
}
<commit_msg>Implement Clone manually to get efficient clone_from.<commit_after>#![feature(augmented_assignments,
           op_assign_traits,
           core_intrinsics)]

extern crate ramp;
extern crate ieee754;
extern crate rand;

use ramp::Int;
use std::{fmt, i64};

mod ops;

mod sign;
pub use sign::Sign;

#[derive(Copy, Clone, Debug)]
enum Style {
    NaN,
    Infinity,
    Zero,
    Normal,
    // no subnormals... awkward to handle, and, the exponent goes down
    // to -2**63 + 1, which is somewhat small.
}

pub struct Float {
    prec: u32,
    sign: Sign,
    exp: i64,
    signif: Int,
    style: Style
}

impl Clone for Float {
    fn clone(&self) -> Float {
        let mut x = Float::zero(0);
        x.clone_from(self);
        x
    }
    fn clone_from(&mut self, other: &Float) {
        other.debug_assert_valid();
        self.prec = other.prec;
        self.sign = other.sign;
        self.exp = other.exp;
        self.signif.clone_from(&other.signif);
        self.style = other.style;
    }
}

impl fmt::Debug for Float {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.debug_assert_valid();
        match self.style {
            Style::NaN => write!(f, "NaN"),
            Style::Zero => write!(f, "{}0.0", self.sign),
            Style::Infinity => write!(f, "{}inf", self.sign),
            Style::Normal => write!(f, "{}{:b} * 2^({} - {})",
                                    self.sign, self.signif, self.exp, self.prec),
        }
    }
}

impl Float {
    pub fn zero(p: u32) -> Float {
        Float::zero_(p, Sign::Pos)
    }

    pub fn neg_zero(p: u32) -> Float {
        Float::zero_(p, Sign::Neg)
    }

    pub fn max(p: u32) -> Float {
        Float {
            prec: p,
            sign: Sign::Pos,
            exp: i64::MAX - 1,
            signif: (Int::from(1) << p as usize) - 1,
            style: Style::Normal
        }
    }
    pub fn min(p: u32) -> Float {
        -Float::max(p)
    }
    pub fn min_positive(p: u32) -> Float {
        Float {
            prec: p,
            sign: Sign::Pos,
            exp: i64::MIN + 1,
            signif: (Int::from(1) << (p as usize - 1)),
            style: Style::Normal,
        }
    }

    pub fn infinity(p: u32) -> Float {
        Float::inf(p, Sign::Pos)
    }

    pub fn neg_infinity(p: u32) -> Float {
        Float::inf(p, Sign::Neg)
    }

    pub fn nan(p: u32) -> Float {
        Float {
            prec: p,
            sign: Sign::Pos,
            exp: i64::MAX,
            signif: Int::zero(),
            style: Style::NaN,
        }
    }

    pub fn next_above(mut self) -> Float {
        if self.sign == Sign::Pos {
            self.add_ulp();
        } else {
            self.sub_ulp();
        }
        self
    }
    pub fn next_below(mut self) -> Float {
        if self.sign == Sign::Neg {
            self.add_ulp();
        } else {
            self.sub_ulp();
        }
        self
    }
    pub fn next_toward(self, target: &Float) -> Float {
        use std::cmp::Ordering;
        match self.partial_cmp(target) {
            None | Some(Ordering::Equal) => self,
            Some(Ordering::Less) => self.next_above(),
            Some(Ordering::Greater) => self.next_below(),
        }
    }

    /// Generate a float in [0, 1), with the same distribution as
    /// generating an integer in [0, 2**p) and dividing by
    /// 2**p. (i.e. pretty close to uniform, but the smallest bits
    /// aren't quite right).
    pub fn rand<R: rand::Rng>(r: &mut R, p: u32) -> Float {
        use ramp::RandomInt;

        let mut signif = RandomInt::gen_uint(r, p as usize);
        let bits = signif.bit_length();
        assert!(bits <= p);
        let shift = p - bits;

        let (exp, style) = if signif == 0 {
            (i64::MIN, Style::Zero)
        } else {
            signif <<= shift as usize;

            (-1 - (shift as i64), Style::Normal)
        };
        Float {
            prec: p,
            sign: Sign::Pos,
            exp: exp,
            signif: signif,
            style: style
        }
    }

    pub fn abs(mut self) -> Float {
        self.debug_assert_valid();
        self.sign = Sign::Pos;
        self
    }
    pub fn sign(&self) -> Option<Sign> {
        self.debug_assert_valid();
        if let Style::NaN = self.style {
            None
        } else {
            Some(self.sign)
        }
    }
    pub fn negate(&mut self) {
        self.sign = -self.sign;
    }
    pub fn precision(&self) -> u32 {
        self.debug_assert_valid();
        self.prec
    }
    pub fn with_precision(mut self, prec: u32) -> Float {
        self.debug_assert_valid();
        assert!(prec > 0);
        let old_prec = self.prec;
        self.prec = prec;
        match self.style {
            Style::NaN | Style::Infinity | Style::Zero => {}
            Style::Normal => {
                if prec < old_prec {
                    // less precision:
                    let trailing_zeros = self.signif.trailing_zeros();
                    let has_trailing_one = trailing_zeros < old_prec - prec - 1;
                    let half_ulp_bit = self.signif.bit(old_prec - prec - 1);
                    let ulp_bit = self.signif.bit(old_prec - prec);
                    let round = half_ulp_bit & (ulp_bit | has_trailing_one);

                    self.signif >>= (old_prec - prec) as usize;
                    if round {
                        self.add_ulp();
                    }
                } else if prec > old_prec {
                    self.signif <<= (prec - old_prec) as usize;
                }
            }
        }
        self.debug_assert_valid();
        self
    }

    // self * 2**exp
    pub fn mul_exp2(mut self, exp: i64) -> Float {
        self.debug_assert_valid();
        match self.style {
            Style::Normal => {
                self.exp = self.exp.saturating_add(exp);
                self.normalise(false);
            }
            Style::NaN | Style::Infinity | Style::Zero => {}
        }
        self
    }

    fn zero_(p: u32, sign: Sign) -> Float {
        Float {
            prec: p,
            sign: sign,
            exp: i64::MIN,
            signif: Int::zero(),
            style: Style::Zero,
        }
    }
    fn inf(p: u32, sign: Sign) -> Float {
        Float {
            prec: p,
            sign: sign,
            exp: i64::MAX,
            signif: Int::zero(),
            style: Style::Infinity
        }
    }
    fn normalise(&mut self, check_bits: bool) {
        let diff = if check_bits {
            let bits = self.signif.bit_length() as i64;
            if self.signif == 0 {
                *self = Float::zero_(self.prec, self.sign);
                return
            }
            bits - self.prec as i64
        } else {
            0
        };
        self.exp = self.exp.saturating_add(diff);
        match self.exp {
            // FIXME (#13)
            i64::MAX => *self = Float::inf(self.prec, self.sign),
            i64::MIN => *self = Float::zero_(self.prec, self.sign),
            _ => {
                use std::cmp::Ordering;
                match diff.cmp(&0) {
                    Ordering::Greater => self.signif >>= diff as usize,
                    Ordering::Equal => {},
                    Ordering::Less => self.signif <<= (-diff) as usize,
                }
            }
        }
    }

    fn add_ulp(&mut self) {
        self.debug_assert_valid();
        match self.style {
            Style::NaN => {},
            Style::Infinity => {}
            Style::Zero => {
                let s = self.sign;
                // FIXME (#13)
                *self = Float::min_positive(self.prec);
                self.sign = s;
            }
            Style::Normal => {
                self.signif += 1;
                if self.signif.bit(self.prec) {
                    self.exp += 1;
                    if self.exp == i64::MAX {
                        // FIXME (#13)
                        *self = Float::inf(self.prec, self.sign)
                    } else {
                        self.signif >>= 1;
                    }
                }
            }
        }
    }
    fn sub_ulp(&mut self) {
        self.debug_assert_valid();
        match self.style {
            Style::NaN => {},
            Style::Infinity => {
                // FIXME (#13)
                *self = Float::max(self.prec)
            }
            Style::Zero => {
                // FIXME (#13)
                *self = Float::min_positive(self.prec);
                self.sign = -self.sign;
            }
            Style::Normal => {
                self.signif -= 1;
                if !self.signif.bit(self.prec - 1) {
                    self.exp -= 1;
                    if self.exp == i64::MIN {
                        // FIXME (#13)
                        *self = Float::zero_(self.prec, self.sign);
                    } else {
                        self.signif <<= 1;
                        self.signif |= 1;
                    }
                }
            }
        }
    }

    fn is_valid(&self) -> bool {
        match self.style {
            Style::NaN => {
                // theoretically we could require self.signif != 0,
                // but that would force an allocation
                self.exp == i64::MAX
            }
            Style::Infinity => {
                self.exp == i64::MAX && self.signif == 0
            }
            Style::Zero => {
                self.exp == i64::MIN && self.signif == 0
            }
            Style::Normal => {
                i64::MIN < self.exp && self.exp < i64::MAX &&
                    self.signif.bit_length() == self.prec
            }
        }
    }
    fn debug_assert_valid(&self) {
        // FIXME: everything is debugging at the moment
        assert!(self.is_valid());
    }
}

fn add_overflow(x: i64, y: i64) -> (i64, bool) {
    unsafe {
        std::intrinsics::add_with_overflow(x, y)
    }
}
fn sub_overflow(x: i64, y: i64) -> (i64, bool) {
    unsafe {
        std::intrinsics::sub_with_overflow(x, y)
    }
}
<|endoftext|>