<commit_before>extern crate rand;
extern crate timely;
extern crate timely_sort;
extern crate differential_dataflow;
extern crate vec_map;

use timely::dataflow::*;
use timely::dataflow::operators::*;

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

use differential_dataflow::AsCollection;
use differential_dataflow::operators::arrange::ArrangeByKey;
use differential_dataflow::trace::Cursor;

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();

    // define a new timely dataflow computation.
    timely::execute_from_args(std::env::args().skip(4), move |worker| {

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

    	// create a a degree counting differential dataflow
    	let (mut input, probe, trace) = worker.scoped(|scope| {

    		// create edge input, count a few ways.
    		let (input, edges) = scope.new_input();

    		// pull off source, and count.
    		let arranged = edges.as_collection()
    							.arrange_by_key_hashed();

		    (input, arranged.stream.probe().0, arranged.trace.clone())
    	});

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

        // load up graph dataz
        let &time = input.time();
        for edge in 0..edges {
        	if edge % peers == index {
        		input.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), time, 1));
        	}

        	// move the data along a bit
        	if edge % 10000 == 9999 {
        		worker.step();
        	}
		}

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

		input.advance_to(1);
		worker.step_while(|| probe.lt(input.time()));

		if index == 0 {
			let timer = timer.elapsed();
			let nanos = timer.as_secs() * 1000000000 + timer.subsec_nanos() as u64;
			println!("Loading finished after {:?}", nanos);
		}

		// change graph, forever
		if batch > 0 {

			for edge in 0usize .. {
				let &time = input.time();
				if edge % peers == index {
	        		input.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), time, 1));
	        		input.send(((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)), time,-1));
				}

	        	if edge % batch == (batch - 1) {

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

	        		let next = input.epoch() + 1;
	        		input.advance_to(next);
					worker.step_while(|| probe.lt(input.time()));

					if index == 0 {
						let timer = timer.elapsed();
						let nanos = timer.as_secs() * 1000000000 + timer.subsec_nanos() as u64;
						println!("Round {} finished after {:?}", next - 1, nanos);

						let mut count = 0;
		        		let timer = ::std::time::Instant::now();
		        		let mut cursor = trace.cursor();
		        		while cursor.key_valid() {
		        			while cursor.val_valid() {
								let mut sum = 0;
								cursor.map_times(|_,d| sum += d);
								if sum > 0 { count += 1; }
								cursor.step_val();
		        			}

		        			cursor.step_key()
		        		}

		        		println!("count: {} in {:?}", count, timer.elapsed());
					}
	        	}
	        }
	    }

    }).unwrap();
}<commit_msg>arrange example demonstrates shared queue<commit_after>extern crate rand;
extern crate timely;
extern crate timely_sort;
extern crate differential_dataflow;
extern crate vec_map;

use timely::dataflow::*;
use timely::dataflow::operators::*;

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

use differential_dataflow::AsCollection;
use differential_dataflow::operators::arrange::ArrangeByKey;
use differential_dataflow::trace::Cursor;
use differential_dataflow::trace::Batch;

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();

    // define a new timely dataflow computation.
    timely::execute_from_args(std::env::args().skip(4), move |worker| {

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

        // create a a degree counting differential dataflow
        let (mut input, probe, trace) = worker.scoped(|scope| {

            // create edge input, count a few ways.
            let (input, edges) = scope.new_input();

            // pull off source, and count.
            let arranged = edges.as_collection()
                                .arrange_by_key_hashed();

            (input, arranged.stream.probe().0, arranged.trace.clone())
        });

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

        // load up graph dataz
        let &time = input.time();
        for edge in 0..edges {
            if edge % peers == index {
                input.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), time, 1));
            }

            // move the data along a bit
            if edge % 10000 == 9999 {
                worker.step();
            }
        }

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

        input.advance_to(1);
        worker.step_while(|| probe.lt(input.time()));

        if index == 0 {
            let timer = timer.elapsed();
            let nanos = timer.as_secs() * 1000000000 + timer.subsec_nanos() as u64;
            println!("Loading finished after {:?}", nanos);
        }

        // change graph, forever
        if batch > 0 {

            for edge in 0usize .. {
                let &time = input.time();
                if edge % peers == index {
                    input.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), time, 1));
                    input.send(((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)), time,-1));
                }

                if edge % batch == (batch - 1) {

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

                    let next = input.epoch() + 1;
                    input.advance_to(next);
                    worker.step_while(|| probe.lt(input.time()));

                    if index == 0 {
                        let timer = timer.elapsed();
                        let nanos = timer.as_secs() * 1000000000 + timer.subsec_nanos() as u64;
                        println!("Round {} finished after {:?}", next - 1, nanos);

                        let mut count = 0;

                        // we can directly interrogate the trace...
                        let timer = ::std::time::Instant::now();
                        let mut cursor = trace.cursor();
                        while cursor.key_valid() {
                            while cursor.val_valid() {
                                let mut sum = 0;
                                cursor.map_times(|_,d| sum += d);
                                if sum > 0 { count += 1; }
                                cursor.step_val();
                            }

                            cursor.step_key()
                        }

                        println!("count: {} in {:?}", count, timer.elapsed());

                        // or we can monitor data from a shared queue...
                        let queue = trace.new_listener();
                        let mut borrow = queue.borrow_mut();
                        while let Some((frontier, batch)) = borrow.pop_front() {
                            println!("received from queue:");
                            println!("  frontier: {:?}", frontier);
                            if let Some(batch) = batch {
                                println!("  batch from: {:?} -> {:?}, since: {:?}", batch.lower(), batch.upper(), batch.description().since());
                            }
                        }
                    }
                }
            }
        }

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


<commit_before>//! A hangman game to guess the hidden word.
// To run this example, use the command: cargo run --features unstable --example hangman
#[cfg(all(not(feature = "unstable")))]
compile_error!("This example relies on unstable features. Run with `--features unstable`");

use std::io::{Error, Write};

use turtle::{rand::RandomSlice, Drawing, Point, Speed, Turtle};

// A small word list to choose from
const WORDS: &[&str; 28] = &[
    "poetry",
    "formal",
    "type",
    "expresses",
    "personal",
    "emotions",
    "feelings",
    "typically",
    "spoken",
    "equivalent",
    "lyrics",
    "term",
    "derives",
    "literature",
    "defined",
    "musical",
    "accompaniment",
    "usually",
    "stringed",
    "instrument",
    "term",
    "importance",
    "literary",
    "theory",
    "division",
    "developed",
    "between",
    "categories",
];

fn main() {
    let mut drawing = Drawing::new();

    // the turtle that is responsible for drawing the hangman design
    let mut hangman = drawing.add_turtle();

    // the turtle that is responsible for drawing the lines on which the letters appear.
    let mut lines = drawing.add_turtle();

    // the turtle that is responsible for drawing the Won or lost smiley.
    let mut wl = drawing.add_turtle();
    wl.hide();

    // the secret word that is to be guessed
    let secret = *WORDS.choose().unwrap();

    // this list stores all the steps of the hangman so that they can be drawn from a for loop or an index.
    let hangman_design = HangmanDesign::default();
    graphic::setup(&mut hangman);

    let mut all_guesses = String::new();

    // Loop over each step basically there are two ways to do this either one loops over the steps or one loops over guesses. Both need two nested loops.
    // HangmanDesign has the [`Iterator`] trait implemented which is why we can loop it directly.
    // The `'won:` syntax is to be able to conviniently `break` from both nested loops.
    'won: for step in hangman_design {
        // for each step we only draw it after a wron guess. So the following loops guesses and only `break`s to the for loop on a wrong guess. If all characters have been guessed correctly then it `break`s both loops and continues with a won or lost smiley.
        loop {
            draw_lines(&mut lines, secret, &all_guesses);
            let mut new_guess = String::new();
            ask_for_letter(&mut new_guess).expect("Failed to read letter");
            if secret.contains(&new_guess) {
                println!("This was correct!");
                all_guesses += &new_guess;
                if secret.chars().all(|c| all_guesses.contains(c)) {
                    break 'won;
                }
            } else {
                println!("No that letter is not in the word");
                break;
            }
        }
        step(&mut hangman);
    }
    // Redraw the lines else they could be outdated.
    draw_lines(&mut lines, secret, &all_guesses);
    wl.set_speed(Speed::instant());
    // Draw a circle
    wl.arc_right(100.0, 360.0);
    // Draw the left eye
    teleport_relative(&mut wl, Point { x: 55.0, y: 40.0 });
    wl.arc_right(5.0, 360.0);
    // Draw the right eye
    teleport_relative(&mut wl, Point { x: 85.0, y: 0.0 });
    wl.arc_right(5.0, 360.0);
    // Go to the start of the mouth
    teleport_relative(&mut wl, Point { x: -85.0, y: -80.0 });
    wl.right(90.0);
    // Either draw it smiling or sad
    if secret.chars().all(|c| all_guesses.contains(c)) {
        println!("You Won!");
        wl.right(45.0);
        wl.arc_left(65.0, 90.0);
    } else {
        println!("You Lost!");
        wl.left(45.0);
        wl.arc_right(65.0, 90.0);
    }
}

/// A function to ask the user for a letter
fn ask_for_letter(guess: &mut String) -> Result<(), Error> {
    print!("Please guess a letter: ");
    std::io::stdout().flush()?;
    std::io::stdin().read_line(guess)?;

    // remove trailing newline characters
    let to_trim = guess.trim_end_matches(&['\r', '\n'][..]).len();
    guess.truncate(to_trim);

    println!("You guessed: {}", &guess);
    Ok(())
}

/// A function to conveniently teleport the turtle relative to its current position.
fn teleport_relative(turtle: &mut Turtle, direction: Point) {
    let cur = turtle.position();
    let new: Point = cur + direction;
    turtle.pen_up();
    turtle.go_to(new);
    turtle.pen_down();
}

/// Draw the lines one for each character. If the character has been guessed already correctly draw a green circle above the line.
fn draw_lines(lines: &mut Turtle, secret: &str, all_guesses: &str) {
    // hide the lines-turtle and go th the startigpoint of the lines.
    lines.reset();
    lines.hide();
    lines.set_speed(Speed::instant());
    lines.right(90.0);
    teleport_relative(lines, Point { x: -300.0, y: 200.0 });

    // draw a line for every character in the secret.
    for letter in secret.chars() {
        if all_guesses.contains(letter) {
            teleport_relative(lines, Point { x: 2.5, y: 10.0 });

            // as turtle is not yet able to draw text draw a green replacement circle.
            lines.left(90.0);
            lines.set_fill_color("green");
            lines.set_pen_color("green");
            lines.begin_fill();
            lines.arc_right(7.5, 360.0);
            lines.end_fill();
            lines.set_pen_color("black");
            lines.right(90.0);

            teleport_relative(lines, Point { x: -2.5, y: -10.0 });

            // print to the terminal
            print!(" {} ", letter);
        } else {
            print!(" _ ");
        }
        lines.forward(20.0);
        teleport_relative(lines, Point { x: 20.0, y: 0.0 });
    }
    println!(); // to switch to the next line and flush the output.
}

// This module contains the drawing logic for the hangman graphic
//
// It is used by creating an instance of a [`HangmanDesign`] struct using [`HangmanDesign::default()`].
// Therein is contained a list of all the steps neccessary to draw the hangman in chronologic order.

use turtle::{Point, Speed, Turtle};

use crate::teleport_relative;

pub struct HangmanDesign {
    state: usize,
    steps: &'static [fn(&mut turtle::Turtle); 9],
}

impl Default for HangmanDesign {
    fn default() -> Self {
        Self {
            state: 0,
            steps: &[hill, mast, bar, support, rope, head, arms, body, legs],
        }
    }
}

impl Iterator for HangmanDesign {
    type Item = &'static fn(&mut turtle::Turtle);

    fn next(&mut self) -> Option<Self::Item> {
        self.state += 1;
        self.steps.get(self.state - 1)
    }
}

pub fn setup(hangman: &mut Turtle) {
    // hide the hangman-turtle and go th the startigpoint of the graphic.
    hangman.hide();
    hangman.set_speed(Speed::instant());
    hangman.set_pen_size(10.0);
    teleport_relative(hangman, Point { x: -300.0, y: -300.0 });
}

fn hill(hangman: &mut Turtle) {
    // start drawing
    hangman.arc_right(100.0, 180.0);
    hangman.left(180.0);
    hangman.arc_left(100.0, 90.0);
    hangman.right(90.0);
}

fn mast(hangman: &mut Turtle) {
    hangman.forward(300.0);
}

fn bar(hangman: &mut Turtle) {
    hangman.right(90.0);
    hangman.forward(150.0);
}

fn support(hangman: &mut Turtle) {
    hangman.backward(100.0);
    hangman.right(135.0);
    hangman.forward(70.710678119);
    hangman.backward(70.710678119);
    hangman.left(135.0);
    hangman.forward(100.0);
}

fn rope(hangman: &mut Turtle) {
    hangman.set_pen_size(3.0);
    hangman.right(90.0);
    hangman.forward(70.0);
}

fn head(hangman: &mut Turtle) {
    hangman.left(90.0);
    hangman.arc_right(30.0, 540.0);
}

fn arms(hangman: &mut Turtle) {
    hangman.left(60.0);
    hangman.forward(100.0);
    hangman.backward(100.0);
    hangman.left(60.0);
    hangman.forward(100.0);
    hangman.backward(100.0);
    hangman.right(30.0);
}

fn body(hangman: &mut Turtle) {
    hangman.forward(100.0);
}

fn legs(hangman: &mut Turtle) {
    hangman.right(20.0);
    hangman.forward(120.0);
    hangman.backward(120.0);
    hangman.left(40.0);
    hangman.forward(120.0);
    hangman.backward(120.0);
    hangman.right(20.0);
}
<commit_msg>move the wordlist and use choose differently.<commit_after>//! A hangman game to guess the hidden word.
// To run this example, use the command: cargo run --features unstable --example hangman
#[cfg(all(not(feature = "unstable")))]
compile_error!("This example relies on unstable features. Run with `--features unstable`");

use std::io::{Error, Write};

use turtle::{rand, Drawing, Point, Speed, Turtle};

fn main() {
    let mut drawing = Drawing::new();

    // the turtle that is responsible for drawing the hangman design
    let mut hangman = drawing.add_turtle();

    // the turtle that is responsible for drawing the lines on which the letters appear.
    let mut lines = drawing.add_turtle();

    // the turtle that is responsible for drawing the Won or lost smiley.
    let mut wl = drawing.add_turtle();
    wl.hide();

    // the secret word that is to be guessed
    let secret = rand::choose(WORDS).expect("Failed to choose a ranodm word.");

    // this list stores all the steps of the hangman so that they can be drawn from a for loop or an index.
    let hangman_design = HangmanDesign::default();
    graphic::setup(&mut hangman);

    let mut all_guesses = String::new();

    // Loop over each step basically there are two ways to do this either one loops over the steps or one loops over guesses. Both need two nested loops.
    // HangmanDesign has the [`Iterator`] trait implemented which is why we can loop it directly.
    // The `'won:` syntax is to be able to conviniently `break` from both nested loops.
    'won: for step in hangman_design {
        // for each step we only draw it after a wron guess. So the following loops guesses and only `break`s to the for loop on a wrong guess. If all characters have been guessed correctly then it `break`s both loops and continues with a won or lost smiley.
        loop {
            draw_lines(&mut lines, secret, &all_guesses);
            let mut new_guess = String::new();
            ask_for_letter(&mut new_guess).expect("Failed to read letter");
            if secret.contains(&new_guess) {
                println!("This was correct!");
                all_guesses += &new_guess;
                if secret.chars().all(|c| all_guesses.contains(c)) {
                    break 'won;
                }
            } else {
                println!("No that letter is not in the word");
                break;
            }
        }
        step(&mut hangman);
    }
    // Redraw the lines else they could be outdated.
    draw_lines(&mut lines, secret, &all_guesses);
    wl.set_speed(Speed::instant());
    // Draw a circle
    wl.arc_right(100.0, 360.0);
    // Draw the left eye
    teleport_relative(&mut wl, Point { x: 55.0, y: 40.0 });
    wl.arc_right(5.0, 360.0);
    // Draw the right eye
    teleport_relative(&mut wl, Point { x: 85.0, y: 0.0 });
    wl.arc_right(5.0, 360.0);
    // Go to the start of the mouth
    teleport_relative(&mut wl, Point { x: -85.0, y: -80.0 });
    wl.right(90.0);
    // Either draw it smiling or sad
    if secret.chars().all(|c| all_guesses.contains(c)) {
        println!("You Won!");
        wl.right(45.0);
        wl.arc_left(65.0, 90.0);
    } else {
        println!("You Lost!");
        wl.left(45.0);
        wl.arc_right(65.0, 90.0);
    }
}

/// A function to ask the user for a letter
fn ask_for_letter(guess: &mut String) -> Result<(), Error> {
    print!("Please guess a letter: ");
    std::io::stdout().flush()?;
    std::io::stdin().read_line(guess)?;

    // remove trailing newline characters
    let to_trim = guess.trim_end_matches(&['\r', '\n'][..]).len();
    guess.truncate(to_trim);

    println!("You guessed: {}", &guess);
    Ok(())
}

/// A function to conveniently teleport the turtle relative to its current position.
fn teleport_relative(turtle: &mut Turtle, direction: Point) {
    let cur = turtle.position();
    let new: Point = cur + direction;
    turtle.pen_up();
    turtle.go_to(new);
    turtle.pen_down();
}

/// Draw the lines one for each character. If the character has been guessed already correctly draw a green circle above the line.
fn draw_lines(lines: &mut Turtle, secret: &str, all_guesses: &str) {
    // hide the lines-turtle and go th the startigpoint of the lines.
    lines.reset();
    lines.hide();
    lines.set_speed(Speed::instant());
    lines.right(90.0);
    teleport_relative(lines, Point { x: -300.0, y: 200.0 });

    // draw a line for every character in the secret.
    for letter in secret.chars() {
        if all_guesses.contains(letter) {
            teleport_relative(lines, Point { x: 2.5, y: 10.0 });

            // as turtle is not yet able to draw text draw a green replacement circle.
            lines.left(90.0);
            lines.set_fill_color("green");
            lines.set_pen_color("green");
            lines.begin_fill();
            lines.arc_right(7.5, 360.0);
            lines.end_fill();
            lines.set_pen_color("black");
            lines.right(90.0);

            teleport_relative(lines, Point { x: -2.5, y: -10.0 });

            // print to the terminal
            print!(" {} ", letter);
        } else {
            print!(" _ ");
        }
        lines.forward(20.0);
        teleport_relative(lines, Point { x: 20.0, y: 0.0 });
    }
    println!(); // to switch to the next line and flush the output.
}

// A small word list to choose from
const WORDS: &[&str; 28] = &[
    "poetry",
    "formal",
    "type",
    "expresses",
    "personal",
    "emotions",
    "feelings",
    "typically",
    "spoken",
    "equivalent",
    "lyrics",
    "term",
    "derives",
    "literature",
    "defined",
    "musical",
    "accompaniment",
    "usually",
    "stringed",
    "instrument",
    "term",
    "importance",
    "literary",
    "theory",
    "division",
    "developed",
    "between",
    "categories",
];

/// The struct contains the drawing logic for the hangman graphic
///
/// It is used by creating an instance of a [`HangmanDesign`] struct using [`HangmanDesign::default()`].
/// Since [`HangmanDesign`] implements [`Iterator`] you can directly iterate over the instance using a for loop.
pub struct HangmanDesign {
    state: usize,
    steps: &'static [fn(&mut turtle::Turtle); 9],
}

impl Default for HangmanDesign {
    fn default() -> Self {
        Self {
            state: 0,
            steps: &[hill, mast, bar, support, rope, head, arms, body, legs],
        }
    }
}

impl Iterator for HangmanDesign {
    type Item = &'static fn(&mut turtle::Turtle);

    fn next(&mut self) -> Option<Self::Item> {
        self.state += 1;
        self.steps.get(self.state - 1)
    }
}

pub fn setup(hangman: &mut Turtle) {
    // hide the hangman-turtle and go th the startigpoint of the graphic.
    hangman.hide();
    hangman.set_speed(Speed::instant());
    hangman.set_pen_size(10.0);
    teleport_relative(hangman, Point { x: -300.0, y: -300.0 });
}

fn hill(hangman: &mut Turtle) {
    // start drawing
    hangman.arc_right(100.0, 180.0);
    hangman.left(180.0);
    hangman.arc_left(100.0, 90.0);
    hangman.right(90.0);
}

fn mast(hangman: &mut Turtle) {
    hangman.forward(300.0);
}

fn bar(hangman: &mut Turtle) {
    hangman.right(90.0);
    hangman.forward(150.0);
}

fn support(hangman: &mut Turtle) {
    hangman.backward(100.0);
    hangman.right(135.0);
    hangman.forward(70.710678119);
    hangman.backward(70.710678119);
    hangman.left(135.0);
    hangman.forward(100.0);
}

fn rope(hangman: &mut Turtle) {
    hangman.set_pen_size(3.0);
    hangman.right(90.0);
    hangman.forward(70.0);
}

fn head(hangman: &mut Turtle) {
    hangman.left(90.0);
    hangman.arc_right(30.0, 540.0);
}

fn arms(hangman: &mut Turtle) {
    hangman.left(60.0);
    hangman.forward(100.0);
    hangman.backward(100.0);
    hangman.left(60.0);
    hangman.forward(100.0);
    hangman.backward(100.0);
    hangman.right(30.0);
}

fn body(hangman: &mut Turtle) {
    hangman.forward(100.0);
}

fn legs(hangman: &mut Turtle) {
    hangman.right(20.0);
    hangman.forward(120.0);
    hangman.backward(120.0);
    hangman.left(40.0);
    hangman.forward(120.0);
    hangman.backward(120.0);
    hangman.right(20.0);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate wlroots;

use std::cell::RefCell;
use std::rc::Rc;
use wlroots::{AxisEvent, ButtonEvent, Compositor, CompositorBuilder, Cursor, InputManagerHandler,
              KeyEvent, KeyboardHandler, MotionEvent, OutputBuilder, OutputBuilderResult,
              OutputHandler, OutputLayout, OutputManagerHandler, PointerHandler, XCursorTheme};
use wlroots::types::{KeyboardHandle, OutputHandle, PointerHandle};
use wlroots::wlroots_sys::gl;
use wlroots::wlroots_sys::wlr_button_state::WLR_BUTTON_RELEASED;
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

struct State {
    color: [f32; 4],
    default_color: [f32; 4],
    cursor: Cursor
}

impl State {
    fn new(cursor: Cursor) -> Self {
        State {
            color: [0.25, 0.25, 0.25, 1.0],
            default_color: [0.25, 0.25, 0.25, 1.0],
            cursor
        }
    }
}

compositor_data!(State);

struct OutputManager;

struct Output;

struct InputManager;

struct Pointer;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: &mut Compositor,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let result = builder.build_best_mode(Output);
        let state: &mut State = compositor.into();
        let cursor = &mut state.cursor;
        // TODO use output config if present instead of auto
        {
            let layout = cursor
                .output_layout()
                .as_ref()
                .expect("Could not get output layout");
            result.output.add_layout_auto(layout.clone());
            /*let xcursor = cursor.xcursor().expect("XCursor was not set!");
            let image = &xcursor.images()[0];
            if result.output.set_cursor(image).is_err() {
                wlr_log!(L_DEBUG, "Failed to set hardware cursor");
                return None;
            }*/
        }
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
        Some(result)
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self,
              compositor: &mut Compositor,
              _: &mut KeyboardHandle,
              key_event: &mut KeyEvent) {
        for key in key_event.input_keys() {
            if key == KEY_Escape {
                compositor.terminate()
            }
        }
    }
}

impl PointerHandler for Pointer {
    fn on_motion(&mut self,
                 compositor: &mut Compositor,
                 _: &mut PointerHandle,
                 event: &MotionEvent) {
        let state: &mut State = compositor.into();
        let (delta_x, delta_y) = event.delta();
        state.cursor.move_to(&event.device(), delta_x, delta_y);
    }

    fn on_button(&mut self,
                 compositor: &mut Compositor,
                 _: &mut PointerHandle,
                 event: &ButtonEvent) {
        let state: &mut State = compositor.into();
        if event.state() == WLR_BUTTON_RELEASED {
            state.color = state.default_color;
        } else {
            state.color = [0.25, 0.25, 0.25, 1.0];
            state.color[event.button() as usize % 3] = 1.0;
        }
    }

    fn on_axis(&mut self, compositor: &mut Compositor, _: &mut PointerHandle, event: &AxisEvent) {
        let state: &mut State = compositor.into();
        for color_byte in &mut state.default_color[..3] {
            *color_byte += if event.delta() > 0.0 { -0.05 } else { 0.05 };
            if *color_byte > 1.0 {
                *color_byte = 1.0
            }
            if *color_byte < 0.0 {
                *color_byte = 0.0
            }
        }
        state.color = state.default_color.clone()
    }
}

impl OutputHandler for Output {
    fn output_frame(&mut self, compositor: &mut Compositor, output: &mut OutputHandle) {
        let state: &mut State = compositor.into();
        output.make_current();
        unsafe {
            gl::ClearColor(state.color[0], state.color[1], state.color[2], 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }
        output.swap_buffers();
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: &mut Compositor,
                     _: &mut PointerHandle)
                     -> Option<Box<PointerHandler>> {
        Some(Box::new(Pointer))
    }

    fn keyboard_added(&mut self,
                      _: &mut Compositor,
                      _: &mut KeyboardHandle)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    let mut cursor = Cursor::new().expect("Could not create cursor");
    /*let xcursor_theme = XCursorTheme::load_theme(None, 16).expect("Could not load theme");
    let xcursor = xcursor_theme
        .get_cursor("left_ptr".into())
        .expect("Could not load cursor from theme");
    let layout = Rc::new(RefCell::new(OutputLayout::new()));
    cursor.set_xcursor(Some(xcursor));

    cursor.attach_output_layout(layout);*/
    let compositor = CompositorBuilder::new().build_auto(State::new(cursor),
                                                         Box::new(InputManager),
                                                         Box::new(OutputManager));
    compositor.run();
}
<commit_msg>Fixed pointer example so it runs again<commit_after>#[macro_use]
extern crate wlroots;

use std::cell::RefCell;
use std::rc::Rc;
use wlroots::{AxisEvent, ButtonEvent, Compositor, CompositorBuilder, Cursor, InputManagerHandler,
              KeyEvent, KeyboardHandler, MotionEvent, OutputBuilder, OutputBuilderResult,
              OutputHandler, OutputLayout, OutputManagerHandler, PointerHandler, XCursorTheme};
use wlroots::types::{KeyboardHandle, OutputHandle, PointerHandle};
use wlroots::wlroots_sys::gl;
use wlroots::wlroots_sys::wlr_button_state::WLR_BUTTON_RELEASED;
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

struct State {
    color: [f32; 4],
    default_color: [f32; 4],
    cursor: Cursor
}

impl State {
    fn new(cursor: Cursor) -> Self {
        State {
            color: [0.25, 0.25, 0.25, 1.0],
            default_color: [0.25, 0.25, 0.25, 1.0],
            cursor
        }
    }
}

compositor_data!(State);

struct OutputManager;

struct Output;

struct InputManager;

struct Pointer;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: &mut Compositor,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let result = builder.build_best_mode(Output);
        let state: &mut State = compositor.into();
        let cursor = &mut state.cursor;
        // TODO use output config if present instead of auto
        {
            let layout = cursor
                .output_layout()
                .as_ref()
                .expect("Could not get output layout");
            result.output.add_layout_auto(layout.clone());
            /*let xcursor = cursor.xcursor().expect("XCursor was not set!");
            let image = &xcursor.images()[0];
            if result.output.set_cursor(image).is_err() {
                wlr_log!(L_DEBUG, "Failed to set hardware cursor");
                return None;
            }*/
        }
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
        Some(result)
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self,
              compositor: &mut Compositor,
              _: &mut KeyboardHandle,
              key_event: &mut KeyEvent) {
        for key in key_event.input_keys() {
            if key == KEY_Escape {
                compositor.terminate()
            }
        }
    }
}

impl PointerHandler for Pointer {
    fn on_motion(&mut self,
                 compositor: &mut Compositor,
                 _: &mut PointerHandle,
                 event: &MotionEvent) {
        let state: &mut State = compositor.into();
        let (delta_x, delta_y) = event.delta();
        state.cursor.move_to(&event.device(), delta_x, delta_y);
    }

    fn on_button(&mut self,
                 compositor: &mut Compositor,
                 _: &mut PointerHandle,
                 event: &ButtonEvent) {
        let state: &mut State = compositor.into();
        if event.state() == WLR_BUTTON_RELEASED {
            state.color = state.default_color;
        } else {
            state.color = [0.25, 0.25, 0.25, 1.0];
            state.color[event.button() as usize % 3] = 1.0;
        }
    }

    fn on_axis(&mut self, compositor: &mut Compositor, _: &mut PointerHandle, event: &AxisEvent) {
        let state: &mut State = compositor.into();
        for color_byte in &mut state.default_color[..3] {
            *color_byte += if event.delta() > 0.0 { -0.05 } else { 0.05 };
            if *color_byte > 1.0 {
                *color_byte = 1.0
            }
            if *color_byte < 0.0 {
                *color_byte = 0.0
            }
        }
        state.color = state.default_color.clone()
    }
}

impl OutputHandler for Output {
    fn output_frame(&mut self, compositor: &mut Compositor, output: &mut OutputHandle) {
        let state: &mut State = compositor.into();
        output.make_current();
        unsafe {
            gl::ClearColor(state.color[0], state.color[1], state.color[2], 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }
        output.swap_buffers();
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: &mut Compositor,
                     _: &mut PointerHandle)
                     -> Option<Box<PointerHandler>> {
        Some(Box::new(Pointer))
    }

    fn keyboard_added(&mut self,
                      _: &mut Compositor,
                      _: &mut KeyboardHandle)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    let mut cursor = Cursor::new().expect("Could not create cursor");
    /*let xcursor_theme = XCursorTheme::load_theme(None, 16).expect("Could not load theme");
    let xcursor = xcursor_theme
        .get_cursor("left_ptr".into())
        .expect("Could not load cursor from theme");
    cursor.set_xcursor(Some(xcursor));
    */
    let layout = Rc::new(RefCell::new(OutputLayout::new()));

    cursor.attach_output_layout(layout);
    let compositor = CompositorBuilder::new().build_auto(State::new(cursor),
                                                         Box::new(InputManager),
                                                         Box::new(OutputManager));
    compositor.run();
}
<|endoftext|>


<commit_before>extern crate kafka;
use kafka::client::KafkaClient;

fn main() {
    let dest = "localhost:9092";
    println!("Publishing to {}", dest);
    let mut client = KafkaClient::new(vec!(dest.to_owned()));
    client.load_metadata_all().unwrap();
    match client.send_message(1, 100, "my-topic".to_owned(), "msg".to_owned().into_bytes()) {
        Ok(e) => {println!("OK {:?}", e);},
        Err(e) => {println!("Error {:?}", e);}
    }
}
<commit_msg>#! Print a message when target topic does not yet exist<commit_after>extern crate kafka;

use kafka::client::KafkaClient;

/// This program demonstrates sending a single message through
/// `KafkaClient`.
fn main() {
    let broker = "localhost:9092";
    let topic = "my-topic";
    let data = "hello, kafka";

    println!("About to publish a message at {} to: {}", broker, topic);

    // ~ create the client and load metadata for all available topics
    let mut client = KafkaClient::new(vec!(broker.to_owned()));
    if let Err(e) = client.load_metadata_all() {
        println!("Failed to load meta data from {}: {}", broker, e);
        return;
    }
    // ~ make sure to print out a warning message when the target
    // topic does not yet exist
    if !client.topic_partitions.contains_key(topic) {
        println!("No such topic at {}: {}", broker, topic);
        return;
    }
    // ~ now send a small message (if the specified topic would have
    // not been existent) the client would drop the message.
    let r = client.send_message(1, 100, topic.to_owned(), data.as_bytes().to_owned());
    println!("message sent: {:?}", r);
}
<|endoftext|>


<commit_before>//! Compiler plugin defining macros that create PHF data structures.
//!
//! # Example
//!
//! ```rust
//! #![feature(plugin, core)]
//! #![plugin(phf_macros)]
//!
//! extern crate phf;
//!
//! #[derive(Clone)]
//! pub enum Keyword {
//!     Loop,
//!     Continue,
//!     Break,
//!     Fn,
//!     Extern,
//! }
//!
//! static KEYWORDS: phf::Map<&'static str, Keyword> = phf_map! {
//!     "loop" => Keyword::Loop,
//!     "continue" => Keyword::Continue,
//!     "break" => Keyword::Break,
//!     "fn" => Keyword::Fn,
//!     "extern" => Keyword::Extern,
//! };
//!
//! pub fn parse_keyword(keyword: &str) -> Option<Keyword> {
//!     KEYWORDS.get(keyword).cloned()
//! }
//! # fn main() {}
//! ```
#![doc(html_root_url="http://sfackler.github.io/rust-phf/doc/v0.7.6")]
#![feature(plugin_registrar, quote, rustc_private)]

extern crate syntax;
#[cfg(feature = "stats")]
extern crate time;
extern crate rustc;
extern crate phf_shared;
extern crate phf_generator;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use syntax::ast::{self, TokenTree, LitStr, LitByteStr, LitByte, LitChar, Expr, ExprLit, ExprVec};
use syntax::codemap::{Span, Spanned};
use syntax::ext::base::{DummyResult, ExtCtxt, MacResult};
use syntax::fold::Folder;
use syntax::parse;
use syntax::parse::token::{InternedString, Comma, Eof, FatArrow};
use syntax::print::pprust;
use rustc::plugin::Registry;
use phf_generator::HashState;
use std::env;

use util::{Entry, Key};
use util::{create_map, create_set, create_ordered_map, create_ordered_set};

pub mod util;
mod macros;

#[plugin_registrar]
#[doc(hidden)]
pub fn macro_registrar(reg: &mut Registry) {
    reg.register_macro("phf_map", expand_phf_map);
    reg.register_macro("phf_set", expand_phf_set);
    reg.register_macro("phf_ordered_map", expand_phf_ordered_map);
    reg.register_macro("phf_ordered_set", expand_phf_ordered_set);
}

fn generate_hash(cx: &mut ExtCtxt, sp: Span, entries: &[Entry]) -> HashState {
    #[cfg(feature = "stats")]
    use time::precise_time_s;
    #[cfg(not(feature = "stats"))]
    fn precise_time_s() -> f64 {
        0.
    }

    let start = precise_time_s();
    let state = phf_generator::generate_hash(entries);
    let time = precise_time_s() - start;

    if cfg!(feature = "stats") && env::var_os("PHF_STATS").is_some() {
        cx.span_note(sp, &format!("PHF generation took {} seconds", time));
    }

    state
}

fn expand_phf_map(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let entries = match parse_map(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_map(cx, sp, entries, state)
}

fn expand_phf_set(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let entries = match parse_set(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_set(cx, sp, entries, state)
}

fn expand_phf_ordered_map(cx: &mut ExtCtxt,
                          sp: Span,
                          tts: &[TokenTree])
                          -> Box<MacResult + 'static> {
    let entries = match parse_map(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_ordered_map(cx, sp, entries, state)
}

fn expand_phf_ordered_set(cx: &mut ExtCtxt,
                          sp: Span,
                          tts: &[TokenTree])
                          -> Box<MacResult + 'static> {
    let entries = match parse_set(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_ordered_set(cx, sp, entries, state)
}

fn parse_map(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_vec());
    let mut entries = Vec::new();

    let mut bad = false;
    while parser.token != Eof {
        let key = cx.expander().fold_expr(parser.parse_expr());
        let key_contents = parse_key(cx, &*key).unwrap_or_else(|| {
            bad = true;
            Key::Str(InternedString::new(""))
        });

        if !parser.eat(&FatArrow).ok().unwrap() {
            cx.span_err(parser.span, "expected `=>`");
            return None;
        }

        let value = parser.parse_expr();

        entries.push(Entry {
            key_contents: key_contents,
            key: key,
            value: value,
        });

        if !parser.eat(&Comma).ok().unwrap() && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    if bad {
        return None;
    }

    Some(entries)
}

fn parse_set(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_vec());
    let mut entries = Vec::new();
    let value = quote_expr!(&*cx, ());

    let mut bad = false;
    while parser.token != Eof {
        let key = cx.expander().fold_expr(parser.parse_expr());
        let key_contents = parse_key(cx, &*key).unwrap_or_else(|| {
            bad = true;
            Key::Str(InternedString::new(""))
        });

        entries.push(Entry {
            key_contents: key_contents,
            key: key,
            value: value.clone(),
        });

        if !parser.eat(&Comma).ok().unwrap() && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    if bad {
        return None;
    }

    Some(entries)
}

fn parse_key(cx: &mut ExtCtxt, e: &Expr) -> Option<Key> {
    match e.node {
        ExprLit(ref lit) => {
            match lit.node {
                ast::LitStr(ref s, _) => Some(Key::Str(s.clone())),
                ast::LitByteStr(ref b) => Some(Key::Binary(b.clone())),
                ast::LitByte(b) => Some(Key::U8(b)),
                ast::LitChar(c) => Some(Key::Char(c)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI8, ast::Plus)) => Some(Key::I8(i as i8)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI8, ast::Minus)) =>
                    Some(Key::I8(-(i as i8))),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI16, ast::Plus)) =>
                    Some(Key::I16(i as i16)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI16, ast::Minus)) =>
                    Some(Key::I16(-(i as i16))),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI32, ast::Plus)) =>
                    Some(Key::I32(i as i32)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI32, ast::Minus)) =>
                    Some(Key::I32(-(i as i32))),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI64, ast::Plus)) =>
                    Some(Key::I64(i as i64)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI64, ast::Minus)) =>
                    Some(Key::I64(-(i as i64))),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU8)) => Some(Key::U8(i as u8)),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU16)) => Some(Key::U16(i as u16)),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU32)) => Some(Key::U32(i as u32)),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU64)) => Some(Key::U64(i as u64)),
                ast::LitBool(b) => Some(Key::Bool(b)),
                _ => {
                    cx.span_err(e.span, "unsupported literal type");
                    None
                }
            }
        }
        ExprVec(ref v) => {
            let bytes: Vec<Option<u8>> = v.iter().map(|expr|
                if let ExprLit(ref p) = expr.node {
                    match **p {
                        Spanned {node: ast::LitInt(val, ast::UnsignedIntLit(ast::UintTy::TyU8)), ..} if val < 256 => Some(val as u8),
                        Spanned {node: ast::LitInt(val, ast::UnsuffixedIntLit(ast::Plus)), ..} if val < 256 => Some(val as u8),
                        _ => None,
                    }
                } else {
                    None
            }).collect();
            if bytes.iter().all(|x| x.is_some()) {
                Some(Key::Binary(std::rc::Rc::new(bytes.iter().map(|x| x.unwrap()).collect())))
            } else {
                cx.span_err(e.span,
                            "not all elements of an expected u8 array literal were u8 literals");
                None
            }
        }
        _ => {
            cx.span_err(e.span, "expected a literal");
            None
        }
    }
}

fn has_duplicates(cx: &mut ExtCtxt, sp: Span, entries: &[Entry]) -> bool {
    let mut dups = false;
    let mut strings = HashMap::new();
    for entry in entries.iter() {
        let &mut (ref mut spans, _) = match strings.entry(&entry.key_contents) {
            Occupied(e) => e.into_mut(),
            Vacant(e) => e.insert((vec![], &entry.key)),
        };
        spans.push(entry.key.span);
    }

    for &(ref spans, key) in strings.values() {
        if spans.len() == 1 {
            continue;
        }

        dups = true;
        cx.span_err(sp,
                    &*format!("duplicate key {}", pprust::expr_to_string(&**key)));
        for span in spans.iter() {
            cx.span_note(*span, "one occurrence here");
        }
    }

    dups
}
<commit_msg>rustup for phf_macros<commit_after>//! Compiler plugin defining macros that create PHF data structures.
//!
//! # Example
//!
//! ```rust
//! #![feature(plugin, core)]
//! #![plugin(phf_macros)]
//!
//! extern crate phf;
//!
//! #[derive(Clone)]
//! pub enum Keyword {
//!     Loop,
//!     Continue,
//!     Break,
//!     Fn,
//!     Extern,
//! }
//!
//! static KEYWORDS: phf::Map<&'static str, Keyword> = phf_map! {
//!     "loop" => Keyword::Loop,
//!     "continue" => Keyword::Continue,
//!     "break" => Keyword::Break,
//!     "fn" => Keyword::Fn,
//!     "extern" => Keyword::Extern,
//! };
//!
//! pub fn parse_keyword(keyword: &str) -> Option<Keyword> {
//!     KEYWORDS.get(keyword).cloned()
//! }
//! # fn main() {}
//! ```
#![doc(html_root_url="http://sfackler.github.io/rust-phf/doc/v0.7.6")]
#![feature(plugin_registrar, quote, rustc_private)]

extern crate syntax;
#[cfg(feature = "stats")]
extern crate time;
extern crate rustc;
extern crate phf_shared;
extern crate phf_generator;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use syntax::ast::{self, TokenTree, LitStr, LitByteStr, LitByte, LitChar, Expr, ExprLit, ExprVec};
use syntax::codemap::{Span, Spanned};
use syntax::ext::base::{DummyResult, ExtCtxt, MacResult};
use syntax::fold::Folder;
use syntax::parse;
use syntax::parse::token::{InternedString, Comma, Eof, FatArrow};
use syntax::print::pprust;
use rustc::plugin::Registry;
use phf_generator::HashState;
use std::env;

use util::{Entry, Key};
use util::{create_map, create_set, create_ordered_map, create_ordered_set};

pub mod util;
mod macros;

#[plugin_registrar]
#[doc(hidden)]
pub fn macro_registrar(reg: &mut Registry) {
    reg.register_macro("phf_map", expand_phf_map);
    reg.register_macro("phf_set", expand_phf_set);
    reg.register_macro("phf_ordered_map", expand_phf_ordered_map);
    reg.register_macro("phf_ordered_set", expand_phf_ordered_set);
}

fn generate_hash(cx: &mut ExtCtxt, sp: Span, entries: &[Entry]) -> HashState {
    #[cfg(feature = "stats")]
    use time::precise_time_s;
    #[cfg(not(feature = "stats"))]
    fn precise_time_s() -> f64 {
        0.
    }

    let start = precise_time_s();
    let state = phf_generator::generate_hash(entries);
    let time = precise_time_s() - start;

    if cfg!(feature = "stats") && env::var_os("PHF_STATS").is_some() {
        cx.span_note(sp, &format!("PHF generation took {} seconds", time));
    }

    state
}

fn expand_phf_map(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let entries = match parse_map(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_map(cx, sp, entries, state)
}

fn expand_phf_set(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let entries = match parse_set(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_set(cx, sp, entries, state)
}

fn expand_phf_ordered_map(cx: &mut ExtCtxt,
                          sp: Span,
                          tts: &[TokenTree])
                          -> Box<MacResult + 'static> {
    let entries = match parse_map(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_ordered_map(cx, sp, entries, state)
}

fn expand_phf_ordered_set(cx: &mut ExtCtxt,
                          sp: Span,
                          tts: &[TokenTree])
                          -> Box<MacResult + 'static> {
    let entries = match parse_set(cx, tts) {
        Some(entries) => entries,
        None => return DummyResult::expr(sp),
    };

    if has_duplicates(cx, sp, &*entries) {
        return DummyResult::expr(sp);
    }

    let state = generate_hash(cx, sp, &*entries);

    create_ordered_set(cx, sp, entries, state)
}

fn parse_map(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_vec());
    let mut entries = Vec::new();

    let mut bad = false;
    while parser.token != Eof {
        let key = cx.expander().fold_expr(parser.parse_expr_panic());
        let key_contents = parse_key(cx, &*key).unwrap_or_else(|| {
            bad = true;
            Key::Str(InternedString::new(""))
        });

        if !parser.eat(&FatArrow).ok().unwrap() {
            cx.span_err(parser.span, "expected `=>`");
            return None;
        }

        let value = parser.parse_expr_panic();

        entries.push(Entry {
            key_contents: key_contents,
            key: key,
            value: value,
        });

        if !parser.eat(&Comma).ok().unwrap() && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    if bad {
        return None;
    }

    Some(entries)
}

fn parse_set(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_vec());
    let mut entries = Vec::new();
    let value = quote_expr!(&*cx, ());

    let mut bad = false;
    while parser.token != Eof {
        let key = cx.expander().fold_expr(parser.parse_expr_panic());
        let key_contents = parse_key(cx, &*key).unwrap_or_else(|| {
            bad = true;
            Key::Str(InternedString::new(""))
        });

        entries.push(Entry {
            key_contents: key_contents,
            key: key,
            value: value.clone(),
        });

        if !parser.eat(&Comma).ok().unwrap() && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    if bad {
        return None;
    }

    Some(entries)
}

fn parse_key(cx: &mut ExtCtxt, e: &Expr) -> Option<Key> {
    match e.node {
        ExprLit(ref lit) => {
            match lit.node {
                ast::LitStr(ref s, _) => Some(Key::Str(s.clone())),
                ast::LitByteStr(ref b) => Some(Key::Binary(b.clone())),
                ast::LitByte(b) => Some(Key::U8(b)),
                ast::LitChar(c) => Some(Key::Char(c)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI8, ast::Plus)) => Some(Key::I8(i as i8)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI8, ast::Minus)) =>
                    Some(Key::I8(-(i as i8))),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI16, ast::Plus)) =>
                    Some(Key::I16(i as i16)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI16, ast::Minus)) =>
                    Some(Key::I16(-(i as i16))),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI32, ast::Plus)) =>
                    Some(Key::I32(i as i32)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI32, ast::Minus)) =>
                    Some(Key::I32(-(i as i32))),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI64, ast::Plus)) =>
                    Some(Key::I64(i as i64)),
                ast::LitInt(i, ast::SignedIntLit(ast::TyI64, ast::Minus)) =>
                    Some(Key::I64(-(i as i64))),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU8)) => Some(Key::U8(i as u8)),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU16)) => Some(Key::U16(i as u16)),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU32)) => Some(Key::U32(i as u32)),
                ast::LitInt(i, ast::UnsignedIntLit(ast::TyU64)) => Some(Key::U64(i as u64)),
                ast::LitBool(b) => Some(Key::Bool(b)),
                _ => {
                    cx.span_err(e.span, "unsupported literal type");
                    None
                }
            }
        }
        ExprVec(ref v) => {
            let bytes: Vec<Option<u8>> = v.iter().map(|expr|
                if let ExprLit(ref p) = expr.node {
                    match **p {
                        Spanned {node: ast::LitInt(val, ast::UnsignedIntLit(ast::UintTy::TyU8)), ..} if val < 256 => Some(val as u8),
                        Spanned {node: ast::LitInt(val, ast::UnsuffixedIntLit(ast::Plus)), ..} if val < 256 => Some(val as u8),
                        _ => None,
                    }
                } else {
                    None
            }).collect();
            if bytes.iter().all(|x| x.is_some()) {
                Some(Key::Binary(std::rc::Rc::new(bytes.iter().map(|x| x.unwrap()).collect())))
            } else {
                cx.span_err(e.span,
                            "not all elements of an expected u8 array literal were u8 literals");
                None
            }
        }
        _ => {
            cx.span_err(e.span, "expected a literal");
            None
        }
    }
}

fn has_duplicates(cx: &mut ExtCtxt, sp: Span, entries: &[Entry]) -> bool {
    let mut dups = false;
    let mut strings = HashMap::new();
    for entry in entries.iter() {
        let &mut (ref mut spans, _) = match strings.entry(&entry.key_contents) {
            Occupied(e) => e.into_mut(),
            Vacant(e) => e.insert((vec![], &entry.key)),
        };
        spans.push(entry.key.span);
    }

    for &(ref spans, key) in strings.values() {
        if spans.len() == 1 {
            continue;
        }

        dups = true;
        cx.span_err(sp,
                    &*format!("duplicate key {}", pprust::expr_to_string(&**key)));
        for span in spans.iter() {
            cx.span_note(*span, "one occurrence here");
        }
    }

    dups
}
<|endoftext|>


<commit_before>use crate::common::*;
use crate::data::packet::Packet;
use crate::data::value::*;
use std::any::Any;
use std::io::{ErrorKind, Seek, SeekFrom, Write};
use std::sync::Arc;

use crate::error::*;

pub trait WriteSeek: Write + Seek {}

impl<T: Write + Seek> WriteSeek for T {}

/// Runtime wrapper around either a [`Write`] or a [`WriteSeek`] trait object which supports querying
/// for seek support.
pub enum Writer {
    NonSeekable(Box<dyn Write>, u64),
    Seekable(Box<dyn WriteSeek>),
}

impl Writer {
    /// Creates a [`Writer`] from a trait object that implements both [`Write`] and [`Seek`].
    pub fn from_seekable(inner: Box<dyn WriteSeek>) -> Self {
        Self::Seekable(inner)
    }

    /// Creates a [`Writer`] from a trait object that implements the [`Write`] trait.
    pub fn from_nonseekable(inner: Box<dyn Write>) -> Self {
        Self::NonSeekable(inner, 0)
    }

    /// Returns whether the [`Writer`] can seek within the source.
    pub fn can_seek(&self) -> bool {
        matches!(self, Self::Seekable(_))
    }
}

impl Write for Writer {
    fn write(&mut self, bytes: &[u8]) -> std::io::Result<usize> {
        match self {
            Self::NonSeekable(inner, ref mut index) => {
                let result = inner.write(bytes);

                if let Ok(written) = result {
                    *index += written as u64;
                }

                result
            }
            Self::Seekable(inner) => inner.write(bytes),
        }
    }

    fn flush(&mut self) -> std::io::Result<()> {
        match self {
            Self::NonSeekable(inner, ..) => inner.flush(),
            Self::Seekable(inner) => inner.flush(),
        }
    }
}

impl Seek for Writer {
    fn seek(&mut self, seek: SeekFrom) -> std::io::Result<u64> {
        match self {
            Self::NonSeekable(_, index) => {
                if let SeekFrom::Current(0) = seek {
                    Ok(*index)
                } else {
                    Err(std::io::Error::new(
                        ErrorKind::Other,
                        "Seeking not supported",
                    ))
                }
            }
            Self::Seekable(inner) => inner.seek(seek),
        }
    }
}

/// Used to implement muxing operations.
pub trait Muxer: Send {
    /// Configures a muxer.
    fn configure(&mut self) -> Result<()>;
    /// Writes a stream header into a data structure implementing
    /// the `Write` trait.
    fn write_header(&mut self, out: &mut Writer) -> Result<()>;
    /// Writes a stream packet into a data structure implementing
    /// the `Write` trait.
    fn write_packet(&mut self, out: &mut Writer, pkt: Arc<Packet>) -> Result<()>;
    /// Writes a stream trailer into a data structure implementing
    /// the `Write` trait.
    fn write_trailer(&mut self, out: &mut Writer) -> Result<()>;

    /// Sets global media file information for a muxer.
    fn set_global_info(&mut self, info: GlobalInfo) -> Result<()>;
    /// Sets a muxer option.
    ///
    /// This method should be called as many times as the number of options
    /// present in a muxer.
    fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()>;
}

/// Auxiliary structure to encapsulate a muxer object and
/// its additional data.
pub struct Context {
    muxer: Box<dyn Muxer + Send>,
    writer: Writer,
    /// User private data.
    ///
    /// This data cannot be cloned.
    pub user_private: Option<Box<dyn Any + Send + Sync>>,
}

impl Context {
    /// Creates a new `Context` instance.
    pub fn new(muxer: Box<dyn Muxer + Send>, writer: Writer) -> Self {
        Context {
            muxer,
            writer,
            user_private: None,
        }
    }

    /// Configures a muxer.
    pub fn configure(&mut self) -> Result<()> {
        self.muxer.configure()
    }

    /// Writes a stream header to an internal buffer and returns how many
    /// bytes were written or an error.
    pub fn write_header(&mut self) -> Result<()> {
        self.muxer.write_header(&mut self.writer)
    }

    /// Writes a stream packet to an internal buffer and returns how many
    /// bytes were written or an error.
    pub fn write_packet(&mut self, pkt: Arc<Packet>) -> Result<()> {
        self.muxer.write_packet(&mut self.writer, pkt)
    }

    /// Writes a stream trailer to an internal buffer and returns how many
    /// bytes were written or an error.
    pub fn write_trailer(&mut self) -> Result<()> {
        self.muxer.write_trailer(&mut self.writer)?;
        self.writer.flush()?;

        Ok(())
    }

    /// Sets global media file information for a muxer.
    pub fn set_global_info(&mut self, info: GlobalInfo) -> Result<()> {
        self.muxer.set_global_info(info)
    }

    /// Sets a muxer option.
    ///
    /// This method should be called as many times as the number of options
    /// present in a muxer.
    pub fn set_option<'a, V>(&mut self, key: &str, val: V) -> Result<()>
    where
        V: Into<Value<'a>>,
    {
        self.muxer.set_option(key, val.into())
    }
}

/// Format descriptor.
///
/// Contains information on a format and its own muxer.
#[derive(Clone, Debug, PartialEq)]
pub struct Descr {
    /// Format name.
    pub name: &'static str,
    /// Muxer name.
    pub demuxer: &'static str,
    /// Format description.
    pub description: &'static str,
    /// Format media file extensions.
    pub extensions: &'static [&'static str],
    /// Format MIME.
    pub mime: &'static [&'static str],
}

/// Used to get a format descriptor and create a new muxer.
pub trait Descriptor {
    /// Creates a new muxer for the requested format.
    fn create(&self) -> Box<dyn Muxer>;
    /// Returns the descriptor of a format.
    fn describe(&self) -> &Descr;
}

/// Used to look for a specific format.
pub trait Lookup {
    /// Retrieves a specific format by name.
    fn by_name(&self, name: &str) -> Option<&'static dyn Descriptor>;
}

impl Lookup for [&'static dyn Descriptor] {
    fn by_name(&self, name: &str) -> Option<&'static dyn Descriptor> {
        self.iter().find(|&&d| d.describe().name == name).copied()
    }
}
<commit_msg>format: Replace Box with a generic for Muxer<commit_after>use crate::common::*;
use crate::data::packet::Packet;
use crate::data::value::*;
use std::any::Any;
use std::io::{ErrorKind, Seek, SeekFrom, Write};
use std::sync::Arc;

use crate::error::*;

pub trait WriteSeek: Write + Seek {}

impl<T: Write + Seek> WriteSeek for T {}

/// Runtime wrapper around either a [`Write`] or a [`WriteSeek`] trait object which supports querying
/// for seek support.
pub enum Writer {
    NonSeekable(Box<dyn Write>, u64),
    Seekable(Box<dyn WriteSeek>),
}

impl Writer {
    /// Creates a [`Writer`] from a trait object that implements both [`Write`] and [`Seek`].
    pub fn from_seekable(inner: Box<dyn WriteSeek>) -> Self {
        Self::Seekable(inner)
    }

    /// Creates a [`Writer`] from a trait object that implements the [`Write`] trait.
    pub fn from_nonseekable(inner: Box<dyn Write>) -> Self {
        Self::NonSeekable(inner, 0)
    }

    /// Returns whether the [`Writer`] can seek within the source.
    pub fn can_seek(&self) -> bool {
        matches!(self, Self::Seekable(_))
    }
}

impl Write for Writer {
    fn write(&mut self, bytes: &[u8]) -> std::io::Result<usize> {
        match self {
            Self::NonSeekable(inner, ref mut index) => {
                let result = inner.write(bytes);

                if let Ok(written) = result {
                    *index += written as u64;
                }

                result
            }
            Self::Seekable(inner) => inner.write(bytes),
        }
    }

    fn flush(&mut self) -> std::io::Result<()> {
        match self {
            Self::NonSeekable(inner, ..) => inner.flush(),
            Self::Seekable(inner) => inner.flush(),
        }
    }
}

impl Seek for Writer {
    fn seek(&mut self, seek: SeekFrom) -> std::io::Result<u64> {
        match self {
            Self::NonSeekable(_, index) => {
                if let SeekFrom::Current(0) = seek {
                    Ok(*index)
                } else {
                    Err(std::io::Error::new(
                        ErrorKind::Other,
                        "Seeking not supported",
                    ))
                }
            }
            Self::Seekable(inner) => inner.seek(seek),
        }
    }
}

/// Used to implement muxing operations.
pub trait Muxer: Send {
    /// Configures a muxer.
    fn configure(&mut self) -> Result<()>;
    /// Writes a stream header into a data structure implementing
    /// the `Write` trait.
    fn write_header(&mut self, out: &mut Writer) -> Result<()>;
    /// Writes a stream packet into a data structure implementing
    /// the `Write` trait.
    fn write_packet(&mut self, out: &mut Writer, pkt: Arc<Packet>) -> Result<()>;
    /// Writes a stream trailer into a data structure implementing
    /// the `Write` trait.
    fn write_trailer(&mut self, out: &mut Writer) -> Result<()>;

    /// Sets global media file information for a muxer.
    fn set_global_info(&mut self, info: GlobalInfo) -> Result<()>;
    /// Sets a muxer option.
    ///
    /// This method should be called as many times as the number of options
    /// present in a muxer.
    fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()>;
}

/// Auxiliary structure to encapsulate a muxer object and
/// its additional data.
pub struct Context<M: Muxer + Send> {
    muxer: M,
    writer: Writer,
    /// User private data.
    ///
    /// This data cannot be cloned.
    pub user_private: Option<Box<dyn Any + Send + Sync>>,
}

impl<M: Muxer + Send> Context<M> {
    /// Creates a new `Context` instance.
    pub fn new(muxer: M, writer: Writer) -> Self {
        Context {
            muxer,
            writer,
            user_private: None,
        }
    }

    /// Configures a muxer.
    pub fn configure(&mut self) -> Result<()> {
        self.muxer.configure()
    }

    /// Writes a stream header to an internal buffer and returns how many
    /// bytes were written or an error.
    pub fn write_header(&mut self) -> Result<()> {
        self.muxer.write_header(&mut self.writer)
    }

    /// Writes a stream packet to an internal buffer and returns how many
    /// bytes were written or an error.
    pub fn write_packet(&mut self, pkt: Arc<Packet>) -> Result<()> {
        self.muxer.write_packet(&mut self.writer, pkt)
    }

    /// Writes a stream trailer to an internal buffer and returns how many
    /// bytes were written or an error.
    pub fn write_trailer(&mut self) -> Result<()> {
        self.muxer.write_trailer(&mut self.writer)?;
        self.writer.flush()?;

        Ok(())
    }

    /// Sets global media file information for a muxer.
    pub fn set_global_info(&mut self, info: GlobalInfo) -> Result<()> {
        self.muxer.set_global_info(info)
    }

    /// Sets a muxer option.
    ///
    /// This method should be called as many times as the number of options
    /// present in a muxer.
    pub fn set_option<'a, V>(&mut self, key: &str, val: V) -> Result<()>
    where
        V: Into<Value<'a>>,
    {
        self.muxer.set_option(key, val.into())
    }
}

/// Format descriptor.
///
/// Contains information on a format and its own muxer.
#[derive(Clone, Debug, PartialEq)]
pub struct Descr {
    /// Format name.
    pub name: &'static str,
    /// Muxer name.
    pub demuxer: &'static str,
    /// Format description.
    pub description: &'static str,
    /// Format media file extensions.
    pub extensions: &'static [&'static str],
    /// Format MIME.
    pub mime: &'static [&'static str],
}

/// Used to get a format descriptor and create a new muxer.
pub trait Descriptor {
    type OutputMuxer: Muxer + Send;

    /// Creates a new muxer for the requested format.
    fn create(&self) -> Self::OutputMuxer;
    /// Returns the descriptor of a format.
    fn describe(&self) -> &Descr;
}

/// Used to look for a specific format.
pub trait Lookup<T: Descriptor + ?Sized> {
    /// Retrieves a specific format by name.
    fn by_name(&self, name: &str) -> Option<&'static T>;
}

impl<T: Descriptor + ?Sized> Lookup<T> for [&'static T] {
    fn by_name(&self, name: &str) -> Option<&'static T> {
        self.iter().find(|&&d| d.describe().name == name).copied()
    }
}
<|endoftext|>


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

#[macro_use]
extern crate prost_derive;

#[macro_use]
extern crate serde_derive;

mod error;
mod generated;
mod types;

use crate::error::Result;
pub use crate::{error::Error, types::*};

pub const LAUNCHER_PIPE_ENV: &str = "HAB_LAUNCHER_PIPE";
pub const LAUNCHER_PID_ENV: &str = "HAB_LAUNCHER_PID";
// Set to instruct the Supervisor to clean the Launcher's process LOCK on startup. This is useful
// when restarting a Supervisor which terminated normally.
pub const LAUNCHER_LOCK_CLEAN_ENV: &str = "HAB_LAUNCHER_LOCK_CLEAN";
/// Process exit code from Supervisor which indicates to Launcher that the Supervisor
/// ran to completion with a successful result. The Launcher should not attempt to restart
/// the Supervisor and should exit immediately with a successful exit code.
pub const OK_NO_RETRY_EXCODE: i32 = 84;
/// Same as `OK_NO_RETRY_EXCODE` except the Supervisor ran to completion with an unsuccessful
/// exit code. The Launcher should exit immediately with a non-zero exit code.
pub const ERR_NO_RETRY_EXCODE: i32 = 86;

#[derive(Debug)]
pub struct NetTxn(Envelope);

impl NetTxn {
    pub fn build<T>(message: &T) -> Result<Self>
    where
        T: LauncherMessage,
    {
        let mut env = Envelope::default();
        env.message_id = T::MESSAGE_ID.to_string();
        env.payload = message.to_bytes()?;
        Ok(NetTxn(env))
    }

    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
        let env = Envelope::from_bytes(bytes)?;
        Ok(NetTxn(env))
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>> {
        self.0.clone().to_bytes()
    }

    pub fn build_reply<T>(&self, message: &T) -> Result<Self>
    where
        T: LauncherMessage,
    {
        Ok(Self::build(message)?)
    }

    pub fn decode<T>(&self) -> Result<T>
    where
        T: LauncherMessage,
    {
        T::from_bytes(&self.0.payload)
    }

    pub fn message_id(&self) -> &str {
        &self.0.message_id
    }
}

pub fn error<T>(err: T) -> NetErr
where
    T: ToString + Into<ErrCode>,
{
    NetErr {
        msg: err.to_string(),
        code: err.into(),
    }
}
<commit_msg>Construct an Envelope directly, rather than mutating one<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate prost_derive;

#[macro_use]
extern crate serde_derive;

mod error;
mod generated;
mod types;

use crate::error::Result;
pub use crate::{error::Error, types::*};

pub const LAUNCHER_PIPE_ENV: &str = "HAB_LAUNCHER_PIPE";
pub const LAUNCHER_PID_ENV: &str = "HAB_LAUNCHER_PID";
// Set to instruct the Supervisor to clean the Launcher's process LOCK on startup. This is useful
// when restarting a Supervisor which terminated normally.
pub const LAUNCHER_LOCK_CLEAN_ENV: &str = "HAB_LAUNCHER_LOCK_CLEAN";
/// Process exit code from Supervisor which indicates to Launcher that the Supervisor
/// ran to completion with a successful result. The Launcher should not attempt to restart
/// the Supervisor and should exit immediately with a successful exit code.
pub const OK_NO_RETRY_EXCODE: i32 = 84;
/// Same as `OK_NO_RETRY_EXCODE` except the Supervisor ran to completion with an unsuccessful
/// exit code. The Launcher should exit immediately with a non-zero exit code.
pub const ERR_NO_RETRY_EXCODE: i32 = 86;

#[derive(Debug)]
pub struct NetTxn(Envelope);

impl NetTxn {
    pub fn build<T>(message: &T) -> Result<Self>
    where
        T: LauncherMessage,
    {
        let env = Envelope {
            message_id: T::MESSAGE_ID.to_string(),
            payload: message.to_bytes()?,
        };
        Ok(NetTxn(env))
    }

    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
        let env = Envelope::from_bytes(bytes)?;
        Ok(NetTxn(env))
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>> {
        self.0.clone().to_bytes()
    }

    pub fn build_reply<T>(&self, message: &T) -> Result<Self>
    where
        T: LauncherMessage,
    {
        Ok(Self::build(message)?)
    }

    pub fn decode<T>(&self) -> Result<T>
    where
        T: LauncherMessage,
    {
        T::from_bytes(&self.0.payload)
    }

    pub fn message_id(&self) -> &str {
        &self.0.message_id
    }
}

pub fn error<T>(err: T) -> NetErr
where
    T: ToString + Into<ErrCode>,
{
    NetErr {
        msg: err.to_string(),
        code: err.into(),
    }
}
<|endoftext|>


<commit_before>use super::*;
use crate::client::Context;
use crate::model::channel::Message;
use uwl::{StrExt, StringStream};

#[derive(Debug, Clone, PartialEq)]
pub enum Prefix<'a> {
    Punct(&'a str),
    Mention(&'a str),
    None,
    #[doc(hidden)]
    __Nonexhaustive,
}

pub fn parse_prefix<'a>(
    ctx: &mut Context,
    msg: &'a Message,
    config: &Configuration,
) -> (Prefix<'a>, &'a str) {
    let mut stream = StringStream::new(&msg.content);
    stream.take_while(|s| s.is_whitespace());

    if let Some(ref mention) = config.on_mention {
        if let Ok(id) = stream.parse("<@(!){}>") {
            if id.is_numeric() && mention == id {
                stream.take_while(|s| s.is_whitespace());
                return (Prefix::Mention(id), stream.rest());
            }
        }
    }

    let mut prefix = None;
    if !config.prefixes.is_empty() || !config.dynamic_prefixes.is_empty() {
        for f in &config.dynamic_prefixes {
            if let Some(p) = f(ctx, msg) {
                let pp = stream.peek_for(p.chars().count());

                if p == pp {
                    prefix = Some(pp);
                    break;
                }
            }
        }

        for p in &config.prefixes {
            // If `dynamic_prefixes` succeeded, don't iterate through the normal prefixes.
            if prefix.is_some() {
                break;
            }

            let pp = stream.peek_for(p.chars().count());

            if p == pp {
                prefix = Some(pp);
                break;
            }
        }
    }

    if let Some(prefix) = prefix {
        stream.increment(prefix.len());

        if config.with_whitespace.prefixes {
            stream.take_while(|s| s.is_whitespace());
        }

        let args = stream.rest();

        return (Prefix::Punct(prefix), args.trim());
    }

    if config.with_whitespace.prefixes {
        stream.take_while(|s| s.is_whitespace());
    }

    let args = stream.rest();
    (Prefix::None, args.trim())
}

struct CommandParser<'msg, 'groups, 'config, 'ctx> {
    msg: &'msg Message,
    stream: StringStream<'msg>,
    groups: &'groups [&'static CommandGroup],
    config: &'config Configuration,
    ctx: &'ctx Context,
    unrecognised: Option<&'msg str>,
}

impl<'msg, 'groups, 'config, 'ctx> CommandParser<'msg, 'groups, 'config, 'ctx> {
    fn new(
        msg: &'msg Message,
        stream: StringStream<'msg>,
        groups: &'groups [&'static CommandGroup],
        config: &'config Configuration,
        ctx: &'ctx Context,
    ) -> Self {
        CommandParser {
            msg,
            stream,
            groups,
            config,
            ctx,
            unrecognised: None,
        }
    }

    fn next_text(&self, length: impl FnOnce() -> usize) -> &'msg str {
        if self.config.by_space {
            self.stream.peek_until(|s| s.is_whitespace())
        } else {
            self.stream.peek_for(length())
        }
    }

    fn as_lowercase(&self, s: &str, f: impl FnOnce(&str) -> bool) -> bool {
        if self.config.case_insensitive {
            let s = s.to_lowercase();
            f(&s)
        } else {
            f(s)
        }
    }

    fn check_discrepancy(&self, options: &impl CommonOptions) -> Result<(), DispatchError> {
        if options.owners_only() && !self.config.owners.contains(&self.msg.author.id) {
            return Err(DispatchError::OnlyForOwners);
        }

        if options.only_in() == OnlyIn::Dm && !self.msg.is_private() {
            return Err(DispatchError::OnlyForDM);
        }

        if (!self.config.allow_dm || options.only_in() == OnlyIn::Guild) && self.msg.is_private() {
            return Err(DispatchError::OnlyForGuilds);
        }

        #[cfg(feature = "cache")]
        {
            if let Some(guild_id) = self.msg.guild_id {
                let guild = match guild_id.to_guild_cached(&self.ctx) {
                    Some(g) => g,
                    None => return Ok(()),
                };

                let guild = guild.read();

                let perms = guild.permissions_in(self.msg.channel_id, self.msg.author.id);

                if !perms.contains(*options.required_permissions()) &&
                    !(options.owner_privilege() &&
                        self.config.owners.contains(&self.msg.author.id)) {
                    return Err(DispatchError::LackingPermissions(*options.required_permissions()));
                }

                if let Some(member) = guild.members.get(&self.msg.author.id) {
                    if !perms.administrator() && !has_correct_roles(options, &guild, &member) {
                        return Err(DispatchError::LackingRole);
                    }
                }

            }
        }

        Ok(())
    }

    fn command(&mut self, command: &'static Command) -> Result<Option<&'static Command>, DispatchError> {
        for name in command.options.names {
            // FIXME: If `by_space` option is set true, we shouldn't be retrieving the block of text
            // again and again for the command name.
            let n = self.next_text(|| name.chars().count());

            let equals = self.as_lowercase(n, |n| n == *name && !self.config.disabled_commands.contains(n));

            if equals {
                self.stream.increment(n.len());

                if self.config.with_whitespace.commands {
                    self.stream.take_while(|s| s.is_whitespace());
                }

                for sub in command.options.sub_commands {
                    if let Some(cmd) = self.command(sub)? {
                        self.unrecognised = None;
                        return Ok(Some(cmd));
                    }
                }

                self.check_discrepancy(&command.options)?;

                self.unrecognised = None;
                return Ok(Some(command));
            }

            self.unrecognised = Some(n);
        }

        Ok(None)
    }

    fn group(&mut self, group: &'static CommandGroup) -> Result<(Option<&'msg str>, &'static CommandGroup), DispatchError> {
        // Do not bother going through this group's prefixes if it doesn't contain any, but
        // try if its sub-groups maybe do and are satisfied in the message.
        if group.options.prefixes.is_empty() {
            for sub_group in group.sub_groups {
                let x = self.group(*sub_group)?;

                if x.0.is_some() {
                    return Ok(x);
                }
            }

            // It appears they don't. Fall back to using this group.
            self.check_discrepancy(&group.options)?;

            return Ok((None, group));
        }

        for p in group.options.prefixes {
            let pp = self.next_text(|| p.chars().count());

            if *p == pp {
                self.stream.increment(pp.len());

                if self.config.with_whitespace.groups {
                    self.stream.take_while(|s| s.is_whitespace());
                }

                for sub_group in group.sub_groups {
                    let x = self.group(*sub_group)?;

                    if x.0.is_some() {
                        return Ok(x);
                    }
                }

                self.check_discrepancy(&group.options)?;
                return Ok((Some(pp), group));
            }
        }

        Ok((None, group))
    }

    fn parse(mut self, prefix: Prefix<'msg>) -> Result<Invoke<'msg>, Result<Option<&'msg str>, DispatchError>> {
        let pos = self.stream.offset();
        for group in self.groups {
            let (gprefix, group) = match self.group(*group) {
                Ok(t) => t,
                Err(err) => return Err(Err(err)),
            };

            if gprefix.is_none() && !group.options.prefixes.is_empty() {
                unsafe { self.stream.set_unchecked(pos) };
                continue;
            }

            for command in group.commands {
                let command = match self.command(command)  {
                    Ok(c) => c,
                    Err(err) => return Err(Err(err)),
                };

                if let Some(command) = command {
                    return Ok(Invoke::Command {
                        prefix,
                        group,
                        gprefix,
                        command,
                        args: self.stream.rest(),
                    });
                }
            }

            // Only execute the default command if a group prefix is present.
            if let Some(command) = group.options.default_command {
                if gprefix.is_some() {
                    return Ok(Invoke::Command {
                        prefix,
                        group,
                        gprefix,
                        command,
                        args: self.stream.rest(),
                    });
                }
            }

            unsafe { self.stream.set_unchecked(pos) };
        }

        Err(Ok(self.unrecognised))
    }
}

pub(crate) fn parse_command<'a>(
    message: &'a str,
    msg: &'a Message,
    prefix: Prefix<'a>,
    groups: &[&'static CommandGroup],
    config: &Configuration,
    ctx: &Context,
    help_was_set: Option<&[&'static str]>,
) -> Result<Invoke<'a>, Result<Option<&'a str>, DispatchError>> {
    let mut stream = StringStream::new(message);
    stream.take_while(|s| s.is_whitespace());

    // We take precedence over commands named help command's name.
    if let Some(names) = help_was_set {
        for name in names {
            if stream.eat(name) {
                stream.take_while(|s| s.is_whitespace());

                let args = stream.rest();

                return Ok(Invoke::Help { prefix, name, args });
            }
        }
    }

    CommandParser::new(msg, stream, groups, config, ctx).parse(prefix)
}

#[derive(Debug)]
pub enum Invoke<'a> {
    Command {
        prefix: Prefix<'a>,
        // Group prefix
        gprefix: Option<&'a str>,

        group: &'static CommandGroup,
        command: &'static Command,
        args: &'a str,
    },
    Help {
        prefix: Prefix<'a>,
        name: &'static str,
        args: &'a str,
    },
}
<commit_msg>Move the discrepancy check of prefixless groups much below<commit_after>use super::*;
use crate::client::Context;
use crate::model::channel::Message;
use uwl::{StrExt, StringStream};

#[derive(Debug, Clone, PartialEq)]
pub enum Prefix<'a> {
    Punct(&'a str),
    Mention(&'a str),
    None,
    #[doc(hidden)]
    __Nonexhaustive,
}

pub fn parse_prefix<'a>(
    ctx: &mut Context,
    msg: &'a Message,
    config: &Configuration,
) -> (Prefix<'a>, &'a str) {
    let mut stream = StringStream::new(&msg.content);
    stream.take_while(|s| s.is_whitespace());

    if let Some(ref mention) = config.on_mention {
        if let Ok(id) = stream.parse("<@(!){}>") {
            if id.is_numeric() && mention == id {
                stream.take_while(|s| s.is_whitespace());
                return (Prefix::Mention(id), stream.rest());
            }
        }
    }

    let mut prefix = None;
    if !config.prefixes.is_empty() || !config.dynamic_prefixes.is_empty() {
        for f in &config.dynamic_prefixes {
            if let Some(p) = f(ctx, msg) {
                let pp = stream.peek_for(p.chars().count());

                if p == pp {
                    prefix = Some(pp);
                    break;
                }
            }
        }

        for p in &config.prefixes {
            // If `dynamic_prefixes` succeeded, don't iterate through the normal prefixes.
            if prefix.is_some() {
                break;
            }

            let pp = stream.peek_for(p.chars().count());

            if p == pp {
                prefix = Some(pp);
                break;
            }
        }
    }

    if let Some(prefix) = prefix {
        stream.increment(prefix.len());

        if config.with_whitespace.prefixes {
            stream.take_while(|s| s.is_whitespace());
        }

        let args = stream.rest();

        return (Prefix::Punct(prefix), args.trim());
    }

    if config.with_whitespace.prefixes {
        stream.take_while(|s| s.is_whitespace());
    }

    let args = stream.rest();
    (Prefix::None, args.trim())
}

struct CommandParser<'msg, 'groups, 'config, 'ctx> {
    msg: &'msg Message,
    stream: StringStream<'msg>,
    groups: &'groups [&'static CommandGroup],
    config: &'config Configuration,
    ctx: &'ctx Context,
    unrecognised: Option<&'msg str>,
}

impl<'msg, 'groups, 'config, 'ctx> CommandParser<'msg, 'groups, 'config, 'ctx> {
    fn new(
        msg: &'msg Message,
        stream: StringStream<'msg>,
        groups: &'groups [&'static CommandGroup],
        config: &'config Configuration,
        ctx: &'ctx Context,
    ) -> Self {
        CommandParser {
            msg,
            stream,
            groups,
            config,
            ctx,
            unrecognised: None,
        }
    }

    fn next_text(&self, length: impl FnOnce() -> usize) -> &'msg str {
        if self.config.by_space {
            self.stream.peek_until(|s| s.is_whitespace())
        } else {
            self.stream.peek_for(length())
        }
    }

    fn as_lowercase(&self, s: &str, f: impl FnOnce(&str) -> bool) -> bool {
        if self.config.case_insensitive {
            let s = s.to_lowercase();
            f(&s)
        } else {
            f(s)
        }
    }

    fn check_discrepancy(&self, options: &impl CommonOptions) -> Result<(), DispatchError> {
        if options.owners_only() && !self.config.owners.contains(&self.msg.author.id) {
            return Err(DispatchError::OnlyForOwners);
        }

        if options.only_in() == OnlyIn::Dm && !self.msg.is_private() {
            return Err(DispatchError::OnlyForDM);
        }

        if (!self.config.allow_dm || options.only_in() == OnlyIn::Guild) && self.msg.is_private() {
            return Err(DispatchError::OnlyForGuilds);
        }

        #[cfg(feature = "cache")]
        {
            if let Some(guild_id) = self.msg.guild_id {
                let guild = match guild_id.to_guild_cached(&self.ctx) {
                    Some(g) => g,
                    None => return Ok(()),
                };

                let guild = guild.read();

                let perms = guild.permissions_in(self.msg.channel_id, self.msg.author.id);

                if !perms.contains(*options.required_permissions()) &&
                    !(options.owner_privilege() &&
                        self.config.owners.contains(&self.msg.author.id)) {
                    return Err(DispatchError::LackingPermissions(*options.required_permissions()));
                }

                if let Some(member) = guild.members.get(&self.msg.author.id) {
                    if !perms.administrator() && !has_correct_roles(options, &guild, &member) {
                        return Err(DispatchError::LackingRole);
                    }
                }

            }
        }

        Ok(())
    }

    fn command(&mut self, command: &'static Command) -> Result<Option<&'static Command>, DispatchError> {
        for name in command.options.names {
            // FIXME: If `by_space` option is set true, we shouldn't be retrieving the block of text
            // again and again for the command name.
            let n = self.next_text(|| name.chars().count());

            let equals = self.as_lowercase(n, |n| n == *name && !self.config.disabled_commands.contains(n));

            if equals {
                self.stream.increment(n.len());

                if self.config.with_whitespace.commands {
                    self.stream.take_while(|s| s.is_whitespace());
                }

                for sub in command.options.sub_commands {
                    if let Some(cmd) = self.command(sub)? {
                        self.unrecognised = None;
                        return Ok(Some(cmd));
                    }
                }

                self.check_discrepancy(&command.options)?;

                self.unrecognised = None;
                return Ok(Some(command));
            }

            self.unrecognised = Some(n);
        }

        Ok(None)
    }

    fn group(&mut self, group: &'static CommandGroup) -> Result<(Option<&'msg str>, &'static CommandGroup), DispatchError> {
        // Do not bother going through this group's prefixes if it doesn't contain any, but
        // try if its sub-groups maybe do and are satisfied in the message.
        if group.options.prefixes.is_empty() {
            for sub_group in group.sub_groups {
                let x = self.group(*sub_group)?;

                if x.0.is_some() {
                    return Ok(x);
                }
            }

            return Ok((None, group));
        }

        for p in group.options.prefixes {
            let pp = self.next_text(|| p.chars().count());

            if *p == pp {
                self.stream.increment(pp.len());

                if self.config.with_whitespace.groups {
                    self.stream.take_while(|s| s.is_whitespace());
                }

                for sub_group in group.sub_groups {
                    let x = self.group(*sub_group)?;

                    if x.0.is_some() {
                        return Ok(x);
                    }
                }

                self.check_discrepancy(&group.options)?;
                return Ok((Some(pp), group));
            }
        }

        Ok((None, group))
    }

    fn parse(mut self, prefix: Prefix<'msg>) -> Result<Invoke<'msg>, Result<Option<&'msg str>, DispatchError>> {
        let pos = self.stream.offset();
        for group in self.groups {
            let (gprefix, group) = match self.group(*group) {
                Ok(t) => t,
                Err(err) => return Err(Err(err)),
            };

            if gprefix.is_none() && !group.options.prefixes.is_empty() {
                unsafe { self.stream.set_unchecked(pos) };
                continue;
            }

            for command in group.commands {
                let command = match self.command(command)  {
                    Ok(c) => c,
                    Err(err) => return Err(Err(err)),
                };

                if let Some(command) = command {
                    if group.options.prefixes.is_empty() {
                        // Might seem a little late to do at this point of time, like it would
                        // have been better to test against any discrepancies of this group
                        // in the `group` method then continue said test in the `command` method,
                        // but we can't accurately perform that on a group with no prefixes.
                        // I.e. Does the message contain this group? Well, maybe God knows, but we
                        // certainly don't and cannot if we don't have any sort of text to verify with.
                        if let Err(err) = self.check_discrepancy(&group.options) {
                            return Err(Err(err));
                        }
                    }

                    return Ok(Invoke::Command {
                        prefix,
                        group,
                        gprefix,
                        command,
                        args: self.stream.rest(),
                    });
                }
            }

            // Only execute the default command if a group prefix is present.
            if let Some(command) = group.options.default_command {
                if gprefix.is_some() {
                    return Ok(Invoke::Command {
                        prefix,
                        group,
                        gprefix,
                        command,
                        args: self.stream.rest(),
                    });
                }
            }

            unsafe { self.stream.set_unchecked(pos) };
        }

        Err(Ok(self.unrecognised))
    }
}

pub(crate) fn parse_command<'a>(
    message: &'a str,
    msg: &'a Message,
    prefix: Prefix<'a>,
    groups: &[&'static CommandGroup],
    config: &Configuration,
    ctx: &Context,
    help_was_set: Option<&[&'static str]>,
) -> Result<Invoke<'a>, Result<Option<&'a str>, DispatchError>> {
    let mut stream = StringStream::new(message);
    stream.take_while(|s| s.is_whitespace());

    // We take precedence over commands named help command's name.
    if let Some(names) = help_was_set {
        for name in names {
            if stream.eat(name) {
                stream.take_while(|s| s.is_whitespace());

                let args = stream.rest();

                return Ok(Invoke::Help { prefix, name, args });
            }
        }
    }

    CommandParser::new(msg, stream, groups, config, ctx).parse(prefix)
}

#[derive(Debug)]
pub enum Invoke<'a> {
    Command {
        prefix: Prefix<'a>,
        // Group prefix
        gprefix: Option<&'a str>,

        group: &'static CommandGroup,
        command: &'static Command,
        args: &'a str,
    },
    Help {
        prefix: Prefix<'a>,
        name: &'static str,
        args: &'a str,
    },
}
<|endoftext|>