<commit_before>extern crate rand;
extern crate timely;
extern crate differential_dataflow;
extern crate core_affinity;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::operators::{Exchange, Probe};
use timely::progress::nested::product::Product;
use timely::progress::timestamp::RootTimestamp;

use differential_dataflow::input::Input;
use differential_dataflow::operators::arrange::Arrange;
use differential_dataflow::operators::count::CountTotalCore;
use differential_dataflow::operators::JoinCore;

use differential_dataflow::trace::implementations::ord::OrdKeySpine;

#[derive(Debug)]
enum Comp {
    Nothing,
    Exchange,
    Arrange,
    Maintain,
    Count,
}

#[derive(Debug)]
enum Mode {
    OpenLoop,
    ClosedLoop,
}

fn main() {

    let keys: usize = std::env::args().nth(1).unwrap().parse().unwrap();
    let recs: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let rate: usize = std::env::args().nth(3).unwrap().parse().unwrap();
    let work: usize = std::env::args().nth(4).unwrap().parse().unwrap_or(usize::max_value());
    let comp: Comp = match std::env::args().nth(5).unwrap().as_str() {
        "exchange" => Comp::Exchange,
        "arrange" => Comp::Arrange,
        "count" => Comp::Count,
        _ => Comp::Nothing,
    };
    let mode: Mode = if std::env::args().any(|x| x == "open-loop") { Mode::OpenLoop } else { Mode::ClosedLoop };

    // define a new computational scope, in which to run BFS
    timely::execute_from_args(std::env::args().skip(4), move |worker| {

        let index = worker.index();
        let core_ids = core_affinity::get_core_ids().unwrap();
        core_affinity::set_for_current(core_ids[index]);

        // create a a degree counting differential dataflow
        let (mut input, probe) = worker.dataflow::<u64,_,_>(|scope| {

            let (handle, data) = scope.new_collection();

            let probe = match comp {
                Comp::Nothing => data.probe(),
                Comp::Exchange => data.inner.exchange(|&(x,_,_): &((usize,()),_,_)| x.0 as u64).probe(),
                Comp::Arrange => data.arrange(OrdKeySpine::<usize, Product<RootTimestamp,u64>,isize>::with_effort(work)).stream.probe(),
                Comp::Count => data.arrange(OrdKeySpine::<usize, Product<RootTimestamp,u64>,isize>::with_effort(work)).count_total_core().probe(),
            };

            (handle, probe)
        });

        let index = worker.index();
        let peers = worker.peers();

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for deletions

        let timer = ::std::time::Instant::now();

        for _ in 0 .. ((recs as usize) / peers) + if index < ((recs as usize) % peers) { 1 } else { 0 } {
            input.insert((rng1.gen_range(0, keys),()));
        }

        input.advance_to(1u64);
        input.flush();
        while probe.less_than(input.time()) { worker.step(); }

        if index == 0 {
            let elapsed1 = timer.elapsed();
            let elapsed1_ns = elapsed1.as_secs() * 1_000_000_000 + (elapsed1.subsec_nanos() as u64);
            // println!("{:?}\tdata loaded; rate: {:?}", elapsed1, 1000000000.0 * (recs as f64) / (elapsed1_ns as f64));
            println!("ARRANGE\tLOADING\t{}\t{:?}", peers, 1000000000.0 * (recs as f64) / (elapsed1_ns as f64));
        }

        if rate > 0 {

            let timer = ::std::time::Instant::now();
            // let mut counts = vec![0u64; 64];

            let mut counts = vec![[0u64; 16]; 64];

            match mode {

                // closed-loop latency-throughput test, parameterized by rate size.
                Mode::ClosedLoop => {

                    let mut wave = 1;
                    let mut elapsed = timer.elapsed();

                    while elapsed.as_secs() < 25 {

                        for round in 0 .. rate {
                            input.advance_to((((wave * rate) + round) * peers + index) as u64);
                            input.insert((rng1.gen_range(0, keys),()));
                            input.remove((rng2.gen_range(0, keys),()));
                        }
                        wave += 1;
                        input.advance_to((wave * rate * peers) as u64);
                        input.flush();

                        let elapsed1 = elapsed.clone();
                        let elapsed1_ns = elapsed1.as_secs() * 1_000_000_000 + (elapsed1.subsec_nanos() as u64);
                        while probe.less_than(input.time()) { worker.step(); }
                        elapsed = timer.elapsed();
                        let elapsed2 = elapsed.clone();
                        let elapsed2_ns = elapsed2.as_secs() * 1_000_000_000 + (elapsed2.subsec_nanos() as u64);
                        let count_index = (elapsed2_ns - elapsed1_ns).next_power_of_two().trailing_zeros() as usize;
                        if elapsed.as_secs() > 5 {
                            let low_bits = ((elapsed2_ns - elapsed1_ns) >> (count_index - 5)) & 0xF;
                            counts[count_index][low_bits as usize] += 1;
                        }
                    }

                    let elapsed = timer.elapsed();
                    let seconds = elapsed.as_secs() as f64 + (elapsed.subsec_nanos() as f64) / 1000000000.0;
                    if index == 0 {
                        // println!("{:?}, {:?}", seconds / (wave - 1) as f64, 2.0 * ((wave - 1) * rate * peers) as f64 / seconds);
                        println!("ARRANGE\tTHROUGHPUT\t{}\t{:?}", peers, 2.0 * ((wave - 1) * rate * peers) as f64 / seconds);
                    }

                },
                Mode::OpenLoop => {

                    let requests_per_sec = rate / 2;
                    let ns_per_request = 1_000_000_000 / requests_per_sec;
                    let mut request_counter = peers + index;    // skip first request for each.
                    let mut ack_counter = peers + index;

                    let mut inserted_ns = 1;

                    let ack_target = 10 * keys;
                    while ack_counter < ack_target {
                    // while ((timer.elapsed().as_secs() as usize) * rate) < (10 * keys) {

                        // Open-loop latency-throughput test, parameterized by offered rate `ns_per_request`.
                        let elapsed = timer.elapsed();
                        let elapsed_ns = elapsed.as_secs() * 1_000_000_000 + (elapsed.subsec_nanos() as u64);

                        // Determine completed ns.
                        let acknowledged_ns: u64 = probe.with_frontier(|frontier| frontier[0].inner);

                        // any un-recorded measurements that are complete should be recorded.
                        while ((ack_counter * ns_per_request) as u64) < acknowledged_ns && ack_counter < ack_target {
                            let requested_at = (ack_counter * ns_per_request) as u64;
                            let count_index = (elapsed_ns - requested_at).next_power_of_two().trailing_zeros() as usize;
                            if ack_counter > ack_target / 2 {
                                // counts[count_index] += 1;
                                let low_bits = ((elapsed_ns - requested_at) >> (count_index - 5)) & 0xF;
                                counts[count_index][low_bits as usize] += 1;
                            }
                            ack_counter += peers;
                        }

                        // Now, should we introduce more records before stepping the worker?
                        //
                        // Thinking: inserted_ns - acknowledged_ns is some amount of time that
                        // is currently outstanding in the system, and we needn't advance our
                        // inputs unless by this order of magnitude.
                        //
                        // The more sophisticated plan is: we compute the next power of two
                        // greater than inserted_ns - acknowledged_ns and look for the last
                        // multiple of this number in the interval [inserted_ns, elapsed_ns].
                        // If such a multiple exists, we introduce records to that point and
                        // advance the input.

                        // let scale = (inserted_ns - acknowledged_ns).next_power_of_two();
                        // let target_ns = elapsed_ns & !(scale - 1);

                        let target_ns = if acknowledged_ns >= inserted_ns { elapsed_ns } else { inserted_ns };

                        // let target_ns = elapsed_ns & !((1 << 16) - 1);

                        if inserted_ns < target_ns {

                            while ((request_counter * ns_per_request) as u64) < target_ns {
                                input.advance_to((request_counter * ns_per_request) as u64);
                                input.insert((rng1.gen_range(0, keys),()));
                                input.remove((rng2.gen_range(0, keys),()));
                                request_counter += peers;
                            }
                            input.advance_to(target_ns);
                            input.flush();
                            inserted_ns = target_ns;
                        }

                        worker.step();
                    }

                }
            }

            if index == 0 {

                let mut results = Vec::new();
                let total = counts.iter().map(|x| x.iter().sum::<u64>()).sum();
                let mut sum = 0;
                for index in (10 .. counts.len()).rev() {
                    for sub in (0 .. 16).rev() {
                        if sum > 0 && sum < total {
                            let latency = (1 << (index-1)) + (sub << (index-5));
                            let fraction = (sum as f64) / (total as f64);
                            results.push((latency, fraction));
                        }
                        sum += counts[index][sub];
                    }
                }
                for (latency, fraction) in results.drain(..).rev() {
                    println!("ARRANGE\tLATENCY\t{}\t{}\t{}\t{}\t{}\t{:?}\t{:?}\t{}\t{}", peers, keys, recs, rate, work, comp, mode, latency, fraction);
                }
            }
        }

    }).unwrap();
}<commit_msg>core pinning<commit_after>extern crate rand;
extern crate timely;
extern crate differential_dataflow;
extern crate core_affinity;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::operators::{Exchange, Probe};
use timely::progress::nested::product::Product;
use timely::progress::timestamp::RootTimestamp;

use differential_dataflow::input::Input;
use differential_dataflow::operators::arrange::Arrange;
use differential_dataflow::operators::count::CountTotalCore;
use differential_dataflow::operators::JoinCore;

use differential_dataflow::trace::implementations::ord::OrdKeySpine;

#[derive(Debug)]
enum Comp {
    Nothing,
    Exchange,
    Arrange,
    Count,
}

#[derive(Debug)]
enum Mode {
    OpenLoop,
    ClosedLoop,
}

fn main() {

    let keys: usize = std::env::args().nth(1).unwrap().parse().unwrap();
    let recs: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let rate: usize = std::env::args().nth(3).unwrap().parse().unwrap();
    let work: usize = std::env::args().nth(4).unwrap().parse().unwrap_or(usize::max_value());
    let comp: Comp = match std::env::args().nth(5).unwrap().as_str() {
        "exchange" => Comp::Exchange,
        "arrange" => Comp::Arrange,
        "count" => Comp::Count,
        _ => Comp::Nothing,
    };
    let mode: Mode = if std::env::args().any(|x| x == "open-loop") { Mode::OpenLoop } else { Mode::ClosedLoop };

    // define a new computational scope, in which to run BFS
    timely::execute_from_args(std::env::args().skip(4), move |worker| {

        let index = worker.index();
        let core_ids = core_affinity::get_core_ids().unwrap();
        core_affinity::set_for_current(core_ids[index]);

        // create a a degree counting differential dataflow
        let (mut input, probe) = worker.dataflow::<u64,_,_>(|scope| {

            let (handle, data) = scope.new_collection();

            let probe = match comp {
                Comp::Nothing => data.probe(),
                Comp::Exchange => data.inner.exchange(|&(x,_,_): &((usize,()),_,_)| x.0 as u64).probe(),
                Comp::Arrange => data.arrange(OrdKeySpine::<usize, Product<RootTimestamp,u64>,isize>::with_effort(work)).stream.probe(),
                Comp::Count => data.arrange(OrdKeySpine::<usize, Product<RootTimestamp,u64>,isize>::with_effort(work)).count_total_core().probe(),
            };

            (handle, probe)
        });

        let index = worker.index();
        let peers = worker.peers();

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for deletions

        let timer = ::std::time::Instant::now();

        for _ in 0 .. ((recs as usize) / peers) + if index < ((recs as usize) % peers) { 1 } else { 0 } {
            input.insert((rng1.gen_range(0, keys),()));
        }

        input.advance_to(1u64);
        input.flush();
        while probe.less_than(input.time()) { worker.step(); }

        if index == 0 {
            let elapsed1 = timer.elapsed();
            let elapsed1_ns = elapsed1.as_secs() * 1_000_000_000 + (elapsed1.subsec_nanos() as u64);
            // println!("{:?}\tdata loaded; rate: {:?}", elapsed1, 1000000000.0 * (recs as f64) / (elapsed1_ns as f64));
            println!("ARRANGE\tLOADING\t{}\t{:?}", peers, 1000000000.0 * (recs as f64) / (elapsed1_ns as f64));
        }

        if rate > 0 {

            let timer = ::std::time::Instant::now();
            // let mut counts = vec![0u64; 64];

            let mut counts = vec![[0u64; 16]; 64];

            match mode {

                // closed-loop latency-throughput test, parameterized by rate size.
                Mode::ClosedLoop => {

                    let mut wave = 1;
                    let mut elapsed = timer.elapsed();

                    while elapsed.as_secs() < 25 {

                        for round in 0 .. rate {
                            input.advance_to((((wave * rate) + round) * peers + index) as u64);
                            input.insert((rng1.gen_range(0, keys),()));
                            input.remove((rng2.gen_range(0, keys),()));
                        }
                        wave += 1;
                        input.advance_to((wave * rate * peers) as u64);
                        input.flush();

                        let elapsed1 = elapsed.clone();
                        let elapsed1_ns = elapsed1.as_secs() * 1_000_000_000 + (elapsed1.subsec_nanos() as u64);
                        while probe.less_than(input.time()) { worker.step(); }
                        elapsed = timer.elapsed();
                        let elapsed2 = elapsed.clone();
                        let elapsed2_ns = elapsed2.as_secs() * 1_000_000_000 + (elapsed2.subsec_nanos() as u64);
                        let count_index = (elapsed2_ns - elapsed1_ns).next_power_of_two().trailing_zeros() as usize;
                        if elapsed.as_secs() > 5 {
                            let low_bits = ((elapsed2_ns - elapsed1_ns) >> (count_index - 5)) & 0xF;
                            counts[count_index][low_bits as usize] += 1;
                        }
                    }

                    let elapsed = timer.elapsed();
                    let seconds = elapsed.as_secs() as f64 + (elapsed.subsec_nanos() as f64) / 1000000000.0;
                    if index == 0 {
                        // println!("{:?}, {:?}", seconds / (wave - 1) as f64, 2.0 * ((wave - 1) * rate * peers) as f64 / seconds);
                        println!("ARRANGE\tTHROUGHPUT\t{}\t{:?}", peers, 2.0 * ((wave - 1) * rate * peers) as f64 / seconds);
                    }

                },
                Mode::OpenLoop => {

                    let requests_per_sec = rate / 2;
                    let ns_per_request = 1_000_000_000 / requests_per_sec;
                    let mut request_counter = peers + index;    // skip first request for each.
                    let mut ack_counter = peers + index;

                    let mut inserted_ns = 1;

                    let ack_target = 10 * keys;
                    while ack_counter < ack_target {
                    // while ((timer.elapsed().as_secs() as usize) * rate) < (10 * keys) {

                        // Open-loop latency-throughput test, parameterized by offered rate `ns_per_request`.
                        let elapsed = timer.elapsed();
                        let elapsed_ns = elapsed.as_secs() * 1_000_000_000 + (elapsed.subsec_nanos() as u64);

                        // Determine completed ns.
                        let acknowledged_ns: u64 = probe.with_frontier(|frontier| frontier[0].inner);

                        // any un-recorded measurements that are complete should be recorded.
                        while ((ack_counter * ns_per_request) as u64) < acknowledged_ns && ack_counter < ack_target {
                            let requested_at = (ack_counter * ns_per_request) as u64;
                            let count_index = (elapsed_ns - requested_at).next_power_of_two().trailing_zeros() as usize;
                            if ack_counter > ack_target / 2 {
                                // counts[count_index] += 1;
                                let low_bits = ((elapsed_ns - requested_at) >> (count_index - 5)) & 0xF;
                                counts[count_index][low_bits as usize] += 1;
                            }
                            ack_counter += peers;
                        }

                        // Now, should we introduce more records before stepping the worker?
                        //
                        // Thinking: inserted_ns - acknowledged_ns is some amount of time that
                        // is currently outstanding in the system, and we needn't advance our
                        // inputs unless by this order of magnitude.
                        //
                        // The more sophisticated plan is: we compute the next power of two
                        // greater than inserted_ns - acknowledged_ns and look for the last
                        // multiple of this number in the interval [inserted_ns, elapsed_ns].
                        // If such a multiple exists, we introduce records to that point and
                        // advance the input.

                        // let scale = (inserted_ns - acknowledged_ns).next_power_of_two();
                        // let target_ns = elapsed_ns & !(scale - 1);

                        let target_ns = if acknowledged_ns >= inserted_ns { elapsed_ns } else { inserted_ns };

                        // let target_ns = elapsed_ns & !((1 << 16) - 1);

                        if inserted_ns < target_ns {

                            while ((request_counter * ns_per_request) as u64) < target_ns {
                                input.advance_to((request_counter * ns_per_request) as u64);
                                input.insert((rng1.gen_range(0, keys),()));
                                input.remove((rng2.gen_range(0, keys),()));
                                request_counter += peers;
                            }
                            input.advance_to(target_ns);
                            input.flush();
                            inserted_ns = target_ns;
                        }

                        worker.step();
                    }

                }
            }

            if index == 0 {

                let mut results = Vec::new();
                let total = counts.iter().map(|x| x.iter().sum::<u64>()).sum();
                let mut sum = 0;
                for index in (10 .. counts.len()).rev() {
                    for sub in (0 .. 16).rev() {
                        if sum > 0 && sum < total {
                            let latency = (1 << (index-1)) + (sub << (index-5));
                            let fraction = (sum as f64) / (total as f64);
                            results.push((latency, fraction));
                        }
                        sum += counts[index][sub];
                    }
                }
                for (latency, fraction) in results.drain(..).rev() {
                    println!("ARRANGE\tLATENCY\t{}\t{}\t{}\t{}\t{}\t{:?}\t{:?}\t{}\t{}", peers, keys, recs, rate, work, comp, mode, latency, fraction);
                }
            }
        }

    }).unwrap();
}<|endoftext|>


<commit_before>mod terminal;
mod ansi;

use std::io::{self, Write};
use self::terminal::{Terminal, Event, Key};
use self::ansi::{clear, color, cursor, style};
use rayon::prelude::*;
use rff::choice::Choice;

#[derive(Debug)]
pub enum Error {
    Exit,
    Write(io::Error),
    Reset(terminal::Error)
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Write(err)
    }
}

impl From<terminal::Error> for Error {
    fn from(err: terminal::Error) -> Error {
        Error::Reset(err)
    }
}

pub struct Options {
    pub choices: Vec<String>,
    pub initial: String,
}

pub struct Interface {
    choices: Vec<String>,
    matching: Vec<Choice>,
    selected: usize,
    search: String,
    width: usize,
    terminal: Terminal,
}

impl Interface {
    /// Creates a new Interface from the provided options.
    pub fn from_opts(opts: Options) -> Interface {
        let mut term = Terminal::from("/dev/tty").unwrap();
        term.set_raw_mode().unwrap();

        Interface {
            choices: opts.choices,
            matching: Vec::new(),
            selected: 0,
            search: opts.initial,
            width: term.max_width,
            terminal: term
        }
    }

    // Starts the interface
    pub fn run(&mut self) -> Result<&str, Error> {
        self.filter_choices();
        self.render()?;

        for event in self.terminal.events()? {
            if let Event::Key(key) = event? {
                match key {
                    Key::Ctrl('c') | Key::Ctrl('d') => {
                        self.clear()?;
                        return Err(Error::Exit);
                    }

                    Key::Char('\n') => {
                        break;
                    },

                    Key::Ctrl('n') => {
                        self.selected += 1;
                        self.clamp_selected();
                        self.render()?;
                    },

                    Key::Ctrl('p') => {
                        self.selected = self.selected.
                            checked_sub(1).
                            unwrap_or(0);

                        self.clamp_selected();
                        self.render()?;
                    },

                    Key::Char(ch) => {
                        self.search.push(ch);
                        self.filter_existing_matches();
                        self.render()?;
                    },

                    Key::Backspace | Key::Ctrl('h') => {
                        self.search.pop();
                        self.filter_choices();
                        self.render()?;
                    }

                    Key::Ctrl('u') => {
                        self.search.clear();
                        self.filter_choices();
                        self.render()?;
                    }

                    _ => {}
                }
            };
        }

        self.clear()?;
        Ok(self.result())
    }

    fn filter_choices(&mut self) {
        let mut matches = self.choices.
            par_iter().
            cloned().
            filter_map(|choice| Choice::with_positions(&self.search, choice)).
            collect::<Vec<_>>();

        matches.sort_by(|a, b| b.partial_cmp(a).unwrap());

        self.matching = matches;
    }

    fn filter_existing_matches(&mut self) {
        let mut matches = self.matching.
            par_iter().
            map(|c| c.text().to_string()).
            filter_map(|choice| Choice::with_positions(&self.search, choice)).
            collect::<Vec<_>>();

        matches.sort_by(|a, b| b.partial_cmp(a).unwrap());

        self.matching = matches;
    }

    fn render(&mut self) -> io::Result<()> {
        write!(self.terminal, "{}{}", cursor::Column(1), clear::Screen)?;
        write!(self.terminal, "> {}", self.search)?;

        let n = self.matching.iter().take(10).len() as u16;

        self.render_matches()?;

        if n > 0 {
            let column = format!("> {}", self.search).len() as u16;
            write!(self.terminal, "{}{}", cursor::Up(n), cursor::Column(column + 1))?;
        }

        Ok(())
    }

    fn render_matches(&mut self) -> io::Result<()> {
        let matches = self.matching.iter().take(10);

        for (i, choice) in matches.enumerate() {
            let selected = i == self.selected;
            let chars = choice.text().chars().take(self.width);

            write!(self.terminal, "\r\n")?;

            if selected {
                write!(self.terminal, "{}", style::Invert)?;
            }

            if let Some(positions) = choice.positions() {
                for (i, ch) in chars.enumerate() {
                    let match_position = positions.iter().any(|p| *p == i);

                    if match_position {
                        let color = color::Fg(color::Colors::Magenta);
                        let reset = color::Fg(color::Reset);
                        write!(self.terminal, "{}{}{}", color, ch, reset)?;
                    } else {
                        write!(self.terminal, "{}", ch)?;
                    }
                }

            } else {
                write!(self.terminal, "{}", chars.collect::<String>())?;
            }

            if selected {
                write!(self.terminal, "{}", style::NoInvert)?;
            }
        }

        Ok(())
    }

    #[inline(always)]
    fn clamp_selected(&mut self) {
        let mut max = self.matching.len();
        if max > 10 { max = 10; }

        if self.selected >= max {
            self.selected = max - 1;
        }
    }

    fn clear(&mut self) -> Result<(), Error> {
        write!(self.terminal, "{}{}", cursor::Column(1), clear::Screen)?;
        self.terminal.reset()?;
        Ok(())
    }

    fn result(&mut self) -> &str {
        self.matching.iter().
            map(|c| c.text()).
            nth(self.selected).
            unwrap_or(&self.search)
    }
}
<commit_msg>Use buffered writer when rendering matches<commit_after>mod terminal;
mod ansi;

use std::io::{self, Write, BufWriter};
use self::terminal::{Terminal, Event, Key};
use self::ansi::{clear, color, cursor, style};
use rayon::prelude::*;
use rff::choice::Choice;

#[derive(Debug)]
pub enum Error {
    Exit,
    Write(io::Error),
    Reset(terminal::Error)
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Write(err)
    }
}

impl From<terminal::Error> for Error {
    fn from(err: terminal::Error) -> Error {
        Error::Reset(err)
    }
}

pub struct Options {
    pub choices: Vec<String>,
    pub initial: String,
}

pub struct Interface {
    choices: Vec<String>,
    matching: Vec<Choice>,
    selected: usize,
    search: String,
    width: usize,
    terminal: Terminal,
}

impl Interface {
    /// Creates a new Interface from the provided options.
    pub fn from_opts(opts: Options) -> Interface {
        let mut term = Terminal::from("/dev/tty").unwrap();
        term.set_raw_mode().unwrap();

        Interface {
            choices: opts.choices,
            matching: Vec::new(),
            selected: 0,
            search: opts.initial,
            width: term.max_width,
            terminal: term
        }
    }

    // Starts the interface
    pub fn run(&mut self) -> Result<&str, Error> {
        self.filter_choices();
        self.render()?;

        for event in self.terminal.events()? {
            if let Event::Key(key) = event? {
                match key {
                    Key::Ctrl('c') | Key::Ctrl('d') => {
                        self.clear()?;
                        return Err(Error::Exit);
                    }

                    Key::Char('\n') => {
                        break;
                    },

                    Key::Ctrl('n') => {
                        self.selected += 1;
                        self.clamp_selected();
                        self.render()?;
                    },

                    Key::Ctrl('p') => {
                        self.selected = self.selected.
                            checked_sub(1).
                            unwrap_or(0);

                        self.clamp_selected();
                        self.render()?;
                    },

                    Key::Char(ch) => {
                        self.search.push(ch);
                        self.filter_existing_matches();
                        self.render()?;
                    },

                    Key::Backspace | Key::Ctrl('h') => {
                        self.search.pop();
                        self.filter_choices();
                        self.render()?;
                    }

                    Key::Ctrl('u') => {
                        self.search.clear();
                        self.filter_choices();
                        self.render()?;
                    }

                    _ => {}
                }
            };
        }

        self.clear()?;
        Ok(self.result())
    }

    fn filter_choices(&mut self) {
        let mut matches = self.choices.
            par_iter().
            cloned().
            filter_map(|choice| Choice::with_positions(&self.search, choice)).
            collect::<Vec<_>>();

        matches.sort_by(|a, b| b.partial_cmp(a).unwrap());

        self.matching = matches;
    }

    fn filter_existing_matches(&mut self) {
        let mut matches = self.matching.
            par_iter().
            map(|c| c.text().to_string()).
            filter_map(|choice| Choice::with_positions(&self.search, choice)).
            collect::<Vec<_>>();

        matches.sort_by(|a, b| b.partial_cmp(a).unwrap());

        self.matching = matches;
    }

    fn render(&mut self) -> io::Result<()> {
        write!(self.terminal, "{}{}", cursor::Column(1), clear::Screen)?;
        write!(self.terminal, "> {}", self.search)?;

        let n = self.matching.iter().take(10).len() as u16;

        self.render_matches()?;

        if n > 0 {
            let column = format!("> {}", self.search).len() as u16;
            write!(self.terminal, "{}{}", cursor::Up(n), cursor::Column(column + 1))?;
        }

        Ok(())
    }

    fn render_matches(&mut self) -> io::Result<()> {
        let mut term = BufWriter::new(&mut self.terminal);
        let matches = self.matching.iter().take(10);

        for (i, choice) in matches.enumerate() {
            let selected = i == self.selected;
            let chars = choice.text().chars().take(self.width);

            write!(term, "\r\n")?;

            if selected {
                write!(term, "{}", style::Invert)?;
            }

            if let Some(positions) = choice.positions() {
                for (i, ch) in chars.enumerate() {
                    let match_position = positions.iter().any(|p| *p == i);

                    if match_position {
                        let color = color::Fg(color::Colors::Magenta);
                        let reset = color::Fg(color::Reset);
                        write!(term, "{}{}{}", color, ch, reset)?;
                    } else {
                        write!(term, "{}", ch)?;
                    }
                }

            } else {
                write!(term, "{}", chars.collect::<String>())?;
            }

            if selected {
                write!(term, "{}", style::NoInvert)?;
            }
        }

        Ok(())
    }

    #[inline(always)]
    fn clamp_selected(&mut self) {
        let mut max = self.matching.len();
        if max > 10 { max = 10; }

        if self.selected >= max {
            self.selected = max - 1;
        }
    }

    fn clear(&mut self) -> Result<(), Error> {
        write!(self.terminal, "{}{}", cursor::Column(1), clear::Screen)?;
        self.terminal.reset()?;
        Ok(())
    }

    fn result(&mut self) -> &str {
        self.matching.iter().
            map(|c| c.text()).
            nth(self.selected).
            unwrap_or(&self.search)
    }
}
<|endoftext|>


<commit_before>// CString wrappers.

use std::{str, fmt, ops, default, hash};
use std::ffi::{CStr, CString};
use std::borrow::Cow;
use std::os::raw::c_char;

#[cfg(not(feature = "no-string-validation"))]
use Error;
#[cfg(not(feature = "no-string-validation"))]
use ffi;

macro_rules! cstring_wrapper {
    ($t: ident, $s: ident) => {

impl<'m> $t<'m> {
    #[cfg(feature = "no-string-validation")]
    fn check_valid(_: *const c_char) -> Result<(), String> { Ok(()) }

    #[cfg(not(feature = "no-string-validation"))]
    fn check_valid(c: *const c_char) -> Result<(), String> {
        let mut e = Error::empty();
        let b = unsafe { ffi::$s(c, e.get_mut()) };
        if b != 0 { Ok(()) } else { Err(e.message().unwrap().into()) }
    }

    /// Creates a new instance of this struct.
    ///
    /// Note: If the no-string-validation feature is activated, this string
    /// will not be checked for conformance with the D-Bus specification.
    pub fn new<S: Into<Vec<u8>>>(s: S) -> Result<$t<'m>, String> {
        let c = try!(CString::new(s).map_err(|e| e.to_string()));
        $t::check_valid(c.as_ptr()).map(|_| $t(Cow::Owned(c)))
    }

    /// Creates a new instance of this struct. If you end it with \0,
    /// it can borrow the slice without extra allocation.
    ///
    /// Note: If the no-string-validation feature is activated, this string
    /// will not be checked for conformance with the D-Bus specification.
    pub fn from_slice(s: &'m [u8]) -> Result<$t<'m>, String> {
        if s.len() == 0 || s[s.len()-1] != 0 { return $t::new(s) };
        $t::check_valid(s.as_ptr() as *const i8).map(|_| {
            let c = unsafe { CStr::from_ptr(s.as_ptr() as *const c_char) };
            $t(Cow::Borrowed(c))
        })
    }

    /// This function creates a new instance of this struct, without checking.
    /// It's up to you to guarantee that s ends with a \0 and is valid.
    pub unsafe fn from_slice_unchecked(s: &'m [u8]) -> $t<'m> {
        debug_assert!(s[s.len()-1] == 0);
        $t(Cow::Borrowed(CStr::from_ptr(s.as_ptr() as *const c_char)))
    }

    /// View this struct as a CStr.
    pub fn as_cstr(&self) -> &CStr { &self.0 }

    /// Makes sure this string does not contain borrows.
    pub fn into_static(self) -> $t<'static> {
        $t(Cow::Owned(self.0.into_owned()))
    }
}

/*
/// #Panics
///
/// If given string is not valid.
/// impl<S: Into<Vec<u8>>> From<S> for $t { fn from(s: S) -> $t { $t::new(s).unwrap() } }
*/

/// #Panics
///
/// If given string is not valid.
impl<'m> From<String> for $t<'m> { fn from(s: String) -> $t<'m> { $t::new(s).unwrap() } }

/// #Panics
///
/// If given string is not valid.
impl<'m> From<&'m String> for $t<'m> { fn from(s: &'m String) -> $t<'m> { $t::from_slice(s.as_bytes()).unwrap() } }

/// #Panics
///
/// If given string is not valid.
impl<'m> From<&'m str> for $t<'m> { fn from(s: &'m str) -> $t<'m> { $t::from_slice(s.as_bytes()).unwrap() } }

/// #Panics
///
/// If given string is not valid.
impl<'m> From<Cow<'m, str>> for $t<'m> {
    fn from(s: Cow<'m, str>) -> $t<'m> {
        match s {
            Cow::Borrowed(z) => z.into(),
            Cow::Owned(z) => z.into(),
        }
    }
}

impl<'m> ops::Deref for $t<'m> {
    type Target = str;
    fn deref(&self) -> &str { str::from_utf8(self.0.to_bytes()).unwrap() }
}

impl<'m> fmt::Display for $t<'m> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s: &str = &self;
        (&s as &fmt::Display).fmt(f)
    }
}

impl<'m> AsRef<CStr> for $t<'m> {
    fn as_ref(&self) -> &CStr { &self.0 }
}

impl<'m> hash::Hash for $t<'m> {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.0.hash(state);
    }
}

}}

/// A wrapper around a string that is guaranteed to be
/// a valid (single) D-Bus type signature. Supersedes TypeSig.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Signature<'a>(Cow<'a, CStr>);

cstring_wrapper!(Signature, dbus_signature_validate_single);

impl Signature<'static> {
    /// Makes a D-Bus signature that corresponds to A.
    pub fn make<A: super::arg::Arg>() -> Signature<'static> { A::signature() }
}

/// A wrapper around a string that is guaranteed to be
/// a valid D-Bus object path.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Path<'a>(Cow<'a, CStr>);

cstring_wrapper!(Path, dbus_validate_path);

// This is needed so one can make arrays of paths easily
impl<'a> default::Default for Path<'a> {
    fn default() -> Path<'a> { Path(Cow::Borrowed(unsafe { CStr::from_ptr(b"/\0".as_ptr() as *const c_char)})) }
}

/// A wrapper around a string that is guaranteed to be
/// a valid D-Bus member, i e, a signal or method name.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Member<'a>(Cow<'a, CStr>);

cstring_wrapper!(Member, dbus_validate_member);

/// A wrapper around a string that is guaranteed to be
/// a valid D-Bus interface name.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Interface<'a>(Cow<'a, CStr>);

cstring_wrapper!(Interface, dbus_validate_interface);

/// A wrapper around a string that is guaranteed to be
/// a valid D-Bus bus name.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct BusName<'a>(Cow<'a, CStr>);

cstring_wrapper!(BusName, dbus_validate_bus_name);

/// A wrapper around a string that is guaranteed to be
/// a valid D-Bus bus name.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct ErrorName<'a>(Cow<'a, CStr>);

cstring_wrapper!(ErrorName, dbus_validate_error_name);

#[test]
fn some_path() {
    use std::os::raw::c_char;
    let p1: Path = "/valid".into();
    let p2 = Path::new("##invalid##");
    assert_eq!(p1, Path(Cow::Borrowed(unsafe { CStr::from_ptr(b"/valid\0".as_ptr() as *const c_char) })));
    #[cfg(not(feature = "no-string-validation"))]
    assert_eq!(p2, Err("Object path was not valid: '##invalid##'".into()));
    #[cfg(feature = "no-string-validation")]
    assert_eq!(p2, Ok(Path(Cow::Borrowed(unsafe { CStr::from_ptr(b"##invalid##\0".as_ptr() as *const c_char) }))));
}

#[test]
fn make_sig() {
    assert_eq!(&*Signature::make::<(&str, u8)>(), "(sy)");
}
<commit_msg>Fix compilation errors on platforms with unsigned chars<commit_after>// CString wrappers.

use std::{str, fmt, ops, default, hash};
use std::ffi::{CStr, CString};
use std::borrow::Cow;
use std::os::raw::c_char;

#[cfg(not(feature = "no-string-validation"))]
use Error;
#[cfg(not(feature = "no-string-validation"))]
use ffi;

macro_rules! cstring_wrapper {
    ($t: ident, $s: ident) => {

impl<'m> $t<'m> {
    #[cfg(feature = "no-string-validation")]
    fn check_valid(_: *const c_char) -> Result<(), String> { Ok(()) }

    #[cfg(not(feature = "no-string-validation"))]
    fn check_valid(c: *const c_char) -> Result<(), String> {
        let mut e = Error::empty();
        let b = unsafe { ffi::$s(c, e.get_mut()) };
        if b != 0 { Ok(()) } else { Err(e.message().unwrap().into()) }
    }

    /// Creates a new instance of this struct.
    ///
    /// Note: If the no-string-validation feature is activated, this string
    /// will not be checked for conformance with the D-Bus specification.
    pub fn new<S: Into<Vec<u8>>>(s: S) -> Result<$t<'m>, String> {
        let c = try!(CString::new(s).map_err(|e| e.to_string()));
        $t::check_valid(c.as_ptr()).map(|_| $t(Cow::Owned(c)))
    }

    /// Creates a new instance of this struct. If you end it with \0,
    /// it can borrow the slice without extra allocation.
    ///
    /// Note: If the no-string-validation feature is activated, this string
    /// will not be checked for conformance with the D-Bus specification.
    pub fn from_slice(s: &'m [u8]) -> Result<$t<'m>, String> {
        if s.len() == 0 || s[s.len()-1] != 0 { return $t::new(s) };
        $t::check_valid(s.as_ptr() as *const c_char).map(|_| {
            let c = unsafe { CStr::from_ptr(s.as_ptr() as *const c_char) };
            $t(Cow::Borrowed(c))
        })
    }

    /// This function creates a new instance of this struct, without checking.
    /// It's up to you to guarantee that s ends with a \0 and is valid.
    pub unsafe fn from_slice_unchecked(s: &'m [u8]) -> $t<'m> {
        debug_assert!(s[s.len()-1] == 0);
        $t(Cow::Borrowed(CStr::from_ptr(s.as_ptr() as *const c_char)))
    }

    /// View this struct as a CStr.
    pub fn as_cstr(&self) -> &CStr { &self.0 }

    /// Makes sure this string does not contain borrows.
    pub fn into_static(self) -> $t<'static> {
        $t(Cow::Owned(self.0.into_owned()))
    }
}

/*
/// #Panics
///
/// If given string is not valid.
/// impl<S: Into<Vec<u8>>> From<S> for $t { fn from(s: S) -> $t { $t::new(s).unwrap() } }
*/

/// #Panics
///
/// If given string is not valid.
impl<'m> From<String> for $t<'m> { fn from(s: String) -> $t<'m> { $t::new(s).unwrap() } }

/// #Panics
///
/// If given string is not valid.
impl<'m> From<&'m String> for $t<'m> { fn from(s: &'m String) -> $t<'m> { $t::from_slice(s.as_bytes()).unwrap() } }

/// #Panics
///
/// If given string is not valid.
impl<'m> From<&'m str> for $t<'m> { fn from(s: &'m str) -> $t<'m> { $t::from_slice(s.as_bytes()).unwrap() } }

/// #Panics
///
/// If given string is not valid.
impl<'m> From<Cow<'m, str>> for $t<'m> {
    fn from(s: Cow<'m, str>) -> $t<'m> {
        match s {
            Cow::Borrowed(z) => z.into(),
            Cow::Owned(z) => z.into(),
        }
    }
}

impl<'m> ops::Deref for $t<'m> {
    type Target = str;
    fn deref(&self) -> &str { str::from_utf8(self.0.to_bytes()).unwrap() }
}

impl<'m> fmt::Display for $t<'m> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s: &str = &self;
        (&s as &fmt::Display).fmt(f)
    }
}

impl<'m> AsRef<CStr> for $t<'m> {
    fn as_ref(&self) -> &CStr { &self.0 }
}

impl<'m> hash::Hash for $t<'m> {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.0.hash(state);
    }
}

}}

/// A wrapper around a string that is guaranteed to be
/// a valid (single) D-Bus type signature. Supersedes TypeSig.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Signature<'a>(Cow<'a, CStr>);

cstring_wrapper!(Signature, dbus_signature_validate_single);

impl Signature<'static> {
    /// Makes a D-Bus signature that corresponds to A.
    pub fn make<A: super::arg::Arg>() -> Signature<'static> { A::signature() }
}

/// A wrapper around a string that is guaranteed to be
/// a valid D-Bus object path.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Path<'a>(Cow<'a, CStr>);

cstring_wrapper!(Path, dbus_validate_path);

// This is needed so one can make arrays of paths easily
impl<'a> default::Default for Path<'a> {
    fn default() -> Path<'a> { Path(Cow::Borrowed(unsafe { CStr::from_ptr(b"/\0".as_ptr() as *const c_char)})) }
}

/// A wrapper around a string that is guaranteed to be
/// a valid D-Bus member, i e, a signal or method name.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Member<'a>(Cow<'a, CStr>);

cstring_wrapper!(Member, dbus_validate_member);

/// A wrapper around a string that is guaranteed to be
/// a valid D-Bus interface name.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Interface<'a>(Cow<'a, CStr>);

cstring_wrapper!(Interface, dbus_validate_interface);

/// A wrapper around a string that is guaranteed to be
/// a valid D-Bus bus name.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct BusName<'a>(Cow<'a, CStr>);

cstring_wrapper!(BusName, dbus_validate_bus_name);

/// A wrapper around a string that is guaranteed to be
/// a valid D-Bus bus name.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct ErrorName<'a>(Cow<'a, CStr>);

cstring_wrapper!(ErrorName, dbus_validate_error_name);

#[test]
fn some_path() {
    use std::os::raw::c_char;
    let p1: Path = "/valid".into();
    let p2 = Path::new("##invalid##");
    assert_eq!(p1, Path(Cow::Borrowed(unsafe { CStr::from_ptr(b"/valid\0".as_ptr() as *const c_char) })));
    #[cfg(not(feature = "no-string-validation"))]
    assert_eq!(p2, Err("Object path was not valid: '##invalid##'".into()));
    #[cfg(feature = "no-string-validation")]
    assert_eq!(p2, Ok(Path(Cow::Borrowed(unsafe { CStr::from_ptr(b"##invalid##\0".as_ptr() as *const c_char) }))));
}

#[test]
fn make_sig() {
    assert_eq!(&*Signature::make::<(&str, u8)>(), "(sy)");
}
<|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>,
    {
    }
}
<commit_msg>Test the comment behavior<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 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. -->");
    }
}
<|endoftext|>


<commit_before>extern crate pb_rs;
extern crate prost_build;
extern crate protobuf_codegen_pure;

use pb_rs::types::{RpcService, Config, FileDescriptor};
use std::path::{Path, PathBuf};
use std::{env, fs};
use std::io::Write;

fn generate_rpc_add_1_test<W: Write + ?Sized>(rpc: &RpcService, w: &mut W) -> Result<(), pb_rs::errors::Error> {
    /* Example:
        trait <service> {
            fn <func>(&self, arg: &<arg>) -> Result<<ret>, failure::Error>;
        }
    */

    writeln!(w, "\npub trait {SERVICE} {{", SERVICE = rpc.service_name)?;
    for func in rpc.functions.iter() {
        writeln!(w, "   fn {FUNC}(&self, arg: &{ARG}) -> std::result::Result<{RET}, failure::Error>;",
            FUNC = func.name, ARG = func.arg, RET = func.ret)?;
    }
    writeln!(w, "}}\n")?;

    Ok(())
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();

    // protobuf
    protobuf_codegen_pure::run(protobuf_codegen_pure::Args {
        out_dir: "src",
        input: &["src/perftest_data.proto"],
        includes: &["src"],
        customize: protobuf_codegen_pure::Customize {
            ..Default::default()
        },
    }).expect("protoc");

    // quick-protobuf
    let quick_dest = Path::new(&out_dir).join("perftest_data_quick.rs");
    let config = Config {
        in_file: PathBuf::from("src/perftest_data.proto"),
        out_file: quick_dest,
        single_module: true,
        import_search_path: vec![PathBuf::from("src")],
        no_output: false,
        error_cycle: false,
        headers: false,
        dont_use_cow: false,
        custom_struct_derive: vec![],
        custom_rpc_generator: Box::new(|rpc, writer| generate_rpc_add_1_test(rpc, writer))
    };
    FileDescriptor::write_proto(&config).unwrap();

    // prost
    let old = ::std::env::var("OUT_DIR");
    env::set_var("OUT_DIR", ".");
    prost_build::compile_protos(&["src/perftest_data.proto"], &["src"]).unwrap();
    let _ = old.map(|val| env::set_var("OUT_DIR", &val));
    fs::rename("perftest_data.rs", "src/perftest_data_prost.rs").unwrap();
}
<commit_msg>Added custom_includes to Config generation<commit_after>extern crate pb_rs;
extern crate prost_build;
extern crate protobuf_codegen_pure;

use pb_rs::types::{RpcService, Config, FileDescriptor};
use std::path::{Path, PathBuf};
use std::{env, fs};
use std::io::Write;

fn generate_rpc_test<W: Write + ?Sized>(rpc: &RpcService, w: &mut W) -> Result<(), pb_rs::errors::Error> {
    /* Example:
        trait <service> {
            fn <func>(&self, arg: &<arg>) -> Result<<ret>, failure::Error>;
        }
    */

    writeln!(w, "\npub trait {SERVICE} {{", SERVICE = rpc.service_name)?;
    for func in rpc.functions.iter() {
        writeln!(w, "   fn {FUNC}(&self, arg: &{ARG}) -> std::result::Result<{RET}, failure::Error>;",
            FUNC = func.name, ARG = func.arg, RET = func.ret)?;
    }
    writeln!(w, "}}\n")?;

    Ok(())
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();

    // protobuf
    protobuf_codegen_pure::run(protobuf_codegen_pure::Args {
        out_dir: "src",
        input: &["src/perftest_data.proto"],
        includes: &["src"],
        customize: protobuf_codegen_pure::Customize {
            ..Default::default()
        },
    }).expect("protoc");

    // quick-protobuf
    let quick_dest = Path::new(&out_dir).join("perftest_data_quick.rs");
    let config = Config {
        in_file: PathBuf::from("src/perftest_data.proto"),
        out_file: quick_dest,
        single_module: true,
        import_search_path: vec![PathBuf::from("src")],
        no_output: false,
        error_cycle: false,
        headers: false,
        dont_use_cow: false,
        custom_struct_derive: vec![],
        custom_rpc_generator: Box::new(|rpc, writer| generate_rpc_test(rpc, writer)),
        custom_includes: Vec::new()
    };
    FileDescriptor::write_proto(&config).unwrap();

    // prost
    let old = ::std::env::var("OUT_DIR");
    env::set_var("OUT_DIR", ".");
    prost_build::compile_protos(&["src/perftest_data.proto"], &["src"]).unwrap();
    let _ = old.map(|val| env::set_var("OUT_DIR", &val));
    fs::rename("perftest_data.rs", "src/perftest_data_prost.rs").unwrap();
}
<|endoftext|>


<commit_before>//! Module with system specific types.
//!
//! `Event`: a type alias for the system specific event, e.g.
//!          `kevent` or `epoll_event`.
//! `event`: a module with various helper functions for `Event`, see
//!          `crate::event::Event` for the required functions.

#[cfg(unix)]
pub use self::unix::{
    event, Event, Events, Selector, SocketAddr, SourceFd, TcpListener, TcpStream, UdpSocket,
    UnixDatagram, UnixListener, UnixStream, Waker,
};

#[cfg(unix)]
mod unix;

#[cfg(windows)]
pub use self::windows::{event, Event, Events, Selector, TcpListener, TcpStream, UdpSocket, Waker};

#[cfg(windows)]
mod windows;
<commit_msg>Document require types in sys module<commit_after>//! Module with system specific types.
//!
//! Required types:
//!
//! * `Event`: a type alias for the system specific event, e.g. `kevent` or
//!            `epoll_event`.
//! * `event`: a module with various helper functions for `Event`, see
//!            [`crate::event::Event`] for the required functions.
//! * `Events`: collection of `Event`s, see [`crate::Events`].
//! * `Selector`: selector used to register event sources and poll for events,
//!               see [`crate::Poll`] and [`crate::Registry`] for required
//!               methods.
//! * `TcpListener`, `TcpStream` and `UdpSocket`: see [`crate::net`] module.
//! * `Waker`: see [`crate::Waker`].

#[cfg(unix)]
pub use self::unix::{
    event, Event, Events, Selector, SocketAddr, SourceFd, TcpListener, TcpStream, UdpSocket,
    UnixDatagram, UnixListener, UnixStream, Waker,
};

#[cfg(unix)]
mod unix;

#[cfg(windows)]
pub use self::windows::{event, Event, Events, Selector, TcpListener, TcpStream, UdpSocket, Waker};

#[cfg(windows)]
mod windows;
<|endoftext|>


<commit_before>use std::u16;
use std::net::{TcpStream};
use std::io::{Write, Read, Result};
use std::time::Duration;
use std::process::{Command, Child, Stdio};
use std::thread;

use byteorder::{BigEndian, WriteBytesExt};
use bincode::rustc_serialize::{encode, decode};
use bincode::SizeLimit;

use {FunctionCode, ModbusResult, ExceptionCode, BitValue};

const PROTOCOL_MODBUS_TCP: u16 = 0x0000;
const MODBUS_TCP_DEFAULT_PORT: u16 = 502;

/// Context object which holds state for all modbus operations.
pub struct Ctx {
    tid: u16,
    uid: u8,
    stream: TcpStream
}

impl Ctx {
    /// Create a new context `Ctx` context object and connect it to `addr` on modbus-tcp default
    /// port (502)
    pub fn new(addr: &str) -> Result<Ctx> {
        Self::new_with_port(addr, MODBUS_TCP_DEFAULT_PORT)
    }

    /// Create a new context `Ctx` context object and connect it to `addr` on port `port`
    pub fn new_with_port(addr: &str, port: u16) -> Result<Ctx> {
        match TcpStream::connect((addr, port)) {
            Ok(s) => {
                // set some sane tcp socket options
                let t = Duration::from_secs(5);
                try!(s.set_read_timeout(Some(t)));
                try!(s.set_write_timeout(Some(t)));
//                try!(s.set_nodelay(true));
//                try!(s.set_keepalive(None));
                Ok(Ctx { tid: 0, uid: 0, stream: s })
            }
            Err(e) => Err(e)
        }
    }

    /// Create a new transaction Id, incrementing the previous one.
    ///
    /// The Id is wrapping around if the Id reaches `u16::MAX`.
    fn new_tid(self: &mut Self) -> u16 {
        // wrap around or increment
        if self.tid  < u16::MAX {
            self.tid += 1u16;
        } else {
            self.tid = 0u16;
        }
        self.tid
    }
}

#[derive(RustcEncodable, RustcDecodable)]
#[repr(packed)]
struct Packet {
    tid: u16,
    pid: u16,
    len: u16,
    uid: u8,
    fun: u8,
    addr: u16,
}

impl Packet {
    fn new(ctx: &mut Ctx, fun: FunctionCode, addr: u16) -> Packet {
        Packet {
            tid: ctx.new_tid(),
            pid: PROTOCOL_MODBUS_TCP,
            len: 4u16,
            uid: ctx.uid,
            fun: fun as u8,
            addr: addr,
        }
    }

    fn encode_with_data(self: &mut Self, data: &mut Vec<u8>) -> Vec<u8>
    {
        self.len += data.len() as u16;
        let mut pack: Vec<u8> = encode(self, SizeLimit::Infinite).unwrap();
        pack.append(data);
        pack
    }
}

fn write_single(ctx: &mut Ctx, fun: FunctionCode, addr: u16, value: u16) -> ModbusResult
{
    let mut data = vec![];
    data.write_u16::<BigEndian>(value).unwrap();
    let pack = Packet::new(ctx, fun, addr).encode_with_data(&mut data);
    println!("{:?}", pack);
    match ctx.stream.write_all(&pack) {
        Ok(_)  => {
            let mut in_buf = Vec::new();
            ctx.stream.read_to_end(&mut in_buf);
            Ok(ExceptionCode::Acknowledge)
        }
        Err(e) => panic!("Error sending data: {}", e)
    }

}

pub fn write_single_coil(ctx: &mut Ctx, addr: u16, v: BitValue) -> ModbusResult
{
    write_single(ctx, FunctionCode::WriteSingleCoil, addr, v as u16)
}

#[cfg(test)]
fn start_dummy_server(port: &str) -> Child {
    Command::new("./test/diagslave")
                     .arg("-m").arg("tcp")
                     .arg("-p").arg(port)
                     .stdout(Stdio::null())
                     .spawn()
                     .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) })
}

#[test]
fn test_packet_tid_creation() {
    let mut server = start_dummy_server("2222");
    thread::sleep_ms(500);
    let mut ctx = Ctx::new_with_port("127.0.0.1", 2222).unwrap();
    let mut hd = Packet::new(&mut ctx, FunctionCode::ReadCoils, 0);
    assert!(hd.tid == 1u16);
    hd = Packet::new(&mut ctx, FunctionCode::ReadCoils, 0);
    assert!(hd.tid == 2u16);
    ctx.tid = u16::MAX;
    hd = Packet::new(&mut ctx, FunctionCode::ReadCoils, 0);
    assert!(hd.tid == 0);
    server.kill();
}

#[test]
fn test_write_single_coil() {
    let mut server = start_dummy_server("2223");
    thread::sleep_ms(500);
    let mut ctx = Ctx::new_with_port("127.0.0.1", 2223).unwrap();
    assert!(write_single_coil(&mut ctx, 0, BitValue::On).is_ok());
    server.kill();
}
<commit_msg>Add automatic server cleanup via `impl Drop`<commit_after>use std::u16;
use std::net::{TcpStream};
use std::io::{Write, Read, Result};
use std::time::Duration;
use std::process::{Command, Child, Stdio};
use std::thread;

use byteorder::{BigEndian, WriteBytesExt};
use bincode::rustc_serialize::{encode, decode};
use bincode::SizeLimit;

use {FunctionCode, ModbusResult, ExceptionCode, BitValue};

const PROTOCOL_MODBUS_TCP: u16 = 0x0000;
const MODBUS_TCP_DEFAULT_PORT: u16 = 502;

/// Context object which holds state for all modbus operations.
pub struct Ctx {
    tid: u16,
    uid: u8,
    stream: TcpStream
}

impl Ctx {
    /// Create a new context `Ctx` context object and connect it to `addr` on modbus-tcp default
    /// port (502)
    pub fn new(addr: &str) -> Result<Ctx> {
        Self::new_with_port(addr, MODBUS_TCP_DEFAULT_PORT)
    }

    /// Create a new context `Ctx` context object and connect it to `addr` on port `port`
    pub fn new_with_port(addr: &str, port: u16) -> Result<Ctx> {
        match TcpStream::connect((addr, port)) {
            Ok(s) => {
                // set some sane tcp socket options
                let t = Duration::from_secs(5);
                try!(s.set_read_timeout(Some(t)));
                try!(s.set_write_timeout(Some(t)));
//                try!(s.set_nodelay(true));
//                try!(s.set_keepalive(None));
                Ok(Ctx { tid: 0, uid: 0, stream: s })
            }
            Err(e) => Err(e)
        }
    }

    /// Create a new transaction Id, incrementing the previous one.
    ///
    /// The Id is wrapping around if the Id reaches `u16::MAX`.
    fn new_tid(self: &mut Self) -> u16 {
        // wrap around or increment
        if self.tid  < u16::MAX {
            self.tid += 1u16;
        } else {
            self.tid = 0u16;
        }
        self.tid
    }
}

#[derive(RustcEncodable, RustcDecodable)]
#[repr(packed)]
struct Packet {
    tid: u16,
    pid: u16,
    len: u16,
    uid: u8,
    fun: u8,
    addr: u16,
}

impl Packet {
    fn new(ctx: &mut Ctx, fun: FunctionCode, addr: u16) -> Packet {
        Packet {
            tid: ctx.new_tid(),
            pid: PROTOCOL_MODBUS_TCP,
            len: 4u16,
            uid: ctx.uid,
            fun: fun as u8,
            addr: addr,
        }
    }

    fn encode_with_data(self: &mut Self, data: &mut Vec<u8>) -> Vec<u8>
    {
        self.len += data.len() as u16;
        let mut pack: Vec<u8> = encode(self, SizeLimit::Infinite).unwrap();
        pack.append(data);
        pack
    }
}

fn write_single(ctx: &mut Ctx, fun: FunctionCode, addr: u16, value: u16) -> ModbusResult
{
    let mut data = vec![];
    data.write_u16::<BigEndian>(value).unwrap();
    let pack = Packet::new(ctx, fun, addr).encode_with_data(&mut data);
    println!("{:?}", pack);
    match ctx.stream.write_all(&pack) {
        Ok(_)  => {
            let mut in_buf = Vec::new();
            ctx.stream.read_to_end(&mut in_buf);
            Ok(ExceptionCode::Acknowledge)
        }
        Err(e) => panic!("Error sending data: {}", e)
    }

}

pub fn write_single_coil(ctx: &mut Ctx, addr: u16, v: BitValue) -> ModbusResult
{
    write_single(ctx, FunctionCode::WriteSingleCoil, addr, v as u16)
}

#[cfg(test)]
fn start_dummy_server(port: &str) -> Result<ChildKiller> {
    Ok(ChildKiller(Command::new("./test/diagslave")
                        .arg("-m").arg("tcp")
                        .arg("-p").arg(port)
                        .stdout(Stdio::null())
                        .spawn()
                        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) })))
}

#[cfg(test)]
struct ChildKiller(Child);

#[cfg(test)]
impl Drop for ChildKiller {
    fn drop(&mut self) {
        self.0.kill().unwrap();
    }
}

#[test]
fn test_packet_tid_creation() {
    let _s = start_dummy_server("2222");
    thread::sleep_ms(500);
    let mut ctx = Ctx::new_with_port("127.0.0.1", 2222).unwrap();
    let mut hd = Packet::new(&mut ctx, FunctionCode::ReadCoils, 0);
    assert!(hd.tid == 1u16);
    hd = Packet::new(&mut ctx, FunctionCode::ReadCoils, 0);
    assert!(hd.tid == 2u16);
    ctx.tid = u16::MAX;
    hd = Packet::new(&mut ctx, FunctionCode::ReadCoils, 0);
    assert!(hd.tid == 0);
}

#[test]
fn test_write_single_coil() {
    let _s = start_dummy_server("2223");
    thread::sleep_ms(500);
    let mut ctx = Ctx::new_with_port("127.0.0.1", 2223).unwrap();
    assert!(write_single_coil(&mut ctx, 0, BitValue::On).is_ok());
}
<|endoftext|>


<commit_before>//! **Plexus** is a library for polygonal mesh processing.
//!
//! Please note that versions in the `0.0.*` series are experimental and
//! unstable! Use exact version constraints when specifying a dependency to
//! avoid spurious breakage.

// TODO: Documentation comments include static image content from the GitHub
//       repository. This is fragile and difficult to maintain. Use a mechanism
//       provided by rustdoc or doxidize for this instead.

use std::fmt::Debug;

// Feature modules. These are empty unless features are enabled.
mod cgmath;
mod mint;
mod nalgebra;

pub mod buffer;
pub mod encoding;
pub mod graph;
pub mod index;
pub mod primitive;

pub use theon::{AsPosition, Position};
pub use typenum::{U2, U3, U4};

use crate::graph::PayloadBinding;

pub mod prelude {
    //! Re-exports commonly used types and traits.
    //!
    //! Importing the contents of this module is recommended when working with
    //! generators and iterator expressions, as those operations are expressed
    //! mostly through traits.
    //!
    //! # Traits
    //!
    //! This module re-exports numerous traits. Traits from the `primitive`
    //! module for generating and decomposing iterators over topological data
    //! (e.g., `Trigon`, `Tetragon`, etc.) are re-exported so that functions in
    //! iterator expressions can be used without lengthy imports.
    //!
    //! Basic traits for (de)constructing `MeshBuffer`s and `MeshGraph`s are
    //! also re-exported. These traits allow mesh types to be constructed from
    //! raw buffers and buffers to be re-indexed.
    //!
    //! # Types
    //!
    //! The `Selector` enum and its variants are re-exported for convenience.
    //! `Selector` is often used when mutating `MeshGraph`s.

    pub use crate::buffer::{IntoFlatIndex as _, IntoStructuredIndex as _};
    #[cfg(feature = "encoding-ply")]
    pub use crate::encoding::ply::{FromPly as _, ToPly as _};
    pub use crate::graph::Selector;
    pub use crate::index::{CollectWithIndexer as _, IndexVertices as _};
    pub use crate::primitive::decompose::{
        Edges as _, IntoEdges as _, IntoSubdivisions as _, IntoTetrahedrons as _, IntoTrigons as _,
        IntoVertices as _, Subdivide as _, Tetrahedrons as _, Triangulate as _, Vertices as _,
    };
    pub use crate::primitive::generate::Generator as _;
    pub use crate::primitive::{MapVertices as _, Topological as _};
    pub use crate::IteratorExt as _;
    pub use crate::{
        FromGeometry as _, FromRawBuffers as _, FromRawBuffersWithArity as _, IntoGeometry as _,
    };

    pub use Selector::ByIndex;
    pub use Selector::ByKey;
}

pub enum Arity {
    Uniform(usize),
    NonUniform(usize, usize),
}

pub trait FromRawBuffers<N, G>: Sized {
    type Error: Debug;

    fn from_raw_buffers<I, J>(indices: I, vertices: J) -> Result<Self, Self::Error>
    where
        I: IntoIterator<Item = N>,
        J: IntoIterator<Item = G>;
}

pub trait FromRawBuffersWithArity<N, G>: Sized {
    type Error: Debug;

    fn from_raw_buffers_with_arity<I, J>(
        indices: I,
        vertices: J,
        arity: usize,
    ) -> Result<Self, Self::Error>
    where
        I: IntoIterator<Item = N>,
        J: IntoIterator<Item = G>;
}

pub trait FromGeometry<T> {
    fn from_geometry(other: T) -> Self;
}

impl<T> FromGeometry<T> for T {
    fn from_geometry(other: T) -> Self {
        other
    }
}

impl<T> FromGeometry<()> for T
where
    T: UnitGeometry,
{
    fn from_geometry(_: ()) -> Self {
        T::default()
    }
}

pub trait UnitGeometry: Default {}

pub trait IntoGeometry<T> {
    fn into_geometry(self) -> T;
}

impl<T, U> IntoGeometry<U> for T
where
    U: FromGeometry<T>,
{
    fn into_geometry(self) -> U {
        U::from_geometry(self)
    }
}

/// Extension methods for types implementing `Iterator`.
pub trait IteratorExt: Iterator + Sized {
    /// Provides an iterator over a window of duplets that includes the first
    /// value in the sequence at the beginning and end of the iteration.
    ///
    /// Given a collection of ordered elements $\\{a, b, c\\}$, this iterator
    /// yeilds the ordered items $\\{(a, b), (b, c), (c, a)\\}$.
    fn perimeter(self) -> Perimeter<Self>
    where
        Self::Item: Clone,
    {
        Perimeter::new(self)
    }

    /// Maps an iterator over topological views to the keys of those views.
    ///
    /// It is often useful to examine or collect the keys of views over a
    /// `MeshGraph`. This iterator avoids redundant use of `map` to extract
    /// keys.
    ///
    /// # Examples
    ///
    /// Collecting keys of faces before a topological mutation:
    ///
    /// ```rust
    /// # extern crate decorum;
    /// # extern crate nalgebra;
    /// # extern crate plexus;
    /// #
    /// use decorum::R64;
    /// use nalgebra::Point3;
    /// use plexus::graph::MeshGraph;
    /// use plexus::prelude::*;
    /// use plexus::primitive::generate::Position;
    /// use plexus::primitive::sphere::UvSphere;
    ///
    /// type E3 = Point3<R64>;
    ///
    /// # fn main() {
    /// let mut graph = UvSphere::new(6, 6)
    ///     .polygons::<Position<E3>>()
    ///     .collect::<MeshGraph<E3>>();
    ///
    /// let keys = graph
    ///     .faces()
    ///     .filter(|face| face.arity() > 3)
    ///     .keys()
    ///     .collect::<Vec<_>>();
    /// for key in keys {
    ///     graph.face_mut(key).unwrap().poke_with_offset(0.5);
    /// }
    /// # }
    /// ```
    fn keys(self) -> Keys<Self>
    where
        Self::Item: PayloadBinding,
    {
        Keys::new(self)
    }
}

impl<I> IteratorExt for I where I: Iterator {}

/// Iterator that produces a window of duplets over its input.
///
/// The duplets produced include the first value in the input sequence at both
/// the beginning and end of the iteration, forming a perimeter. Given a
/// collection of ordered elements $\\{a, b, c\\}$, this iterator yields the
/// ordered items $\\{(a, b), (b, c), (c, a)\\}$.
pub struct Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    input: I,
    first: Option<I::Item>,
    previous: Option<I::Item>,
}

impl<I> Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    fn new(mut input: I) -> Self {
        let first = input.next();
        let previous = first.clone();
        Perimeter {
            input,
            first,
            previous,
        }
    }
}

impl<I> Iterator for Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    type Item = (I::Item, I::Item);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.input.next();
        match (self.previous.clone(), next.or_else(|| self.first.take())) {
            (Some(a), Some(b)) => {
                self.previous = Some(b.clone());
                Some((a, b))
            }
            _ => None,
        }
    }

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

pub struct Keys<I>
where
    I: Iterator,
    I::Item: PayloadBinding,
{
    input: I,
}

impl<I> Keys<I>
where
    I: Iterator,
    I::Item: PayloadBinding,
{
    fn new(input: I) -> Self {
        Keys { input }
    }
}

impl<I> Iterator for Keys<I>
where
    I: Iterator,
    I::Item: PayloadBinding,
{
    type Item = <I::Item as PayloadBinding>::Key;

    fn next(&mut self) -> Option<Self::Item> {
        self.input.next().map(|view| view.key())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}
<commit_msg>Remove encoding traits from the prelude.<commit_after>//! **Plexus** is a library for polygonal mesh processing.
//!
//! Please note that versions in the `0.0.*` series are experimental and
//! unstable! Use exact version constraints when specifying a dependency to
//! avoid spurious breakage.

// TODO: Documentation comments include static image content from the GitHub
//       repository. This is fragile and difficult to maintain. Use a mechanism
//       provided by rustdoc or doxidize for this instead.

use std::fmt::Debug;

// Feature modules. These are empty unless features are enabled.
mod cgmath;
mod mint;
mod nalgebra;

pub mod buffer;
pub mod encoding;
pub mod graph;
pub mod index;
pub mod primitive;

pub use theon::{AsPosition, Position};
pub use typenum::{U2, U3, U4};

use crate::graph::PayloadBinding;

pub mod prelude {
    //! Re-exports commonly used types and traits.
    //!
    //! Importing the contents of this module is recommended when working with
    //! generators and iterator expressions, as those operations are expressed
    //! mostly through traits.
    //!
    //! # Traits
    //!
    //! This module re-exports numerous traits. Traits from the `primitive`
    //! module for generating and decomposing iterators over topological data
    //! (e.g., `Trigon`, `Tetragon`, etc.) are re-exported so that functions in
    //! iterator expressions can be used without lengthy imports.
    //!
    //! Basic traits for (de)constructing `MeshBuffer`s and `MeshGraph`s are
    //! also re-exported. These traits allow mesh types to be constructed from
    //! raw buffers and buffers to be re-indexed.
    //!
    //! # Types
    //!
    //! The `Selector` enum and its variants are re-exported for convenience.
    //! `Selector` is often used when mutating `MeshGraph`s.

    pub use crate::buffer::{IntoFlatIndex as _, IntoStructuredIndex as _};
    pub use crate::graph::Selector;
    pub use crate::index::{CollectWithIndexer as _, IndexVertices as _};
    pub use crate::primitive::decompose::{
        Edges as _, IntoEdges as _, IntoSubdivisions as _, IntoTetrahedrons as _, IntoTrigons as _,
        IntoVertices as _, Subdivide as _, Tetrahedrons as _, Triangulate as _, Vertices as _,
    };
    pub use crate::primitive::generate::Generator as _;
    pub use crate::primitive::{MapVertices as _, Topological as _};
    pub use crate::IteratorExt as _;
    pub use crate::{
        FromGeometry as _, FromRawBuffers as _, FromRawBuffersWithArity as _, IntoGeometry as _,
    };

    pub use Selector::ByIndex;
    pub use Selector::ByKey;
}

pub enum Arity {
    Uniform(usize),
    NonUniform(usize, usize),
}

pub trait FromRawBuffers<N, G>: Sized {
    type Error: Debug;

    fn from_raw_buffers<I, J>(indices: I, vertices: J) -> Result<Self, Self::Error>
    where
        I: IntoIterator<Item = N>,
        J: IntoIterator<Item = G>;
}

pub trait FromRawBuffersWithArity<N, G>: Sized {
    type Error: Debug;

    fn from_raw_buffers_with_arity<I, J>(
        indices: I,
        vertices: J,
        arity: usize,
    ) -> Result<Self, Self::Error>
    where
        I: IntoIterator<Item = N>,
        J: IntoIterator<Item = G>;
}

pub trait FromGeometry<T> {
    fn from_geometry(other: T) -> Self;
}

impl<T> FromGeometry<T> for T {
    fn from_geometry(other: T) -> Self {
        other
    }
}

impl<T> FromGeometry<()> for T
where
    T: UnitGeometry,
{
    fn from_geometry(_: ()) -> Self {
        T::default()
    }
}

pub trait UnitGeometry: Default {}

pub trait IntoGeometry<T> {
    fn into_geometry(self) -> T;
}

impl<T, U> IntoGeometry<U> for T
where
    U: FromGeometry<T>,
{
    fn into_geometry(self) -> U {
        U::from_geometry(self)
    }
}

/// Extension methods for types implementing `Iterator`.
pub trait IteratorExt: Iterator + Sized {
    /// Provides an iterator over a window of duplets that includes the first
    /// value in the sequence at the beginning and end of the iteration.
    ///
    /// Given a collection of ordered elements $\\{a, b, c\\}$, this iterator
    /// yeilds the ordered items $\\{(a, b), (b, c), (c, a)\\}$.
    fn perimeter(self) -> Perimeter<Self>
    where
        Self::Item: Clone,
    {
        Perimeter::new(self)
    }

    /// Maps an iterator over topological views to the keys of those views.
    ///
    /// It is often useful to examine or collect the keys of views over a
    /// `MeshGraph`. This iterator avoids redundant use of `map` to extract
    /// keys.
    ///
    /// # Examples
    ///
    /// Collecting keys of faces before a topological mutation:
    ///
    /// ```rust
    /// # extern crate decorum;
    /// # extern crate nalgebra;
    /// # extern crate plexus;
    /// #
    /// use decorum::R64;
    /// use nalgebra::Point3;
    /// use plexus::graph::MeshGraph;
    /// use plexus::prelude::*;
    /// use plexus::primitive::generate::Position;
    /// use plexus::primitive::sphere::UvSphere;
    ///
    /// type E3 = Point3<R64>;
    ///
    /// # fn main() {
    /// let mut graph = UvSphere::new(6, 6)
    ///     .polygons::<Position<E3>>()
    ///     .collect::<MeshGraph<E3>>();
    ///
    /// let keys = graph
    ///     .faces()
    ///     .filter(|face| face.arity() > 3)
    ///     .keys()
    ///     .collect::<Vec<_>>();
    /// for key in keys {
    ///     graph.face_mut(key).unwrap().poke_with_offset(0.5);
    /// }
    /// # }
    /// ```
    fn keys(self) -> Keys<Self>
    where
        Self::Item: PayloadBinding,
    {
        Keys::new(self)
    }
}

impl<I> IteratorExt for I where I: Iterator {}

/// Iterator that produces a window of duplets over its input.
///
/// The duplets produced include the first value in the input sequence at both
/// the beginning and end of the iteration, forming a perimeter. Given a
/// collection of ordered elements $\\{a, b, c\\}$, this iterator yields the
/// ordered items $\\{(a, b), (b, c), (c, a)\\}$.
pub struct Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    input: I,
    first: Option<I::Item>,
    previous: Option<I::Item>,
}

impl<I> Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    fn new(mut input: I) -> Self {
        let first = input.next();
        let previous = first.clone();
        Perimeter {
            input,
            first,
            previous,
        }
    }
}

impl<I> Iterator for Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    type Item = (I::Item, I::Item);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.input.next();
        match (self.previous.clone(), next.or_else(|| self.first.take())) {
            (Some(a), Some(b)) => {
                self.previous = Some(b.clone());
                Some((a, b))
            }
            _ => None,
        }
    }

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

pub struct Keys<I>
where
    I: Iterator,
    I::Item: PayloadBinding,
{
    input: I,
}

impl<I> Keys<I>
where
    I: Iterator,
    I::Item: PayloadBinding,
{
    fn new(input: I) -> Self {
        Keys { input }
    }
}

impl<I> Iterator for Keys<I>
where
    I: Iterator,
    I::Item: PayloadBinding,
{
    type Item = <I::Item as PayloadBinding>::Key;

    fn next(&mut self) -> Option<Self::Item> {
        self.input.next().map(|view| view.key())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use libc::{c_int, c_uint};

#[repr(C)]
#[derive(Copy)]
pub struct RawEvent {
    pub etype: u8,
    pub emod: u8,
    pub key: u16,
    pub ch: u32,
    pub w: i32,
    pub h: i32,
}

extern "C" {
    pub fn tb_init() -> c_int;
    pub fn tb_shutdown();

    pub fn tb_width() -> c_uint;
    pub fn tb_height() -> c_uint;

    pub fn tb_clear();
    pub fn tb_present();

    pub fn tb_set_cursor(cx: c_int, cy: c_int);
    pub fn tb_change_cell(x: c_uint, y: c_uint, ch: u32, fg: u16, bg: u16);

    pub fn tb_select_input_mode(mode: c_int) -> c_int;
    pub fn tb_set_clear_attributes(fg: u16, bg: u16);

    pub fn tb_peek_event(ev: *const ::RawEvent, timeout: c_uint) -> c_int;
    pub fn tb_poll_event(ev: *const ::RawEvent) -> c_int;
}
<commit_msg>Allow unstable<commit_after>#![allow(unstable)]
extern crate libc;

use libc::{c_int, c_uint};

#[repr(C)]
#[derive(Copy)]
pub struct RawEvent {
    pub etype: u8,
    pub emod: u8,
    pub key: u16,
    pub ch: u32,
    pub w: i32,
    pub h: i32,
}

extern "C" {
    pub fn tb_init() -> c_int;
    pub fn tb_shutdown();

    pub fn tb_width() -> c_uint;
    pub fn tb_height() -> c_uint;

    pub fn tb_clear();
    pub fn tb_present();

    pub fn tb_set_cursor(cx: c_int, cy: c_int);
    pub fn tb_change_cell(x: c_uint, y: c_uint, ch: u32, fg: u16, bg: u16);

    pub fn tb_select_input_mode(mode: c_int) -> c_int;
    pub fn tb_set_clear_attributes(fg: u16, bg: u16);

    pub fn tb_peek_event(ev: *const ::RawEvent, timeout: c_uint) -> c_int;
    pub fn tb_poll_event(ev: *const ::RawEvent) -> c_int;
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Syntax extension to generate FourCCs.

Once loaded, fourcc!() is called with a single 4-character string,
and an optional ident that is either `big`, `little`, or `target`.
The ident represents endianness, and specifies in which direction
the characters should be read. If the ident is omitted, it is assumed
to be `big`, i.e. left-to-right order. It returns a u32.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(syntax)]
extern crate fourcc;

fn main() {
    let val = fourcc!("\xC0\xFF\xEE!");
    assert_eq!(val, 0xC0FFEE21u32);
    let little_val = fourcc!("foo ", little);
    assert_eq!(little_val, 0x21EEFFC0u32);
}
 ```

# References

* [Wikipedia: FourCC](http://en.wikipedia.org/wiki/FourCC)

*/

#![crate_id = "fourcc#0.11-pre"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://static.rust-lang.org/doc/master")]

#![deny(deprecated_owned_vector)]
#![feature(macro_registrar, managed_boxes)]

extern crate syntax;

use syntax::ast;
use syntax::ast::Name;
use syntax::attr::contains;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::InternedString;

#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register(token::intern("fourcc"),
        NormalTT(~BasicMacroExpander {
            expander: expand_syntax_ext,
            span: None,
        },
        None));
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
    let (expr, endian) = parse_tts(cx, tts);

    let little = match endian {
        None => false,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "little" => true,
            "big" => false,
            "target" => target_endian_little(cx, sp),
            _ => {
                cx.span_err(span, "invalid endian directive in fourcc!");
                target_endian_little(cx, sp)
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(ref lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                if s.get().char_len() != 4 {
                    cx.span_err(expr.span, "string literal with len != 4 in fourcc!");
                }
                s
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in fourcc!");
                return base::DummyResult::expr(sp)
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in fourcc!");
            return base::DummyResult::expr(sp)
        }
    };

    let mut val = 0u32;
    for codepoint in s.get().chars().take(4) {
        let byte = if codepoint as u32 > 0xFF {
            cx.span_err(expr.span, "fourcc! literal character out of range 0-255");
            0u8
        } else {
            codepoint as u8
        };

        val = if little {
            (val >> 8) | ((byte as u32) << 24)
        } else {
            (val << 8) | (byte as u32)
        };
    }
    let e = cx.expr_lit(sp, ast::LitUint(val as u64, ast::TyU32));
    MacExpr::new(e)
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt, tts: &[ast::TokenTree]) -> (@ast::Expr, Option<Ident>) {
    let p = &mut parse::new_parser_from_tts(cx.parse_sess(),
                                            cx.cfg(),
                                            tts.iter()
                                               .map(|x| (*x).clone())
                                               .collect());
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

fn target_endian_little(cx: &ExtCtxt, sp: Span) -> bool {
    let meta = cx.meta_name_value(sp, InternedString::new("target_endian"),
        ast::LitStr(InternedString::new("little"), ast::CookedStr));
    contains(cx.cfg().as_slice(), meta)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<commit_msg>rustdoc: Migrate from sundown to hoedown<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Syntax extension to generate FourCCs.

Once loaded, fourcc!() is called with a single 4-character string,
and an optional ident that is either `big`, `little`, or `target`.
The ident represents endianness, and specifies in which direction
the characters should be read. If the ident is omitted, it is assumed
to be `big`, i.e. left-to-right order. It returns a u32.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(syntax)]
extern crate fourcc;

fn main() {
    let val = fourcc!("\xC0\xFF\xEE!");
    assert_eq!(val, 0xC0FFEE21u32);
    let little_val = fourcc!("foo ", little);
    assert_eq!(little_val, 0x21EEFFC0u32);
}
```

# References

* [Wikipedia: FourCC](http://en.wikipedia.org/wiki/FourCC)

*/

#![crate_id = "fourcc#0.11-pre"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://static.rust-lang.org/doc/master")]

#![deny(deprecated_owned_vector)]
#![feature(macro_registrar, managed_boxes)]

extern crate syntax;

use syntax::ast;
use syntax::ast::Name;
use syntax::attr::contains;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::InternedString;

#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register(token::intern("fourcc"),
        NormalTT(~BasicMacroExpander {
            expander: expand_syntax_ext,
            span: None,
        },
        None));
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
    let (expr, endian) = parse_tts(cx, tts);

    let little = match endian {
        None => false,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "little" => true,
            "big" => false,
            "target" => target_endian_little(cx, sp),
            _ => {
                cx.span_err(span, "invalid endian directive in fourcc!");
                target_endian_little(cx, sp)
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(ref lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                if s.get().char_len() != 4 {
                    cx.span_err(expr.span, "string literal with len != 4 in fourcc!");
                }
                s
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in fourcc!");
                return base::DummyResult::expr(sp)
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in fourcc!");
            return base::DummyResult::expr(sp)
        }
    };

    let mut val = 0u32;
    for codepoint in s.get().chars().take(4) {
        let byte = if codepoint as u32 > 0xFF {
            cx.span_err(expr.span, "fourcc! literal character out of range 0-255");
            0u8
        } else {
            codepoint as u8
        };

        val = if little {
            (val >> 8) | ((byte as u32) << 24)
        } else {
            (val << 8) | (byte as u32)
        };
    }
    let e = cx.expr_lit(sp, ast::LitUint(val as u64, ast::TyU32));
    MacExpr::new(e)
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt, tts: &[ast::TokenTree]) -> (@ast::Expr, Option<Ident>) {
    let p = &mut parse::new_parser_from_tts(cx.parse_sess(),
                                            cx.cfg(),
                                            tts.iter()
                                               .map(|x| (*x).clone())
                                               .collect());
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

fn target_endian_little(cx: &ExtCtxt, sp: Span) -> bool {
    let meta = cx.meta_name_value(sp, InternedString::new("target_endian"),
        ast::LitStr(InternedString::new("little"), ast::CookedStr));
    contains(cx.cfg().as_slice(), meta)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<|endoftext|>