<commit_before>#![allow(warnings)]
use std::env;
use std::io::prelude::*;
use std::fs::File;
use std::process::exit;
use std::collections::linked_list::LinkedList;
use std::f32;
use std::clone;

#[derive(Clone)]
struct Node {
	id : i32,
	x : i32,
	y : i32,
}

fn main() {
	// println!("\n\n--\nTesting\n--\n\n");

	//Get test_file path
	let mut args_iterator = env::args();
	let mut path_string = String::new();
	if args_iterator.nth(1).is_some() {
		args_iterator = env::args();
		path_string = args_iterator.nth(1).unwrap();
		// println!("TestFile Path: {}\n", path_string);
	}
	else {
		println!("ERROR: No input file specified.");
		exit(0);
	}

	let mut test_file = File::open(path_string).unwrap();
	let mut all_text = String::new();
	test_file.read_to_string(&mut all_text);
	// println!("\nFile contents:\n{}\nEND File contents\n", all_text);

	let mut split_point = all_text.find("NODE_COORD_SECTION");

	if split_point == None {
		println!("ERROR: Input file has invalid syntax. No NODE_COORD_SECTION.");
		exit(0);
	}

	let (trash, nodes_text) = all_text.split_at(split_point.unwrap());
	drop(trash);

	split_point = nodes_text.find("\n");

	if split_point == None {
		println!("ERROR: Input file has invalid syntax. No data after NODE_COORD_SECTION");
		exit(0);
	}

	let (trash, nodes_text) = nodes_text.split_at(split_point.unwrap()+1);
	drop(trash);

	split_point = nodes_text.find("EOF");

	if split_point == None {
		println!("ERROR: Input file has invalid syntax. No explicit (literal) EOF.");
		exit(0);
	}

	let (nodes_text, trash) = nodes_text.split_at(split_point.unwrap()-1);
	drop(trash);

	// println!("\nnodes_text:\n{}", nodes_text);
	// println!("-\nEND nodes_text\n");

	let nodes_iterator = nodes_text.lines();

	let mut path : Vec<Node> = Vec::new();
	let mut temp_id : i32 = 0;
	let mut temp_x : i32 = 0;
	let mut temp_y : i32 = 0;

	for each_node in nodes_iterator {

		let mut coords_iterator = each_node.split_whitespace();
		//First num will be id
		temp_id = coords_iterator.next().unwrap().parse::<i32>().unwrap();
		//Second num will be x coordinate
		temp_x = coords_iterator.next().unwrap().parse::<i32>().unwrap();
		//Third num will be y coordinate
		temp_y = coords_iterator.next().unwrap().parse::<i32>().unwrap();
		//That should be the end of this line.

		let mut new_node = Node {id:temp_id, x:temp_x, y:temp_y};
		// println!("Adding Node ({}, {}, {}, {})", new_node.index, new_node.id, new_node.x, new_node.y);
		path.push(new_node);
	}

	// println!("{}, {}, {}, {}", path[26].index, path[26].id, path[26].x, path[26].y);
	let mut yeezy : usize = 1;
	let mut slim_shady : usize = yeezy;
	let mut new_distance : f32 = 0.0;
	let original_distance = total_distance(&path);
	let mut current_distance = original_distance;
	let mut flag_reset_loop : bool = false;
	let path_length = path.len();
	let mut counter : u64 = 0;
	let mut new_path : Vec<Node> = Vec::new();

	//Attemp each possible swap
	'outer: loop {
		if yeezy >= path_length {
			break 'outer;
		}
		// if counter >= 500 {
		// 	break 'outer;
		// }
		'inner: loop {
			if slim_shady >= path_length {
				slim_shady = yeezy+1;
				break 'inner;
			}
			// println!("Testing {}[{}]\t{}[{}]", yeezy, path[yeezy].id, slim_shady, path[slim_shady].id);
			// let current_distance = distance(yeezy, slim_shady, &path);
			new_distance = test_distance(yeezy, slim_shady, &path, current_distance);
			if new_distance < current_distance {
				// println!("FOUND BETTER PATH by swapping {} and {}\t\t{}", yeezy, slim_shady, counter);
				// println!("{:?}", current_distance);
				// println!("{:?}", new_distance);

				//make the swap
				new_path.clear();
				new_path.extend_from_slice(swap(yeezy, slim_shady, & mut path));
				// v.extend(s.iter().cloned());
				path.clear();
				path.extend_from_slice(&new_path);
				//update current_distance
				current_distance = total_distance(&path);
				//restart from very beginning
				flag_reset_loop = true;
				counter += 1;
				break 'inner;
			}
			// println!("Distance from {} to {} = {}", yeezy, slim_shady, current_distance);
			slim_shady += 1;
		}
		if flag_reset_loop {
			yeezy = 1;
			slim_shady = yeezy;
			flag_reset_loop = false;
			continue 'outer;
		}
		yeezy += 1;
	}
	// println!("current_distance:\t{}", current_distance);
	// new_distance = test_distance(1, 3, &path, current_distance);

	// println!("new_distance:\t{}", new_distance);

	// path.swap(1, 3);

	//Print IDs for verification
	//
	for eachNode in path.iter() {
		println!("{:?}", eachNode.id);
	}

	let totes_distance = total_distance(&path);
	println!("\nOriginal Distance: {}", original_distance);
	println!("Solution Distance: {}", totes_distance);

	//If starting from a280, then solution distance will be 2727.229

	// println!("\n\n--\nEND\n--\n\n");
}

//return the distance between two nodes
fn distance(yeezy: usize, slim_shady : usize, billboard: &[Node]) -> f32{
	let mut distance : f32 = 0.0;
	let mut x_distance: f32 = 0.0;
	let mut y_distance: f32 = 0.0;
	x_distance = (billboard[yeezy].x - billboard[slim_shady].x) as f32;
	y_distance = (billboard[yeezy].y - billboard[slim_shady].y) as f32;
	distance = x_distance.powi(2) + y_distance.powi(2);
	distance = distance.sqrt();

	distance

}

//Return the total distance of the tour (index 0 to max)
fn total_distance(billboard : &[Node]) -> f32{
	let mut distance_accumulator : f32 = 0.0;
	let max_index = billboard.len() - 1;

	//Compute sum of all distances except from last to first.
	//Upper bound is excluded in for loops
	//max(index) will be billboard.len()-1-1 = 280-2 = 278
	//So the for loop will computer the sum till index 279
	for index in 0..max_index {
		distance_accumulator += distance(index as usize, index+1 as usize, billboard);
		// println!("Distance from {} to {}", index, index+1);
	}
	//Add 279 to 0
	distance_accumulator += distance(max_index as usize, 0 as usize, billboard);
	// println!("Distance from {} to {}", max_index, 0);

	distance_accumulator
}

//Swap edges
fn swap(mut yeezy: usize, mut slim_shady : usize, billboard: & mut[Node]) -> & mut [Node]{
	while yeezy < slim_shady {
		billboard.swap(yeezy, slim_shady);
		yeezy += 1;
		slim_shady -= 1;
	}
	billboard
}

//Virtually swap two nodes and return new distance.
//No swapping actually occurs. Vector is unmuatable.
fn test_distance(yeezy: usize, slim_shady : usize, billboard: &[Node], current_distance: f32) -> f32{

	let mut new_distance = current_distance;

	if yeezy == slim_shady {
		return current_distance
	}

	//Edge case handling.
	// if yeezy == billboard.len()-1 {
	// 	new_distance -= distance(yeezy, 0, billboard);
	// 	new_distance -= distance(slim_shady, slim_shady+1, billboard);

	// 	new_distance += distance(yeezy, slim_shady, billboard);
	// 	new_distance += distance(0, slim_shady+1, billboard);

	// 	return new_distance
	// }

	if slim_shady == billboard.len()-1 {
		new_distance -= distance(yeezy-1, yeezy, billboard);
		new_distance -= distance(slim_shady, 0, billboard);

		new_distance += distance(yeezy-1, slim_shady, billboard);
		new_distance += distance(yeezy, 0, billboard);

		return new_distance
	}

	//Remove yeezy->yeezy+1 and slim_shady->slim_shady+1
	//Remove old edges
	new_distance -= distance(yeezy-1, yeezy, billboard);
	new_distance -= distance(slim_shady, slim_shady+1, billboard);
	//Add new edges
	new_distance += distance(yeezy-1, slim_shady, billboard);
	new_distance += distance(yeezy, slim_shady+1, billboard);

	new_distance

}<commit_msg>Cleanup functions and comments<commit_after>#![allow(warnings)]
use std::env;
use std::io::Error;
use std::io::prelude::*;
use std::fs::File;
use std::process::exit;
use std::f32;

#[derive(Clone)]
struct Node {
	id : i32,
	x : i32,
	y : i32,
}

fn main() {
	//Rust's type system is pretty good.
	//There are so many compile time checks!

	//If a process can error, like file reading, then you can set the return type
	//	of the function in which it is called to Result<T, E>
	//	where T is the result of success and E is the error.
	//See get_test_file() for more details.

	//Get the text in the test file.
	//The only way to get a value out of an enum is pattern matching.
	let mut all_text : String = match get_test_file() {
		Ok(text) => text,
		Err(error) => file_read_error(error),
	};

	//Parse the text in the input file. See function for more details.
	//Type declaration here is optional, it will be inferred from return type of parse()
	let mut path : Vec<Node> = parse(all_text);

	//Save the original distance for comparision later.
	let original_distance = total_distance(&path);

	//Get solution. See function for more details.
	//Notice there is no type declaration here. Just demonstrating.
	let solution_path = two_opt(path);

	print_solution(&solution_path);

	//Print original and solution distances for comparision.
	let totes_distance = total_distance(&solution_path);
	println!("\nOriginal Distance: {}", original_distance);
	println!("Solution Distance: {}", totes_distance);

	//If starting from a280, then solution distance will be:	2756.788
	//If the starting node i is set to 1 instead of 0, then
	//	the solution distance will be:							2727.229
}

fn two_opt(mut path : Vec<Node>) -> Vec<Node> {
	//yeezy 		is index i
	//slim_shady 	is index j
	//For a280.tsp, starting at 1 instead of 0 gives a better solution.
	//	That is, set yeezy = 1 to get a better solution for a280.tsp
	let mut yeezy : usize = 0;
	let mut slim_shady : usize = yeezy;
	//Used to hold the tour length of the current solution
	let mut current_distance = total_distance(&path);
	//Used to indicate that a swap has occured and the loop must start from the beginning
	let mut flag_reset_loop : bool = false;
	//Used to break from the loop if either index variable has increased out of bounds
	let path_length = path.len();
	//Used to teporarily hold the solution path for copying.
	let mut new_path : Vec<Node> = Vec::new();

	//Attemp each possible swap. For each edge, attempt swap with every other edge.
	//Edges are tracked by the index of the node they start from.
	//There is no need to attempt swapping with edges that come before the current edge because
	//	that combination has already been attempted. Therefore yeezy <= slim_shady

	//For loops in Rust work only on iterators, kinda like python.
	//Hence, an infinite loop with break conditions has to be used.
	//Index variables are modified manually.
	'outer: loop {
		//Break condition. All swaps attepted. Current solution is final solution.
		if yeezy >= path_length {
			break 'outer;
		}

		'inner: loop {
			//Break condition. All edges j for edge i have been attempted. Increment i.
			if slim_shady >= path_length {
				//i will be incremented upon breaking from this loop, but j has to incremented right here
				slim_shady = yeezy+1;
				break 'inner;
			}

			//Test the cuurent swap
			let new_distance = test_distance(yeezy, slim_shady, &path, current_distance);

			if new_distance < current_distance {
				//make the swap
				//Copy the solution to new_path
				new_path.clear();
				new_path.extend_from_slice(swap(yeezy, slim_shady, & mut path));
				//Erase the old path and copy the solution to it.
				path.clear();
				path.extend_from_slice(&new_path);
				//update current_distance
				current_distance = total_distance(&path);
				//restart from very beginning
				flag_reset_loop = true;
				break 'inner;
			}
			//This swap was not an improvement.
			//Increment j
			slim_shady += 1;
		}
		//break 'inner will arrive here.
		if flag_reset_loop {
			//Increment i, set j=i, reset the reset flag, and continue
			yeezy = 1;
			slim_shady = yeezy;
			flag_reset_loop = false;
			continue 'outer;
		}
		//All swaps with this edge i have been attempted, increment i.
		yeezy += 1;
	}

	path
}

//return the distance between two nodes, indicated by index.
//No error checking. This method is only called by other methods that have error checking
fn distance(yeezy: usize, slim_shady : usize, billboard: &[Node]) -> f32{

	let x_distance = (billboard[yeezy].x - billboard[slim_shady].x) as f32;
	let y_distance = (billboard[yeezy].y - billboard[slim_shady].y) as f32;
	let distance = f32::sqrt(x_distance.powi(2) + y_distance.powi(2));
	distance
}

//Return the total distance of the tour (cyclical tour, so max->0 is included)
fn total_distance(billboard : &[Node]) -> f32{

	let mut distance_accumulator : f32 = 0.0;
	let max_index = billboard.len() - 1;

	//Compute sum of all distances except from last to first.
	//In Rust for loops, the upper bound is excluded. Therefore:
	//	max(index) will be billboard.len()-1-1 = 280-2 = 278
	//So the for loop will compute the sum till index 279
	for index in 0..max_index {
		distance_accumulator += distance(index as usize, index+1 as usize, billboard);
	}
	//Add 279 to 0
	distance_accumulator += distance(max_index as usize, 0 as usize, billboard);

	distance_accumulator
}

//Swap edges
//The vector containing the path is passed as a mutable slice, and the modified slice is returned.
fn swap(mut yeezy: usize, mut slim_shady : usize, billboard: & mut[Node]) -> & mut [Node]{

	//If the requested swap is the first and last node, then simply swap them.
	if yeezy == 0 && slim_shady == billboard.len()-1 {
		billboard.swap(yeezy, slim_shady);
		billboard
	}
	//If the requested swap is anything else, then reverse all the nodes between the specified nodes inclusive.
	//1 2 3 4 5 6 7 8 9 10 and we want to swap edges between (3,4) and (8,9)
	//Then 3 will be followed by 8, and 4 will be followed by 9.
	//1 2 3 8 7 6 5 4 9 10
	else {
		while yeezy < slim_shady {
			billboard.swap(yeezy, slim_shady);
			yeezy += 1;
			slim_shady -= 1;
		}
		billboard
	}
}

//Virtually swap two nodes and return new distance.
//No swapping actually occurs. The Vector containing the path is passed as an unmuatble slice.
fn test_distance(yeezy: usize, slim_shady : usize, billboard: &[Node], current_distance: f32) -> f32{

	let mut new_distance = current_distance;

	//Swapping with self
	if yeezy == slim_shady {
		return current_distance
	}
	//Edge case handling
	//Swapping the first and last nodes.
	else if yeezy == 0 && slim_shady == billboard.len()-1 {
		new_distance -= distance(0, 1, billboard);
		new_distance -= distance(billboard.len()-2, billboard.len()-1, billboard);
		//Add new edges
		new_distance += distance(billboard.len()-1, 1, billboard);
		new_distance += distance(billboard.len()-2, 0, billboard);

		return new_distance
	}
	//Swapping the first node with some other node except the last
	else if yeezy == 0 && slim_shady != billboard.len()-1{
		new_distance -= distance(billboard.len()-1, yeezy, billboard);
		new_distance -= distance(slim_shady, slim_shady+1, billboard);
		//Add new edges
		new_distance += distance(billboard.len()-1, slim_shady, billboard);
		new_distance += distance(yeezy, slim_shady+1, billboard);

		return new_distance
	}
	//Swapping the last node with some other node except the first.
	else if yeezy != 0 && slim_shady == billboard.len()-1 {
		new_distance -= distance(yeezy-1, yeezy, billboard);
		new_distance -= distance(slim_shady, 0, billboard);

		new_distance += distance(yeezy-1, slim_shady, billboard);
		new_distance += distance(yeezy, 0, billboard);

		return new_distance
	}
	//Swapping a central node with another central node.
	else {
		new_distance -= distance(yeezy-1, yeezy, billboard);
		new_distance -= distance(slim_shady, slim_shady+1, billboard);
		//Add new edges
		new_distance += distance(yeezy-1, slim_shady, billboard);
		new_distance += distance(yeezy, slim_shady+1, billboard);

		new_distance
	}
}

//Attempt to get the test file.
//This showcases some of Rust's safety measures.
fn get_test_file() -> Result<String, Error> {

	//Get test_file path. Does not need to be in main(). WOW.
	let mut args_iterator = env::args();
	if args_iterator.nth(1).is_some() {
		//Path has been supplied. Reset iterator so it can be grabbed.
		args_iterator = env::args();
	}
	else {
		println!("ERROR: No input file specified.");
		exit(0);
	}

	//We know args_iterator.nth(1).is_some() == true so we can "safely" unwrap it.
	//The unwrap function will get the result of success.
	//If the open errors, then the try! macro will return early
	let mut test_file = try!(File::open(args_iterator.nth(1).unwrap()));
	let mut all_text = String::new();
	//If the file is empty or corrupted, then read_to_string will return an error.
	//So it is wrapped in a try! macro, which will early return an error
	try!(test_file.read_to_string(&mut all_text));
	//Phew, all of that worked. all_text now contains the text in the file.
	//Return an Ok()
	Ok(all_text)
}

//To satisfy types, this returns a string. But it will just exit.
fn file_read_error(error:Error) -> String {
	println!("ERROR: File cannot be read.");
	exit(0);
}

//Parse the input file into a Vec<Node>
fn parse(all_text : String) -> Vec<Node> {

	//Find the relevant section. We want the data after "NODE_COORD_SECTION"
	let mut split_point = all_text.find("NODE_COORD_SECTION");

	//Relevant section does not exist.
	if split_point == None {
		println!("ERROR: Input file has invalid syntax. No NODE_COORD_SECTION.");
		exit(0);
	}

	//Dump the data before "NODE_COORD_SECTION". Our data is in all_text
	let (trash, all_text) = all_text.split_at(split_point.unwrap());
	drop(trash);

	//"NODE_COORD_SECTION" is included in all_text so split at the first \n
	split_point = all_text.find("\n");

	//No data
	if split_point == None {
		println!("ERROR: Input file has invalid syntax. No data after NODE_COORD_SECTION");
		exit(0);
	}

	//Dump "NODE_COORD_SECTION\n"
	let (trash, all_text) = all_text.split_at(split_point.unwrap()+1);
	drop(trash);

	//.tsp files contain a literal "EOF"
	split_point = all_text.find("EOF");

	//"EOF" not found
	if split_point == None {
		println!("ERROR: Input file has invalid syntax. No explicit (literal) EOF.");
		exit(0);
	}

	//Dump all the data after "EOF"
	let (all_text, trash) = all_text.split_at(split_point.unwrap()-1);
	drop(trash);

	//Now have list of nodes, in the format "[id] [x] [y]" with one node per line.

	let nodes_iterator = all_text.lines();
	//An array of Nodes
	let mut path : Vec<Node> = Vec::new();

	//Parsing has no error handling. If the data is in an invalid format, the function will fail.
	//Iterate over each line in all_text, and parse the data into Node objects
	for each_node in nodes_iterator {
		//An iterator split by whitespace
		let mut coords_iterator = each_node.split_whitespace();
		//First num will be id
		let id = coords_iterator.next().unwrap().parse::<i32>().unwrap();
		//Second num will be x coordinate
		let x = coords_iterator.next().unwrap().parse::<i32>().unwrap();
		//Third num will be y coordinate
		let y = coords_iterator.next().unwrap().parse::<i32>().unwrap();
		//That should be the end of this line.

		let new_node = Node {id:id, x:x, y:y};
		path.push(new_node);
	}

	path
}

//Print solution path in array format
fn print_array(path : &[Node]){
	print!("[");
	let path_length = path.len();
	let mut counter = 0;
	for each_node in path.iter() {
		print!("{}", each_node.id);
		if counter < path_length-1 {
			print!(", ");
		}
		counter += 1;
	}
	print!("]");
}

//Print solution path in list format (one node ID on each line)
fn print_list(path : &[Node]){
	for each_node in path.iter() {
		println!("{:?}", each_node.id);
	}
}

//Print the solution path as per the flag specified when called
//Defaults to list format (one node ID on each line)
fn print_solution(solution_path : &[Node]){

	//Check if flag -printarray was specified after testfile
	let mut args_iterator = env::args();
	if args_iterator.nth(2).is_some() {
		//Flag has been specified. Reset iterator so it can be grabbed.
		args_iterator = env::args();
		let run_flag = args_iterator.nth(2).unwrap();
		if run_flag == "-printarray" {
			print_array(solution_path);
		}
		else{
			print_list(solution_path);
		}
	}
	else {
		print_list(solution_path);
	}
}<|endoftext|>


<commit_before>use VRPose;

// Represents all the information needed to render a single frame of a VR scene
#[allow(unused_attributes)]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct VRFrameData {
    // Monotonically increasing value that allows the author
    // to determine if position state data been updated from the hardware
    pub timestamp: u64,

    // major order column matrix describing the projection to be used for the left eye’s rendering
    pub left_projection_matrix: [f32; 16],

    // major order column matrix describing the view transform to be used for the left eye’s rendering
    pub left_view_matrix: [f32; 16],

    // major order column matrix describing the projection to be used for the right eye’s rendering
    pub right_projection_matrix: [f32; 16],

    // major order column matrix describing the view transform to be used for the right eye’s rendering
    pub right_view_matrix: [f32; 16],

    // VRPose containing the future predicted pose of the VRDisplay
    // when the current frame will be presented.
    pub pose: VRPose,
}

impl Default for VRFrameData {
    fn default() -> VRFrameData {
        VRFrameData {
            timestamp: 0,
            left_projection_matrix: identity_matrix!(),
            left_view_matrix: identity_matrix!(),
            right_projection_matrix: identity_matrix!(),
            right_view_matrix: identity_matrix!(),
            pose: VRPose::default(),
        }
    }
}<commit_msg>Transmute VRFrameData to bytes to implement forward serialization in ipc-channels<commit_after>use VRPose;
use std::mem;
use std::ptr;

// Represents all the information needed to render a single frame of a VR scene
#[allow(unused_attributes)]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct VRFrameData {
    // Monotonically increasing value that allows the author
    // to determine if position state data been updated from the hardware
    pub timestamp: u64,

    // major order column matrix describing the projection to be used for the left eye’s rendering
    pub left_projection_matrix: [f32; 16],

    // major order column matrix describing the view transform to be used for the left eye’s rendering
    pub left_view_matrix: [f32; 16],

    // major order column matrix describing the projection to be used for the right eye’s rendering
    pub right_projection_matrix: [f32; 16],

    // major order column matrix describing the view transform to be used for the right eye’s rendering
    pub right_view_matrix: [f32; 16],

    // VRPose containing the future predicted pose of the VRDisplay
    // when the current frame will be presented.
    pub pose: VRPose,
}

impl Default for VRFrameData {
    fn default() -> VRFrameData {
        VRFrameData {
            timestamp: 0,
            left_projection_matrix: identity_matrix!(),
            left_view_matrix: identity_matrix!(),
            right_projection_matrix: identity_matrix!(),
            right_view_matrix: identity_matrix!(),
            pose: VRPose::default(),
        }
    }
}

impl VRFrameData {
    pub fn to_bytes(&self) -> Vec<u8> {
        let mut vec = vec![0u8; mem::size_of::<VRFrameData>()];
        unsafe {
            ptr::copy_nonoverlapping(mem::transmute(self),
                                    vec.as_mut_ptr(),
                                    mem::size_of::<VRFrameData>());
        }
        vec
    }

    pub fn from_bytes(bytes: &[u8]) -> VRFrameData {
        unsafe {
            let mut result: VRFrameData = mem::uninitialized();
            ptr::copy_nonoverlapping(bytes.as_ptr(),
                                     mem::transmute(&mut result),
                                     mem::size_of::<VRFrameData>());

            result
        }
    }
}<|endoftext|>


<commit_before>// `cargo test --benches` and `#[feature(test)]` work only in nightly
#![cfg(rustc_nightly)]
#![feature(test)]

extern crate protobuf;
extern crate test;

use std::io;
use std::io::Read;

use protobuf::CodedInputStream;

use self::test::Bencher;

fn make_bytes(len: usize) -> Vec<u8> {
    let mut r = Vec::with_capacity(len);
    for i in 0..len {
        r.push((i % 10) as u8);
    }
    test::black_box(r)
}

#[bench]
fn read_byte(b: &mut Bencher) {
    let v = make_bytes(1_000);
    b.iter(|| {
        let mut is = CodedInputStream::from_bytes(test::black_box(&v));
        while !is.eof().expect("eof") {
            test::black_box(is.read_raw_byte().expect("read"));
        }
    });
}

#[bench]
fn read_byte_no_eof(b: &mut Bencher) {
    let v = make_bytes(1_000);
    b.iter(|| {
        let mut is = CodedInputStream::from_bytes(test::black_box(&v));
        for _ in 0..v.len() {
            test::black_box(is.read_raw_byte().expect("read"));
        }
        assert!(is.eof().expect("eof"));
    });
}

#[bench]
fn read_byte_from_vec(b: &mut Bencher) {
    let v = make_bytes(1_000);
    b.iter(|| {
        let mut v = io::Cursor::new(test::black_box(&v));
        loop {
            let mut buf = [0];
            let count = v.read(&mut buf).expect("read");
            if count == 0 {
                break;
            }
            test::black_box(buf);
        }
    });
}

#[bench]
fn read_varint_12(b: &mut Bencher) {
    let mut v = Vec::new();
    {
        let mut v = protobuf::CodedOutputStream::vec(&mut v);
        for i in 0..1000 {
            // one or two byte varints
            v.write_raw_varint32((i * 7919) % (1 << 14)).expect("write");
        }
        v.flush().expect("flush");
    }
    b.iter(|| {
        let mut is = CodedInputStream::from_bytes(test::black_box(&v));
        let mut count = 0;
        while !is.eof().expect("eof") {
            test::black_box(is.read_raw_varint32().expect("read"));
            count += 1;
        }
        assert_eq!(1000, count);
    })
}

#[bench]
fn read_varint_1(b: &mut Bencher) {
    let mut v = Vec::new();
    {
        let mut v = protobuf::CodedOutputStream::vec(&mut v);
        for i in 0..1000 {
            // one or two byte varints
            v.write_raw_varint32((i * 7919) % (1 << 7)).expect("write");
        }
        v.flush().expect("flush");
    }
    b.iter(|| {
        let mut is = CodedInputStream::from_bytes(test::black_box(&v));
        let mut count = 0;
        while !is.eof().expect("eof") {
            test::black_box(is.read_raw_varint32().expect("read"));
            count += 1;
        }
        assert_eq!(1000, count);
    })
}
<commit_msg>Benchmark reading large integers<commit_after>// `cargo test --benches` and `#[feature(test)]` work only in nightly
#![cfg(rustc_nightly)]
#![feature(test)]

extern crate protobuf;
extern crate test;

use std::io;
use std::io::Read;

use protobuf::CodedInputStream;

use self::test::Bencher;

fn make_bytes(len: usize) -> Vec<u8> {
    let mut r = Vec::with_capacity(len);
    for i in 0..len {
        r.push((i % 10) as u8);
    }
    test::black_box(r)
}

#[bench]
fn read_byte(b: &mut Bencher) {
    let v = make_bytes(1_000);
    b.iter(|| {
        let mut is = CodedInputStream::from_bytes(test::black_box(&v));
        while !is.eof().expect("eof") {
            test::black_box(is.read_raw_byte().expect("read"));
        }
    });
}

#[bench]
fn read_byte_no_eof(b: &mut Bencher) {
    let v = make_bytes(1_000);
    b.iter(|| {
        let mut is = CodedInputStream::from_bytes(test::black_box(&v));
        for _ in 0..v.len() {
            test::black_box(is.read_raw_byte().expect("read"));
        }
        assert!(is.eof().expect("eof"));
    });
}

#[bench]
fn read_byte_from_vec(b: &mut Bencher) {
    let v = make_bytes(1_000);
    b.iter(|| {
        let mut v = io::Cursor::new(test::black_box(&v));
        loop {
            let mut buf = [0];
            let count = v.read(&mut buf).expect("read");
            if count == 0 {
                break;
            }
            test::black_box(buf);
        }
    });
}

#[bench]
fn read_varint_12(b: &mut Bencher) {
    let mut v = Vec::new();
    {
        let mut v = protobuf::CodedOutputStream::vec(&mut v);
        for i in 0..1000 {
            // one or two byte varints
            v.write_raw_varint32((i * 7919) % (1 << 14)).expect("write");
        }
        v.flush().expect("flush");
    }
    b.iter(|| {
        let mut is = CodedInputStream::from_bytes(test::black_box(&v));
        let mut count = 0;
        while !is.eof().expect("eof") {
            test::black_box(is.read_raw_varint32().expect("read"));
            count += 1;
        }
        assert_eq!(1000, count);
    })
}

#[bench]
fn read_varint_1(b: &mut Bencher) {
    let mut v = Vec::new();
    {
        let mut v = protobuf::CodedOutputStream::vec(&mut v);
        for i in 0..1000 {
            // one or two byte varints
            v.write_raw_varint32((i * 7919) % (1 << 7)).expect("write");
        }
        v.flush().expect("flush");
    }
    b.iter(|| {
        let mut is = CodedInputStream::from_bytes(test::black_box(&v));
        let mut count = 0;
        while !is.eof().expect("eof") {
            test::black_box(is.read_raw_varint32().expect("read"));
            count += 1;
        }
        assert_eq!(1000, count);
    })
}

fn xorshift(mut x: u64) -> u64 {
    x ^= x << 13;
    x ^= x >> 7;
    x ^= x << 17;
    x
}

#[bench]
fn read_varint_large(b: &mut Bencher) {
    let mut v = Vec::new();
    {
        let mut v = protobuf::CodedOutputStream::vec(&mut v);
        let mut rng = 1;
        for _ in 0..1000 {
            // one or two byte varints
            v.write_raw_varint64(rng).unwrap();
            rng = xorshift(rng);
        }
        v.flush().expect("flush");
    }
    b.iter(|| {
        let mut is = CodedInputStream::from_bytes(test::black_box(&v));
        let mut count = 0;
        while !is.eof().expect("eof") {
            test::black_box(is.read_raw_varint64().expect("read"));
            count += 1;
        }
        assert_eq!(1000, count);
    })
}
<|endoftext|>


<commit_before>//! Rust-PHF is a library to generate efficient lookup tables at compile time using
//! [perfect hash functions](http://en.wikipedia.org/wiki/Perfect_hash_function).
//!
//! It currently uses the
//! [CHD algorithm](http://cmph.sourceforge.net/papers/esa09.pdf) and can generate
//! a 100,000 entry map in roughly .4 seconds. By default statistics are not
//! produced, but if you set the environment variable `PHF_STATS` it will issue
//! a compiler note about how long it took.
//!
//! MSRV (minimum supported rust version) is Rust 1.46.
//!
//! ## Usage
//!
//! PHF data structures can be constructed via either the procedural
//! macros in the `phf_macros` crate or code generation supported by the
//! `phf_codegen` crate. If you prefer macros, you can easily use them by
//! enabling the `macros` feature of the `phf` crate, like:
//!
//!```toml
//! [dependencies]
//! phf = { version = "0.10", features = ["macros"] }
//! ```
//!
//! To compile the `phf` crate with a dependency on
//! libcore instead of libstd, enabling use in environments where libstd
//! will not work, set `default-features = false` for the dependency:
//!
//! ```toml
//! [dependencies]
//! # to use `phf` in `no_std` environments
//! phf = { version = "0.10", default-features = false }
//! ```
//!
//! ## Example (with the `macros` feature enabled)
//!
//! ```rust
//! use phf::phf_map;
//!
//! #[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()
//! }
//! ```
//!
//! Alternatively, you can use the [`phf_codegen`] crate to generate PHF datatypes
//! in a build script.
//!
//! [`phf_codegen`]: https://docs.rs/phf_codegen
//!
//! ## Note
//!
//! Currently, the macro syntax has some limitations and may not
//! work as you want. See [#183] or [#196] for example.
//!
//! [#183]: https://github.com/rust-phf/rust-phf/issues/183
//! [#196]: https://github.com/rust-phf/rust-phf/issues/196

#![doc(html_root_url = "https://docs.rs/phf/0.10")]
#![warn(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "std")]
extern crate std as core;

#[cfg(feature = "macros")]
/// Macro to create a `static` (compile-time) [`Map`].
///
/// Requires the `macros` feature.
///
/// # Example
///
/// ```
/// use phf::{phf_map, Map};
///
/// static MY_MAP: Map<&'static str, u32> = phf_map! {
///     "hello" => 1,
///     "world" => 2,
/// };
///
/// fn main () {
///     assert_eq!(MY_MAP["hello"], 1);
/// }
/// ```
#[proc_macro_hack::proc_macro_hack]
pub use phf_macros::phf_map;

#[cfg(feature = "macros")]
/// Macro to create a `static` (compile-time) [`OrderedMap`].
///
/// Requires the `macros` feature. Same usage as [`phf_map`].
#[proc_macro_hack::proc_macro_hack]
pub use phf_macros::phf_ordered_map;

#[cfg(feature = "macros")]
/// Macro to create a `static` (compile-time) [`Set`].
///
/// Requires the `macros` feature.
///
/// # Example
///
/// ```
/// use phf::{phf_set, Set};
///
/// static MY_SET: Set<&'static str> = phf_set! {
///     "hello world",
///     "hola mundo",
/// };
///
/// fn main () {
///     assert!(MY_SET.contains("hello world"));
/// }
/// ```
#[proc_macro_hack::proc_macro_hack]
pub use phf_macros::phf_set;

#[cfg(feature = "macros")]
/// Macro to create a `static` (compile-time) [`OrderedSet`].
///
/// Requires the `macros` feature. Same usage as [`phf_set`].
#[proc_macro_hack::proc_macro_hack]
pub use phf_macros::phf_ordered_set;

#[doc(inline)]
pub use self::map::Map;
#[doc(inline)]
pub use self::ordered_map::OrderedMap;
#[doc(inline)]
pub use self::ordered_set::OrderedSet;
#[doc(inline)]
pub use self::set::Set;
pub use phf_shared::PhfHash;

pub mod map;
pub mod ordered_map;
pub mod ordered_set;
pub mod set;
<commit_msg>docs: state allowed key expressions in `phf_map`<commit_after>//! Rust-PHF is a library to generate efficient lookup tables at compile time using
//! [perfect hash functions](http://en.wikipedia.org/wiki/Perfect_hash_function).
//!
//! It currently uses the
//! [CHD algorithm](http://cmph.sourceforge.net/papers/esa09.pdf) and can generate
//! a 100,000 entry map in roughly .4 seconds. By default statistics are not
//! produced, but if you set the environment variable `PHF_STATS` it will issue
//! a compiler note about how long it took.
//!
//! MSRV (minimum supported rust version) is Rust 1.46.
//!
//! ## Usage
//!
//! PHF data structures can be constructed via either the procedural
//! macros in the `phf_macros` crate or code generation supported by the
//! `phf_codegen` crate. If you prefer macros, you can easily use them by
//! enabling the `macros` feature of the `phf` crate, like:
//!
//!```toml
//! [dependencies]
//! phf = { version = "0.10", features = ["macros"] }
//! ```
//!
//! To compile the `phf` crate with a dependency on
//! libcore instead of libstd, enabling use in environments where libstd
//! will not work, set `default-features = false` for the dependency:
//!
//! ```toml
//! [dependencies]
//! # to use `phf` in `no_std` environments
//! phf = { version = "0.10", default-features = false }
//! ```
//!
//! ## Example (with the `macros` feature enabled)
//!
//! ```rust
//! use phf::phf_map;
//!
//! #[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()
//! }
//! ```
//!
//! Alternatively, you can use the [`phf_codegen`] crate to generate PHF datatypes
//! in a build script.
//!
//! [`phf_codegen`]: https://docs.rs/phf_codegen
//!
//! ## Note
//!
//! Currently, the macro syntax has some limitations and may not
//! work as you want. See [#183] or [#196] for example.
//!
//! [#183]: https://github.com/rust-phf/rust-phf/issues/183
//! [#196]: https://github.com/rust-phf/rust-phf/issues/196

#![doc(html_root_url = "https://docs.rs/phf/0.10")]
#![warn(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "std")]
extern crate std as core;

#[cfg(feature = "macros")]
/// Macro to create a `static` (compile-time) [`Map`].
///
/// Requires the `macros` feature.
///
/// Supported key expressions are:
/// - literals: bools, (byte) strings, bytes, chars, and integers (these must have a type suffix)
/// - arrays of `u8` integers
/// - `UniCase::unicode(string)` or `UniCase::ascii(string)` if the `unicase` feature is enabled
///
/// # Example
///
/// ```
/// use phf::{phf_map, Map};
///
/// static MY_MAP: Map<&'static str, u32> = phf_map! {
///     "hello" => 1,
///     "world" => 2,
/// };
///
/// fn main () {
///     assert_eq!(MY_MAP["hello"], 1);
/// }
/// ```
#[proc_macro_hack::proc_macro_hack]
pub use phf_macros::phf_map;

#[cfg(feature = "macros")]
/// Macro to create a `static` (compile-time) [`OrderedMap`].
///
/// Requires the `macros` feature. Same usage as [`phf_map`].
#[proc_macro_hack::proc_macro_hack]
pub use phf_macros::phf_ordered_map;

#[cfg(feature = "macros")]
/// Macro to create a `static` (compile-time) [`Set`].
///
/// Requires the `macros` feature.
///
/// # Example
///
/// ```
/// use phf::{phf_set, Set};
///
/// static MY_SET: Set<&'static str> = phf_set! {
///     "hello world",
///     "hola mundo",
/// };
///
/// fn main () {
///     assert!(MY_SET.contains("hello world"));
/// }
/// ```
#[proc_macro_hack::proc_macro_hack]
pub use phf_macros::phf_set;

#[cfg(feature = "macros")]
/// Macro to create a `static` (compile-time) [`OrderedSet`].
///
/// Requires the `macros` feature. Same usage as [`phf_set`].
#[proc_macro_hack::proc_macro_hack]
pub use phf_macros::phf_ordered_set;

#[doc(inline)]
pub use self::map::Map;
#[doc(inline)]
pub use self::ordered_map::OrderedMap;
#[doc(inline)]
pub use self::ordered_set::OrderedSet;
#[doc(inline)]
pub use self::set::Set;
pub use phf_shared::PhfHash;

pub mod map;
pub mod ordered_map;
pub mod ordered_set;
pub mod set;
<|endoftext|>


<commit_before>use {Future, IntoFuture, Callback, PollResult};
use util;
use chain::Chain;

pub struct AndThen<A, B, F> {
    state: Chain<A, B, F>,
}

pub fn new<A, B, F>(future: A, f: F) -> AndThen<A, B, F>
    where A: Future,
          B: Future,
          F: Send + 'static,
{
    AndThen {
        state: Chain::new(future, f),
    }
}

fn and_then<A, B, F>(a: PollResult<A::Item, A::Error>, f: F)
                     -> PollResult<Result<B::Item, B::Future>, B::Error>
    where A: Future,
          B: IntoFuture<Error=A::Error>,
          F: FnOnce(A::Item) -> B + Send + 'static,
{
    let e = try!(a);
    util::recover(|| f(e)).map(|b| Err(b.into_future()))
}

impl<A, B, F> Future for AndThen<A, B::Future, F>
    where A: Future,
          B: IntoFuture<Error=A::Error>,
          F: FnOnce(A::Item) -> B + Send + 'static,
{
    type Item = B::Item;
    type Error = B::Error;

    fn poll(&mut self) -> Option<PollResult<B::Item, B::Error>> {
        self.state.poll(and_then::<A, B, F>)
    }

    fn cancel(&mut self) {
        self.state.cancel()
    }

    // fn await(&mut self) -> FutureResult<B::Item, B::Error> {
    //     self.state.await(and_then::<A, B, F>)
    // }

    fn schedule<G>(&mut self, g: G)
        where G: FnOnce(PollResult<B::Item, B::Error>) + Send + 'static
    {
        self.state.schedule(g, and_then::<A, B, F>)
    }

    fn schedule_boxed(&mut self, cb: Box<Callback<B::Item, B::Error>>) {
        // TODO: wut? UFCS?
        Future::schedule(self, |r| cb.call(r))
    }
}
<commit_msg>Bad in main lib<commit_after>use {Future, IntoFuture, Callback, PollResult};
use util;
use chain::Chain;

pub struct AndThen<A, B, F> {
    state: Chain<A, B, F>,
}

pub fn new<A, B, F>(future: A, f: F) -> AndThen<A, B, F>
    where A: Future,
          B: Future,
          F: Send + 'static,
{
    AndThen {
        state: Chain::new(future, f),
    }
}

fn and_then<A, B, F>(a: PollResult<A::Item, A::Error>, f: F)
                     -> PollResult<Result<B::Item, B::Future>, B::Error>
    where A: Future,
          B: IntoFuture<Error=A::Error>,
          F: FnOnce(A::Item) -> B + Send + 'static,
{
    let e = try!(a);
    util::recover(|| f(e)).map(|b| Err(b.into_future()))
}

impl<A, B, F> Future for AndThen<A, B::Future, F>
    where A: Future,
          B: IntoFuture<Error=A::Error>,
          F: FnOnce(A::Item) -> B + Send + 'static,
{
    type Item = B::Item;
    type Error = B::Error;

    fn poll(&mut self) -> Option<PollResult<B::Item, B::Error>> {
        self.state.poll(and_then::<A, B, F>)
    }

    fn cancel(&mut self) {
        self.state.cancel()
    }

    // fn await(&mut self) -> FutureResult<B::Item, B::Error> {
    //     self.state.await(and_then::<A, B, F>)
    // }

    fn schedule<G>(&mut self, g: G)
        where G: FnOnce(PollResult<B::Item, B::Error>) + Send + 'static
    {
        self.state.schedule(g, and_then::<A, B, F>)
    }

    fn schedule_boxed(&mut self, cb: Box<Callback<B::Item, B::Error>>) {
        // TODO: wut? UFCS?
        self.schedule(|r| cb.call(r))
    }
}
<|endoftext|>


<commit_before>use common;
use json::iterators::Members;
use nickel::status::StatusCode;
use hyper::client::Client;
use nickel::{Request, Response, MiddlewareResult, QueryString};
use mustache::MapBuilder;
use time;
use itertools::Itertools;
use json;
use std::collections::HashSet;

pub fn arrivals_handler<'a, D>(request: &mut Request<D>,
                               mut response: Response<'a, D>)
                               -> MiddlewareResult<'a, D> {
    let client = Client::new();
    let favourites = common::favourites(&request.origin);
    let stopid = request.param("stopid").expect("Missing stopid").to_string();
    let line_filter = request.query().get("line");
    let obj =
        match common::json_for_request(
            client.get(&format!("https://api.tfl.gov.uk/StopPoint/{}/Arrivals",
                          stopid))) {
            Ok(val) => val,
            Err(val) => {
                response.set(StatusCode::BadGateway);
                return response.send(val);
            }
        };

    let members = match obj.members() {
        Members::Some(val) => val,
        Members::None => {
            response.set(StatusCode::BadGateway);
            return response.send(format!("No stops in: {:?}", obj));
        }
    };
    let member_slice = members.as_slice();
    let data = {
        if member_slice.len() == 0 {
            let stopobj = match common::json_for_request(
                client.get(&format!("https://api.tfl.gov.uk/StopPoint/{}",
                              stopid))) {
                Ok(val) => val,
                Err(val) => {
                    response.set(StatusCode::BadGateway);
                    return response.send(val);
                }
            };
            MapBuilder::new()
                .insert_str("stopName",
                            stopobj["commonName"].as_str().expect("commonName"))
                .insert_str("stopNumber", "".to_string())
                .insert_str("when", time::now().strftime("%H:%M").expect("time.now"))
                .build()
        } else {
            let last_item = member_slice[0].clone();
            let sorted_members = members.sorted_by(|a, b| {
                a["expectedArrival"].as_str().expect("expectedArrival a").cmp(b["expectedArrival"].as_str().expect("expectedArrival a"))
            });
            let platform_name = last_item["platformName"].as_str().expect("platformName");
            let stop_number = if platform_name == "null" {
                format!(" towards {}", last_item["destinationName"].as_str().expect("destinationName"))
            } else {
                format!(" (Stop {})", platform_name)
            };

            let mut lines = HashSet::new();
            MapBuilder::new()
                .insert_vec("buses", |vecbuilder| {
                    let mut vecb = vecbuilder;
                    for stop in sorted_members.clone() {
                        let line = stop["lineName"].as_str().expect("lineName");
                        lines.insert(line);
                        if line_filter.is_some() && line_filter.expect("line filter") != line {
                            continue;
                        }
                        vecb = vecb.push_map(|mapbuilder| {
                            let expected_arrival = stop["expectedArrival"].as_str().expect("expectedArrival");
                            let when = time::strptime(expected_arrival, "%FT%TZ")
                                .expect(&format!("strptime: {}", expected_arrival));
                            let until = (when - time::now()).num_minutes();
                            let until_text = if until == 1 {
                                "1 minute".to_string()
                            } else if until > 0 {
                                format!("{} minutes", until)
                            } else {
                                "due".to_string()
                            };
                            mapbuilder.insert_str("line", line)
                                .insert_str("destination",
                                            stop["destinationName"].as_str().expect("destinationName"))
                                .insert_str("towards", stop["towards"].as_str().expect("towards"))
                                .insert_str("minutes", until_text)
                                .insert_str("expectedArrival",
                                            when.to_local().strftime("%H:%M").expect("when"))
                        });
                    }
                    vecb
                })
                .insert_vec("lines", |vecbuilder| {
                    let mut vecb = vecbuilder;
                    let mut linesv: Vec<&&str> = lines.iter().collect();
                    linesv.sort_by_key(|k| k.parse::<i32>().unwrap_or(0));
                    for line in linesv {
                        vecb = vecb.push_map(|mapbuilder| mapbuilder.insert_str("line", line))
                    }
                    vecb
                })
                .insert_str("stopId", &stopid)
                .insert_bool("inFavourites", favourites[&stopid] != json::JsonValue::Null)
                .insert_str("stopName", last_item["stationName"].as_str().expect("stationName"))
                .insert_str("stopNumber", stop_number)
                .insert_str("when", time::now().strftime("%H:%M").expect("time now"))
                .build()
        }
    };

    common::render_to_response(response, "resources/templates/arrivals.mustache", &data)
}
<commit_msg>TfL apparently added fractional seconds...<commit_after>use common;
use json::iterators::Members;
use nickel::status::StatusCode;
use hyper::client::Client;
use nickel::{Request, Response, MiddlewareResult, QueryString};
use mustache::MapBuilder;
use time;
use itertools::Itertools;
use json;
use std::collections::HashSet;

pub fn arrivals_handler<'a, D>(request: &mut Request<D>,
                               mut response: Response<'a, D>)
                               -> MiddlewareResult<'a, D> {
    let client = Client::new();
    let favourites = common::favourites(&request.origin);
    let stopid = request.param("stopid").expect("Missing stopid").to_string();
    let line_filter = request.query().get("line");
    let obj =
        match common::json_for_request(
            client.get(&format!("https://api.tfl.gov.uk/StopPoint/{}/Arrivals",
                          stopid))) {
            Ok(val) => val,
            Err(val) => {
                response.set(StatusCode::BadGateway);
                return response.send(val);
            }
        };

    let members = match obj.members() {
        Members::Some(val) => val,
        Members::None => {
            response.set(StatusCode::BadGateway);
            return response.send(format!("No stops in: {:?}", obj));
        }
    };
    let member_slice = members.as_slice();
    let data = {
        if member_slice.len() == 0 {
            let stopobj = match common::json_for_request(
                client.get(&format!("https://api.tfl.gov.uk/StopPoint/{}",
                              stopid))) {
                Ok(val) => val,
                Err(val) => {
                    response.set(StatusCode::BadGateway);
                    return response.send(val);
                }
            };
            MapBuilder::new()
                .insert_str("stopName",
                            stopobj["commonName"].as_str().expect("commonName"))
                .insert_str("stopNumber", "".to_string())
                .insert_str("when", time::now().strftime("%H:%M").expect("time.now"))
                .build()
        } else {
            let last_item = member_slice[0].clone();
            let sorted_members = members.sorted_by(|a, b| {
                a["expectedArrival"].as_str().expect("expectedArrival a").cmp(b["expectedArrival"].as_str().expect("expectedArrival a"))
            });
            let platform_name = last_item["platformName"].as_str().expect("platformName");
            let stop_number = if platform_name == "null" {
                format!(" towards {}", last_item["destinationName"].as_str().expect("destinationName"))
            } else {
                format!(" (Stop {})", platform_name)
            };

            let mut lines = HashSet::new();
            MapBuilder::new()
                .insert_vec("buses", |vecbuilder| {
                    let mut vecb = vecbuilder;
                    for stop in sorted_members.clone() {
                        let line = stop["lineName"].as_str().expect("lineName");
                        lines.insert(line);
                        if line_filter.is_some() && line_filter.expect("line filter") != line {
                            continue;
                        }
                        vecb = vecb.push_map(|mapbuilder| {
                            let expected_arrival = stop["expectedArrival"].as_str().expect("expectedArrival");
                            let when = time::strptime(expected_arrival, "%FT%T.%fZ")
                                .expect(&format!("strptime: {}", expected_arrival));
                            let until = (when - time::now()).num_minutes();
                            let until_text = if until == 1 {
                                "1 minute".to_string()
                            } else if until > 0 {
                                format!("{} minutes", until)
                            } else {
                                "due".to_string()
                            };
                            mapbuilder.insert_str("line", line)
                                .insert_str("destination",
                                            stop["destinationName"].as_str().expect("destinationName"))
                                .insert_str("towards", stop["towards"].as_str().expect("towards"))
                                .insert_str("minutes", until_text)
                                .insert_str("expectedArrival",
                                            when.to_local().strftime("%H:%M").expect("when"))
                        });
                    }
                    vecb
                })
                .insert_vec("lines", |vecbuilder| {
                    let mut vecb = vecbuilder;
                    let mut linesv: Vec<&&str> = lines.iter().collect();
                    linesv.sort_by_key(|k| k.parse::<i32>().unwrap_or(0));
                    for line in linesv {
                        vecb = vecb.push_map(|mapbuilder| mapbuilder.insert_str("line", line))
                    }
                    vecb
                })
                .insert_str("stopId", &stopid)
                .insert_bool("inFavourites", favourites[&stopid] != json::JsonValue::Null)
                .insert_str("stopName", last_item["stationName"].as_str().expect("stationName"))
                .insert_str("stopNumber", stop_number)
                .insert_str("when", time::now().strftime("%H:%M").expect("time now"))
                .build()
        }
    };

    common::render_to_response(response, "resources/templates/arrivals.mustache", &data)
}
<|endoftext|>


<commit_before>use stack::Stack;

/// Represents a builtin function
#[derive(Debug, Clone, PartialEq)]
pub enum Builtin {
    Dot,
    Plus,
    Minus,
    Star,
    Slash,
    Abs,
    And,
    Or,
    Xor,
    Equals,
    LessThan,
    GreaterThan,
    LessEqual,
    GreaterEqual,
    Emit,
    Dup,
    Swap,
    Over,
    Rot,
    Tuck,
    Drop,
}

impl Builtin {
    pub fn call(&self, stack: &mut Stack) {
        match *self {
            Builtin::Dot => print!("{}", stack.pop::<i32>()),
            Builtin::Plus => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1 + n2);
            }
            Builtin::Minus => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1 - n2);
            }
            Builtin::Star => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1 * n2);
            }
            Builtin::Slash => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1 / n2);
            }
            Builtin::Abs => {
                let n: i32 = stack.pop();
                stack.push(n.abs());
            }
            Builtin::And => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1 & n2);
            }
            Builtin::Or => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1 | n2);
            }
            Builtin::Xor => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1 ^ n2);
            }
            Builtin::Equals => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1 == n2);
            }
            Builtin::LessThan => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1 < n2);
            }
            Builtin::GreaterThan => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1 > n2);
            }
            Builtin::LessEqual => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1 <= n2);
            }
            Builtin::GreaterEqual => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1 >= n2);
            }
            Builtin::Emit => {
                let c: char = stack.pop();
                print!("{}", c);
            }
            Builtin::Dup => {
                let n: i32 = stack.peak();
                stack.push(n);
            }
            Builtin::Swap => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n2);
                stack.push(n1);
            }
            Builtin::Over => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1);
                stack.push(n2);
                stack.push(n1);
            }
            Builtin::Rot => {
                let n3: i32 = stack.pop();
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1);
                stack.push(n3);
                stack.push(n2);
            }
            Builtin::Tuck => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n2);
                stack.push(n1);
                stack.push(n2);
            }
            Builtin::Drop => {
                stack.pop::<i32>();
            }
        }
    }
}
<commit_msg>Write stackexpr! macro to reduce redundancy<commit_after>use stack::Stack;

/// Represents a builtin function
#[derive(Debug, Clone, PartialEq)]
pub enum Builtin {
    Dot,
    Plus,
    Minus,
    Star,
    Slash,
    Abs,
    And,
    Or,
    Xor,
    Equals,
    LessThan,
    GreaterThan,
    LessEqual,
    GreaterEqual,
    Emit,
    Dup,
    Swap,
    Over,
    Rot,
    Tuck,
    Drop,
}

impl Builtin {
    pub fn call(&self, stack: &mut Stack) {
        macro_rules! stackexpr {
            ( $($aname:ident : $atype:ty),+ => $value:expr ) => {
                {
                    $(
                        let $aname: $atype = stack.pop();
                    )+
                    stack.push($value)
                }
            }
        }
        match *self {
            Builtin::Dot => print!("{}", stack.pop::<i32>()),
            Builtin::Plus => stackexpr!(n2: i32, n1: i32 => n1 + n2),
            Builtin::Minus => stackexpr!(n2: i32, n1: i32 => n1 - n2),
            Builtin::Star => stackexpr!(n2: i32, n1: i32 => n1 * n2),
            Builtin::Slash => stackexpr!(n2: i32, n1: i32 => n1 / n2),
            Builtin::Abs => stackexpr!(n: i32 => n.abs()),
            Builtin::And => stackexpr!(n2: i32, n1: i32 => n1 & n2),
            Builtin::Or => stackexpr!(n2: i32, n1: i32 => n1 | n2),
            Builtin::Xor => stackexpr!(n2: i32, n1: i32 => n1 ^ n2),
            Builtin::Equals => stackexpr!(n2: i32, n1: i32 => n1 == n2),
            Builtin::LessThan => stackexpr!(n2: i32, n1: i32 => n1 < n2),
            Builtin::GreaterThan => stackexpr!(n2: i32, n1: i32 => n1 > n2),
            Builtin::LessEqual => stackexpr!(n2: i32, n1: i32 => n1 <= n2),
            Builtin::GreaterEqual => stackexpr!(n2: i32, n1: i32 => n1 >= n2),
            Builtin::Emit => print!("{}", stack.pop::<char>()),
            Builtin::Dup => {
                let n: i32 = stack.peak();
                stack.push(n);
            }
            Builtin::Swap => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n2);
                stack.push(n1);
            }
            Builtin::Over => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1);
                stack.push(n2);
                stack.push(n1);
            }
            Builtin::Rot => {
                let n3: i32 = stack.pop();
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n1);
                stack.push(n3);
                stack.push(n2);
            }
            Builtin::Tuck => {
                let n2: i32 = stack.pop();
                let n1: i32 = stack.pop();
                stack.push(n2);
                stack.push(n1);
                stack.push(n2);
            }
            Builtin::Drop => {
                stack.pop::<i32>();
            }
        }
    }
}
<|endoftext|>


<commit_before>// Implements the `zakopane checksum` subcommand.

use std::io::Read;
use std::io::Write;

use crate::structs::ChecksumCliOptions;
use crate::structs::ZakopaneError;

const MAX_TASKS: usize = 8;
const READ_SIZE: usize = 2 << 20;

struct ChecksumWithPath {
    checksum: String,
    path: std::path::PathBuf,
}

impl ChecksumWithPath {
    pub fn new(checksum: String, path: std::path::PathBuf) -> Self {
        Self { checksum, path }
    }
}

type ChecksumResult = Result<ChecksumWithPath, ZakopaneError>;
type ChecksumTaskJoinHandle = tokio::task::JoinHandle<Vec<ChecksumWithPath>>;

struct ChecksumTaskDispatcherData {
    cli_options: ChecksumCliOptions,

    // Rate-limiter for spawned checksum tasks.
    semaphore: std::sync::Arc<tokio::sync::Semaphore>,

    // Counts total number of spawned checksum tasks.
    spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,

    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
}

impl ChecksumTaskDispatcherData {
    pub fn new(
        cli_options: ChecksumCliOptions,
        spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,
        sender: tokio::sync::mpsc::Sender<ChecksumResult>,
    ) -> Self {
        Self {
            cli_options,
            semaphore: std::sync::Arc::new(tokio::sync::Semaphore::new(MAX_TASKS)),
            spawn_counter,
            sender,
        }
    }
}

// Sends a checksum task result downstream to the collector task.
fn checksum_task_send_result(
    result: ChecksumResult,
    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
) {
    if let Err(e) = sender.blocking_send(result) {
        eprintln!("BUG: Sender::send() failed: {}", e);
    }
}

fn checksum_task_impl(path: std::path::PathBuf) -> ChecksumResult {
    let mut hasher = crypto_hash::Hasher::new(crypto_hash::Algorithm::SHA256);
    let mut buffer: Vec<u8> = vec![0; READ_SIZE];
    let mut file = std::fs::File::open(&path).map_err(ZakopaneError::Io)?;
    loop {
        let read_bytes = file.read(&mut buffer).map_err(ZakopaneError::Io)?;
        if read_bytes == 0 {
            let checksum = hasher
                .finish()
                .into_iter()
                .map(|byte| format!("{:02x}", byte))
                .collect::<Vec<String>>()
                .join("");
            return Ok(ChecksumWithPath::new(checksum, path));
        }
        hasher
            .write_all(&buffer[..read_bytes])
            .map_err(ZakopaneError::Io)?;
    }
}

// Represents a spawned checksum task.
//
// `_permit` is moved into this checksum task simply to hold onto the
// semaphore-dispensed resource for the duration of this task.
fn checksum_task(
    path: std::path::PathBuf,
    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
    _permit: tokio::sync::OwnedSemaphorePermit,
) {
    let result = checksum_task_impl(path);
    checksum_task_send_result(result, sender);
}

// Represents the spawned collection task.
async fn collector_task(
    mut receiver: tokio::sync::mpsc::Receiver<ChecksumResult>,
    spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,
) -> Vec<ChecksumWithPath> {
    let mut sums: Vec<ChecksumWithPath> = Vec::new();
    let mut errors: usize = 0;
    loop {
        while let Some(result) = receiver.recv().await {
            match result {
                Ok(digest_with_path) => sums.push(digest_with_path),
                Err(_) => errors += 1,
            }
        }
        if sums.len() + errors == spawn_counter.load(std::sync::atomic::Ordering::SeqCst) {
            break;
        }
    }
    if errors != 0 {
        eprintln!("WARNING: {} errors collected", errors);
    }
    sums
}

// Spawns the collector task that listens for checksum results
// provided by the checksum tasks.
async fn spawn_collector(
    options: ChecksumCliOptions,
) -> (ChecksumTaskDispatcherData, ChecksumTaskJoinHandle) {
    let (sender, receiver) = tokio::sync::mpsc::channel(MAX_TASKS);
    let spawn_counter = std::sync::Arc::new(std::sync::atomic::AtomicUsize::new(0));
    let join_handle = tokio::task::spawn(collector_task(receiver, spawn_counter.clone()));
    (
        ChecksumTaskDispatcherData::new(options, spawn_counter, sender),
        join_handle,
    )
}

async fn spawn_checksum_tasks(context: ChecksumTaskDispatcherData) {
    let walk_iter = walkdir::WalkDir::new(&context.cli_options.path).into_iter();
    // The `filter_entry()` call is crafted s.t.
    // *    we skip and don't descend into hidden directories
    // *    unless the hidden directory is the target directory, because
    //      the target directory is always the first yielded value from
    //      the `WalkDir`.
    for entry in walk_iter.filter_entry(|e| {
        e.path() == &context.cli_options.path
            || !e
                .file_name()
                .to_str()
                .map(|path| path.starts_with("."))
                .unwrap_or(false)
    }) {
        if let Ok(direntry) = entry {
            let path = direntry.into_path();
            if let Ok(metadata) = std::fs::symlink_metadata(&path) {
                if !metadata.file_type().is_file() {
                    continue;
                }
            } else {
                continue;
            }

            context
                .spawn_counter
                .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
            let permit = context.semaphore.clone().acquire_owned().await.unwrap();
            let sender = context.sender.clone();
            tokio::task::spawn_blocking(move || checksum_task(path, sender, permit));
        }
    }
}

// Pretty-prints the sorted `checksums` in a format much like what the
// `sha256sum` binary outputs.
//
// Note that the standard zakopane snapshot header is not added here.
fn pretty_format_checksums(path: std::path::PathBuf, checksums: Vec<ChecksumWithPath>) -> String {
    let mut buffer: Vec<String> = checksums
        .into_iter()
        .map(|e| {
            format!(
                "{}  ./{}",
                e.checksum,
                e.path.strip_prefix(&path).unwrap().to_str().unwrap()
            )
        })
        .collect();
    buffer.push(String::new());
    buffer.join("\n")
}

async fn checksum_impl(options: ChecksumCliOptions) -> String {
    let path = options.path.clone();
    let (dispatcher_data, join_handle) = spawn_collector(options).await;
    spawn_checksum_tasks(dispatcher_data).await;
    let mut checksums: Vec<ChecksumWithPath> = join_handle.await.unwrap();
    checksums.sort_by(|a, b| a.path.cmp(&b.path));
    pretty_format_checksums(path, checksums)
}

pub fn checksum(options: ChecksumCliOptions) -> String {
    let runtime = tokio::runtime::Runtime::new().unwrap();
    runtime.block_on(checksum_impl(options))
}
<commit_msg>checksum: Use `ChecksumCliOptions::max_tasks`<commit_after>// Implements the `zakopane checksum` subcommand.

use std::io::Read;
use std::io::Write;

use crate::structs::ChecksumCliOptions;
use crate::structs::ZakopaneError;

const READ_SIZE: usize = 2 << 20;

struct ChecksumWithPath {
    checksum: String,
    path: std::path::PathBuf,
}

impl ChecksumWithPath {
    pub fn new(checksum: String, path: std::path::PathBuf) -> Self {
        Self { checksum, path }
    }
}

type ChecksumResult = Result<ChecksumWithPath, ZakopaneError>;
type ChecksumTaskJoinHandle = tokio::task::JoinHandle<Vec<ChecksumWithPath>>;

struct ChecksumTaskDispatcherData {
    // Rate-limiter for spawned checksum tasks.
    semaphore: std::sync::Arc<tokio::sync::Semaphore>,

    cli_options: ChecksumCliOptions,

    // Counts total number of spawned checksum tasks.
    spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,

    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
}

impl ChecksumTaskDispatcherData {
    pub fn new(
        cli_options: ChecksumCliOptions,
        spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,
        sender: tokio::sync::mpsc::Sender<ChecksumResult>,
    ) -> Self {
        Self {
            semaphore: std::sync::Arc::new(tokio::sync::Semaphore::new(cli_options.max_tasks)),
            cli_options,
            spawn_counter,
            sender,
        }
    }
}

// Sends a checksum task result downstream to the collector task.
fn checksum_task_send_result(
    result: ChecksumResult,
    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
) {
    if let Err(e) = sender.blocking_send(result) {
        eprintln!("BUG: Sender::send() failed: {}", e);
    }
}

fn checksum_task_impl(path: std::path::PathBuf) -> ChecksumResult {
    let mut hasher = crypto_hash::Hasher::new(crypto_hash::Algorithm::SHA256);
    let mut buffer: Vec<u8> = vec![0; READ_SIZE];
    let mut file = std::fs::File::open(&path).map_err(ZakopaneError::Io)?;
    loop {
        let read_bytes = file.read(&mut buffer).map_err(ZakopaneError::Io)?;
        if read_bytes == 0 {
            let checksum = hasher
                .finish()
                .into_iter()
                .map(|byte| format!("{:02x}", byte))
                .collect::<Vec<String>>()
                .join("");
            return Ok(ChecksumWithPath::new(checksum, path));
        }
        hasher
            .write_all(&buffer[..read_bytes])
            .map_err(ZakopaneError::Io)?;
    }
}

// Represents a spawned checksum task.
//
// `_permit` is moved into this checksum task simply to hold onto the
// semaphore-dispensed resource for the duration of this task.
fn checksum_task(
    path: std::path::PathBuf,
    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
    _permit: tokio::sync::OwnedSemaphorePermit,
) {
    let result = checksum_task_impl(path);
    checksum_task_send_result(result, sender);
}

// Represents the spawned collection task.
async fn collector_task(
    mut receiver: tokio::sync::mpsc::Receiver<ChecksumResult>,
    spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,
) -> Vec<ChecksumWithPath> {
    let mut sums: Vec<ChecksumWithPath> = Vec::new();
    let mut errors: usize = 0;
    loop {
        while let Some(result) = receiver.recv().await {
            match result {
                Ok(digest_with_path) => sums.push(digest_with_path),
                Err(_) => errors += 1,
            }
        }
        if sums.len() + errors == spawn_counter.load(std::sync::atomic::Ordering::SeqCst) {
            break;
        }
    }
    if errors != 0 {
        eprintln!("WARNING: {} errors collected", errors);
    }
    sums
}

// Spawns the collector task that listens for checksum results
// provided by the checksum tasks.
async fn spawn_collector(
    options: ChecksumCliOptions,
) -> (ChecksumTaskDispatcherData, ChecksumTaskJoinHandle) {
    let (sender, receiver) = tokio::sync::mpsc::channel(options.max_tasks);
    let spawn_counter = std::sync::Arc::new(std::sync::atomic::AtomicUsize::new(0));
    let join_handle = tokio::task::spawn(collector_task(receiver, spawn_counter.clone()));
    (
        ChecksumTaskDispatcherData::new(options, spawn_counter, sender),
        join_handle,
    )
}

async fn spawn_checksum_tasks(context: ChecksumTaskDispatcherData) {
    let walk_iter = walkdir::WalkDir::new(&context.cli_options.path).into_iter();
    // The `filter_entry()` call is crafted s.t.
    // *    we skip and don't descend into hidden directories
    // *    unless the hidden directory is the target directory, because
    //      the target directory is always the first yielded value from
    //      the `WalkDir`.
    for entry in walk_iter.filter_entry(|e| {
        e.path() == &context.cli_options.path
            || !e
                .file_name()
                .to_str()
                .map(|path| path.starts_with("."))
                .unwrap_or(false)
    }) {
        if let Ok(direntry) = entry {
            let path = direntry.into_path();
            if let Ok(metadata) = std::fs::symlink_metadata(&path) {
                if !metadata.file_type().is_file() {
                    continue;
                }
            } else {
                continue;
            }

            context
                .spawn_counter
                .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
            let permit = context.semaphore.clone().acquire_owned().await.unwrap();
            let sender = context.sender.clone();
            tokio::task::spawn_blocking(move || checksum_task(path, sender, permit));
        }
    }
}

// Pretty-prints the sorted `checksums` in a format much like what the
// `sha256sum` binary outputs.
//
// Note that the standard zakopane snapshot header is not added here.
fn pretty_format_checksums(path: std::path::PathBuf, checksums: Vec<ChecksumWithPath>) -> String {
    let mut buffer: Vec<String> = checksums
        .into_iter()
        .map(|e| {
            format!(
                "{}  ./{}",
                e.checksum,
                e.path.strip_prefix(&path).unwrap().to_str().unwrap()
            )
        })
        .collect();
    buffer.push(String::new());
    buffer.join("\n")
}

async fn checksum_impl(options: ChecksumCliOptions) -> String {
    let path = options.path.clone();
    let (dispatcher_data, join_handle) = spawn_collector(options).await;
    spawn_checksum_tasks(dispatcher_data).await;
    let mut checksums: Vec<ChecksumWithPath> = join_handle.await.unwrap();
    checksums.sort_by(|a, b| a.path.cmp(&b.path));
    pretty_format_checksums(path, checksums)
}

pub fn checksum(options: ChecksumCliOptions) -> String {
    let runtime = tokio::runtime::Runtime::new().unwrap();
    runtime.block_on(checksum_impl(options))
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

use std::path::{Path, PathBuf};
use std::io::{Read, Write, Result};

const PROTOS: &'static [&'static str] = &[
    "grr/grr/proto/grr_response_proto/semantic.proto",
    "grr/grr/proto/grr_response_proto/knowledge_base.proto",
    "grr/grr/proto/grr_response_proto/jobs.proto",
];

const INCLUDES: &'static [&'static str] = &[
    "grr/grr/proto",
];

fn main() {
    // Because GRR proto files are not something that PROST! can accept (because
    // of the missing package definitions), we create a temporary directory with
    // recreated file structure. We apply the patch to each of them and feed the
    // Protocol Buffers compiler with updated files.
    let tempdir = tempfile::tempdir()
        .expect("failed to create temp dir");

    let mut protos = Vec::new();
    let mut includes = Vec::new();

    for path_before in PROTOS {
        let path_after = tempdir.path().join(path_before);

        patch_path(&path_before, &path_after)
            .expect(&format!("failed to patch file '{}'", path_before));

        protos.push(path_after);
    }

    for path_before in INCLUDES {
        let path_after = tempdir.path().join(path_before);
        includes.push(path_after);
    }

    prost_build::compile_protos(&protos, &includes)
        .expect("failed to compile proto files");

    // There is also a problem with one enum generated by PROST!: it's values
    // use name mangling, but it's default value does not. This is likely a bug
    // in PROST! itself, but for now we hack around it by replacing the spurious
    // line in the output file ourselves.
    let outdir: PathBuf = std::env::var("OUT_DIR")
        .expect("no output directory")
        .into();

    let target = outdir.join("grr.rs");

    let grr = std::fs::read_to_string(&target)
        .expect("failed to read the generated output file")
        .replace("TskFsAttrTypeDefault", "Default");

    std::fs::write(&target, grr)
        .expect("failed to write updated output file");
}

/// Patches given file at path `input`, writing patched content at `output`.
///
/// This function takes a path to malformed (i.e. lacking package definition)
/// GRR proto file and converts it to something that PROST! can understand. This
/// workaround has to be used as long as GRR does not fixes its proto files
/// upstream, which might be hard because of compatibility reasons.
fn patch_path<PI, PO>(input: PI, output: PO) -> Result<()>
where
    PI: AsRef<Path>,
    PO: AsRef<Path>,
{
    let mut input = file::open(&input)?;
    let mut output = file::create(&output)?;

    patch_buffer(&mut input, &mut output)
}

/// Patches given `input` buffer, writing patched content to `output`.
///
/// This function takes a buffer with malformed (lacking package definition)
/// GRR proto file and converts it to something that PROST! can understand. This
/// workaround has to be used as long as GRR does not fixes its proto files
/// upstream, which might be hard because of compatibility reasons.
fn patch_buffer<R, W>(input: &mut R, output: &mut W) -> Result<()>
where
    R: Read,
    W: Write,
{
    let mut buffer = String::new();
    input.read_to_string(&mut buffer)?;

    for line in buffer.lines() {
        writeln!(output, "{}", line)?;
        if line.starts_with("syntax =") {
            writeln!(output, "package grr;")?;
        }
    }

    Ok(())
}

mod file {
    use std::fs::File;
    use std::io::Result;
    use std::path::Path;

    /// Opens a file at the specified `path`.
    ///
    /// This function simply delegates to the standard library `File::open` and
    /// exists purely for aesthetic purposes.
    pub fn open<P: AsRef<Path>>(path: P) -> Result<File> {
        File::open(path)
    }

    /// Creates a file at the specified `path` and all the necessary folders
    /// along the way.
    ///
    /// Except for directory creation, this function should behave identically
    /// to the standard library's `File::create`.
    pub fn create<P: AsRef<Path>>(path: P) -> Result<File> {
        if let Some(parent) = path.as_ref().parent() {
            std::fs::create_dir_all(parent)?;
        }

        File::create(path)
    }
}
<commit_msg>Fix a misleading comment.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

use std::path::{Path, PathBuf};
use std::io::{Read, Write, Result};

const PROTOS: &'static [&'static str] = &[
    "grr/grr/proto/grr_response_proto/semantic.proto",
    "grr/grr/proto/grr_response_proto/knowledge_base.proto",
    "grr/grr/proto/grr_response_proto/jobs.proto",
];

const INCLUDES: &'static [&'static str] = &[
    "grr/grr/proto",
];

fn main() {
    // Because GRR proto files are not something that PROST! can accept (because
    // of the missing package declaration), we create a temporary directory with
    // recreated file structure. We apply the patch to each of them and feed the
    // Protocol Buffers compiler with updated files.
    let tempdir = tempfile::tempdir()
        .expect("failed to create temp dir");

    let mut protos = Vec::new();
    let mut includes = Vec::new();

    for path_before in PROTOS {
        let path_after = tempdir.path().join(path_before);

        patch_path(&path_before, &path_after)
            .expect(&format!("failed to patch file '{}'", path_before));

        protos.push(path_after);
    }

    for path_before in INCLUDES {
        let path_after = tempdir.path().join(path_before);
        includes.push(path_after);
    }

    prost_build::compile_protos(&protos, &includes)
        .expect("failed to compile proto files");

    // There is also a problem with one enum generated by PROST!: it's values
    // use name mangling, but it's default value does not. This is likely a bug
    // in PROST! itself, but for now we hack around it by replacing the spurious
    // line in the output file ourselves.
    let outdir: PathBuf = std::env::var("OUT_DIR")
        .expect("no output directory")
        .into();

    let target = outdir.join("grr.rs");

    let grr = std::fs::read_to_string(&target)
        .expect("failed to read the generated output file")
        .replace("TskFsAttrTypeDefault", "Default");

    std::fs::write(&target, grr)
        .expect("failed to write updated output file");
}

/// Patches given file at path `input`, writing patched content at `output`.
///
/// This function takes a path to malformed (i.e. lacking package definition)
/// GRR proto file and converts it to something that PROST! can understand. This
/// workaround has to be used as long as GRR does not fixes its proto files
/// upstream, which might be hard because of compatibility reasons.
fn patch_path<PI, PO>(input: PI, output: PO) -> Result<()>
where
    PI: AsRef<Path>,
    PO: AsRef<Path>,
{
    let mut input = file::open(&input)?;
    let mut output = file::create(&output)?;

    patch_buffer(&mut input, &mut output)
}

/// Patches given `input` buffer, writing patched content to `output`.
///
/// This function takes a buffer with malformed (lacking package definition)
/// GRR proto file and converts it to something that PROST! can understand. This
/// workaround has to be used as long as GRR does not fixes its proto files
/// upstream, which might be hard because of compatibility reasons.
fn patch_buffer<R, W>(input: &mut R, output: &mut W) -> Result<()>
where
    R: Read,
    W: Write,
{
    let mut buffer = String::new();
    input.read_to_string(&mut buffer)?;

    for line in buffer.lines() {
        writeln!(output, "{}", line)?;
        if line.starts_with("syntax =") {
            writeln!(output, "package grr;")?;
        }
    }

    Ok(())
}

mod file {
    use std::fs::File;
    use std::io::Result;
    use std::path::Path;

    /// Opens a file at the specified `path`.
    ///
    /// This function simply delegates to the standard library `File::open` and
    /// exists purely for aesthetic purposes.
    pub fn open<P: AsRef<Path>>(path: P) -> Result<File> {
        File::open(path)
    }

    /// Creates a file at the specified `path` and all the necessary folders
    /// along the way.
    ///
    /// Except for directory creation, this function should behave identically
    /// to the standard library's `File::create`.
    pub fn create<P: AsRef<Path>>(path: P) -> Result<File> {
        if let Some(parent) = path.as_ref().parent() {
            std::fs::create_dir_all(parent)?;
        }

        File::create(path)
    }
}
<|endoftext|>


<commit_before>//#![feature(trace_macros)]
#![allow(dead_code)]
#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))]

#[macro_use]
extern crate nom;

use nom::{character::{is_digit, streaming::space}, Err, IResult, Needed, error::ErrorKind, number::streaming::le_u64};

#[allow(dead_code)]
struct Range {
  start: char,
  end: char,
}

pub fn take_char(input: &[u8]) -> IResult<&[u8], char> {
  if !input.is_empty() {
    Ok((&input[1..], input[0] as char))
  } else {
    Err(Err::Incomplete(Needed::Size(1)))
  }
}

//trace_macros!(true);

#[allow(dead_code)]
named!(range<&[u8], Range>,
    alt!(
        do_parse!(
            start: take_char >>
            tag!("-")        >>
            end: take_char   >>
            (Range {
                start: start,
                end:   end,
            })
        ) |
        map!(
            take_char,
            |c| {
                Range {
                    start: c,
                    end:   c,
                }
            }
        )
    )
);

#[allow(dead_code)]
named!(literal<&[u8], Vec<char> >,
    map!(
        many1!(take_char),
        |cs| {
          cs
        }
    )
);

#[test]
fn issue_58() {
  let _ = range(&b"abcd"[..]);
  let _ = literal(&b"abcd"[..]);
}

//trace_macros!(false);

#[cfg(feature = "std")]
mod parse_int {
  use nom::HexDisplay;
  use nom::{IResult, character::streaming::{digit, space}};
  use std::str;

  named!(parse_ints<Vec<i32>>, many0!(spaces_or_int));

  fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32> {
    println!("{}", input.to_hex(8));
    do_parse!(
      input,
      opt!(complete!(space)) >> res: map!(complete!(digit), |x| {
        println!("x: {:?}", x);
        let result = str::from_utf8(x).unwrap();
        println!("Result: {}", result);
        println!("int is empty?: {}", x.is_empty());
        match result.parse() {
          Ok(i) => i,
          Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e),
        }
      }) >> (res)
    )
  }

  #[test]
  fn issue_142() {
    let subject = parse_ints(&b"12 34 5689a"[..]);
    let expected = Ok((&b"a"[..], vec![12, 34, 5689]));
    assert_eq!(subject, expected);

    let subject = parse_ints(&b"12 34 5689 "[..]);
    let expected = Ok((&b" "[..], vec![12, 34, 5689]));
    assert_eq!(subject, expected)
  }
}

#[test]
fn usize_length_bytes_issue() {
  use nom::number::streaming::be_u16;
  let _: IResult<&[u8], &[u8], (&[u8], ErrorKind)> = length_bytes!(b"012346", be_u16);
}

/*
 DOES NOT COMPILE
#[test]
fn issue_152() {
  named!(take4, take!(4));
  named!(xyz, tag!("XYZ"));
  named!(abc, tag!("abc"));

  named!(sw,
    switch!(take4,
      b"abcd" => xyz |
      b"efgh" => abc
    )
  );
}
*/

#[test]
fn take_till_issue() {
  named!(nothing, take_till!(call!(|_| true)));

  assert_eq!(nothing(b""), Err(Err::Incomplete(Needed::Size(1))));
  assert_eq!(nothing(b"abc"), Ok((&b"abc"[..], &b""[..])));
}

named!(
  issue_498<Vec<&[u8]>>,
  separated_nonempty_list!(opt!(space), tag!("abcd"))
);

named!(issue_308(&str) -> bool,
    do_parse! (
        tag! ("foo") >>
        b: alt_complete! (
            map! (tag! ("1"), |_: &str|->bool {true}) |
            value! (false)
        ) >>
        (b) ));

#[cfg(feature = "alloc")]
fn issue_302(input: &[u8]) -> IResult<&[u8], Option<Vec<u64>>> {
  do_parse!(input, entries: cond!(true, count!(le_u64, 3)) >> (entries))
}

#[test]
fn issue_655() {
  use nom::character::streaming::{line_ending, not_line_ending};
  named!(twolines(&str) -> (&str, &str),
    do_parse!(
      l1 : not_line_ending >>
           line_ending >>
      l2 : not_line_ending >>
           line_ending >>
      ((l1, l2))
    )
  );

  assert_eq!(twolines("foo\nbar\n"), Ok(("", ("foo", "bar"))));
  assert_eq!(twolines("féo\nbar\n"), Ok(("", ("féo", "bar"))));
  assert_eq!(twolines("foé\nbar\n"), Ok(("", ("foé", "bar"))));
  assert_eq!(twolines("foé\r\nbar\n"), Ok(("", ("foé", "bar"))));
}

#[test]
fn issue_721() {
  named!(f1<&str, u16>, parse_to!(u16));
  named!(f2<&str, String>, parse_to!(String));
  assert_eq!(f1("1234"), Ok(("", 1234)));
  assert_eq!(f2("foo"), Ok(("", "foo".to_string())));
  //assert_eq!(parse_to!("1234", u16), Ok(("", 1234)));
  //assert_eq!(parse_to!("foo", String), Ok(("", "foo".to_string())));
}

#[cfg(feature = "alloc")]
named!(issue_717<&[u8], Vec<&[u8]> >,
  separated_list!(tag!([0x0]), is_not!([0x0u8]))
);

struct NoPartialEq {
  value: i32,
}

named!(issue_724<&str, i32>,
  do_parse!(
    metadata: permutation!(
      map!(tag!("hello"), |_| NoPartialEq { value: 1 }),
      map!(tag!("world"), |_| NoPartialEq { value: 2 })
    ) >>
    (metadata.0.value + metadata.1.value)
  )
);

#[test]
fn issue_752() {
    assert_eq!(
        Err::Error(("ab", nom::error::ErrorKind::ParseTo)),
        parse_to!("ab", usize).unwrap_err()
    )
}

fn atom_specials(c: u8) -> bool {
    c == b'q'
}

named!(
    capability<&str>,
    do_parse!(tag!(" ") >> _atom: map_res!(take_till1!(atom_specials), std::str::from_utf8) >> ("a"))
);

#[test]
fn issue_759() {
    assert_eq!(capability(b" abcqd"), Ok((&b"qd"[..], "a")));
}

named_args!(issue_771(count: usize)<Vec<u32>>,
  length_count!(value!(count), call!(nom::number::streaming::be_u32))
);

/// This test is in a separate module to check that all required symbols are imported in
/// `escaped_transform!()`. Without the module, the `use`-es of the current module would
/// mask the error ('"Use of undeclared type or module `Needed`" in escaped_transform!').
mod issue_780 {
  named!(issue_780<&str, String>,
    escaped_transform!(call!(::nom::character::streaming::alpha), '\\', tag!("n"))
  );
}

// issue 617
named!(digits, take_while1!( is_digit ));
named!(multi_617<&[u8], () >, fold_many0!( digits, (), |_, _| {}));

// Sad :(
named!(multi_617_fails<&[u8], () >, fold_many0!( take_while1!( is_digit ), (), |_, _| {}));

mod issue_647 {
  use nom::{Err, number::streaming::be_f64, error::ErrorKind};
  pub type Input<'a> = &'a [u8];

  #[derive(PartialEq, Debug, Clone)]
  struct Data {
      c: f64,
      v: Vec<f64>
  }

  fn list<'a,'b>(input: Input<'a>, _cs: &'b f64) -> Result<(Input<'a>,Vec<f64>), Err<(&'a [u8], ErrorKind)>> {
      separated_list_complete!(input, tag!(","),be_f64)
  }

  named!(data<Input,Data>, map!(
      do_parse!(
          c: be_f64 >>
          tag!("\n") >>
          v: call!(list,&c) >>
          (c,v)
      ), |(c,v)| {
          Data {
              c: c,
              v: v
          }
      }
  ));
}

named!(issue_775, take_till1!(|_| true));

#[test]
fn issue_848_overflow_incomplete_bits_to_bytes() {
  named!(parser<&[u8], &[u8]>, bits!(bytes!(take!(0x2000000000000000))));
  assert_eq!(parser(&b""[..]), Err(Err::Failure(error_position!(&b""[..], ErrorKind::TooLarge))));
}
<commit_msg>fix unit tests<commit_after>//#![feature(trace_macros)]
#![allow(dead_code)]
#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))]

#[macro_use]
extern crate nom;

use nom::{character::{is_digit, streaming::space1 as space}, Err, IResult, Needed, error::ErrorKind, number::streaming::le_u64};

#[allow(dead_code)]
struct Range {
  start: char,
  end: char,
}

pub fn take_char(input: &[u8]) -> IResult<&[u8], char> {
  if !input.is_empty() {
    Ok((&input[1..], input[0] as char))
  } else {
    Err(Err::Incomplete(Needed::Size(1)))
  }
}

//trace_macros!(true);

#[allow(dead_code)]
named!(range<&[u8], Range>,
    alt!(
        do_parse!(
            start: take_char >>
            tag!("-")        >>
            end: take_char   >>
            (Range {
                start: start,
                end:   end,
            })
        ) |
        map!(
            take_char,
            |c| {
                Range {
                    start: c,
                    end:   c,
                }
            }
        )
    )
);

#[allow(dead_code)]
named!(literal<&[u8], Vec<char> >,
    map!(
        many1!(take_char),
        |cs| {
          cs
        }
    )
);

#[test]
fn issue_58() {
  let _ = range(&b"abcd"[..]);
  let _ = literal(&b"abcd"[..]);
}

//trace_macros!(false);

#[cfg(feature = "std")]
mod parse_int {
  use nom::HexDisplay;
  use nom::{IResult, character::streaming::{digit1 as digit, space1 as space}};
  use std::str;

  named!(parse_ints<Vec<i32>>, many0!(spaces_or_int));

  fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32> {
    println!("{}", input.to_hex(8));
    do_parse!(
      input,
      opt!(complete!(space)) >> res: map!(complete!(digit), |x| {
        println!("x: {:?}", x);
        let result = str::from_utf8(x).unwrap();
        println!("Result: {}", result);
        println!("int is empty?: {}", x.is_empty());
        match result.parse() {
          Ok(i) => i,
          Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e),
        }
      }) >> (res)
    )
  }

  #[test]
  fn issue_142() {
    let subject = parse_ints(&b"12 34 5689a"[..]);
    let expected = Ok((&b"a"[..], vec![12, 34, 5689]));
    assert_eq!(subject, expected);

    let subject = parse_ints(&b"12 34 5689 "[..]);
    let expected = Ok((&b" "[..], vec![12, 34, 5689]));
    assert_eq!(subject, expected)
  }
}

#[test]
fn usize_length_bytes_issue() {
  use nom::number::streaming::be_u16;
  let _: IResult<&[u8], &[u8], (&[u8], ErrorKind)> = length_bytes!(b"012346", be_u16);
}

/*
 DOES NOT COMPILE
#[test]
fn issue_152() {
  named!(take4, take!(4));
  named!(xyz, tag!("XYZ"));
  named!(abc, tag!("abc"));

  named!(sw,
    switch!(take4,
      b"abcd" => xyz |
      b"efgh" => abc
    )
  );
}
*/

#[test]
fn take_till_issue() {
  named!(nothing, take_till!(call!(|_| true)));

  assert_eq!(nothing(b""), Err(Err::Incomplete(Needed::Size(1))));
  assert_eq!(nothing(b"abc"), Ok((&b"abc"[..], &b""[..])));
}

named!(
  issue_498<Vec<&[u8]>>,
  separated_nonempty_list!(opt!(space), tag!("abcd"))
);

named!(issue_308(&str) -> bool,
    do_parse! (
        tag! ("foo") >>
        b: alt_complete! (
            map! (tag! ("1"), |_: &str|->bool {true}) |
            value! (false)
        ) >>
        (b) ));

#[cfg(feature = "alloc")]
fn issue_302(input: &[u8]) -> IResult<&[u8], Option<Vec<u64>>> {
  do_parse!(input, entries: cond!(true, count!(le_u64, 3)) >> (entries))
}

#[test]
fn issue_655() {
  use nom::character::streaming::{line_ending, not_line_ending};
  named!(twolines(&str) -> (&str, &str),
    do_parse!(
      l1 : not_line_ending >>
           line_ending >>
      l2 : not_line_ending >>
           line_ending >>
      ((l1, l2))
    )
  );

  assert_eq!(twolines("foo\nbar\n"), Ok(("", ("foo", "bar"))));
  assert_eq!(twolines("féo\nbar\n"), Ok(("", ("féo", "bar"))));
  assert_eq!(twolines("foé\nbar\n"), Ok(("", ("foé", "bar"))));
  assert_eq!(twolines("foé\r\nbar\n"), Ok(("", ("foé", "bar"))));
}

#[test]
fn issue_721() {
  named!(f1<&str, u16>, parse_to!(u16));
  named!(f2<&str, String>, parse_to!(String));
  assert_eq!(f1("1234"), Ok(("", 1234)));
  assert_eq!(f2("foo"), Ok(("", "foo".to_string())));
  //assert_eq!(parse_to!("1234", u16), Ok(("", 1234)));
  //assert_eq!(parse_to!("foo", String), Ok(("", "foo".to_string())));
}

#[cfg(feature = "alloc")]
named!(issue_717<&[u8], Vec<&[u8]> >,
  separated_list!(tag!([0x0]), is_not!([0x0u8]))
);

struct NoPartialEq {
  value: i32,
}

named!(issue_724<&str, i32>,
  do_parse!(
    metadata: permutation!(
      map!(tag!("hello"), |_| NoPartialEq { value: 1 }),
      map!(tag!("world"), |_| NoPartialEq { value: 2 })
    ) >>
    (metadata.0.value + metadata.1.value)
  )
);

#[test]
fn issue_752() {
    assert_eq!(
        Err::Error(("ab", nom::error::ErrorKind::ParseTo)),
        parse_to!("ab", usize).unwrap_err()
    )
}

fn atom_specials(c: u8) -> bool {
    c == b'q'
}

named!(
    capability<&str>,
    do_parse!(tag!(" ") >> _atom: map_res!(take_till1!(atom_specials), std::str::from_utf8) >> ("a"))
);

#[test]
fn issue_759() {
    assert_eq!(capability(b" abcqd"), Ok((&b"qd"[..], "a")));
}

named_args!(issue_771(count: usize)<Vec<u32>>,
  length_count!(value!(count), call!(nom::number::streaming::be_u32))
);

/// This test is in a separate module to check that all required symbols are imported in
/// `escaped_transform!()`. Without the module, the `use`-es of the current module would
/// mask the error ('"Use of undeclared type or module `Needed`" in escaped_transform!').
mod issue_780 {
  named!(issue_780<&str, String>,
    escaped_transform!(call!(::nom::character::streaming::alpha1), '\\', tag!("n"))
  );
}

// issue 617
named!(digits, take_while1!( is_digit ));
named!(multi_617<&[u8], () >, fold_many0!( digits, (), |_, _| {}));

// Sad :(
named!(multi_617_fails<&[u8], () >, fold_many0!( take_while1!( is_digit ), (), |_, _| {}));

mod issue_647 {
  use nom::{Err, number::streaming::be_f64, error::ErrorKind};
  pub type Input<'a> = &'a [u8];

  #[derive(PartialEq, Debug, Clone)]
  struct Data {
      c: f64,
      v: Vec<f64>
  }

  fn list<'a,'b>(input: Input<'a>, _cs: &'b f64) -> Result<(Input<'a>,Vec<f64>), Err<(&'a [u8], ErrorKind)>> {
      separated_list_complete!(input, tag!(","),be_f64)
  }

  named!(data<Input,Data>, map!(
      do_parse!(
          c: be_f64 >>
          tag!("\n") >>
          v: call!(list,&c) >>
          (c,v)
      ), |(c,v)| {
          Data {
              c: c,
              v: v
          }
      }
  ));
}

named!(issue_775, take_till1!(|_| true));

#[test]
fn issue_848_overflow_incomplete_bits_to_bytes() {
  named!(parser<&[u8], &[u8]>, bits!(bytes!(take!(0x2000000000000000))));
  assert_eq!(parser(&b""[..]), Err(Err::Failure(error_position!(&b""[..], ErrorKind::TooLarge))));
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;

#[test]
fn base() {
    info!("hello");
    info!("hello",);
}

#[test]
fn with_args() {
    info!("hello {}", "cats");
    info!("hello {}", "cats",);
    info!("hello {}", "cats",);
}

#[test]
fn named_arg() {
    info!("hello {value}", value = "cats");
}

#[test]
fn kv() {
    info!("hello {}", "cats", {
        cat_1: "chashu",
        cat_2: "nori",
    });
}

#[test]
fn kv_and_named_arg() {
    info!("hello {value}", value = "cats", {
        cat_1: "chashu",
        cat_2: "nori",
    });
}
<commit_msg>remove named tests<commit_after>#[macro_use]
extern crate log;

#[test]
fn base() {
    info!("hello");
    info!("hello",);
}

#[test]
fn with_args() {
    info!("hello {}", "cats");
    info!("hello {}", "cats",);
    info!("hello {}", "cats",);
}

#[test]
fn kv() {
    info!("hello {}", "cats", {
        cat_1: "chashu",
        cat_2: "nori",
    });
}
<|endoftext|>


<commit_before>extern crate futures;

use std::thread;
use futures::sync::oneshot;
use futures::Future;

fn send_shared_oneshot_and_wait_on_multiple_threads(threads_number: u32) {
    let (tx, rx) = oneshot::channel::<u32>();
    let f = rx.shared();
    let mut cloned_futures_waited_oneshots = vec![];
    for _ in 0..threads_number {
        let cloned_future = f.clone();
        let (tx2, rx2) = oneshot::channel::<()>();
        cloned_futures_waited_oneshots.push(rx2);
        thread::spawn(move || {
            assert!(*cloned_future.wait().unwrap() == 6);
            tx2.complete(());
        });
    }
    tx.complete(6);
    for f in cloned_futures_waited_oneshots {
        f.wait().unwrap();
    }
}

#[test]
fn one_threads() {
    send_shared_oneshot_and_wait_on_multiple_threads(2);
}

#[test]
fn two_threads() {
    send_shared_oneshot_and_wait_on_multiple_threads(2);
}

#[test]
fn many_threads() {
    send_shared_oneshot_and_wait_on_multiple_threads(1000);
}
<commit_msg>Use single thread in `one_thread` test<commit_after>extern crate futures;

use std::thread;
use futures::sync::oneshot;
use futures::Future;

fn send_shared_oneshot_and_wait_on_multiple_threads(threads_number: u32) {
    let (tx, rx) = oneshot::channel::<u32>();
    let f = rx.shared();
    let mut cloned_futures_waited_oneshots = vec![];
    for _ in 0..threads_number {
        let cloned_future = f.clone();
        let (tx2, rx2) = oneshot::channel::<()>();
        cloned_futures_waited_oneshots.push(rx2);
        thread::spawn(move || {
            assert!(*cloned_future.wait().unwrap() == 6);
            tx2.complete(());
        });
    }
    tx.complete(6);
    for f in cloned_futures_waited_oneshots {
        f.wait().unwrap();
    }
}

#[test]
fn one_thread() {
    send_shared_oneshot_and_wait_on_multiple_threads(1);
}

#[test]
fn two_threads() {
    send_shared_oneshot_and_wait_on_multiple_threads(2);
}

#[test]
fn many_threads() {
    send_shared_oneshot_and_wait_on_multiple_threads(1000);
}
<|endoftext|>