<commit_before>use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;

use crate::error::Error;

// Indicate an interest in read and/or write events.
struct Interest(bool, bool);

// The EventLoop sets up a polling::Poller and use it to wait for events on file descriptors as
// directed by the c-ares library.
pub struct EventLoop {
    poller: Arc<polling::Poller>,
    rx_msg_channel: crossbeam_channel::Receiver<polling::Event>,
    interests: HashMap<c_ares::Socket, Interest>,
    pub ares_channel: Arc<Mutex<c_ares::Channel>>,
    quit: Arc<AtomicBool>,
}

// Object returned when the EventLoop is run.  Call `stop()` to stop the associated EventLoop.
pub struct EventLoopStopper {
    poller: Arc<polling::Poller>,
    quit: Arc<AtomicBool>,
}

impl EventLoopStopper {
    pub fn new(poller: Arc<polling::Poller>, quit: Arc<AtomicBool>) -> Self {
        Self { poller, quit }
    }

    pub fn stop(&self) {
        self.quit.store(true, Ordering::Relaxed);
        let _ = self.poller.notify();
    }
}

impl EventLoop {
    // Create a new event loop.
    pub fn new(mut options: c_ares::Options) -> Result<Self, Error> {
        // Create a polling::Poller on which to wait for events, and a channel for sending messages
        // to the event loop.
        let poller = Arc::new(polling::Poller::new()?);
        let (tx, rx) = crossbeam_channel::unbounded();

        // Whenever c-ares tells us what to do with a file descriptor, we'll send a message
        // registering our interest, and wake up the poller.
        {
            let poller = Arc::clone(&poller);
            let sock_callback = move |socket: c_ares::Socket, readable: bool, writable: bool| {
                let event = polling::Event {
                    key: socket as usize,
                    readable,
                    writable,
                };
                let _ = tx.send(event);
                let _ = poller.notify();
            };
            options.set_socket_state_callback(sock_callback);
        }

        // Create the c-ares channel.
        let ares_channel = c_ares::Channel::with_options(options)?;
        let locked_channel = Arc::new(Mutex::new(ares_channel));

        // Create and return the event loop.
        let event_loop = EventLoop {
            poller,
            rx_msg_channel: rx,
            interests: HashMap::new(),
            ares_channel: locked_channel,
            quit: Arc::new(AtomicBool::new(false)),
        };
        Ok(event_loop)
    }

    // Run the event loop.
    pub fn run(self) -> EventLoopStopper {
        // Create a stopper.
        let poller = Arc::clone(&self.poller);
        let quit = Arc::clone(&self.quit);
        let stopper = EventLoopStopper::new(poller, quit);

        thread::spawn(|| self.event_loop_thread());
        stopper
    }

    // Event loop thread - waits for events, and handles them.
    fn event_loop_thread(mut self) {
        let mut events = vec![];
        let timeout = Duration::from_millis(500);
        loop {
            // Wait for something to happen.
            events.clear();
            let results = self
                .poller
                .wait(&mut events, Some(timeout))
                .expect("poll failed");

            // If we're asked to quit, then quit.
            if self.quit.load(Ordering::Relaxed) {
                break;
            }

            // Process any events.
            match results {
                0 => {
                    // No events.  Have c-ares process any timeouts.
                    self.ares_channel
                        .lock()
                        .unwrap()
                        .process_fd(c_ares::SOCKET_BAD, c_ares::SOCKET_BAD);
                }
                _ => {
                    // Process events.
                    for event in &events {
                        self.handle_event(&event);
                    }
                }
            }

            // Process any messages.
            self.handle_messages();
        }
    }

    // Handle a single event.
    fn handle_event(&mut self, event: &polling::Event) {
        // `polling` always operates in oneshot mode, but c-ares expects us to maintain an interest
        // in sockets until told otherwise.
        //
        // So re-assert our interest in this socket.
        let socket = event.key as c_ares::Socket;
        if let Some(Interest(readable, writable)) = self.interests.get(&socket) {
            let new_event = polling::Event {
                key: event.key,
                readable: *readable,
                writable: *writable,
            };
            self.poller
                .interest(socket, new_event)
                .expect("failed to register interest");
        }

        // Tell c-ares that something happened.
        let rfd = if event.readable {
            socket
        } else {
            c_ares::SOCKET_BAD
        };
        let wfd = if event.writable {
            socket
        } else {
            c_ares::SOCKET_BAD
        };
        self.ares_channel.lock().unwrap().process_fd(rfd, wfd);
    }

    // Process messages incoming on the channel.
    fn handle_messages(&mut self) {
        while let Ok(event) = self.rx_msg_channel.try_recv() {
            let socket = event.key as c_ares::Socket;
            if !event.readable && !event.writable {
                self.interests.remove(&socket);
                let _ = self.poller.remove(socket);
            } else {
                let interest = Interest(event.readable, event.writable);
                if self.interests.insert(socket, interest).is_none() {
                    self.poller
                        .insert(socket)
                        .expect("failed to add socket to poller");
                }
                self.poller
                    .interest(socket, event)
                    .expect("failed to register interest");
            }
        }
    }
}
<commit_msg>slightly prettier<commit_after>use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;

use crate::error::Error;

// Indicate an interest in read and/or write events.
struct Interest(bool, bool);

// The EventLoop sets up a polling::Poller and use it to wait for events on file descriptors as
// directed by the c-ares library.
pub struct EventLoop {
    poller: Arc<polling::Poller>,
    rx_msg_channel: crossbeam_channel::Receiver<polling::Event>,
    interests: HashMap<c_ares::Socket, Interest>,
    pub ares_channel: Arc<Mutex<c_ares::Channel>>,
    quit: Arc<AtomicBool>,
}

// Object returned when the EventLoop is run.  Call `stop()` to stop the associated EventLoop.
pub struct EventLoopStopper {
    poller: Arc<polling::Poller>,
    quit: Arc<AtomicBool>,
}

impl EventLoopStopper {
    pub fn new(poller: Arc<polling::Poller>, quit: Arc<AtomicBool>) -> Self {
        Self { poller, quit }
    }

    pub fn stop(&self) {
        self.quit.store(true, Ordering::Relaxed);
        let _ = self.poller.notify();
    }
}

impl EventLoop {
    // Create a new event loop.
    pub fn new(mut options: c_ares::Options) -> Result<Self, Error> {
        // Create a polling::Poller on which to wait for events, and a channel for sending messages
        // to the event loop.
        let poller = Arc::new(polling::Poller::new()?);
        let (tx, rx) = crossbeam_channel::unbounded();

        // Whenever c-ares tells us what to do with a file descriptor, we'll send a message
        // registering our interest, and wake up the poller.
        {
            let poller = Arc::clone(&poller);
            let sock_callback = move |socket: c_ares::Socket, readable: bool, writable: bool| {
                let event = polling::Event {
                    key: socket as usize,
                    readable,
                    writable,
                };
                let _ = tx.send(event);
                let _ = poller.notify();
            };
            options.set_socket_state_callback(sock_callback);
        }

        // Create the c-ares channel.
        let ares_channel = c_ares::Channel::with_options(options)?;
        let locked_channel = Arc::new(Mutex::new(ares_channel));

        // Create and return the event loop.
        let event_loop = EventLoop {
            poller,
            rx_msg_channel: rx,
            interests: HashMap::new(),
            ares_channel: locked_channel,
            quit: Arc::new(AtomicBool::new(false)),
        };
        Ok(event_loop)
    }

    // Run the event loop.
    pub fn run(self) -> EventLoopStopper {
        // Create a stopper.
        let poller = Arc::clone(&self.poller);
        let quit = Arc::clone(&self.quit);
        let stopper = EventLoopStopper::new(poller, quit);

        thread::spawn(|| self.event_loop_thread());
        stopper
    }

    // Event loop thread - waits for events, and handles them.
    fn event_loop_thread(mut self) {
        let mut events = vec![];
        let timeout = Duration::from_millis(500);
        loop {
            // Wait for something to happen.
            events.clear();
            let results = self
                .poller
                .wait(&mut events, Some(timeout))
                .expect("poll failed");

            // If we're asked to quit, then quit.
            if self.quit.load(Ordering::Relaxed) {
                break;
            }

            // Process any events.
            match results {
                0 => {
                    // No events.  Have c-ares process any timeouts.
                    self.ares_channel
                        .lock()
                        .unwrap()
                        .process_fd(c_ares::SOCKET_BAD, c_ares::SOCKET_BAD);
                }
                _ => {
                    // Process events.
                    for event in &events {
                        self.handle_event(&event);
                    }
                }
            }

            // Process any messages.
            self.handle_messages();
        }
    }

    // Handle a single event.
    fn handle_event(&mut self, event: &polling::Event) {
        // `polling` always operates in oneshot mode, but c-ares expects us to maintain an interest
        // in sockets until told otherwise.
        //
        // So re-assert our interest in this socket.
        let socket = event.key as c_ares::Socket;
        if let Some(Interest(readable, writable)) = self.interests.get(&socket) {
            let new_event = polling::Event {
                key: event.key,
                readable: *readable,
                writable: *writable,
            };
            self.poller
                .interest(socket, new_event)
                .expect("failed to register interest");
        }

        // Tell c-ares that something happened.
        let rfd = if event.readable {
            socket
        } else {
            c_ares::SOCKET_BAD
        };
        let wfd = if event.writable {
            socket
        } else {
            c_ares::SOCKET_BAD
        };
        self.ares_channel.lock().unwrap().process_fd(rfd, wfd);
    }

    // Process messages incoming on the channel.
    fn handle_messages(&mut self) {
        for event in self.rx_msg_channel.try_iter() {
            let socket = event.key as c_ares::Socket;
            if !event.readable && !event.writable {
                self.interests.remove(&socket);
                let _ = self.poller.remove(socket);
            } else {
                let interest = Interest(event.readable, event.writable);
                if self.interests.insert(socket, interest).is_none() {
                    self.poller
                        .insert(socket)
                        .expect("failed to add socket to poller");
                }
                self.poller
                    .interest(socket, event)
                    .expect("failed to register interest");
            }
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;

extern crate serde;

#[macro_use]
extern crate serde_jsonrc;

use serde_jsonrc::{from_str, Value};

#[test]
fn test_trailing_comma_object() {
    let s = r#"
    {
        "key": "value",
    }"#;
    let value: Value = from_str(s).unwrap();
    assert_eq!(value, json!({"key": "value"}));
}

#[test]
fn test_trailing_comma_array() {
    let s = r#"
    {
        "key": [
            "one",
            "two",
            "three",
        ]
    }"#;
    let value: Value = from_str(s).unwrap();
    assert_eq!(value, json!({"key": ["one", "two", "three"]}));
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
enum Animal {
    Dog,
    Frog(String, Vec<isize>),
    Cat { age: usize, name: String },
    AntHive(Vec<String>),
}

#[test]
fn test_parse_enum_animal_and_no_other_test() {
    let animal: Animal = from_str("{\"Cat\":[0, \"Kate\",]}").unwrap();
    assert_eq!(
        animal,
        Animal::Cat {
            age: 0,
            name: "Kate".to_string()
        }
    );
}
<commit_msg>Add test to verify trailing commas works with struct parsing.<commit_after>#[macro_use]
extern crate serde_derive;

extern crate serde;

#[macro_use]
extern crate serde_jsonrc;

use serde_jsonrc::{from_str, Value};

#[test]
fn test_trailing_comma_object() {
    let s = r#"
    {
        "key": "value",
    }"#;
    let value: Value = from_str(s).unwrap();
    assert_eq!(value, json!({"key": "value"}));
}

#[test]
fn test_trailing_comma_array() {
    let s = r#"
    {
        "key": [
            "one",
            "two",
            "three",
        ]
    }"#;
    let value: Value = from_str(s).unwrap();
    assert_eq!(value, json!({"key": ["one", "two", "three"]}));
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
enum Animal {
    Dog,
    Frog(String, Vec<isize>),
    Cat { age: usize, name: String },
    AntHive(Vec<String>),
}

#[test]
fn test_parse_enum_as_array_with_deny_unknown_fields() {
    let animal: Animal = from_str("{\"Cat\":[0, \"Kate\",]}").unwrap();
    assert_eq!(
        animal,
        Animal::Cat {
            age: 0,
            name: "Kate".to_string()
        }
    );
}

#[test]
fn test_parse_enum_as_object_with_deny_unknown_fields() {
    let animal: Animal = from_str("{\"Cat\":{\"age\": 2, \"name\": \"Kate\",}}").unwrap();
    assert_eq!(
        animal,
        Animal::Cat {
            age: 2,
            name: "Kate".to_string()
        }
    );
}
<|endoftext|>


<commit_before><commit_msg>Fix UnitHeader::length_including_self() for Dwarf64<commit_after><|endoftext|>


<commit_before>//! redis-rs is a rust implementation of a Redis client library.  It exposes
//! a general purpose interface to Redis and also provides specific helpers for
//! commonly used functionality.
//!
//! # Basic Operation
//!
//! To open a connection you need to create a client and then to fetch a
//! connection from it.  In the future there will be a connection pool for
//! those, currently each connection is separate and not pooled.
//!
//! Queries are then performed through the `execute` and `query` methods.
//!
//! ```rust,no_run
//! extern crate redis;
//!
//! fn main() {
//!     let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//!     let con = client.get_connection().unwrap();
//!     redis::cmd("SET").arg("my_key").arg(42i).execute(&con);
//!     assert_eq!(redis::cmd("GET").arg("my_key").query(&con), Ok(42i));
//! }
//! ```
//!
//! ## Type Conversions
//!
//! Because redis inherently is mostly type-less and the protocol is not
//! exactly friendly to developers, this library provides flexible support
//! for casting values to the intended results.  This is driven through the
//! `FromRedisValue` and `ToRedisArgs` traits.
//!
//! The `arg` method of the command will accept a wide range of types through
//! the `ToRedisArgs` trait and the `query` method of a command can convert the
//! value to what you expect the function to return through the `FromRedisValue`
//! trait.  This is quite flexible and allows vectors, tuples, hashsets, hashmaps
//! as well as optional values:
//!
//! ```rust,no_run
//! # use std::collections::{HashMap, HashSet};
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let count : i32 = redis::cmd("GET").arg("my_counter").query(&con).unwrap();
//! let count = redis::cmd("GET").arg("my_counter").query(&con).unwrap_or(0i32);
//! let k : Option<String> = redis::cmd("GET").arg("missing_key").query(&con).unwrap();
//! let name : String = redis::cmd("GET").arg("my_name").query(&con).unwrap();
//! let bin : Vec<u8> = redis::cmd("GET").arg("my_binary").query(&con).unwrap();
//! let map : HashMap<String, i32> = redis::cmd("HGETALL").arg("my_hash").query(&con).unwrap();
//! let keys : Vec<String> = redis::cmd("KEYS").query(&con).unwrap();
//! let mems : HashSet<i32> = redis::cmd("SMEMBERS").arg("s").query(&con).unwrap();
//! let (k1, k2) : (String, String) = redis::cmd("MGET").arg("k1").arg("k2").query(&con).unwrap();
//! ```
//!
//! ## Iteration Protocol
//!
//! In addition to sending a single query you iterators are also supported.  When
//! used with regular bulk responses they don't give you much over querying and
//! converting into a vector (both use a vector internally) but they can also
//! be used with `SCAN` like commands in which case iteration will send more
//! queries until the cursor is exhausted:
//!
//! ```rust,no_run
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let mut cmd = redis::cmd("SSCAN");
//! let mut iter : redis::Iter<int> = cmd.arg("my_set").cursor_arg(0).iter(&con).unwrap();
//! for x in iter {
//!     // do something with the item
//! }
//! ```
//!
//! As you can see the cursor argument needs to be defined with `cursor_arg` instead
//! of `arg` so that the library knows which argument needs updating as the
//! query is run for more items.
//!
//! ## Pipelining
//!
//! In addition to simple queries you can also send command pipelines.  This
//! is provided through the `pipe` function.  It works very similar to sending
//! individual commands but you can send more than one in one go.  This also
//! allows you to ignore individual results so that matching on the end result
//! is easier:
//!
//! ```rust,no_run
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = redis::pipe()
//!     .cmd("SET").arg("key_1").arg(42i).ignore()
//!     .cmd("SET").arg("key_2").arg(43i).ignore()
//!     .cmd("GET").arg("key_1")
//!     .cmd("GET").arg("key_2").query(&con).unwrap();
//! ```
//!
//! If you want the pipeline to be wrapped in a `MULTI`/`EXEC` block you can
//! easily do that by switching the pipeline into `atomic` mode.  From the
//! caller's point of view nothing changes, the pipeline itself will take
//! care of the rest for you:
//!
//! ```rust,no_run
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = redis::pipe()
//!     .atomic()
//!     .cmd("SET").arg("key_1").arg(42i).ignore()
//!     .cmd("SET").arg("key_2").arg(43i).ignore()
//!     .cmd("GET").arg("key_1")
//!     .cmd("GET").arg("key_2").query(&con).unwrap();
//! ```
//!
//! ## Transactions
//!
//! Transactions are available through atomic pipelines.  In order to use
//! them in a more simple way you can use the `transaction` function of a
//! connection:
//!
//! ```rust,no_run
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let key = "the_key";
//! let (new_val,) : (int,) = con.transaction([key][], |pipe| {
//!     let old_val : int = try!(redis::cmd("GET").arg(key).query(&con));
//!     pipe
//!         .cmd("SET").arg(key).arg(old_val + 1).ignore()
//!         .cmd("GET").arg(key).query(&con)
//! }).unwrap();
//! println!("The incremented number is: {}", new_val);
//! ```
//!
//! For more information see the `transaction` function.
//!
//! ## PubSub
//!
//! Pubsub is currently work in progress but provided through the `PubSub`
//! connection object.  Due to the fact that Rust does not have support
//! for async IO in libnative yet, the API does not provide a way to
//! read messages with any form of timeout yet.
//!
//! Example usage:
//!
//! ```rust,no_run
//! let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! let mut pubsub = client.get_pubsub().unwrap();
//! pubsub.subscribe("channel_1").unwrap();
//! pubsub.subscribe("channel_2").unwrap();
//!
//! loop {
//!     let msg = pubsub.get_message().unwrap();
//!     let payload : String = msg.get_payload().unwrap();
//!     println!("channel '{}': {}", msg.get_channel_name(), payload);
//! }
//! ```
//!
//! ## Scripts
//!
//! Lua scripts are supported through the `Script` type in a convenient
//! way (it does not support pipelining currently).  It will automatically
//! load the script if it does not exist and invoke it.
//!
//! Example:
//!
//! ```rust,no_run
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let script = redis::Script::new(r"
//!     return tonumber(ARGV[1]) + tonumber(ARGV[2]);
//! ");
//! let result : int = script.arg(1i).arg(2i).invoke(&con).unwrap();
//! assert_eq!(result, 3);
//! ```

#![crate_name = "redis"]
#![crate_type = "lib"]
#![license = "BSD"]
#![comment = "Bindings and wrapper functions for redis."]

#![deny(non_camel_case_types)]

#![feature(macro_rules)]
#![feature(default_type_params)]

#![experimental]

extern crate url;
extern crate serialize;
extern crate "rust-crypto" as crypto;

/* public api */
pub use parser::{parse_redis_value, Parser};
pub use client::Client;
pub use script::{Script, ScriptInvocation};
pub use connection::{Connection, PubSub, Msg};
pub use cmd::{cmd, Cmd, pipe, Pipeline, Iter, pack_command};

#[doc(hidden)]
pub use types::{
    /* low level values */
    Value,
        Nil,
        Int,
        Data,
        Bulk,
        Okay,
        Status,

    /* error and result types */
    Error,
    RedisResult,

    /* error kinds */
    ErrorKind,
        ResponseError,
        TypeError,
        ExecAbortError,
        BusyLoadingError,
        NoScriptError,
        ExtensionError,
        InternalIoError,

    /* utility types */
    InfoDict,

    /* conversion traits */
    FromRedisValue,
    ToRedisArgs,

    /* utility functions */
    from_redis_value,
};

pub mod macros;

mod parser;
mod client;
mod connection;
mod types;
mod script;
mod cmd;
<commit_msg>Slicing syntax was put behind a feature gate<commit_after>//! redis-rs is a rust implementation of a Redis client library.  It exposes
//! a general purpose interface to Redis and also provides specific helpers for
//! commonly used functionality.
//!
//! # Basic Operation
//!
//! To open a connection you need to create a client and then to fetch a
//! connection from it.  In the future there will be a connection pool for
//! those, currently each connection is separate and not pooled.
//!
//! Queries are then performed through the `execute` and `query` methods.
//!
//! ```rust,no_run
//! extern crate redis;
//!
//! fn main() {
//!     let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//!     let con = client.get_connection().unwrap();
//!     redis::cmd("SET").arg("my_key").arg(42i).execute(&con);
//!     assert_eq!(redis::cmd("GET").arg("my_key").query(&con), Ok(42i));
//! }
//! ```
//!
//! ## Type Conversions
//!
//! Because redis inherently is mostly type-less and the protocol is not
//! exactly friendly to developers, this library provides flexible support
//! for casting values to the intended results.  This is driven through the
//! `FromRedisValue` and `ToRedisArgs` traits.
//!
//! The `arg` method of the command will accept a wide range of types through
//! the `ToRedisArgs` trait and the `query` method of a command can convert the
//! value to what you expect the function to return through the `FromRedisValue`
//! trait.  This is quite flexible and allows vectors, tuples, hashsets, hashmaps
//! as well as optional values:
//!
//! ```rust,no_run
//! # use std::collections::{HashMap, HashSet};
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let count : i32 = redis::cmd("GET").arg("my_counter").query(&con).unwrap();
//! let count = redis::cmd("GET").arg("my_counter").query(&con).unwrap_or(0i32);
//! let k : Option<String> = redis::cmd("GET").arg("missing_key").query(&con).unwrap();
//! let name : String = redis::cmd("GET").arg("my_name").query(&con).unwrap();
//! let bin : Vec<u8> = redis::cmd("GET").arg("my_binary").query(&con).unwrap();
//! let map : HashMap<String, i32> = redis::cmd("HGETALL").arg("my_hash").query(&con).unwrap();
//! let keys : Vec<String> = redis::cmd("KEYS").query(&con).unwrap();
//! let mems : HashSet<i32> = redis::cmd("SMEMBERS").arg("s").query(&con).unwrap();
//! let (k1, k2) : (String, String) = redis::cmd("MGET").arg("k1").arg("k2").query(&con).unwrap();
//! ```
//!
//! ## Iteration Protocol
//!
//! In addition to sending a single query you iterators are also supported.  When
//! used with regular bulk responses they don't give you much over querying and
//! converting into a vector (both use a vector internally) but they can also
//! be used with `SCAN` like commands in which case iteration will send more
//! queries until the cursor is exhausted:
//!
//! ```rust,no_run
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let mut cmd = redis::cmd("SSCAN");
//! let mut iter : redis::Iter<int> = cmd.arg("my_set").cursor_arg(0).iter(&con).unwrap();
//! for x in iter {
//!     // do something with the item
//! }
//! ```
//!
//! As you can see the cursor argument needs to be defined with `cursor_arg` instead
//! of `arg` so that the library knows which argument needs updating as the
//! query is run for more items.
//!
//! ## Pipelining
//!
//! In addition to simple queries you can also send command pipelines.  This
//! is provided through the `pipe` function.  It works very similar to sending
//! individual commands but you can send more than one in one go.  This also
//! allows you to ignore individual results so that matching on the end result
//! is easier:
//!
//! ```rust,no_run
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = redis::pipe()
//!     .cmd("SET").arg("key_1").arg(42i).ignore()
//!     .cmd("SET").arg("key_2").arg(43i).ignore()
//!     .cmd("GET").arg("key_1")
//!     .cmd("GET").arg("key_2").query(&con).unwrap();
//! ```
//!
//! If you want the pipeline to be wrapped in a `MULTI`/`EXEC` block you can
//! easily do that by switching the pipeline into `atomic` mode.  From the
//! caller's point of view nothing changes, the pipeline itself will take
//! care of the rest for you:
//!
//! ```rust,no_run
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = redis::pipe()
//!     .atomic()
//!     .cmd("SET").arg("key_1").arg(42i).ignore()
//!     .cmd("SET").arg("key_2").arg(43i).ignore()
//!     .cmd("GET").arg("key_1")
//!     .cmd("GET").arg("key_2").query(&con).unwrap();
//! ```
//!
//! ## Transactions
//!
//! Transactions are available through atomic pipelines.  In order to use
//! them in a more simple way you can use the `transaction` function of a
//! connection:
//!
//! ```rust,no_run
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let key = "the_key";
//! let (new_val,) : (int,) = con.transaction([key][], |pipe| {
//!     let old_val : int = try!(redis::cmd("GET").arg(key).query(&con));
//!     pipe
//!         .cmd("SET").arg(key).arg(old_val + 1).ignore()
//!         .cmd("GET").arg(key).query(&con)
//! }).unwrap();
//! println!("The incremented number is: {}", new_val);
//! ```
//!
//! For more information see the `transaction` function.
//!
//! ## PubSub
//!
//! Pubsub is currently work in progress but provided through the `PubSub`
//! connection object.  Due to the fact that Rust does not have support
//! for async IO in libnative yet, the API does not provide a way to
//! read messages with any form of timeout yet.
//!
//! Example usage:
//!
//! ```rust,no_run
//! let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! let mut pubsub = client.get_pubsub().unwrap();
//! pubsub.subscribe("channel_1").unwrap();
//! pubsub.subscribe("channel_2").unwrap();
//!
//! loop {
//!     let msg = pubsub.get_message().unwrap();
//!     let payload : String = msg.get_payload().unwrap();
//!     println!("channel '{}': {}", msg.get_channel_name(), payload);
//! }
//! ```
//!
//! ## Scripts
//!
//! Lua scripts are supported through the `Script` type in a convenient
//! way (it does not support pipelining currently).  It will automatically
//! load the script if it does not exist and invoke it.
//!
//! Example:
//!
//! ```rust,no_run
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let script = redis::Script::new(r"
//!     return tonumber(ARGV[1]) + tonumber(ARGV[2]);
//! ");
//! let result : int = script.arg(1i).arg(2i).invoke(&con).unwrap();
//! assert_eq!(result, 3);
//! ```

#![crate_name = "redis"]
#![crate_type = "lib"]
#![license = "BSD"]
#![comment = "Bindings and wrapper functions for redis."]

#![deny(non_camel_case_types)]

#![feature(macro_rules)]
#![feature(default_type_params)]
#![feature(slicing_syntax)]

#![experimental]

extern crate url;
extern crate serialize;
extern crate "rust-crypto" as crypto;

/* public api */
pub use parser::{parse_redis_value, Parser};
pub use client::Client;
pub use script::{Script, ScriptInvocation};
pub use connection::{Connection, PubSub, Msg};
pub use cmd::{cmd, Cmd, pipe, Pipeline, Iter, pack_command};

#[doc(hidden)]
pub use types::{
    /* low level values */
    Value,
        Nil,
        Int,
        Data,
        Bulk,
        Okay,
        Status,

    /* error and result types */
    Error,
    RedisResult,

    /* error kinds */
    ErrorKind,
        ResponseError,
        TypeError,
        ExecAbortError,
        BusyLoadingError,
        NoScriptError,
        ExtensionError,
        InternalIoError,

    /* utility types */
    InfoDict,

    /* conversion traits */
    FromRedisValue,
    ToRedisArgs,

    /* utility functions */
    from_redis_value,
};

pub mod macros;

mod parser;
mod client;
mod connection;
mod types;
mod script;
mod cmd;
<|endoftext|>


<commit_before><commit_msg>Refactor check for standard stream interactivity.<commit_after><|endoftext|>


<commit_before>//! An asynchronous `Mutex`-like type.
//!
//! This module provides [`Mutex`], a type that acts similarly to an asynchronous `Mutex`, with one
//! major difference: the [`MutexGuard`] returned by `lock` is not tied to the lifetime of the
//! `Mutex`. This enables you to acquire a lock, and then pass that guard into a future, and then
//! release it at some later point in time.
//!
//! This allows you to do something along the lines of:
//!
//! ```rust,no_run
//! use tokio::sync::Mutex;
//! use std::sync::Arc;
//!
//! #[tokio::main]
//! async fn main() {
//!     let data1 = Arc::new(Mutex::new(0));
//!     let data2 = Arc::clone(&data1);
//!
//!     tokio::spawn(async move {
//!         let mut lock = data2.lock().await;
//!         *lock += 1;
//!     });
//!
//!     let mut lock = data1.lock().await;
//!     *lock += 1;
//! }
//! ```
//!
//! Another example
//! ```rust,no_run
//! #![warn(rust_2018_idioms)]
//!
//! use tokio::sync::Mutex;
//! use std::sync::Arc;
//!
//!
//! #[tokio::main]
//! async fn main() {
//!    let count = Arc::new(Mutex::new(0));
//!
//!    for _ in 0..5 {
//!        let my_count = Arc::clone(&count);
//!        tokio::spawn(async move {
//!            for _ in 0..10 {
//!                let mut lock = my_count.lock().await;
//!                *lock += 1;
//!                println!("{}", lock);
//!            }
//!        });
//!    }
//!
//!    loop {
//!        if *count.lock().await >= 50 {
//!            break;
//!        }
//!    }
//!   println!("Count hit 50.");
//! }
//! ```
//! There are a few things of note here to pay attention to in this example.
//! 1. The mutex is wrapped in an [`std::sync::Arc`] to allow it to be shared across threads.
//! 2. Each spawned task obtains a lock and releases it on every iteration.
//! 3. Mutation of the data the Mutex is protecting is done by de-referencing the the obtained lock
//!    as seen on lines 23 and 30.
//!
//! Tokio's Mutex works in a simple FIFO (first in, first out) style where as requests for a lock are
//! made Tokio will queue them up and provide a lock when it is that requester's turn. In that way
//! the Mutex is "fair" and predictable in how it distributes the locks to inner data. This is why
//! the output of this program is an in-order count to 50. Locks are released and reacquired
//! after every iteration, so basically, each thread goes to the back of the line after it increments
//! the value once. Also, since there is only a single valid lock at any given time there is no
//! possibility of a race condition when mutating the inner value.
//!
//! Note that in contrast to `std::sync::Mutex`, this implementation does not
//! poison the mutex when a thread holding the `MutexGuard` panics. In such a
//! case, the mutex will be unlocked. If the panic is caught, this might leave
//! the data protected by the mutex in an inconsistent state.
//!
//! [`Mutex`]: struct.Mutex.html
//! [`MutexGuard`]: struct.MutexGuard.html

use crate::future::poll_fn;
use crate::sync::semaphore_ll as semaphore;

use std::cell::UnsafeCell;
use std::error::Error;
use std::fmt;
use std::ops::{Deref, DerefMut};

/// An asynchronous mutual exclusion primitive useful for protecting shared data
///
/// Each mutex has a type parameter (`T`) which represents the data that it is protecting. The data
/// can only be accessed through the RAII guards returned from `lock`, which
/// guarantees that the data is only ever accessed when the mutex is locked.
#[derive(Debug)]
pub struct Mutex<T> {
    c: UnsafeCell<T>,
    s: semaphore::Semaphore,
}

/// A handle to a held `Mutex`.
///
/// As long as you have this guard, you have exclusive access to the underlying `T`. The guard
/// internally keeps a reference-couned pointer to the original `Mutex`, so even if the lock goes
/// away, the guard remains valid.
///
/// The lock is automatically released whenever the guard is dropped, at which point `lock`
/// will succeed yet again.
pub struct MutexGuard<'a, T> {
    lock: &'a Mutex<T>,
    permit: semaphore::Permit,
}

// As long as T: Send, it's fine to send and share Mutex<T> between threads.
// If T was not Send, sending and sharing a Mutex<T> would be bad, since you can access T through
// Mutex<T>.
unsafe impl<T> Send for Mutex<T> where T: Send {}
unsafe impl<T> Sync for Mutex<T> where T: Send {}
unsafe impl<'a, T> Sync for MutexGuard<'a, T> where T: Send + Sync {}

/// Error returned from the [`Mutex::try_lock`] function.
///
/// A `try_lock` operation can only fail if the mutex is already locked.
///
/// [`Mutex::try_lock`]: Mutex::try_lock
#[derive(Debug)]
pub struct TryLockError(());

impl fmt::Display for TryLockError {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(fmt, "{}", "operation would block")
    }
}

impl Error for TryLockError {}

#[test]
#[cfg(not(loom))]
fn bounds() {
    fn check<T: Send>() {}
    check::<MutexGuard<'_, u32>>();
}

impl<T> Mutex<T> {
    /// Creates a new lock in an unlocked state ready for use.
    pub fn new(t: T) -> Self {
        Self {
            c: UnsafeCell::new(t),
            s: semaphore::Semaphore::new(1),
        }
    }

    /// A future that resolves on acquiring the lock and returns the `MutexGuard`.
    pub async fn lock(&self) -> MutexGuard<'_, T> {
        let mut guard = MutexGuard {
            lock: self,
            permit: semaphore::Permit::new(),
        };
        poll_fn(|cx| guard.permit.poll_acquire(cx, 1, &self.s))
            .await
            .unwrap_or_else(|_| {
                // The semaphore was closed. but, we never explicitly close it, and we have a
                // handle to it through the Arc, which means that this can never happen.
                unreachable!()
            });
        guard
    }

    /// Tries to acquire the lock
    pub fn try_lock(&self) -> Result<MutexGuard<'_, T>, TryLockError> {
        let mut permit = semaphore::Permit::new();
        match permit.try_acquire(1, &self.s) {
            Ok(_) => Ok(MutexGuard { lock: self, permit }),
            Err(_) => Err(TryLockError(())),
        }
    }
}

impl<'a, T> Drop for MutexGuard<'a, T> {
    fn drop(&mut self) {
        self.permit.release(1, &self.lock.s);
    }
}

impl<T> From<T> for Mutex<T> {
    fn from(s: T) -> Self {
        Self::new(s)
    }
}

impl<T> Default for Mutex<T>
where
    T: Default,
{
    fn default() -> Self {
        Self::new(T::default())
    }
}

impl<'a, T> Deref for MutexGuard<'a, T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        assert!(self.permit.is_acquired());
        unsafe { &*self.lock.c.get() }
    }
}

impl<'a, T> DerefMut for MutexGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        assert!(self.permit.is_acquired());
        unsafe { &mut *self.lock.c.get() }
    }
}

impl<'a, T: fmt::Debug> fmt::Debug for MutexGuard<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

impl<'a, T: fmt::Display> fmt::Display for MutexGuard<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}
<commit_msg>Add `Mutex::into_inner` method (#2250)<commit_after>//! An asynchronous `Mutex`-like type.
//!
//! This module provides [`Mutex`], a type that acts similarly to an asynchronous `Mutex`, with one
//! major difference: the [`MutexGuard`] returned by `lock` is not tied to the lifetime of the
//! `Mutex`. This enables you to acquire a lock, and then pass that guard into a future, and then
//! release it at some later point in time.
//!
//! This allows you to do something along the lines of:
//!
//! ```rust,no_run
//! use tokio::sync::Mutex;
//! use std::sync::Arc;
//!
//! #[tokio::main]
//! async fn main() {
//!     let data1 = Arc::new(Mutex::new(0));
//!     let data2 = Arc::clone(&data1);
//!
//!     tokio::spawn(async move {
//!         let mut lock = data2.lock().await;
//!         *lock += 1;
//!     });
//!
//!     let mut lock = data1.lock().await;
//!     *lock += 1;
//! }
//! ```
//!
//! Another example
//! ```rust,no_run
//! #![warn(rust_2018_idioms)]
//!
//! use tokio::sync::Mutex;
//! use std::sync::Arc;
//!
//!
//! #[tokio::main]
//! async fn main() {
//!    let count = Arc::new(Mutex::new(0));
//!
//!    for _ in 0..5 {
//!        let my_count = Arc::clone(&count);
//!        tokio::spawn(async move {
//!            for _ in 0..10 {
//!                let mut lock = my_count.lock().await;
//!                *lock += 1;
//!                println!("{}", lock);
//!            }
//!        });
//!    }
//!
//!    loop {
//!        if *count.lock().await >= 50 {
//!            break;
//!        }
//!    }
//!   println!("Count hit 50.");
//! }
//! ```
//! There are a few things of note here to pay attention to in this example.
//! 1. The mutex is wrapped in an [`std::sync::Arc`] to allow it to be shared across threads.
//! 2. Each spawned task obtains a lock and releases it on every iteration.
//! 3. Mutation of the data the Mutex is protecting is done by de-referencing the the obtained lock
//!    as seen on lines 23 and 30.
//!
//! Tokio's Mutex works in a simple FIFO (first in, first out) style where as requests for a lock are
//! made Tokio will queue them up and provide a lock when it is that requester's turn. In that way
//! the Mutex is "fair" and predictable in how it distributes the locks to inner data. This is why
//! the output of this program is an in-order count to 50. Locks are released and reacquired
//! after every iteration, so basically, each thread goes to the back of the line after it increments
//! the value once. Also, since there is only a single valid lock at any given time there is no
//! possibility of a race condition when mutating the inner value.
//!
//! Note that in contrast to `std::sync::Mutex`, this implementation does not
//! poison the mutex when a thread holding the `MutexGuard` panics. In such a
//! case, the mutex will be unlocked. If the panic is caught, this might leave
//! the data protected by the mutex in an inconsistent state.
//!
//! [`Mutex`]: struct.Mutex.html
//! [`MutexGuard`]: struct.MutexGuard.html

use crate::future::poll_fn;
use crate::sync::semaphore_ll as semaphore;

use std::cell::UnsafeCell;
use std::error::Error;
use std::fmt;
use std::ops::{Deref, DerefMut};

/// An asynchronous mutual exclusion primitive useful for protecting shared data
///
/// Each mutex has a type parameter (`T`) which represents the data that it is protecting. The data
/// can only be accessed through the RAII guards returned from `lock`, which
/// guarantees that the data is only ever accessed when the mutex is locked.
#[derive(Debug)]
pub struct Mutex<T> {
    c: UnsafeCell<T>,
    s: semaphore::Semaphore,
}

/// A handle to a held `Mutex`.
///
/// As long as you have this guard, you have exclusive access to the underlying `T`. The guard
/// internally keeps a reference-couned pointer to the original `Mutex`, so even if the lock goes
/// away, the guard remains valid.
///
/// The lock is automatically released whenever the guard is dropped, at which point `lock`
/// will succeed yet again.
pub struct MutexGuard<'a, T> {
    lock: &'a Mutex<T>,
    permit: semaphore::Permit,
}

// As long as T: Send, it's fine to send and share Mutex<T> between threads.
// If T was not Send, sending and sharing a Mutex<T> would be bad, since you can access T through
// Mutex<T>.
unsafe impl<T> Send for Mutex<T> where T: Send {}
unsafe impl<T> Sync for Mutex<T> where T: Send {}
unsafe impl<'a, T> Sync for MutexGuard<'a, T> where T: Send + Sync {}

/// Error returned from the [`Mutex::try_lock`] function.
///
/// A `try_lock` operation can only fail if the mutex is already locked.
///
/// [`Mutex::try_lock`]: Mutex::try_lock
#[derive(Debug)]
pub struct TryLockError(());

impl fmt::Display for TryLockError {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(fmt, "{}", "operation would block")
    }
}

impl Error for TryLockError {}

#[test]
#[cfg(not(loom))]
fn bounds() {
    fn check<T: Send>() {}
    check::<MutexGuard<'_, u32>>();
}

impl<T> Mutex<T> {
    /// Creates a new lock in an unlocked state ready for use.
    pub fn new(t: T) -> Self {
        Self {
            c: UnsafeCell::new(t),
            s: semaphore::Semaphore::new(1),
        }
    }

    /// A future that resolves on acquiring the lock and returns the `MutexGuard`.
    pub async fn lock(&self) -> MutexGuard<'_, T> {
        let mut guard = MutexGuard {
            lock: self,
            permit: semaphore::Permit::new(),
        };
        poll_fn(|cx| guard.permit.poll_acquire(cx, 1, &self.s))
            .await
            .unwrap_or_else(|_| {
                // The semaphore was closed. but, we never explicitly close it, and we have a
                // handle to it through the Arc, which means that this can never happen.
                unreachable!()
            });
        guard
    }

    /// Tries to acquire the lock
    pub fn try_lock(&self) -> Result<MutexGuard<'_, T>, TryLockError> {
        let mut permit = semaphore::Permit::new();
        match permit.try_acquire(1, &self.s) {
            Ok(_) => Ok(MutexGuard { lock: self, permit }),
            Err(_) => Err(TryLockError(())),
        }
    }

    /// Consumes the mutex, returning the underlying data.
    pub fn into_inner(self) -> T {
        self.c.into_inner()
    }
}

impl<'a, T> Drop for MutexGuard<'a, T> {
    fn drop(&mut self) {
        self.permit.release(1, &self.lock.s);
    }
}

impl<T> From<T> for Mutex<T> {
    fn from(s: T) -> Self {
        Self::new(s)
    }
}

impl<T> Default for Mutex<T>
where
    T: Default,
{
    fn default() -> Self {
        Self::new(T::default())
    }
}

impl<'a, T> Deref for MutexGuard<'a, T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        assert!(self.permit.is_acquired());
        unsafe { &*self.lock.c.get() }
    }
}

impl<'a, T> DerefMut for MutexGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        assert!(self.permit.is_acquired());
        unsafe { &mut *self.lock.c.get() }
    }
}

impl<'a, T: fmt::Debug> fmt::Debug for MutexGuard<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

impl<'a, T: fmt::Display> fmt::Display for MutexGuard<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}
<|endoftext|>


<commit_before>use std::{
    collections::BTreeMap,
    env,
    fmt::{self, Write as _},
    io::Write as _,
    time::{Instant, SystemTime, UNIX_EPOCH},
};

use anyhow::{bail, format_err, Result};

use crate::not_bash::{fs2, pushd, rm_rf, run};

type Unit = &'static str;

pub fn run_metrics() -> Result<()> {
    let mut metrics = Metrics::new()?;
    metrics.measure_build()?;

    {
        let _d = pushd("target/metrics");
        let mut file = std::fs::OpenOptions::new().append(true).open("metrics.json")?;
        writeln!(file, "{}", metrics.json())?;
        run!("git add .")?;
        run!("git commit --author 'GitHub Action <>' --message '📈' ")?;

        if let Ok(actor) = env::var("GITHUB_ACTOR") {
            let token = env::var("GITHUB_TOKEN").unwrap();
            let repo = format!("https://{}:{}@github.com/rust-analyzer/metrics.git", actor, token);
            run!("git push {}", repo)?;
        }
    }
    eprintln!("{:#?}\n", metrics);
    eprintln!("{}", metrics.json());
    Ok(())
}

impl Metrics {
    fn measure_build(&mut self) -> Result<()> {
        run!("cargo fetch")?;
        rm_rf("./target/release")?;

        let build = Instant::now();
        // run!("cargo build --release --package rust-analyzer --bin rust-analyzer")?;
        let build = build.elapsed();
        self.report("build", build.as_millis() as u64, "ms");
        Ok(())
    }
}

#[derive(Debug)]
struct Metrics {
    host: Host,
    timestamp: SystemTime,
    revision: String,
    metrics: BTreeMap<String, (u64, Unit)>,
}

#[derive(Debug)]
struct Host {
    os: String,
    cpu: String,
    mem: String,
}

impl Metrics {
    fn new() -> Result<Metrics> {
        let host = Host::new()?;
        let timestamp = SystemTime::now();
        let revision = run!("git rev-parse HEAD")?;
        Ok(Metrics { host, timestamp, revision, metrics: BTreeMap::new() })
    }

    fn report(&mut self, name: &str, value: u64, unit: Unit) {
        self.metrics.insert(name.into(), (value, unit));
    }

    fn json(&self) -> Json {
        let mut json = Json::default();
        self.to_json(&mut json);
        json
    }
    fn to_json(&self, json: &mut Json) {
        json.begin_object();
        {
            json.field("host");
            self.host.to_json(json);

            json.field("timestamp");
            let timestamp = self.timestamp.duration_since(UNIX_EPOCH).unwrap();
            json.number(timestamp.as_secs() as f64);

            json.field("revision");
            json.string(&self.revision);

            json.field("metrics");
            json.begin_object();
            {
                for (k, &(value, unit)) in &self.metrics {
                    json.field(k);
                    json.begin_array();
                    {
                        json.number(value as f64);
                        json.string(unit);
                    }
                    json.end_array();
                }
            }
            json.end_object()
        }
        json.end_object();
    }
}

impl Host {
    fn new() -> Result<Host> {
        if cfg!(not(target_os = "linux")) {
            bail!("can only collect metrics on Linux ");
        }

        let os = read_field("/etc/os-release", "PRETTY_NAME=")?.trim_matches('"').to_string();

        let cpu =
            read_field("/proc/cpuinfo", "model name")?.trim_start_matches(':').trim().to_string();

        let mem = read_field("/proc/meminfo", "MemTotal:")?;

        return Ok(Host { os, cpu, mem });

        fn read_field<'a>(path: &str, field: &str) -> Result<String> {
            let text = fs2::read_to_string(path)?;

            let line = text
                .lines()
                .find(|it| it.starts_with(field))
                .ok_or_else(|| format_err!("can't parse {}", path))?;
            Ok(line[field.len()..].trim().to_string())
        }
    }
    fn to_json(&self, json: &mut Json) {
        json.begin_object();
        {
            json.field("os");
            json.string(&self.os);

            json.field("cpu");
            json.string(&self.cpu);

            json.field("mem");
            json.string(&self.mem);
        }
        json.end_object();
    }
}

#[derive(Default)]
struct Json {
    object_comma: bool,
    array_comma: bool,
    buf: String,
}

impl Json {
    fn begin_object(&mut self) {
        self.object_comma = false;
        self.buf.push('{');
    }
    fn end_object(&mut self) {
        self.buf.push('}')
    }
    fn begin_array(&mut self) {
        self.array_comma = false;
        self.buf.push('[');
    }
    fn end_array(&mut self) {
        self.buf.push(']')
    }
    fn field(&mut self, name: &str) {
        self.object_comma();
        self.string_token(name);
        self.buf.push(':');
    }
    fn string(&mut self, value: &str) {
        self.array_comma();
        self.string_token(value);
    }
    fn string_token(&mut self, value: &str) {
        self.buf.push('"');
        self.buf.extend(value.escape_default());
        self.buf.push('"');
    }
    fn number(&mut self, value: f64) {
        self.array_comma();
        write!(self.buf, "{}", value).unwrap();
    }

    fn array_comma(&mut self) {
        if self.array_comma {
            self.buf.push(',');
        }
        self.array_comma = true;
    }

    fn object_comma(&mut self) {
        if self.object_comma {
            self.buf.push(',');
        }
        self.object_comma = true;
    }
}

impl fmt::Display for Json {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.buf)
    }
}
<commit_msg>Fix email<commit_after>use std::{
    collections::BTreeMap,
    env,
    fmt::{self, Write as _},
    io::Write as _,
    time::{Instant, SystemTime, UNIX_EPOCH},
};

use anyhow::{bail, format_err, Result};

use crate::not_bash::{fs2, pushd, rm_rf, run};

type Unit = &'static str;

pub fn run_metrics() -> Result<()> {
    let mut metrics = Metrics::new()?;
    metrics.measure_build()?;

    {
        let _d = pushd("target/metrics");
        let mut file = std::fs::OpenOptions::new().append(true).open("metrics.json")?;
        writeln!(file, "{}", metrics.json())?;
        run!("git add .")?;
        run!("git -c user.name=Bot -c user.email=dummy@example.com commit --message 📈")?;

        if let Ok(actor) = env::var("GITHUB_ACTOR") {
            let token = env::var("GITHUB_TOKEN").unwrap();
            let repo = format!("https://{}:{}@github.com/rust-analyzer/metrics.git", actor, token);
            run!("git push {}", repo)?;
        }
    }
    eprintln!("{:#?}\n", metrics);
    eprintln!("{}", metrics.json());
    Ok(())
}

impl Metrics {
    fn measure_build(&mut self) -> Result<()> {
        run!("cargo fetch")?;
        rm_rf("./target/release")?;

        let build = Instant::now();
        // run!("cargo build --release --package rust-analyzer --bin rust-analyzer")?;
        let build = build.elapsed();
        self.report("build", build.as_millis() as u64, "ms");
        Ok(())
    }
}

#[derive(Debug)]
struct Metrics {
    host: Host,
    timestamp: SystemTime,
    revision: String,
    metrics: BTreeMap<String, (u64, Unit)>,
}

#[derive(Debug)]
struct Host {
    os: String,
    cpu: String,
    mem: String,
}

impl Metrics {
    fn new() -> Result<Metrics> {
        let host = Host::new()?;
        let timestamp = SystemTime::now();
        let revision = run!("git rev-parse HEAD")?;
        Ok(Metrics { host, timestamp, revision, metrics: BTreeMap::new() })
    }

    fn report(&mut self, name: &str, value: u64, unit: Unit) {
        self.metrics.insert(name.into(), (value, unit));
    }

    fn json(&self) -> Json {
        let mut json = Json::default();
        self.to_json(&mut json);
        json
    }
    fn to_json(&self, json: &mut Json) {
        json.begin_object();
        {
            json.field("host");
            self.host.to_json(json);

            json.field("timestamp");
            let timestamp = self.timestamp.duration_since(UNIX_EPOCH).unwrap();
            json.number(timestamp.as_secs() as f64);

            json.field("revision");
            json.string(&self.revision);

            json.field("metrics");
            json.begin_object();
            {
                for (k, &(value, unit)) in &self.metrics {
                    json.field(k);
                    json.begin_array();
                    {
                        json.number(value as f64);
                        json.string(unit);
                    }
                    json.end_array();
                }
            }
            json.end_object()
        }
        json.end_object();
    }
}

impl Host {
    fn new() -> Result<Host> {
        if cfg!(not(target_os = "linux")) {
            bail!("can only collect metrics on Linux ");
        }

        let os = read_field("/etc/os-release", "PRETTY_NAME=")?.trim_matches('"').to_string();

        let cpu =
            read_field("/proc/cpuinfo", "model name")?.trim_start_matches(':').trim().to_string();

        let mem = read_field("/proc/meminfo", "MemTotal:")?;

        return Ok(Host { os, cpu, mem });

        fn read_field<'a>(path: &str, field: &str) -> Result<String> {
            let text = fs2::read_to_string(path)?;

            let line = text
                .lines()
                .find(|it| it.starts_with(field))
                .ok_or_else(|| format_err!("can't parse {}", path))?;
            Ok(line[field.len()..].trim().to_string())
        }
    }
    fn to_json(&self, json: &mut Json) {
        json.begin_object();
        {
            json.field("os");
            json.string(&self.os);

            json.field("cpu");
            json.string(&self.cpu);

            json.field("mem");
            json.string(&self.mem);
        }
        json.end_object();
    }
}

#[derive(Default)]
struct Json {
    object_comma: bool,
    array_comma: bool,
    buf: String,
}

impl Json {
    fn begin_object(&mut self) {
        self.object_comma = false;
        self.buf.push('{');
    }
    fn end_object(&mut self) {
        self.buf.push('}')
    }
    fn begin_array(&mut self) {
        self.array_comma = false;
        self.buf.push('[');
    }
    fn end_array(&mut self) {
        self.buf.push(']')
    }
    fn field(&mut self, name: &str) {
        self.object_comma();
        self.string_token(name);
        self.buf.push(':');
    }
    fn string(&mut self, value: &str) {
        self.array_comma();
        self.string_token(value);
    }
    fn string_token(&mut self, value: &str) {
        self.buf.push('"');
        self.buf.extend(value.escape_default());
        self.buf.push('"');
    }
    fn number(&mut self, value: f64) {
        self.array_comma();
        write!(self.buf, "{}", value).unwrap();
    }

    fn array_comma(&mut self) {
        if self.array_comma {
            self.buf.push(',');
        }
        self.array_comma = true;
    }

    fn object_comma(&mut self) {
        if self.object_comma {
            self.buf.push(',');
        }
        self.object_comma = true;
    }
}

impl fmt::Display for Json {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.buf)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::fmt;
use format::Format;
use framebuffer::RenderPassDesc;
use image::ImageViewAccess;

/// Checks whether the given image view is allowed to be the nth attachment of the given render
/// pass.
///
/// # Panic
///
/// Panicks if the attachment number is out of range.
// TODO: add a specializable trait instead, that uses this function
// TODO: ImageView instead of ImageViewAccess?
pub fn ensure_image_view_compatible<Rp, I>(render_pass: &Rp, attachment_num: usize, image: &I)
                                           -> Result<(), IncompatibleRenderPassAttachmentError>
    where Rp: ?Sized + RenderPassDesc,
          I: ?Sized + ImageViewAccess
{
    let attachment_desc = render_pass.attachment(attachment_num)
                                     .expect("Attachment num out of range");

    if image.format() != attachment_desc.format {
        return Err(IncompatibleRenderPassAttachmentError::FormatMismatch {
            expected: attachment_desc.format,
            obtained: image.format(),
        });
    }

    if image.samples() != attachment_desc.samples {
        return Err(IncompatibleRenderPassAttachmentError::SamplesMismatch {
            expected: attachment_desc.samples,
            obtained: image.samples(),
        });
    }

    if !image.identity_swizzle() {
        return Err(IncompatibleRenderPassAttachmentError::NotIdentitySwizzled);
    }

    for subpass_num in 0 .. render_pass.num_subpasses() {
        let subpass = render_pass.subpass(subpass_num).expect("Subpass num out of range ; \
                                                               wrong RenderPassDesc trait impl");

        if subpass.color_attachments.iter().any(|&(n, _)| n == attachment_num) {
            debug_assert!(image.parent().has_color());  // Was normally checked by the render pass.
            if !image.parent().inner().usage_color_attachment() {
                return Err(IncompatibleRenderPassAttachmentError::MissingColorAttachmentUsage);
            }
        }

        if let Some((ds, _)) = subpass.depth_stencil {
            if ds == attachment_num {
                // Was normally checked by the render pass.
                debug_assert!(image.parent().has_depth() || image.parent().has_stencil());
                if !image.parent().inner().usage_depth_stencil_attachment() {
                    return Err(IncompatibleRenderPassAttachmentError::MissingDepthStencilAttachmentUsage);
                }
            }
        }

        if subpass.input_attachments.iter().any(|&(n, _)| n == attachment_num) {
            if !image.parent().inner().usage_input_attachment() {
                return Err(IncompatibleRenderPassAttachmentError::MissingInputAttachmentUsage);
            }
        }
    }

    // TODO: consider forbidding LoadOp::Load if image is transient

    // TODO: are all image layouts allowed? check this

    Ok(())
}

/// Error that can happen when an image is not compatible with a render pass attachment slot.
#[derive(Copy, Clone, Debug)]
pub enum IncompatibleRenderPassAttachmentError {
    /// The image format expected by the render pass doesn't match the actual format of
    /// the image.
    FormatMismatch {
        /// Format expected by the render pass.
        expected: Format,
        /// Format of the image.
        obtained: Format,
    },

    /// The number of samples expected by the render pass doesn't match the number of samples of
    /// the image.
    SamplesMismatch {
        /// Number of samples expected by the render pass.
        expected: u32,
        /// Number of samples of the image.
        obtained: u32,
    },

    /// The image view has a component swizzle that is different from identity.
    NotIdentitySwizzled,

    /// The image is used as a color attachment but is missing the color attachment usage.
    MissingColorAttachmentUsage,

    /// The image is used as a depth/stencil attachment but is missing the depth-stencil attachment
    /// usage.
    MissingDepthStencilAttachmentUsage,

    /// The image is used as an input attachment but is missing the input attachment usage.
    MissingInputAttachmentUsage,
}

impl error::Error for IncompatibleRenderPassAttachmentError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            IncompatibleRenderPassAttachmentError::FormatMismatch { .. } => {
                "mismatch between the format expected by the render pass and the actual format"
            },
            IncompatibleRenderPassAttachmentError::SamplesMismatch { .. } => {
                "mismatch between the number of samples expected by the render pass and the actual \
                 number of samples"
            },
            IncompatibleRenderPassAttachmentError::NotIdentitySwizzled => {
                "the image view does not use identity swizzling"
            },
            IncompatibleRenderPassAttachmentError::MissingColorAttachmentUsage => {
                "the image is used as a color attachment but is missing the color attachment usage"
            },
            IncompatibleRenderPassAttachmentError::MissingDepthStencilAttachmentUsage => {
                "the image is used as a depth/stencil attachment but is missing the depth-stencil \
                 attachment usage"
            },
            IncompatibleRenderPassAttachmentError::MissingInputAttachmentUsage => {
                "the image is used as an input attachment but is missing the input \
                 attachment usage"
            },
        }
    }
}

impl fmt::Display for IncompatibleRenderPassAttachmentError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

// TODO: add tests
<commit_msg>Add some basic tests in compat_atch<commit_after>// Copyright (c) 2017 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! This module contains the `ensure_image_view_compatible` function, which verifies whether
//! an image view can be used as a render pass attachment.

use std::error;
use std::fmt;
use format::Format;
use framebuffer::RenderPassDesc;
use image::ImageViewAccess;

/// Checks whether the given image view is allowed to be the nth attachment of the given render
/// pass.
///
/// # Panic
///
/// Panicks if the attachment number is out of range.
// TODO: add a specializable trait instead, that uses this function
// TODO: ImageView instead of ImageViewAccess?
pub fn ensure_image_view_compatible<Rp, I>(render_pass: &Rp, attachment_num: usize, image: &I)
                                           -> Result<(), IncompatibleRenderPassAttachmentError>
    where Rp: ?Sized + RenderPassDesc,
          I: ?Sized + ImageViewAccess
{
    let attachment_desc = render_pass.attachment(attachment_num)
                                     .expect("Attachment num out of range");

    if image.format() != attachment_desc.format {
        return Err(IncompatibleRenderPassAttachmentError::FormatMismatch {
            expected: attachment_desc.format,
            obtained: image.format(),
        });
    }

    if image.samples() != attachment_desc.samples {
        return Err(IncompatibleRenderPassAttachmentError::SamplesMismatch {
            expected: attachment_desc.samples,
            obtained: image.samples(),
        });
    }

    if !image.identity_swizzle() {
        return Err(IncompatibleRenderPassAttachmentError::NotIdentitySwizzled);
    }

    for subpass_num in 0 .. render_pass.num_subpasses() {
        let subpass = render_pass.subpass(subpass_num).expect("Subpass num out of range ; \
                                                               wrong RenderPassDesc trait impl");

        if subpass.color_attachments.iter().any(|&(n, _)| n == attachment_num) {
            debug_assert!(image.parent().has_color());  // Was normally checked by the render pass.
            if !image.parent().inner().usage_color_attachment() {
                return Err(IncompatibleRenderPassAttachmentError::MissingColorAttachmentUsage);
            }
        }

        if let Some((ds, _)) = subpass.depth_stencil {
            if ds == attachment_num {
                // Was normally checked by the render pass.
                debug_assert!(image.parent().has_depth() || image.parent().has_stencil());
                if !image.parent().inner().usage_depth_stencil_attachment() {
                    return Err(IncompatibleRenderPassAttachmentError::MissingDepthStencilAttachmentUsage);
                }
            }
        }

        if subpass.input_attachments.iter().any(|&(n, _)| n == attachment_num) {
            if !image.parent().inner().usage_input_attachment() {
                return Err(IncompatibleRenderPassAttachmentError::MissingInputAttachmentUsage);
            }
        }
    }

    // TODO: consider forbidding LoadOp::Load if image is transient

    // TODO: are all image layouts allowed? check this

    Ok(())
}

/// Error that can happen when an image is not compatible with a render pass attachment slot.
#[derive(Copy, Clone, Debug)]
pub enum IncompatibleRenderPassAttachmentError {
    /// The image format expected by the render pass doesn't match the actual format of
    /// the image.
    FormatMismatch {
        /// Format expected by the render pass.
        expected: Format,
        /// Format of the image.
        obtained: Format,
    },

    /// The number of samples expected by the render pass doesn't match the number of samples of
    /// the image.
    SamplesMismatch {
        /// Number of samples expected by the render pass.
        expected: u32,
        /// Number of samples of the image.
        obtained: u32,
    },

    /// The image view has a component swizzle that is different from identity.
    NotIdentitySwizzled,

    /// The image is used as a color attachment but is missing the color attachment usage.
    MissingColorAttachmentUsage,

    /// The image is used as a depth/stencil attachment but is missing the depth-stencil attachment
    /// usage.
    MissingDepthStencilAttachmentUsage,

    /// The image is used as an input attachment but is missing the input attachment usage.
    MissingInputAttachmentUsage,
}

impl error::Error for IncompatibleRenderPassAttachmentError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            IncompatibleRenderPassAttachmentError::FormatMismatch { .. } => {
                "mismatch between the format expected by the render pass and the actual format"
            },
            IncompatibleRenderPassAttachmentError::SamplesMismatch { .. } => {
                "mismatch between the number of samples expected by the render pass and the actual \
                 number of samples"
            },
            IncompatibleRenderPassAttachmentError::NotIdentitySwizzled => {
                "the image view does not use identity swizzling"
            },
            IncompatibleRenderPassAttachmentError::MissingColorAttachmentUsage => {
                "the image is used as a color attachment but is missing the color attachment usage"
            },
            IncompatibleRenderPassAttachmentError::MissingDepthStencilAttachmentUsage => {
                "the image is used as a depth/stencil attachment but is missing the depth-stencil \
                 attachment usage"
            },
            IncompatibleRenderPassAttachmentError::MissingInputAttachmentUsage => {
                "the image is used as an input attachment but is missing the input \
                 attachment usage"
            },
        }
    }
}

impl fmt::Display for IncompatibleRenderPassAttachmentError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

#[cfg(test)]
mod tests {
    use std::sync::Arc;
    use format::Format;
    use image::AttachmentImage;
    use image::ImageView;
    use super::ensure_image_view_compatible;
    use super::IncompatibleRenderPassAttachmentError;

    #[test]
    fn basic_ok() {
        let (device, _) = gfx_dev_and_queue!();

        let rp = Arc::new(single_pass_renderpass!(device.clone(),
            attachments: {
                color: {
                    load: Clear,
                    store: Store,
                    format: Format::R8G8B8A8Unorm,
                    samples: 1,
                }
            },
            pass: {
                color: [color],
                depth_stencil: {}
            }
        ).unwrap());

        let img = AttachmentImage::new(&device, [128, 128], Format::R8G8B8A8Unorm).unwrap();

        ensure_image_view_compatible(&rp, 0, &img.access()).unwrap();
    }

    #[test]
    fn format_mismatch() {
        let (device, _) = gfx_dev_and_queue!();

        let rp = Arc::new(single_pass_renderpass!(device.clone(),
            attachments: {
                color: {
                    load: Clear,
                    store: Store,
                    format: Format::R16G16Sfloat,
                    samples: 1,
                }
            },
            pass: {
                color: [color],
                depth_stencil: {}
            }
        ).unwrap());

        let img = AttachmentImage::new(&device, [128, 128], Format::R8G8B8A8Unorm).unwrap();

        match ensure_image_view_compatible(&rp, 0, &img.access()) {
            Err(IncompatibleRenderPassAttachmentError::FormatMismatch {
                expected: Format::R16G16Sfloat, obtained: Format::R8G8B8A8Unorm }) => (),
            e => panic!("{:?}", e)
        }
    }

    // TODO: more tests
}
<|endoftext|>


<commit_before>use std::fmt;

use crate::node::{Node, Value};

/// A comment node.
#[derive(Clone, Debug)]
pub struct Comment {
    content: String,
}

impl Comment {
    /// Create a comment.
    #[inline]
    pub fn new<T>(content: T) -> Self
    where
        T: Into<String>,
    {
        Self {
            content: content.into(),
        }
    }
}

impl fmt::Display for Comment {
    #[inline]
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "<!-- {} -->", self.content)
    }
}

impl Node for Comment {
    #[inline]
    fn append<T>(&mut self, _: T)
    where
        T: Node,
    {
    }

    #[inline]
    fn assign<T, U>(&mut self, _: T, _: U)
    where
        T: Into<String>,
        U: Into<Value>,
    {
    }
}

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

    #[test]
    fn comment() {
        let comment = Comment::new("a comment.");
        assert_eq!(comment.to_string(), "<!-- a comment. -->");
    }
}
<commit_msg>Change a comment<commit_after>use std::fmt;

use crate::node::{Node, Value};

/// A comment node.
#[derive(Clone, Debug)]
pub struct Comment {
    content: String,
}

impl Comment {
    /// Create a node.
    #[inline]
    pub fn new<T>(content: T) -> Self
    where
        T: Into<String>,
    {
        Self {
            content: content.into(),
        }
    }
}

impl fmt::Display for Comment {
    #[inline]
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "<!-- {} -->", self.content)
    }
}

impl Node for Comment {
    #[inline]
    fn append<T>(&mut self, _: T)
    where
        T: Node,
    {
    }

    #[inline]
    fn assign<T, U>(&mut self, _: T, _: U)
    where
        T: Into<String>,
        U: Into<Value>,
    {
    }
}

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

    #[test]
    fn comment() {
        let comment = Comment::new("a comment.");
        assert_eq!(comment.to_string(), "<!-- a comment. -->");
    }
}
<|endoftext|>


<commit_before>use super::*;
use redox::*;

impl Editor {
    /// Remove from a given motion (row based)
    pub fn remove_rb<'a>(&mut self, (x, y): (usize, usize)) {
        if y == self.y() {
            // Single line mode
            let (a, b) = if self.x() < x {
                (self.x(), x)
            } else {
                (x, self.x())
            };
            for i in a..b {
                self.text[y].remove(i);
            }
        } else {
            // Full line mode
            let (a, b) = if self.y() < y {
                (self.y(), y)
            } else {
                (y, self.y())
            };
            for ln in a..(b + 1) {
                self.text.remove(ln);
            }
        }
    }
}
<commit_msg>Fix out-of-bound bug<commit_after>use super::*;
use redox::*;

impl Editor {
    /// Remove from a given motion (row based)
    pub fn remove_rb<'a>(&mut self, (x, y): (usize, usize)) {
        if y == self.y() {
            // Single line mode
            let (a, b) = if self.x() < x {
                (self.x(), x)
            } else {
                (x, self.x())
            };
            for _ in a..b {
                self.text[y].remove(a);
            }
        } else {
            // Full line mode
            let (a, b) = if self.y() < y {
                (self.y(), y)
            } else {
                (y, self.y())
            };
            for _ in a..(b + 1) {
                if self.text.len() > 1 {
                    self.text.remove(a);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

//! The `ParallelIterator` module makes it easy to write parallel
//! programs using an iterator-style interface. To get access to all
//! the methods you want, the easiest is to write `use
//! rayon::par_iter::*;` at the top of your module, which will import
//! the various traits and methods you need.
//!
//! The submodules of this module mostly just contain implementaton
//! details of little interest to an end-user.

use std::f64;
use std::ops::Fn;
use self::collect::collect_into;
use self::enumerate::Enumerate;
use self::filter::Filter;
use self::filter_map::FilterMap;
use self::flat_map::FlatMap;
use self::map::Map;
use self::reduce::{reduce, ReduceOp, SumOp, MulOp, MinOp, MaxOp, ReduceWithOp,
                   SUM, MUL, MIN, MAX};
use self::state::*;
use self::weight::Weight;
use self::zip::ZipIter;

pub mod collect;
pub mod enumerate;
pub mod filter;
pub mod filter_map;
pub mod flat_map;
pub mod len;
pub mod for_each;
pub mod reduce;
pub mod slice;
pub mod slice_mut;
pub mod state;
pub mod map;
pub mod weight;
pub mod zip;
pub mod range;
mod util;

#[cfg(test)]
mod test;

pub trait IntoParallelIterator {
    type Iter: ParallelIterator<Item=Self::Item>;
    type Item: Send;

    fn into_par_iter(self) -> Self::Iter;
}

pub trait IntoParallelRefIterator<'data> {
    type Iter: ParallelIterator<Item=&'data Self::Item>;
    type Item: Sync + 'data;

    fn par_iter(&'data self) -> Self::Iter;
}

pub trait IntoParallelRefMutIterator<'data> {
    type Iter: ParallelIterator<Item=&'data mut Self::Item>;
    type Item: Send + 'data;

    fn par_iter_mut(&'data mut self) -> Self::Iter;
}

/// The `ParallelIterator` interface.
pub trait ParallelIterator: Sized {
    type Item: Send;

    /// Indicates the relative "weight" of producing each item in this
    /// parallel iterator. A higher weight will cause finer-grained
    /// parallel subtasks. 1.0 indicates something very cheap and
    /// uniform, like copying a value out of an array, or computing `x
    /// + 1`. If your tasks are either very expensive, or very
    /// unpredictable, you are better off with higher values. See also
    /// `weight_max`, which is a convenient shorthand to force the
    /// finest grained parallel execution posible. Tuning this value
    /// should not affect correctness but can improve (or hurt)
    /// performance.
    fn weight(self, scale: f64) -> Weight<Self> {
        Weight::new(self, scale)
    }

    /// Shorthand for `self.weight(f64::INFINITY)`. This forces the
    /// smallest granularity of parallel execution, which makes sense
    /// when your parallel tasks are (potentially) very expensive to
    /// execute.
    fn weight_max(self) -> Weight<Self> {
        self.weight(f64::INFINITY)
    }

    /// Executes `OP` on each item produced by the iterator, in parallel.
    fn for_each<OP>(self, op: OP)
        where OP: Fn(Self::Item) + Sync
    {
        for_each::for_each(self, &op)
    }

    /// Applies `map_op` to each item of his iterator, producing a new
    /// iterator with the results.
    fn map<MAP_OP,R>(self, map_op: MAP_OP) -> Map<Self, MAP_OP>
        where MAP_OP: Fn(Self::Item) -> R
    {
        Map::new(self, map_op)
    }

    /// Applies `map_op` to each item of his iterator, producing a new
    /// iterator with the results.
    fn filter<FILTER_OP>(self, filter_op: FILTER_OP) -> Filter<Self, FILTER_OP>
        where FILTER_OP: Fn(&Self::Item) -> bool
    {
        Filter::new(self, filter_op)
    }

    /// Applies `map_op` to each item of his iterator, producing a new
    /// iterator with the results.
    fn filter_map<FILTER_OP,R>(self, filter_op: FILTER_OP) -> FilterMap<Self, FILTER_OP>
        where FILTER_OP: Fn(Self::Item) -> Option<R>
    {
        FilterMap::new(self, filter_op)
    }

    /// Applies `map_op` to each item of his iterator, producing a new
    /// iterator with the results.
    fn flat_map<MAP_OP,PI>(self, map_op: MAP_OP) -> FlatMap<Self, MAP_OP>
        where MAP_OP: Fn(Self::Item) -> PI, PI: ParallelIterator
    {
        FlatMap::new(self, map_op)
    }

    /// Reduces the items in the iterator into one item using `op`.
    /// See also `sum`, `mul`, `min`, etc, which are slightly more
    /// efficient. Returns `None` if the iterator is empty.
    ///
    /// Note: unlike in a sequential iterator, the order in which `op`
    /// will be applied to reduce the result is not specified. So `op`
    /// should be commutative and associative or else the results will
    /// be non-deterministic.
    fn reduce_with<OP>(self, op: OP) -> Option<Self::Item>
        where OP: Fn(Self::Item, Self::Item) -> Self::Item + Sync,
    {
        reduce(self.map(Some), &ReduceWithOp::new(op))
    }

    /// Sums up the items in the iterator.
    ///
    /// Note that the order in items will be reduced is not specified,
    /// so if the `+` operator is not truly commutative and
    /// associative (as is the case for floating point numbers), then
    /// the results are not fully deterministic.
    fn sum(self) -> Self::Item
        where SumOp: ReduceOp<Self::Item>
    {
        reduce(self, SUM)
    }

    /// Multiplies all the items in the iterator.
    ///
    /// Note that the order in items will be reduced is not specified,
    /// so if the `*` operator is not truly commutative and
    /// associative (as is the case for floating point numbers), then
    /// the results are not fully deterministic.
    fn mul(self) -> Self::Item
        where MulOp: ReduceOp<Self::Item>
    {
        reduce(self, MUL)
    }

    /// Computes the minimum of all the items in the iterator.
    ///
    /// Note that the order in items will be reduced is not specified,
    /// so if the `Ord` impl is not truly commutative and associative
    /// (as is the case for floating point numbers), then the results
    /// are not deterministic.
    fn min(self) -> Self::Item
        where MinOp: ReduceOp<Self::Item>
    {
        reduce(self, MIN)
    }

    /// Computes the maximum of all the items in the iterator.
    ///
    /// Note that the order in items will be reduced is not specified,
    /// so if the `Ord` impl is not truly commutative and associative
    /// (as is the case for floating point numbers), then the results
    /// are not deterministic.
    fn max(self) -> Self::Item
        where MaxOp: ReduceOp<Self::Item>
    {
        reduce(self, MAX)
    }

    /// Reduces the items using the given "reduce operator". You may
    /// prefer `reduce_with` for a simpler interface.
    ///
    /// Note that the order in items will be reduced is not specified,
    /// so if the `reduce_op` impl is not truly commutative and
    /// associative, then the results are not deterministic.
    fn reduce<REDUCE_OP>(self, reduce_op: &REDUCE_OP) -> Self::Item
        where REDUCE_OP: ReduceOp<Self::Item>
    {
        reduce(self, reduce_op)
    }

    /// Internal method used to define the behavior of this parallel
    /// iterator. You should not need to call this directly.
    fn drive_stateless<'c, C: StatelessConsumer<'c, Item=Self::Item>>(self,
                                                                      consumer: C,
                                                                      shared: &'c C::Shared)
                                                                      -> C::Result;
}

impl<T: ParallelIterator> IntoParallelIterator for T {
    type Iter = T;
    type Item = T::Item;

    fn into_par_iter(self) -> T {
        self
    }
}

/// A trait for parallel iterators items where the precise number of
/// items is not known, but we can at least give an upper-bound. These
/// sorts of iterators result from filtering.
///
/// # Safety note
///
/// This trait is declared as **unsafe to implement**, but it is
/// perfectly safe to **use**. It is unsafe to implement because other
/// code relies on the fact that the estimated length is an upper
/// bound in order to guarantee safety invariants.
pub unsafe trait BoundedParallelIterator: ParallelIterator {
    fn upper_bound(&mut self) -> usize;

    /// Internal method used to define the behavior of this parallel
    /// iterator. You should not need to call this directly.
    fn drive<'c, C: Consumer<'c, Item=Self::Item>>(self,
                                                   consumer: C,
                                                   shared: &'c C::Shared)
                                                   -> C::Result;

}

/// A trait for parallel iterators items where the precise number of
/// items is known. This occurs when e.g. iterating over a
/// vector. Knowing precisely how many items will be produced is very
/// useful.
///
/// # Safety note
///
/// This trait is declared as **unsafe to implement**, but it is
/// perfectly safe to **use**. It is unsafe to implement because other
/// code relies on the fact that the estimated length from an
/// `ExactParallelIterator` is precisely correct in order to guarantee
/// safety invariants.
pub unsafe trait ExactParallelIterator: BoundedParallelIterator {
    /// Produces an exact count of how many items this iterator will
    /// produce, presuming no panic occurs.
    ///
    /// # Safety note
    ///
    /// Returning an incorrect value here could lead to **undefined
    /// behavior**.
    fn len(&mut self) -> usize;

    /// Collects the results of the iterator into the specified
    /// vector. The vector is always truncated before execution
    /// begins. If possible, reusing the vector across calls can lead
    /// to better performance since it reuses the same backing buffer.
    fn collect_into(self, target: &mut Vec<Self::Item>) {
        collect_into(self, target);
    }
}

/// An iterator that supports "random access" to its data, meaning
/// that you can split it at arbitrary indices and draw data from
/// those points.
pub trait PullParallelIterator: ExactParallelIterator {
    /// Producer type that this iterator creates. Users of the API
    /// never need to know about this type.
    type Producer: Producer<Item=Self::Item>;

    /// Internal method to convert this parallel iterator into a
    /// producer that can be used to request the items. Users of the
    /// API never need to know about this fn.
    fn into_producer(self) -> (Self::Producer, <Self::Producer as Producer>::Shared);

    /// Iterate over tuples `(A, B)`, where the items `A` are from
    /// this iterator and `B` are from the iterator given as argument.
    /// Like the `zip` method on ordinary iterators, if the two
    /// iterators are of unequal length, you only get the items they
    /// have in common.
    fn zip<ZIP_OP>(self, zip_op: ZIP_OP) -> ZipIter<Self, ZIP_OP::Iter>
        where ZIP_OP: IntoParallelIterator, ZIP_OP::Iter: PullParallelIterator
    {
        ZipIter::new(self, zip_op.into_par_iter())
    }

    /// Yields an index along with each item.
    fn enumerate(self) -> Enumerate<Self> {
        Enumerate::new(self)
    }
}

<commit_msg>Hide internal types from the documentation.<commit_after>#![allow(dead_code)]

//! The `ParallelIterator` module makes it easy to write parallel
//! programs using an iterator-style interface. To get access to all
//! the methods you want, the easiest is to write `use
//! rayon::par_iter::*;` at the top of your module, which will import
//! the various traits and methods you need.
//!
//! The submodules of this module mostly just contain implementaton
//! details of little interest to an end-user.

use std::f64;
use std::ops::Fn;
use self::collect::collect_into;
use self::enumerate::Enumerate;
use self::filter::Filter;
use self::filter_map::FilterMap;
use self::flat_map::FlatMap;
use self::map::Map;
use self::reduce::{reduce, ReduceOp, SumOp, MulOp, MinOp, MaxOp, ReduceWithOp,
                   SUM, MUL, MIN, MAX};
use self::state::*;
use self::weight::Weight;
use self::zip::ZipIter;

pub mod collect;
pub mod enumerate;
pub mod filter;
pub mod filter_map;
pub mod flat_map;
pub mod len;
pub mod for_each;
pub mod reduce;
pub mod slice;
pub mod slice_mut;
pub mod state;
pub mod map;
pub mod weight;
pub mod zip;
pub mod range;
mod util;

#[cfg(test)]
mod test;

pub trait IntoParallelIterator {
    type Iter: ParallelIterator<Item=Self::Item>;
    type Item: Send;

    fn into_par_iter(self) -> Self::Iter;
}

pub trait IntoParallelRefIterator<'data> {
    type Iter: ParallelIterator<Item=&'data Self::Item>;
    type Item: Sync + 'data;

    fn par_iter(&'data self) -> Self::Iter;
}

pub trait IntoParallelRefMutIterator<'data> {
    type Iter: ParallelIterator<Item=&'data mut Self::Item>;
    type Item: Send + 'data;

    fn par_iter_mut(&'data mut self) -> Self::Iter;
}

/// The `ParallelIterator` interface.
pub trait ParallelIterator: Sized {
    type Item: Send;

    /// Indicates the relative "weight" of producing each item in this
    /// parallel iterator. A higher weight will cause finer-grained
    /// parallel subtasks. 1.0 indicates something very cheap and
    /// uniform, like copying a value out of an array, or computing `x
    /// + 1`. If your tasks are either very expensive, or very
    /// unpredictable, you are better off with higher values. See also
    /// `weight_max`, which is a convenient shorthand to force the
    /// finest grained parallel execution posible. Tuning this value
    /// should not affect correctness but can improve (or hurt)
    /// performance.
    fn weight(self, scale: f64) -> Weight<Self> {
        Weight::new(self, scale)
    }

    /// Shorthand for `self.weight(f64::INFINITY)`. This forces the
    /// smallest granularity of parallel execution, which makes sense
    /// when your parallel tasks are (potentially) very expensive to
    /// execute.
    fn weight_max(self) -> Weight<Self> {
        self.weight(f64::INFINITY)
    }

    /// Executes `OP` on each item produced by the iterator, in parallel.
    fn for_each<OP>(self, op: OP)
        where OP: Fn(Self::Item) + Sync
    {
        for_each::for_each(self, &op)
    }

    /// Applies `map_op` to each item of his iterator, producing a new
    /// iterator with the results.
    fn map<MAP_OP,R>(self, map_op: MAP_OP) -> Map<Self, MAP_OP>
        where MAP_OP: Fn(Self::Item) -> R
    {
        Map::new(self, map_op)
    }

    /// Applies `map_op` to each item of his iterator, producing a new
    /// iterator with the results.
    fn filter<FILTER_OP>(self, filter_op: FILTER_OP) -> Filter<Self, FILTER_OP>
        where FILTER_OP: Fn(&Self::Item) -> bool
    {
        Filter::new(self, filter_op)
    }

    /// Applies `map_op` to each item of his iterator, producing a new
    /// iterator with the results.
    fn filter_map<FILTER_OP,R>(self, filter_op: FILTER_OP) -> FilterMap<Self, FILTER_OP>
        where FILTER_OP: Fn(Self::Item) -> Option<R>
    {
        FilterMap::new(self, filter_op)
    }

    /// Applies `map_op` to each item of his iterator, producing a new
    /// iterator with the results.
    fn flat_map<MAP_OP,PI>(self, map_op: MAP_OP) -> FlatMap<Self, MAP_OP>
        where MAP_OP: Fn(Self::Item) -> PI, PI: ParallelIterator
    {
        FlatMap::new(self, map_op)
    }

    /// Reduces the items in the iterator into one item using `op`.
    /// See also `sum`, `mul`, `min`, etc, which are slightly more
    /// efficient. Returns `None` if the iterator is empty.
    ///
    /// Note: unlike in a sequential iterator, the order in which `op`
    /// will be applied to reduce the result is not specified. So `op`
    /// should be commutative and associative or else the results will
    /// be non-deterministic.
    fn reduce_with<OP>(self, op: OP) -> Option<Self::Item>
        where OP: Fn(Self::Item, Self::Item) -> Self::Item + Sync,
    {
        reduce(self.map(Some), &ReduceWithOp::new(op))
    }

    /// Sums up the items in the iterator.
    ///
    /// Note that the order in items will be reduced is not specified,
    /// so if the `+` operator is not truly commutative and
    /// associative (as is the case for floating point numbers), then
    /// the results are not fully deterministic.
    fn sum(self) -> Self::Item
        where SumOp: ReduceOp<Self::Item>
    {
        reduce(self, SUM)
    }

    /// Multiplies all the items in the iterator.
    ///
    /// Note that the order in items will be reduced is not specified,
    /// so if the `*` operator is not truly commutative and
    /// associative (as is the case for floating point numbers), then
    /// the results are not fully deterministic.
    fn mul(self) -> Self::Item
        where MulOp: ReduceOp<Self::Item>
    {
        reduce(self, MUL)
    }

    /// Computes the minimum of all the items in the iterator.
    ///
    /// Note that the order in items will be reduced is not specified,
    /// so if the `Ord` impl is not truly commutative and associative
    /// (as is the case for floating point numbers), then the results
    /// are not deterministic.
    fn min(self) -> Self::Item
        where MinOp: ReduceOp<Self::Item>
    {
        reduce(self, MIN)
    }

    /// Computes the maximum of all the items in the iterator.
    ///
    /// Note that the order in items will be reduced is not specified,
    /// so if the `Ord` impl is not truly commutative and associative
    /// (as is the case for floating point numbers), then the results
    /// are not deterministic.
    fn max(self) -> Self::Item
        where MaxOp: ReduceOp<Self::Item>
    {
        reduce(self, MAX)
    }

    /// Reduces the items using the given "reduce operator". You may
    /// prefer `reduce_with` for a simpler interface.
    ///
    /// Note that the order in items will be reduced is not specified,
    /// so if the `reduce_op` impl is not truly commutative and
    /// associative, then the results are not deterministic.
    fn reduce<REDUCE_OP>(self, reduce_op: &REDUCE_OP) -> Self::Item
        where REDUCE_OP: ReduceOp<Self::Item>
    {
        reduce(self, reduce_op)
    }

    /// Internal method used to define the behavior of this parallel
    /// iterator. You should not need to call this directly.
    #[doc(hidden)]
    fn drive_stateless<'c, C: StatelessConsumer<'c, Item=Self::Item>>(self,
                                                                      consumer: C,
                                                                      shared: &'c C::Shared)
                                                                      -> C::Result;
}

impl<T: ParallelIterator> IntoParallelIterator for T {
    type Iter = T;
    type Item = T::Item;

    fn into_par_iter(self) -> T {
        self
    }
}

/// A trait for parallel iterators items where the precise number of
/// items is not known, but we can at least give an upper-bound. These
/// sorts of iterators result from filtering.
///
/// # Safety note
///
/// This trait is declared as **unsafe to implement**, but it is
/// perfectly safe to **use**. It is unsafe to implement because other
/// code relies on the fact that the estimated length is an upper
/// bound in order to guarantee safety invariants.
pub unsafe trait BoundedParallelIterator: ParallelIterator {
    fn upper_bound(&mut self) -> usize;

    /// Internal method used to define the behavior of this parallel
    /// iterator. You should not need to call this directly.
    #[doc(hidden)]
    fn drive<'c, C: Consumer<'c, Item=Self::Item>>(self,
                                                   consumer: C,
                                                   shared: &'c C::Shared)
                                                   -> C::Result;

}

/// A trait for parallel iterators items where the precise number of
/// items is known. This occurs when e.g. iterating over a
/// vector. Knowing precisely how many items will be produced is very
/// useful.
///
/// # Safety note
///
/// This trait is declared as **unsafe to implement**, but it is
/// perfectly safe to **use**. It is unsafe to implement because other
/// code relies on the fact that the estimated length from an
/// `ExactParallelIterator` is precisely correct in order to guarantee
/// safety invariants.
pub unsafe trait ExactParallelIterator: BoundedParallelIterator {
    /// Produces an exact count of how many items this iterator will
    /// produce, presuming no panic occurs.
    ///
    /// # Safety note
    ///
    /// Returning an incorrect value here could lead to **undefined
    /// behavior**.
    fn len(&mut self) -> usize;

    /// Collects the results of the iterator into the specified
    /// vector. The vector is always truncated before execution
    /// begins. If possible, reusing the vector across calls can lead
    /// to better performance since it reuses the same backing buffer.
    fn collect_into(self, target: &mut Vec<Self::Item>) {
        collect_into(self, target);
    }
}

/// An iterator that supports "random access" to its data, meaning
/// that you can split it at arbitrary indices and draw data from
/// those points.
pub trait PullParallelIterator: ExactParallelIterator {
    /// Producer type that this iterator creates. Users of the API
    /// never need to know about this type.
    #[doc(hidden)]
    type Producer: Producer<Item=Self::Item>;

    /// Internal method to convert this parallel iterator into a
    /// producer that can be used to request the items. Users of the
    /// API never need to know about this fn.
    #[doc(hidden)]
    fn into_producer(self) -> (Self::Producer, <Self::Producer as Producer>::Shared);

    /// Iterate over tuples `(A, B)`, where the items `A` are from
    /// this iterator and `B` are from the iterator given as argument.
    /// Like the `zip` method on ordinary iterators, if the two
    /// iterators are of unequal length, you only get the items they
    /// have in common.
    fn zip<ZIP_OP>(self, zip_op: ZIP_OP) -> ZipIter<Self, ZIP_OP::Iter>
        where ZIP_OP: IntoParallelIterator, ZIP_OP::Iter: PullParallelIterator
    {
        ZipIter::new(self, zip_op.into_par_iter())
    }

    /// Yields an index along with each item.
    fn enumerate(self) -> Enumerate<Self> {
        Enumerate::new(self)
    }
}

<|endoftext|>