<commit_before>use ast::punc::*;
use ast::token::*;
use std::io::{BufReader, BufferedReader, Buffer, IoError, IoResult, EndOfFile};
use std::char::from_u32;
use std::num::from_str_radix;
use std::from_str::FromStr;
/// A Javascript lexer
pub struct Lexer<B> {
	/// The list of tokens generated so far
	pub tokens : Vec<Token>,
	/// The current line number in the script
	line_number : uint,
	/// The current column number in the script
	column_number : uint,
	/// The reader
	buffer: B,
	/// The peeked character buffer
	peek_buffer: String
}
impl<B:Buffer> Lexer<B> {
	/// Creates a new lexer with empty buffers
	pub fn new(buffer: B) -> Lexer<B> {
		Lexer {
			tokens: Vec::new(),
			line_number: 1,
			column_number: 0,
			buffer: buffer,
			peek_buffer: String::new()
		}
	}
	#[inline(always)]
	fn push_token(&mut self, tk:TokenData) {
		self.tokens.push(Token::new(tk, self.line_number, self.column_number))
	}
	#[inline(always)]
	fn push_punc(&mut self, punc:Punctuator) {
		self.push_token(TPunctuator(punc));
	}
	/// Processes an input stream from a string into an array of tokens
	pub fn lex_str(script:&str) -> Vec<Token> {
		let script_bytes:&[u8] = script.as_bytes();
		let reader = BufReader::new(script_bytes);
		let buf_reader = BufferedReader::new(reader);
		let mut lexer = Lexer::new(buf_reader);
		lexer.lex().unwrap();
		lexer.tokens
	}
	fn next(&mut self) -> IoResult<char> {
		if self.peek_buffer.len() == 0 {
			self.buffer.read_char()
		} else {
			Ok(match self.peek_buffer.pop_char() {
				Some(v) => v,
				None => unreachable!()
			})
		}
	}
	fn peek_for(&mut self, peek:char) -> bool {
		if self.peek_buffer.len() > 0 {
			let matched = self.peek_buffer.as_slice().char_at(self.peek_buffer.len() - 1) == peek;
			if matched {
				self.peek_buffer.pop_char();
			}
			matched
		} else {
			match self.buffer.read_char() {
				Ok(ch) if ch == peek => {
					self.column_number += 1;
					true
				},
				Ok(ch) if ch != peek => {
					self.peek_buffer.push_char(ch);
					false
				},
				_ => false
			}
		}
	}
	/// Processes an input stream from the `buffer` into a vector of tokens
	pub fn lex(&mut self) -> IoResult<()> {
		loop {
			let ch = match self.next() {
				Ok(ch) => ch,
				Err(ref err) if err.kind == EndOfFile => break,
				Err(err) => return Err(err)
			};
			self.column_number += 1;
			println!("{}", ch);
			match ch {
				'"' | '\'' => {
					let mut buf = String::new();
					loop {
						match try!(self.next()) {
							'\'' if ch == '\'' => {
								break;
							},
							'"' if ch == '"' => {
								break;
							},
							'\\' => {
								let escape = try!(self.next());
								if escape != '\n' {
									let escaped_ch = match escape {
										'n' => '\n',
										'r' => '\r',
										't' => '\t',
										'b' => '\x08',
										'f' => '\x0c',
										'0' => '\0',
										'x' => {
											let mut nums = String::with_capacity(2);
											for _ in range(0, 2) {
												nums.push_char(try!(self.next()));
											}
											self.column_number += 2;
											let as_num = match from_str_radix(nums.as_slice(), 16) {
												Some(v) => v,
												None => 0
											};
											match from_u32(as_num) {
												Some(v) => v,
												None => fail!("{}:{}: {} is not a valid unicode scalar value", self.line_number, self.column_number, as_num)
											}
										},
										'u' => {
											let mut nums = String::new();
											for _ in range(0, 4) {
												nums.push_char(try!(self.next()));
											}
											self.column_number += 4;
											let as_num = match from_str_radix(nums.as_slice(), 16) {
												Some(v) => v,
												None => 0
											};
											match from_u32(as_num) {
												Some(v) => v,
												None => fail!("{}:{}: {} is not a valid unicode scalar value", self.line_number, self.column_number, as_num)
											}
										},
										'\'' | '"' => escape,
										_ => fail!("{}:{}: Invalid escape `{}`", self.line_number, self.column_number, ch)
									};
									buf.push_char(escaped_ch);
								}
							},
							ch => buf.push_char(ch)
						}
					}
					self.push_token(TStringLiteral(buf))
				},
				'0' if self.peek_for('x') => {
					let mut buf = String::new();
					loop {
						match try!(self.next()) {
							ch if ch.is_digit_radix(16) => buf.push_char(ch),
							ch => {
								self.peek_buffer.push_char(ch);
								break;
							}
						}
					}
					self.push_token(TNumericLiteral(from_str_radix(buf.as_slice(), 16).unwrap()));
				},
				'0' => {
					let mut buf = "0".into_string();
					let mut gone_decimal = false;
					loop {
						let ch = self.next();
						match ch {
							Ok(ch) if ch.is_digit_radix(8) =>
								buf.push_char(ch),
							Ok('8') | Ok('9') | Ok('.') => {
								gone_decimal = true;
								buf.push_char(ch.unwrap());
							},
							Ok(ch) => {
								self.peek_buffer.push_char(ch);
								break;
							},
							Err(IoError {kind: EndOfFile, ..}) =>
								break,
							Err(err) =>
								return Err(err)
						}
					}
					self.push_token(TNumericLiteral(if gone_decimal {
						from_str(buf.as_slice())
					} else {
						from_str_radix(buf.as_slice(), 8)
					}.unwrap()));
				},
				_ if ch.is_digit() => {
					let mut buf = String::new();
					buf.push_char(ch);
					loop {
						let ch = try!(self.next());
						match ch {
							'.' => buf.push_char(ch),
							_ if ch.is_digit() => buf.push_char(ch),
							_ => {
								self.peek_buffer.push_char(ch);
								break;
							}
						}
					}
					self.push_token(TNumericLiteral(from_str(buf.as_slice()).unwrap()));
				},
				_ if ch.is_alphabetic() || ch == '$' || ch == '_' => {
					let mut buf = String::new();
					buf.push_char(ch);
					loop {
						let ch = try!(self.next());
						match ch {
							_ if ch.is_alphabetic() || ch.is_digit() || ch == '_' => buf.push_char(ch),
							_ => {
								self.peek_buffer.push_char(ch);
								break;
							}
						}
					}
					self.push_token(match buf.as_slice() {
						"true" => TBooleanLiteral(true),
						"false" => TBooleanLiteral(false),
						"null" => TNullLiteral,
						slice => match FromStr::from_str(slice) {
							Some(keyword) => TKeyword(keyword),
							None => TIdentifier(buf.clone())
						}
					});
				},
				';' => {
					self.push_punc(PSemicolon);
				},
				':' => {
					self.push_punc(PColon);
				},
				'.' => {
					self.push_punc(PDot);
				},
				'(' => {
					self.push_punc(POpenParen);
				},
				')' => {
					self.push_punc(PCloseParen);
				},
				',' => {
					self.push_punc(PComma);
				},
				'{' => {
					self.push_punc(POpenBlock);
				},
				'}' => {
					self.push_punc(PCloseBlock);
				},
				'[' => {
					self.push_punc(POpenBracket);
				},
				']' => {
					self.push_punc(PCloseBracket);
				},
				'?' => {
					self.push_punc(PQuestion);
				},
				'/' if self.peek_for('/') => {
					let mut buf = String::new();
					loop {
						match try!(self.next()) {
							'\n' => break,
							ch => buf.push_char(ch)
						}
					}
					self.push_token(TComment(buf));
				},
				'/' if self.peek_for('*') => {
					let mut buf = String::new();
					loop {
						match try!(self.next()) {
							'\n' => break,
							'*' if self.peek_for('/') => break,
							ch => buf.push_char(ch)
						}
					}
					self.push_token(TComment(buf));
				},
				'/' if self.peek_for('=') => {
					self.push_punc(PAssignDiv);
				},
				'/' => {
					self.push_punc(PDiv);
				},
				'*' if self.peek_for('=') => {
					self.push_punc(PAssignMul);
				},
				'*' => {
					self.push_punc(PMul);
				},
				'+' if self.peek_for('=') => {
					self.push_punc(PAssignAdd);
				},
				'+' if self.peek_for('+') => {
					self.push_punc(PInc);
				},
				'+' => {
					self.push_punc(PAdd);
				},
				'-' if self.peek_for('=') => {
					self.push_punc(PAssignSub);
				},
				'-' if self.peek_for('-') => {
					self.push_punc(PDec);
				},
				'-' => {
					self.push_punc(PSub);
				},
				'%' if self.peek_for('=') => {
					self.push_punc(PAssignMod);
				},
				'%' => {
					self.push_punc(PMod);
				},
				'|' if self.peek_for('|') => {
					self.push_punc(PBoolOr);
				},
				'|' if self.peek_for('=') => {
					self.push_punc(PAssignOr);
				},
				'|' => {
					self.push_punc(POr);
				},
				'&' if self.peek_for('&') => {
					self.push_punc(PBoolAnd);
				},
				'&' if self.peek_for('=') => {
					self.push_punc(PAssignAnd);
				},
				'&' => {
					self.push_punc(PAnd);
				},
				'^' if self.peek_for('=') => {
					self.push_punc(PAssignXor);
				},
				'^' => {
					self.push_punc(PXor);
				},
				'=' if self.peek_for('>') => {
					self.push_punc(PArrow);
				},
				'=' if self.peek_for('=') => {
					if self.peek_for('=') {
						self.push_punc(PStrictEq);
					} else {
						self.push_punc(PEq);
					}
				},
				'=' => {
					self.push_punc(PAssign);
				},
				'<' if self.peek_for('=') => {
					self.push_punc(PLessThanOrEq);
				},
				'<' if self.peek_for('<') => {
					if self.peek_for('=') {
						self.push_punc(PAssignLeftSh);
					} else {
						self.push_punc(PLeftSh);
					}
				},
				'<' => {
					self.push_punc(PLessThan);
				},
				'>' if self.peek_for('=') => {
					self.push_punc(PGreaterThanOrEq);
				},
				'>' if self.peek_for('>') => {
					if self.peek_for('=') {
						self.push_punc(PAssignRightSh);
					} else if self.peek_for('>') {
						if self.peek_for('=') {
							self.push_punc(PAssignURightSh);
						} else {
							self.push_punc(PURightSh);
						}
					} else {
						self.push_punc(PRightSh);
					}
				},
				'>' => {
						self.push_punc(PGreaterThan);
				},
				'!' if self.peek_for('=') => {
					if self.peek_for('=') {
						self.push_punc(PStrictNotEq);
					} else {
						self.push_punc(PNotEq);
					}
				},
				'!' => {
					self.push_punc(PNot);
				},
				'~' => {
					self.push_punc(PNeg);
				},
				'\n' | '\u2028'|'\u2029' => {
					self.line_number += 1;
					self.column_number = 0;
				},
				'\r' => {
					self.column_number = 0;
				},
				' ' => (),
				ch => fail!("{}:{}: Unexpected '{}'", self.line_number, self.column_number, ch)
			};
		};
		Ok(())
	}
}<commit_msg>Remove leftover print from debugging<commit_after>use ast::punc::*;
use ast::token::*;
use std::io::{BufReader, BufferedReader, Buffer, IoError, IoResult, EndOfFile};
use std::char::from_u32;
use std::num::from_str_radix;
use std::from_str::FromStr;
/// A Javascript lexer
pub struct Lexer<B> {
	/// The list of tokens generated so far
	pub tokens : Vec<Token>,
	/// The current line number in the script
	line_number : uint,
	/// The current column number in the script
	column_number : uint,
	/// The reader
	buffer: B,
	/// The peeked character buffer
	peek_buffer: String
}
impl<B:Buffer> Lexer<B> {
	/// Creates a new lexer with empty buffers
	pub fn new(buffer: B) -> Lexer<B> {
		Lexer {
			tokens: Vec::new(),
			line_number: 1,
			column_number: 0,
			buffer: buffer,
			peek_buffer: String::new()
		}
	}
	#[inline(always)]
	fn push_token(&mut self, tk:TokenData) {
		self.tokens.push(Token::new(tk, self.line_number, self.column_number))
	}
	#[inline(always)]
	fn push_punc(&mut self, punc:Punctuator) {
		self.push_token(TPunctuator(punc));
	}
	/// Processes an input stream from a string into an array of tokens
	pub fn lex_str(script:&str) -> Vec<Token> {
		let script_bytes:&[u8] = script.as_bytes();
		let reader = BufReader::new(script_bytes);
		let buf_reader = BufferedReader::new(reader);
		let mut lexer = Lexer::new(buf_reader);
		lexer.lex().unwrap();
		lexer.tokens
	}
	fn next(&mut self) -> IoResult<char> {
		if self.peek_buffer.len() == 0 {
			self.buffer.read_char()
		} else {
			Ok(match self.peek_buffer.pop_char() {
				Some(v) => v,
				None => unreachable!()
			})
		}
	}
	fn peek_for(&mut self, peek:char) -> bool {
		if self.peek_buffer.len() > 0 {
			let matched = self.peek_buffer.as_slice().char_at(self.peek_buffer.len() - 1) == peek;
			if matched {
				self.peek_buffer.pop_char();
			}
			matched
		} else {
			match self.buffer.read_char() {
				Ok(ch) if ch == peek => {
					self.column_number += 1;
					true
				},
				Ok(ch) if ch != peek => {
					self.peek_buffer.push_char(ch);
					false
				},
				_ => false
			}
		}
	}
	/// Processes an input stream from the `buffer` into a vector of tokens
	pub fn lex(&mut self) -> IoResult<()> {
		loop {
			let ch = match self.next() {
				Ok(ch) => ch,
				Err(ref err) if err.kind == EndOfFile => break,
				Err(err) => return Err(err)
			};
			self.column_number += 1;
			match ch {
				'"' | '\'' => {
					let mut buf = String::new();
					loop {
						match try!(self.next()) {
							'\'' if ch == '\'' => {
								break;
							},
							'"' if ch == '"' => {
								break;
							},
							'\\' => {
								let escape = try!(self.next());
								if escape != '\n' {
									let escaped_ch = match escape {
										'n' => '\n',
										'r' => '\r',
										't' => '\t',
										'b' => '\x08',
										'f' => '\x0c',
										'0' => '\0',
										'x' => {
											let mut nums = String::with_capacity(2);
											for _ in range(0, 2) {
												nums.push_char(try!(self.next()));
											}
											self.column_number += 2;
											let as_num = match from_str_radix(nums.as_slice(), 16) {
												Some(v) => v,
												None => 0
											};
											match from_u32(as_num) {
												Some(v) => v,
												None => fail!("{}:{}: {} is not a valid unicode scalar value", self.line_number, self.column_number, as_num)
											}
										},
										'u' => {
											let mut nums = String::new();
											for _ in range(0, 4) {
												nums.push_char(try!(self.next()));
											}
											self.column_number += 4;
											let as_num = match from_str_radix(nums.as_slice(), 16) {
												Some(v) => v,
												None => 0
											};
											match from_u32(as_num) {
												Some(v) => v,
												None => fail!("{}:{}: {} is not a valid unicode scalar value", self.line_number, self.column_number, as_num)
											}
										},
										'\'' | '"' => escape,
										_ => fail!("{}:{}: Invalid escape `{}`", self.line_number, self.column_number, ch)
									};
									buf.push_char(escaped_ch);
								}
							},
							ch => buf.push_char(ch)
						}
					}
					self.push_token(TStringLiteral(buf))
				},
				'0' if self.peek_for('x') => {
					let mut buf = String::new();
					loop {
						match try!(self.next()) {
							ch if ch.is_digit_radix(16) => buf.push_char(ch),
							ch => {
								self.peek_buffer.push_char(ch);
								break;
							}
						}
					}
					self.push_token(TNumericLiteral(from_str_radix(buf.as_slice(), 16).unwrap()));
				},
				'0' => {
					let mut buf = "0".into_string();
					let mut gone_decimal = false;
					loop {
						let ch = self.next();
						match ch {
							Ok(ch) if ch.is_digit_radix(8) =>
								buf.push_char(ch),
							Ok('8') | Ok('9') | Ok('.') => {
								gone_decimal = true;
								buf.push_char(ch.unwrap());
							},
							Ok(ch) => {
								self.peek_buffer.push_char(ch);
								break;
							},
							Err(IoError {kind: EndOfFile, ..}) =>
								break,
							Err(err) =>
								return Err(err)
						}
					}
					self.push_token(TNumericLiteral(if gone_decimal {
						from_str(buf.as_slice())
					} else {
						from_str_radix(buf.as_slice(), 8)
					}.unwrap()));
				},
				_ if ch.is_digit() => {
					let mut buf = String::new();
					buf.push_char(ch);
					loop {
						let ch = try!(self.next());
						match ch {
							'.' => buf.push_char(ch),
							_ if ch.is_digit() => buf.push_char(ch),
							_ => {
								self.peek_buffer.push_char(ch);
								break;
							}
						}
					}
					self.push_token(TNumericLiteral(from_str(buf.as_slice()).unwrap()));
				},
				_ if ch.is_alphabetic() || ch == '$' || ch == '_' => {
					let mut buf = String::new();
					buf.push_char(ch);
					loop {
						let ch = try!(self.next());
						match ch {
							_ if ch.is_alphabetic() || ch.is_digit() || ch == '_' => buf.push_char(ch),
							_ => {
								self.peek_buffer.push_char(ch);
								break;
							}
						}
					}
					self.push_token(match buf.as_slice() {
						"true" => TBooleanLiteral(true),
						"false" => TBooleanLiteral(false),
						"null" => TNullLiteral,
						slice => match FromStr::from_str(slice) {
							Some(keyword) => TKeyword(keyword),
							None => TIdentifier(buf.clone())
						}
					});
				},
				';' => {
					self.push_punc(PSemicolon);
				},
				':' => {
					self.push_punc(PColon);
				},
				'.' => {
					self.push_punc(PDot);
				},
				'(' => {
					self.push_punc(POpenParen);
				},
				')' => {
					self.push_punc(PCloseParen);
				},
				',' => {
					self.push_punc(PComma);
				},
				'{' => {
					self.push_punc(POpenBlock);
				},
				'}' => {
					self.push_punc(PCloseBlock);
				},
				'[' => {
					self.push_punc(POpenBracket);
				},
				']' => {
					self.push_punc(PCloseBracket);
				},
				'?' => {
					self.push_punc(PQuestion);
				},
				'/' if self.peek_for('/') => {
					let mut buf = String::new();
					loop {
						match try!(self.next()) {
							'\n' => break,
							ch => buf.push_char(ch)
						}
					}
					self.push_token(TComment(buf));
				},
				'/' if self.peek_for('*') => {
					let mut buf = String::new();
					loop {
						match try!(self.next()) {
							'\n' => break,
							'*' if self.peek_for('/') => break,
							ch => buf.push_char(ch)
						}
					}
					self.push_token(TComment(buf));
				},
				'/' if self.peek_for('=') => {
					self.push_punc(PAssignDiv);
				},
				'/' => {
					self.push_punc(PDiv);
				},
				'*' if self.peek_for('=') => {
					self.push_punc(PAssignMul);
				},
				'*' => {
					self.push_punc(PMul);
				},
				'+' if self.peek_for('=') => {
					self.push_punc(PAssignAdd);
				},
				'+' if self.peek_for('+') => {
					self.push_punc(PInc);
				},
				'+' => {
					self.push_punc(PAdd);
				},
				'-' if self.peek_for('=') => {
					self.push_punc(PAssignSub);
				},
				'-' if self.peek_for('-') => {
					self.push_punc(PDec);
				},
				'-' => {
					self.push_punc(PSub);
				},
				'%' if self.peek_for('=') => {
					self.push_punc(PAssignMod);
				},
				'%' => {
					self.push_punc(PMod);
				},
				'|' if self.peek_for('|') => {
					self.push_punc(PBoolOr);
				},
				'|' if self.peek_for('=') => {
					self.push_punc(PAssignOr);
				},
				'|' => {
					self.push_punc(POr);
				},
				'&' if self.peek_for('&') => {
					self.push_punc(PBoolAnd);
				},
				'&' if self.peek_for('=') => {
					self.push_punc(PAssignAnd);
				},
				'&' => {
					self.push_punc(PAnd);
				},
				'^' if self.peek_for('=') => {
					self.push_punc(PAssignXor);
				},
				'^' => {
					self.push_punc(PXor);
				},
				'=' if self.peek_for('>') => {
					self.push_punc(PArrow);
				},
				'=' if self.peek_for('=') => {
					if self.peek_for('=') {
						self.push_punc(PStrictEq);
					} else {
						self.push_punc(PEq);
					}
				},
				'=' => {
					self.push_punc(PAssign);
				},
				'<' if self.peek_for('=') => {
					self.push_punc(PLessThanOrEq);
				},
				'<' if self.peek_for('<') => {
					if self.peek_for('=') {
						self.push_punc(PAssignLeftSh);
					} else {
						self.push_punc(PLeftSh);
					}
				},
				'<' => {
					self.push_punc(PLessThan);
				},
				'>' if self.peek_for('=') => {
					self.push_punc(PGreaterThanOrEq);
				},
				'>' if self.peek_for('>') => {
					if self.peek_for('=') {
						self.push_punc(PAssignRightSh);
					} else if self.peek_for('>') {
						if self.peek_for('=') {
							self.push_punc(PAssignURightSh);
						} else {
							self.push_punc(PURightSh);
						}
					} else {
						self.push_punc(PRightSh);
					}
				},
				'>' => {
						self.push_punc(PGreaterThan);
				},
				'!' if self.peek_for('=') => {
					if self.peek_for('=') {
						self.push_punc(PStrictNotEq);
					} else {
						self.push_punc(PNotEq);
					}
				},
				'!' => {
					self.push_punc(PNot);
				},
				'~' => {
					self.push_punc(PNeg);
				},
				'\n' | '\u2028'|'\u2029' => {
					self.line_number += 1;
					self.column_number = 0;
				},
				'\r' => {
					self.column_number = 0;
				},
				' ' => (),
				ch => fail!("{}:{}: Unexpected '{}'", self.line_number, self.column_number, ch)
			};
		};
		Ok(())
	}
}<|endoftext|>


<commit_before>use crate::common::util::*;
#[cfg(not(windows))]
use std::os::unix::fs::PermissionsExt;
#[cfg(not(windows))]
extern crate libc;
#[cfg(not(windows))]
use self::libc::{mode_t, umask};

static TEST_DIR1: &str = "mkdir_test1";
static TEST_DIR2: &str = "mkdir_test2";
static TEST_DIR3: &str = "mkdir_test3";
static TEST_DIR4: &str = "mkdir_test4/mkdir_test4_1";
static TEST_DIR5: &str = "mkdir_test5/mkdir_test5_1";
static TEST_DIR6: &str = "mkdir_test6";
static TEST_FILE7: &str = "mkdir_test7";
static TEST_DIR8: &str = "mkdir_test8/mkdir_test8_1/mkdir_test8_2";
static TEST_DIR9: &str = "mkdir_test9/../mkdir_test9_1/../mkdir_test9_2";
static TEST_DIR10: &str = "mkdir_test10/.";
static TEST_DIR11: &str = "mkdir_test11/..";
static TEST_DIR12: &str = "mkdir_test12";

#[test]
fn test_mkdir_mkdir() {
    new_ucmd!().arg(TEST_DIR1).succeeds();
}

#[test]
fn test_mkdir_verbose() {
    let expected = "mkdir: created directory 'mkdir_test1'\n";
    new_ucmd!()
        .arg(TEST_DIR1)
        .arg("-v")
        .run()
        .stdout_is(expected);
}

#[test]
fn test_mkdir_dup_dir() {
    let scene = TestScenario::new(util_name!());
    scene.ucmd().arg(TEST_DIR2).succeeds();
    scene.ucmd().arg(TEST_DIR2).fails();
}

#[test]
fn test_mkdir_mode() {
    new_ucmd!().arg("-m").arg("755").arg(TEST_DIR3).succeeds();
}

#[test]
fn test_mkdir_parent() {
    let scene = TestScenario::new(util_name!());
    scene.ucmd().arg("-p").arg(TEST_DIR4).succeeds();
    scene.ucmd().arg("-p").arg(TEST_DIR4).succeeds();
    scene.ucmd().arg("--parent").arg(TEST_DIR4).succeeds();
    scene.ucmd().arg("--parents").arg(TEST_DIR4).succeeds();
}

#[test]
fn test_mkdir_no_parent() {
    new_ucmd!().arg(TEST_DIR5).fails();
}

#[test]
fn test_mkdir_dup_dir_parent() {
    let scene = TestScenario::new(util_name!());
    scene.ucmd().arg(TEST_DIR6).succeeds();
    scene.ucmd().arg("-p").arg(TEST_DIR6).succeeds();
}

#[test]
fn test_mkdir_dup_file() {
    let scene = TestScenario::new(util_name!());
    scene.fixtures.touch(TEST_FILE7);
    scene.ucmd().arg(TEST_FILE7).fails();

    // mkdir should fail for a file even if -p is specified.
    scene.ucmd().arg("-p").arg(TEST_FILE7).fails();
}

#[test]
#[cfg(not(windows))]
fn test_symbolic_mode() {
    let (at, mut ucmd) = at_and_ucmd!();

    ucmd.arg("-m").arg("a=rwx").arg(TEST_DIR1).succeeds();
    let perms = at.metadata(TEST_DIR1).permissions().mode();
    assert_eq!(perms, 0o40777);
}

#[test]
#[cfg(not(windows))]
fn test_symbolic_alteration() {
    let (at, mut ucmd) = at_and_ucmd!();

    ucmd.arg("-m").arg("-w").arg(TEST_DIR1).succeeds();
    let perms = at.metadata(TEST_DIR1).permissions().mode();
    assert_eq!(perms, 0o40555);
}

#[test]
#[cfg(not(windows))]
fn test_multi_symbolic() {
    let (at, mut ucmd) = at_and_ucmd!();

    ucmd.arg("-m")
        .arg("u=rwx,g=rx,o=")
        .arg(TEST_DIR1)
        .succeeds();
    let perms = at.metadata(TEST_DIR1).permissions().mode();
    assert_eq!(perms, 0o40750);
}

#[test]
fn test_recursive_reporting() {
    new_ucmd!()
        .arg("-p")
        .arg("-v")
        .arg(TEST_DIR8)
        .succeeds()
        .stdout_contains("created directory 'mkdir_test8'")
        .stdout_contains("created directory 'mkdir_test8/mkdir_test8_1'")
        .stdout_contains("created directory 'mkdir_test8/mkdir_test8_1/mkdir_test8_2'");
    new_ucmd!().arg("-v").arg(TEST_DIR8).fails().no_stdout();
    new_ucmd!()
        .arg("-p")
        .arg("-v")
        .arg(TEST_DIR9)
        .succeeds()
        .stdout_contains("created directory 'mkdir_test9'")
        .stdout_contains("created directory 'mkdir_test9/../mkdir_test9_1'")
        .stdout_contains("created directory 'mkdir_test9/../mkdir_test9_1/../mkdir_test9_2'");
}

#[test]
fn test_mkdir_trailing_dot() {
    let scene2 = TestScenario::new("ls");
    new_ucmd!()
        .arg("-p")
        .arg("-v")
        .arg("mkdir_test10-2")
        .succeeds();

    new_ucmd!()
        .arg("-p")
        .arg("-v")
        .arg(TEST_DIR10)
        .succeeds()
        .stdout_contains("created directory 'mkdir_test10'");

    new_ucmd!()
        .arg("-p")
        .arg("-v")
        .arg(TEST_DIR11)
        .succeeds()
        .stdout_contains("created directory 'mkdir_test11'");
    let result = scene2.cmd("ls").arg("-al").run();
    println!("ls dest {}", result.stdout_str());
}

#[test]
#[cfg(not(windows))]
fn test_umask_compliance() {
    fn test_single_case(umask_set: mode_t) {
        let (at, mut ucmd) = at_and_ucmd!();

        let original_umask = unsafe { umask(umask_set) };

        ucmd.arg(TEST_DIR12).succeeds();
        let perms = at.metadata(TEST_DIR12).permissions().mode() as mode_t;

        assert_eq!(perms, (!umask_set & 0o0777) + 0o40000); // before compare, add the set GUID, UID bits
        unsafe {
            umask(original_umask);
        } // set umask back to original
    }

    for i in 0o0..0o027 {
        // tests all permission combinations
        test_single_case(i as mode_t);
    }
}
<commit_msg>Fix clippy<commit_after>use crate::common::util::*;
#[cfg(not(windows))]
use std::os::unix::fs::PermissionsExt;
#[cfg(not(windows))]
extern crate libc;
#[cfg(not(windows))]
use self::libc::{mode_t, umask};

static TEST_DIR1: &str = "mkdir_test1";
static TEST_DIR2: &str = "mkdir_test2";
static TEST_DIR3: &str = "mkdir_test3";
static TEST_DIR4: &str = "mkdir_test4/mkdir_test4_1";
static TEST_DIR5: &str = "mkdir_test5/mkdir_test5_1";
static TEST_DIR6: &str = "mkdir_test6";
static TEST_FILE7: &str = "mkdir_test7";
static TEST_DIR8: &str = "mkdir_test8/mkdir_test8_1/mkdir_test8_2";
static TEST_DIR9: &str = "mkdir_test9/../mkdir_test9_1/../mkdir_test9_2";
static TEST_DIR10: &str = "mkdir_test10/.";
static TEST_DIR11: &str = "mkdir_test11/..";
#[cfg(not(windows))]
static TEST_DIR12: &str = "mkdir_test12";

#[test]
fn test_mkdir_mkdir() {
    new_ucmd!().arg(TEST_DIR1).succeeds();
}

#[test]
fn test_mkdir_verbose() {
    let expected = "mkdir: created directory 'mkdir_test1'\n";
    new_ucmd!()
        .arg(TEST_DIR1)
        .arg("-v")
        .run()
        .stdout_is(expected);
}

#[test]
fn test_mkdir_dup_dir() {
    let scene = TestScenario::new(util_name!());
    scene.ucmd().arg(TEST_DIR2).succeeds();
    scene.ucmd().arg(TEST_DIR2).fails();
}

#[test]
fn test_mkdir_mode() {
    new_ucmd!().arg("-m").arg("755").arg(TEST_DIR3).succeeds();
}

#[test]
fn test_mkdir_parent() {
    let scene = TestScenario::new(util_name!());
    scene.ucmd().arg("-p").arg(TEST_DIR4).succeeds();
    scene.ucmd().arg("-p").arg(TEST_DIR4).succeeds();
    scene.ucmd().arg("--parent").arg(TEST_DIR4).succeeds();
    scene.ucmd().arg("--parents").arg(TEST_DIR4).succeeds();
}

#[test]
fn test_mkdir_no_parent() {
    new_ucmd!().arg(TEST_DIR5).fails();
}

#[test]
fn test_mkdir_dup_dir_parent() {
    let scene = TestScenario::new(util_name!());
    scene.ucmd().arg(TEST_DIR6).succeeds();
    scene.ucmd().arg("-p").arg(TEST_DIR6).succeeds();
}

#[test]
fn test_mkdir_dup_file() {
    let scene = TestScenario::new(util_name!());
    scene.fixtures.touch(TEST_FILE7);
    scene.ucmd().arg(TEST_FILE7).fails();

    // mkdir should fail for a file even if -p is specified.
    scene.ucmd().arg("-p").arg(TEST_FILE7).fails();
}

#[test]
#[cfg(not(windows))]
fn test_symbolic_mode() {
    let (at, mut ucmd) = at_and_ucmd!();

    ucmd.arg("-m").arg("a=rwx").arg(TEST_DIR1).succeeds();
    let perms = at.metadata(TEST_DIR1).permissions().mode();
    assert_eq!(perms, 0o40777);
}

#[test]
#[cfg(not(windows))]
fn test_symbolic_alteration() {
    let (at, mut ucmd) = at_and_ucmd!();

    ucmd.arg("-m").arg("-w").arg(TEST_DIR1).succeeds();
    let perms = at.metadata(TEST_DIR1).permissions().mode();
    assert_eq!(perms, 0o40555);
}

#[test]
#[cfg(not(windows))]
fn test_multi_symbolic() {
    let (at, mut ucmd) = at_and_ucmd!();

    ucmd.arg("-m")
        .arg("u=rwx,g=rx,o=")
        .arg(TEST_DIR1)
        .succeeds();
    let perms = at.metadata(TEST_DIR1).permissions().mode();
    assert_eq!(perms, 0o40750);
}

#[test]
fn test_recursive_reporting() {
    new_ucmd!()
        .arg("-p")
        .arg("-v")
        .arg(TEST_DIR8)
        .succeeds()
        .stdout_contains("created directory 'mkdir_test8'")
        .stdout_contains("created directory 'mkdir_test8/mkdir_test8_1'")
        .stdout_contains("created directory 'mkdir_test8/mkdir_test8_1/mkdir_test8_2'");
    new_ucmd!().arg("-v").arg(TEST_DIR8).fails().no_stdout();
    new_ucmd!()
        .arg("-p")
        .arg("-v")
        .arg(TEST_DIR9)
        .succeeds()
        .stdout_contains("created directory 'mkdir_test9'")
        .stdout_contains("created directory 'mkdir_test9/../mkdir_test9_1'")
        .stdout_contains("created directory 'mkdir_test9/../mkdir_test9_1/../mkdir_test9_2'");
}

#[test]
fn test_mkdir_trailing_dot() {
    let scene2 = TestScenario::new("ls");
    new_ucmd!()
        .arg("-p")
        .arg("-v")
        .arg("mkdir_test10-2")
        .succeeds();

    new_ucmd!()
        .arg("-p")
        .arg("-v")
        .arg(TEST_DIR10)
        .succeeds()
        .stdout_contains("created directory 'mkdir_test10'");

    new_ucmd!()
        .arg("-p")
        .arg("-v")
        .arg(TEST_DIR11)
        .succeeds()
        .stdout_contains("created directory 'mkdir_test11'");
    let result = scene2.cmd("ls").arg("-al").run();
    println!("ls dest {}", result.stdout_str());
}

#[test]
#[cfg(not(windows))]
fn test_umask_compliance() {
    fn test_single_case(umask_set: mode_t) {
        let (at, mut ucmd) = at_and_ucmd!();

        let original_umask = unsafe { umask(umask_set) };

        ucmd.arg(TEST_DIR12).succeeds();
        let perms = at.metadata(TEST_DIR12).permissions().mode() as mode_t;

        assert_eq!(perms, (!umask_set & 0o0777) + 0o40000); // before compare, add the set GUID, UID bits
        unsafe {
            umask(original_umask);
        } // set umask back to original
    }

    for i in 0o0..0o027 {
        // tests all permission combinations
        test_single_case(i as mode_t);
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::env;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::Write;

struct Test {
    repo: &'static str,
    name: &'static str,
    sha: &'static str,
    lock: Option<&'static str>,
    packages: &'static [&'static str],
}

const TEST_REPOS: &'static [Test] = &[
    Test {
        name: "iron",
        repo: "https://github.com/iron/iron",
        sha: "21c7dae29c3c214c08533c2a55ac649b418f2fe3",
        lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
        packages: &[],
    },
    Test {
        name: "ripgrep",
        repo: "https://github.com/BurntSushi/ripgrep",
        sha: "b65bb37b14655e1a89c7cd19c8b011ef3e312791",
        lock: None,
        packages: &[],
    },
    Test {
        name: "tokei",
        repo: "https://github.com/Aaronepower/tokei",
        sha: "5e11c4852fe4aa086b0e4fe5885822fbe57ba928",
        lock: None,
        packages: &[],
    },
    Test {
        name: "treeify",
        repo: "https://github.com/dzamlo/treeify",
        sha: "999001b223152441198f117a68fb81f57bc086dd",
        lock: None,
        packages: &[],
    },
    Test {
        name: "xsv",
        repo: "https://github.com/BurntSushi/xsv",
        sha: "66956b6bfd62d6ac767a6b6499c982eae20a2c9f",
        lock: None,
        packages: &[],
    },
    Test {
        name: "servo",
        repo: "https://github.com/servo/servo",
        sha: "38fe9533b93e985657f99a29772bf3d3c8694822",
        lock: None,
        // Only test Stylo a.k.a. Quantum CSS, the parts of Servo going into Firefox.
        // This takes much less time to build than all of Servo and supports stable Rust.
        packages: &["stylo_tests", "selectors"],
    },
    Test {
        name: "webrender",
        repo: "https://github.com/servo/webrender",
        sha: "57250b2b8fa63934f80e5376a29f7dcb3f759ad6",
        lock: None,
        packages: &[],
    },
];

fn main() {
    let args = env::args().collect::<Vec<_>>();
    let ref cargo = args[1];
    let out_dir = Path::new(&args[2]);
    let ref cargo = Path::new(cargo);

    for test in TEST_REPOS.iter().rev() {
        test_repo(cargo, out_dir, test);
    }
}

fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) {
    println!("testing {}", test.repo);
    let dir = clone_repo(test, out_dir);
    if let Some(lockfile) = test.lock {
        File::create(&dir.join("Cargo.lock"))
            .expect("")
            .write_all(lockfile.as_bytes())
            .expect("");
    }
    if !run_cargo_test(cargo, &dir, test.packages) {
        panic!("tests failed for {}", test.repo);
    }
}

fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
    let out_dir = out_dir.join(test.name);

    if !out_dir.join(".git").is_dir() {
        let status = Command::new("git")
                         .arg("init")
                         .arg(&out_dir)
                         .status()
                         .expect("");
        assert!(status.success());
    }

    // Try progressively deeper fetch depths to find the commit
    let mut found = false;
    for depth in &[0, 1, 10, 100, 1000, 100000] {
        if *depth > 0 {
            let status = Command::new("git")
                             .arg("fetch")
                             .arg(test.repo)
                             .arg("master")
                             .arg(&format!("--depth={}", depth))
                             .current_dir(&out_dir)
                             .status()
                             .expect("");
            assert!(status.success());
        }

        let status = Command::new("git")
                         .arg("reset")
                         .arg(test.sha)
                         .arg("--hard")
                         .current_dir(&out_dir)
                         .status()
                         .expect("");

        if status.success() {
            found = true;
            break;
        }
    }

    if !found {
        panic!("unable to find commit {}", test.sha)
    }
    let status = Command::new("git")
                     .arg("clean")
                     .arg("-fdx")
                     .current_dir(&out_dir)
                     .status()
                     .unwrap();
    assert!(status.success());

    out_dir
}

fn run_cargo_test(cargo_path: &Path, crate_path: &Path, packages: &[&str]) -> bool {
    let mut command = Command::new(cargo_path);
    command.arg("test");
    for name in packages {
        command.arg("-p").arg(name);
    }
    let status = command
        // Disable rust-lang/cargo's cross-compile tests
        .env("CFG_DISABLE_CROSS_TESTS", "1")
        // Relax #![deny(warnings)] in some crates
        .env("RUSTFLAGS", "--cap-lints warn")
        .current_dir(crate_path)
        .status()
        .expect("");

    status.success()
}
<commit_msg>cargotest: temporarily use eddyb/servo to include servo/servo#19285.<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::env;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::Write;

struct Test {
    repo: &'static str,
    name: &'static str,
    sha: &'static str,
    lock: Option<&'static str>,
    packages: &'static [&'static str],
}

const TEST_REPOS: &'static [Test] = &[
    Test {
        name: "iron",
        repo: "https://github.com/iron/iron",
        sha: "21c7dae29c3c214c08533c2a55ac649b418f2fe3",
        lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
        packages: &[],
    },
    Test {
        name: "ripgrep",
        repo: "https://github.com/BurntSushi/ripgrep",
        sha: "b65bb37b14655e1a89c7cd19c8b011ef3e312791",
        lock: None,
        packages: &[],
    },
    Test {
        name: "tokei",
        repo: "https://github.com/Aaronepower/tokei",
        sha: "5e11c4852fe4aa086b0e4fe5885822fbe57ba928",
        lock: None,
        packages: &[],
    },
    Test {
        name: "treeify",
        repo: "https://github.com/dzamlo/treeify",
        sha: "999001b223152441198f117a68fb81f57bc086dd",
        lock: None,
        packages: &[],
    },
    Test {
        name: "xsv",
        repo: "https://github.com/BurntSushi/xsv",
        sha: "66956b6bfd62d6ac767a6b6499c982eae20a2c9f",
        lock: None,
        packages: &[],
    },
    Test {
        name: "servo",
        repo: "https://github.com/eddyb/servo",
        sha: "6031de9a397e2feba4ff98725991825f62b68518",
        lock: None,
        // Only test Stylo a.k.a. Quantum CSS, the parts of Servo going into Firefox.
        // This takes much less time to build than all of Servo and supports stable Rust.
        packages: &["stylo_tests", "selectors"],
    },
    Test {
        name: "webrender",
        repo: "https://github.com/servo/webrender",
        sha: "57250b2b8fa63934f80e5376a29f7dcb3f759ad6",
        lock: None,
        packages: &[],
    },
];

fn main() {
    let args = env::args().collect::<Vec<_>>();
    let ref cargo = args[1];
    let out_dir = Path::new(&args[2]);
    let ref cargo = Path::new(cargo);

    for test in TEST_REPOS.iter().rev() {
        test_repo(cargo, out_dir, test);
    }
}

fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) {
    println!("testing {}", test.repo);
    let dir = clone_repo(test, out_dir);
    if let Some(lockfile) = test.lock {
        File::create(&dir.join("Cargo.lock"))
            .expect("")
            .write_all(lockfile.as_bytes())
            .expect("");
    }
    if !run_cargo_test(cargo, &dir, test.packages) {
        panic!("tests failed for {}", test.repo);
    }
}

fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
    let out_dir = out_dir.join(test.name);

    if !out_dir.join(".git").is_dir() {
        let status = Command::new("git")
                         .arg("init")
                         .arg(&out_dir)
                         .status()
                         .expect("");
        assert!(status.success());
    }

    // Try progressively deeper fetch depths to find the commit
    let mut found = false;
    for depth in &[0, 1, 10, 100, 1000, 100000] {
        if *depth > 0 {
            let status = Command::new("git")
                             .arg("fetch")
                             .arg(test.repo)
                             .arg("master")
                             .arg(&format!("--depth={}", depth))
                             .current_dir(&out_dir)
                             .status()
                             .expect("");
            assert!(status.success());
        }

        let status = Command::new("git")
                         .arg("reset")
                         .arg(test.sha)
                         .arg("--hard")
                         .current_dir(&out_dir)
                         .status()
                         .expect("");

        if status.success() {
            found = true;
            break;
        }
    }

    if !found {
        panic!("unable to find commit {}", test.sha)
    }
    let status = Command::new("git")
                     .arg("clean")
                     .arg("-fdx")
                     .current_dir(&out_dir)
                     .status()
                     .unwrap();
    assert!(status.success());

    out_dir
}

fn run_cargo_test(cargo_path: &Path, crate_path: &Path, packages: &[&str]) -> bool {
    let mut command = Command::new(cargo_path);
    command.arg("test");
    for name in packages {
        command.arg("-p").arg(name);
    }
    let status = command
        // Disable rust-lang/cargo's cross-compile tests
        .env("CFG_DISABLE_CROSS_TESTS", "1")
        // Relax #![deny(warnings)] in some crates
        .env("RUSTFLAGS", "--cap-lints warn")
        .current_dir(crate_path)
        .status()
        .expect("");

    status.success()
}
<|endoftext|>


<commit_before>//! TODO Documentation
use std::{fmt, panic};
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use errors::{UpgradeHandleErr, UpgradeHandleResult};
use wlroots_sys::{wlr_input_device, wlr_keyboard, wlr_keyboard_get_modifiers, wlr_keyboard_led,
                  wlr_keyboard_led_update, wlr_keyboard_modifier, wlr_keyboard_set_keymap};
pub use wlroots_sys::{wlr_key_state, wlr_keyboard_modifiers};

use xkbcommon::xkb::{self, Keycode, Keymap, LedIndex, ModIndex};
use xkbcommon::xkb::ffi::{xkb_keymap, xkb_state};

use InputDevice;

struct KeyboardState {
    handle: Weak<AtomicBool>,
    device: InputDevice
}

/// Information about repeated keypresses for a particular Keyboard.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct RepeatInfo {
    /// The rate at which extended keypresses will fire more events.
    rate: i32,
    /// How long it takes for a keypress to register on this device.
    delay: i32
}

#[derive(Debug)]
pub struct Keyboard {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `KeyboardHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `KeyboardHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard
}

#[derive(Debug)]
pub struct KeyboardHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the keyboard associated with this handle,
    handle: Weak<AtomicBool>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard
}

impl Keyboard {
    /// Tries to convert an input device to a Keyboard
    ///
    /// Returns None if it is of a different type of input variant.
    ///
    /// # Safety
    /// This creates a totally new Keyboard (e.g with its own reference count)
    /// so only do this once per `wlr_input_device`!
    pub(crate) unsafe fn new_from_input_device(device: *mut wlr_input_device) -> Option<Self> {
        use wlroots_sys::wlr_input_device_type::*;
        match (*device).type_ {
            WLR_INPUT_DEVICE_KEYBOARD => {
                let keyboard = (*device).__bindgen_anon_1.keyboard;
                let liveliness = Rc::new(AtomicBool::new(false));
                let handle = Rc::downgrade(&liveliness);
                let state = Box::new(KeyboardState { handle,
                                                     device: InputDevice::from_ptr(device) });
                (*keyboard).data = Box::into_raw(state) as *mut _;
                Some(Keyboard { liveliness: Some(liveliness),
                                device: InputDevice::from_ptr(device),
                                keyboard })
            }
            _ => None
        }
    }

    unsafe fn from_handle(handle: &KeyboardHandle) -> Self {
        Keyboard { liveliness: None,
                   device: handle.input_device().clone(),
                   keyboard: handle.as_ptr() }
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Set the keymap for this Keyboard.
    pub fn set_keymap(&mut self, keymap: &Keymap) {
        unsafe {
            // NOTE wlr_keyboard_set_keymap updates the reference count,
            // so we don't need to mem::forget the key map here
            // or take it by value.
            wlr_keyboard_set_keymap(self.keyboard, keymap.get_raw_ptr() as _);
        }
    }

    /// Get the XKB keymap associated with this Keyboard.
    pub fn get_keymap(&mut self) -> Option<Keymap> {
        unsafe {
            let keymap_ptr = (*self.keyboard).keymap as *mut xkb_keymap;
            if keymap_ptr.is_null() {
                None
            } else {
                Some(Keymap::from_raw_ptr(keymap_ptr))
            }
        }
    }

    /// Get the keycodes for this keyboard as reported by XKB.
    ///
    /// # Limitations
    /// wlroots limits this list to `WLR_KEYBOARD_KEYS_CAP` elements,
    /// which at the time of writing is `32`.
    pub fn keycodes(&self) -> Vec<Keycode> {
        unsafe {
            let mut result = (*self.keyboard).keycodes.to_vec();
            result.truncate((*self.keyboard).num_keycodes);
            result
        }
    }

    /// Get the list of LEDs for this keyboard as reported by XKB.
    pub fn led_list(&self) -> &[LedIndex] {
        unsafe { &(*self.keyboard).led_indexes }
    }

    /// Get the list of modifiers for this keyboard as reported by XKB.
    pub fn modifier_list(&self) -> &[ModIndex] {
        unsafe { &(*self.keyboard).mod_indexes }
    }

    /// Get the size of the keymap.
    pub fn keymap_size(&self) -> usize {
        unsafe { (*self.keyboard).keymap_size }
    }

    /// Get the XKB state associated with this `Keyboard`.
    pub fn get_xkb_state(&mut self) -> Option<xkb::State> {
        unsafe {
            let xkb_state_ptr = (*self.keyboard).xkb_state as *mut xkb_state;
            if xkb_state_ptr.is_null() {
                None
            } else {
                Some(xkb::State::from_raw_ptr(xkb_state_ptr))
            }
        }
    }

    /// Get the repeat info for this keyboard.
    pub fn repeat_info(&self) -> RepeatInfo {
        unsafe {
            RepeatInfo { rate: (*self.keyboard).repeat_info.rate,
                         delay: (*self.keyboard).repeat_info.delay }
        }
    }

    /// Update the LED lights using the provided bitmap.
    ///
    /// 1 means one, 0 means off.
    pub fn update_led(&mut self, leds: KeyboardLed) {
        unsafe {
            wlr_keyboard_led_update(self.keyboard, leds.bits() as u32);
        }
    }

    /// Get the modifiers that are currently pressed on the keyboard.
    pub fn get_modifiers(&self) -> KeyboardModifier {
        unsafe { KeyboardModifier::from_bits_truncate(wlr_keyboard_get_modifiers(self.keyboard)) }
    }

    /// Get the modifier masks for each group.
    pub fn get_modifier_masks(&self) -> wlr_keyboard_modifiers {
        unsafe { (*self.keyboard).modifiers }
    }

    /// Creates a weak reference to a `Keyboard`.
    ///
    /// # Panics
    /// If this `Keyboard` is a previously upgraded `KeyboardHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> KeyboardHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade previously upgraded KeyboardHandle!");
        KeyboardHandle { handle: Rc::downgrade(arc),
                         // NOTE Rationale for cloning:
                         // We can't use the keyboard handle unless the keyboard is alive,
                         // which means the device pointer is still alive.
                         device: unsafe { self.device.clone() },
                         keyboard: self.keyboard }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Keyboard")
            .store(val, Ordering::Release);
    }
}

impl Drop for Keyboard {
    fn drop(&mut self) {
        match self.liveliness {
            None => {}
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped Keyboard {:p}", self.keyboard);
                    unsafe {
                        let _ = Box::from_raw((*self.keyboard).data as *mut KeyboardState);
                    }
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Keyboard {:p}",
                                 weak_count,
                                 self.keyboard);
                    }
                }
            }
        }
    }
}

impl KeyboardHandle {
    /// Creates an KeyboardHandle from the raw pointer, using the saved
    /// user data to recreate the memory model.
    pub(crate) unsafe fn from_ptr(keyboard: *mut wlr_keyboard) -> Self {
        let data = Box::from_raw((*keyboard).data as *mut KeyboardState);
        let handle = data.handle.clone();
        let device = data.device.clone();
        (*keyboard).data = Box::into_raw(data) as *mut _;
        KeyboardHandle { handle,
                         keyboard,
                         device }
    }
    /// Upgrades the keyboard handle to a reference to the backing `Keyboard`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbounded `Keyboard`
    /// which may live forever..
    /// But no keyboard lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Keyboard> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let keyboard = Keyboard::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(keyboard)
            })
    }

    /// Run a function on the referenced Keyboard, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Keyboard does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<R>
        where F: FnOnce(&mut Keyboard) -> R
    {
        let mut keyboard = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| runner(&mut keyboard)));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running keyboard callback, mutable \
                                                    lock was false for: {:?}",
                                                   keyboard);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }
}

impl Clone for KeyboardHandle {
    fn clone(&self) -> Self {
        KeyboardHandle { keyboard: self.keyboard,
                         handle: self.handle.clone(),
                         /// NOTE Rationale for unsafe clone:
                         ///
                         /// You can only access it after a call to `upgrade`,
                         /// and that implicitly checks that it is valid.
                         device: unsafe { self.device.clone() } }
    }
}

bitflags! {
    pub struct KeyboardLed: u32 {
        const WLR_LED_NUM_LOCK = wlr_keyboard_led::WLR_LED_NUM_LOCK as u32;
        const WLR_LED_CAPS_LOCK = wlr_keyboard_led::WLR_LED_CAPS_LOCK as u32;
        const WLR_LED_SCROLL_LOCK = wlr_keyboard_led::WLR_LED_SCROLL_LOCK as u32;
    }
}

bitflags! {
    pub struct KeyboardModifier: u32 {
        const WLR_MODIFIER_SHIFT = wlr_keyboard_modifier::WLR_MODIFIER_SHIFT as u32;
        const WLR_MODIFIER_CAPS = wlr_keyboard_modifier::WLR_MODIFIER_CAPS as u32;
        const WLR_MODIFIER_CTRL = wlr_keyboard_modifier::WLR_MODIFIER_CTRL as u32;
        const WLR_MODIFIER_ALT = wlr_keyboard_modifier::WLR_MODIFIER_ALT as u32;
        const WLR_MODIFIER_MOD2 = wlr_keyboard_modifier::WLR_MODIFIER_MOD2 as u32;
        const WLR_MODIFIER_MOD3 = wlr_keyboard_modifier::WLR_MODIFIER_MOD3 as u32;
        const WLR_MODIFIER_LOGO = wlr_keyboard_modifier::WLR_MODIFIER_LOGO as u32;
        const WLR_MODIFIER_MOD5 = wlr_keyboard_modifier::WLR_MODIFIER_MOD5 as u32;
    }
}

impl fmt::Display for KeyboardModifier {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let mod_vec = vec![("Shift", KeyboardModifier::WLR_MODIFIER_SHIFT),
                           ("Caps lock", KeyboardModifier::WLR_MODIFIER_CAPS),
                           ("Ctrl", KeyboardModifier::WLR_MODIFIER_CTRL),
                           ("Alt", KeyboardModifier::WLR_MODIFIER_ALT),
                           ("Mod2", KeyboardModifier::WLR_MODIFIER_MOD2),
                           ("Mod3", KeyboardModifier::WLR_MODIFIER_MOD3),
                           ("Logo", KeyboardModifier::WLR_MODIFIER_LOGO),
                           ("Mod5", KeyboardModifier::WLR_MODIFIER_MOD5)];

        let mods: Vec<&str> = mod_vec.into_iter()
                                     .filter(|&(_, flag)| self.contains(flag))
                                     .map(|(st, _)| st)
                                     .collect();

        write!(formatter, "{:?}", mods)
    }
}

impl PartialEq for KeyboardHandle {
    fn eq(&self, other: &KeyboardHandle) -> bool {
        self.keyboard == other.keyboard
    }
}

impl Eq for KeyboardHandle {}
<commit_msg>RepeatInfo has public fields now<commit_after>//! TODO Documentation
use std::{fmt, panic};
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use errors::{UpgradeHandleErr, UpgradeHandleResult};
use wlroots_sys::{wlr_input_device, wlr_keyboard, wlr_keyboard_get_modifiers, wlr_keyboard_led,
                  wlr_keyboard_led_update, wlr_keyboard_modifier, wlr_keyboard_set_keymap};
pub use wlroots_sys::{wlr_key_state, wlr_keyboard_modifiers};

use xkbcommon::xkb::{self, Keycode, Keymap, LedIndex, ModIndex};
use xkbcommon::xkb::ffi::{xkb_keymap, xkb_state};

use InputDevice;

struct KeyboardState {
    handle: Weak<AtomicBool>,
    device: InputDevice
}

/// Information about repeated keypresses for a particular Keyboard.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct RepeatInfo {
    /// The rate at which extended keypresses will fire more events.
    pub rate: i32,
    /// How long it takes for a keypress to register on this device.
    pub delay: i32
}

#[derive(Debug)]
pub struct Keyboard {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `KeyboardHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `KeyboardHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard
}

#[derive(Debug)]
pub struct KeyboardHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the keyboard associated with this handle,
    handle: Weak<AtomicBool>,
    /// The device that refers to this keyboard.
    device: InputDevice,
    /// The underlying keyboard data.
    keyboard: *mut wlr_keyboard
}

impl Keyboard {
    /// Tries to convert an input device to a Keyboard
    ///
    /// Returns None if it is of a different type of input variant.
    ///
    /// # Safety
    /// This creates a totally new Keyboard (e.g with its own reference count)
    /// so only do this once per `wlr_input_device`!
    pub(crate) unsafe fn new_from_input_device(device: *mut wlr_input_device) -> Option<Self> {
        use wlroots_sys::wlr_input_device_type::*;
        match (*device).type_ {
            WLR_INPUT_DEVICE_KEYBOARD => {
                let keyboard = (*device).__bindgen_anon_1.keyboard;
                let liveliness = Rc::new(AtomicBool::new(false));
                let handle = Rc::downgrade(&liveliness);
                let state = Box::new(KeyboardState { handle,
                                                     device: InputDevice::from_ptr(device) });
                (*keyboard).data = Box::into_raw(state) as *mut _;
                Some(Keyboard { liveliness: Some(liveliness),
                                device: InputDevice::from_ptr(device),
                                keyboard })
            }
            _ => None
        }
    }

    unsafe fn from_handle(handle: &KeyboardHandle) -> Self {
        Keyboard { liveliness: None,
                   device: handle.input_device().clone(),
                   keyboard: handle.as_ptr() }
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Set the keymap for this Keyboard.
    pub fn set_keymap(&mut self, keymap: &Keymap) {
        unsafe {
            // NOTE wlr_keyboard_set_keymap updates the reference count,
            // so we don't need to mem::forget the key map here
            // or take it by value.
            wlr_keyboard_set_keymap(self.keyboard, keymap.get_raw_ptr() as _);
        }
    }

    /// Get the XKB keymap associated with this Keyboard.
    pub fn get_keymap(&mut self) -> Option<Keymap> {
        unsafe {
            let keymap_ptr = (*self.keyboard).keymap as *mut xkb_keymap;
            if keymap_ptr.is_null() {
                None
            } else {
                Some(Keymap::from_raw_ptr(keymap_ptr))
            }
        }
    }

    /// Get the keycodes for this keyboard as reported by XKB.
    ///
    /// # Limitations
    /// wlroots limits this list to `WLR_KEYBOARD_KEYS_CAP` elements,
    /// which at the time of writing is `32`.
    pub fn keycodes(&self) -> Vec<Keycode> {
        unsafe {
            let mut result = (*self.keyboard).keycodes.to_vec();
            result.truncate((*self.keyboard).num_keycodes);
            result
        }
    }

    /// Get the list of LEDs for this keyboard as reported by XKB.
    pub fn led_list(&self) -> &[LedIndex] {
        unsafe { &(*self.keyboard).led_indexes }
    }

    /// Get the list of modifiers for this keyboard as reported by XKB.
    pub fn modifier_list(&self) -> &[ModIndex] {
        unsafe { &(*self.keyboard).mod_indexes }
    }

    /// Get the size of the keymap.
    pub fn keymap_size(&self) -> usize {
        unsafe { (*self.keyboard).keymap_size }
    }

    /// Get the XKB state associated with this `Keyboard`.
    pub fn get_xkb_state(&mut self) -> Option<xkb::State> {
        unsafe {
            let xkb_state_ptr = (*self.keyboard).xkb_state as *mut xkb_state;
            if xkb_state_ptr.is_null() {
                None
            } else {
                Some(xkb::State::from_raw_ptr(xkb_state_ptr))
            }
        }
    }

    /// Get the repeat info for this keyboard.
    pub fn repeat_info(&self) -> RepeatInfo {
        unsafe {
            RepeatInfo { rate: (*self.keyboard).repeat_info.rate,
                         delay: (*self.keyboard).repeat_info.delay }
        }
    }

    /// Update the LED lights using the provided bitmap.
    ///
    /// 1 means one, 0 means off.
    pub fn update_led(&mut self, leds: KeyboardLed) {
        unsafe {
            wlr_keyboard_led_update(self.keyboard, leds.bits() as u32);
        }
    }

    /// Get the modifiers that are currently pressed on the keyboard.
    pub fn get_modifiers(&self) -> KeyboardModifier {
        unsafe { KeyboardModifier::from_bits_truncate(wlr_keyboard_get_modifiers(self.keyboard)) }
    }

    /// Get the modifier masks for each group.
    pub fn get_modifier_masks(&self) -> wlr_keyboard_modifiers {
        unsafe { (*self.keyboard).modifiers }
    }

    /// Creates a weak reference to a `Keyboard`.
    ///
    /// # Panics
    /// If this `Keyboard` is a previously upgraded `KeyboardHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> KeyboardHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade previously upgraded KeyboardHandle!");
        KeyboardHandle { handle: Rc::downgrade(arc),
                         // NOTE Rationale for cloning:
                         // We can't use the keyboard handle unless the keyboard is alive,
                         // which means the device pointer is still alive.
                         device: unsafe { self.device.clone() },
                         keyboard: self.keyboard }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Keyboard")
            .store(val, Ordering::Release);
    }
}

impl Drop for Keyboard {
    fn drop(&mut self) {
        match self.liveliness {
            None => {}
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped Keyboard {:p}", self.keyboard);
                    unsafe {
                        let _ = Box::from_raw((*self.keyboard).data as *mut KeyboardState);
                    }
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Keyboard {:p}",
                                 weak_count,
                                 self.keyboard);
                    }
                }
            }
        }
    }
}

impl KeyboardHandle {
    /// Creates an KeyboardHandle from the raw pointer, using the saved
    /// user data to recreate the memory model.
    pub(crate) unsafe fn from_ptr(keyboard: *mut wlr_keyboard) -> Self {
        let data = Box::from_raw((*keyboard).data as *mut KeyboardState);
        let handle = data.handle.clone();
        let device = data.device.clone();
        (*keyboard).data = Box::into_raw(data) as *mut _;
        KeyboardHandle { handle,
                         keyboard,
                         device }
    }
    /// Upgrades the keyboard handle to a reference to the backing `Keyboard`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbounded `Keyboard`
    /// which may live forever..
    /// But no keyboard lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Keyboard> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let keyboard = Keyboard::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(keyboard)
            })
    }

    /// Run a function on the referenced Keyboard, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Keyboard does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<R>
        where F: FnOnce(&mut Keyboard) -> R
    {
        let mut keyboard = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| runner(&mut keyboard)));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running keyboard callback, mutable \
                                                    lock was false for: {:?}",
                                                   keyboard);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    /// Gets the wlr_input_device associated with this KeyboardHandle
    pub fn input_device(&self) -> &InputDevice {
        &self.device
    }

    /// Gets the wlr_keyboard associated with this KeyboardHandle.
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_keyboard {
        self.keyboard
    }
}

impl Clone for KeyboardHandle {
    fn clone(&self) -> Self {
        KeyboardHandle { keyboard: self.keyboard,
                         handle: self.handle.clone(),
                         /// NOTE Rationale for unsafe clone:
                         ///
                         /// You can only access it after a call to `upgrade`,
                         /// and that implicitly checks that it is valid.
                         device: unsafe { self.device.clone() } }
    }
}

bitflags! {
    pub struct KeyboardLed: u32 {
        const WLR_LED_NUM_LOCK = wlr_keyboard_led::WLR_LED_NUM_LOCK as u32;
        const WLR_LED_CAPS_LOCK = wlr_keyboard_led::WLR_LED_CAPS_LOCK as u32;
        const WLR_LED_SCROLL_LOCK = wlr_keyboard_led::WLR_LED_SCROLL_LOCK as u32;
    }
}

bitflags! {
    pub struct KeyboardModifier: u32 {
        const WLR_MODIFIER_SHIFT = wlr_keyboard_modifier::WLR_MODIFIER_SHIFT as u32;
        const WLR_MODIFIER_CAPS = wlr_keyboard_modifier::WLR_MODIFIER_CAPS as u32;
        const WLR_MODIFIER_CTRL = wlr_keyboard_modifier::WLR_MODIFIER_CTRL as u32;
        const WLR_MODIFIER_ALT = wlr_keyboard_modifier::WLR_MODIFIER_ALT as u32;
        const WLR_MODIFIER_MOD2 = wlr_keyboard_modifier::WLR_MODIFIER_MOD2 as u32;
        const WLR_MODIFIER_MOD3 = wlr_keyboard_modifier::WLR_MODIFIER_MOD3 as u32;
        const WLR_MODIFIER_LOGO = wlr_keyboard_modifier::WLR_MODIFIER_LOGO as u32;
        const WLR_MODIFIER_MOD5 = wlr_keyboard_modifier::WLR_MODIFIER_MOD5 as u32;
    }
}

impl fmt::Display for KeyboardModifier {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let mod_vec = vec![("Shift", KeyboardModifier::WLR_MODIFIER_SHIFT),
                           ("Caps lock", KeyboardModifier::WLR_MODIFIER_CAPS),
                           ("Ctrl", KeyboardModifier::WLR_MODIFIER_CTRL),
                           ("Alt", KeyboardModifier::WLR_MODIFIER_ALT),
                           ("Mod2", KeyboardModifier::WLR_MODIFIER_MOD2),
                           ("Mod3", KeyboardModifier::WLR_MODIFIER_MOD3),
                           ("Logo", KeyboardModifier::WLR_MODIFIER_LOGO),
                           ("Mod5", KeyboardModifier::WLR_MODIFIER_MOD5)];

        let mods: Vec<&str> = mod_vec.into_iter()
                                     .filter(|&(_, flag)| self.contains(flag))
                                     .map(|(st, _)| st)
                                     .collect();

        write!(formatter, "{:?}", mods)
    }
}

impl PartialEq for KeyboardHandle {
    fn eq(&self, other: &KeyboardHandle) -> bool {
        self.keyboard == other.keyboard
    }
}

impl Eq for KeyboardHandle {}
<|endoftext|>


<commit_before>#![crate_name = "uu_factor"]

/*
* This file is part of the uutils coreutils package.
*
* (c) T. Jameson Little <t.jameson.little@gmail.com>
* (c) Wiktor Kuropatwa <wiktor.kuropatwa@gmail.com>
*     20150223 added Pollard rho method implementation
* (c) kwantam <kwantam@gmail.com>
*     20150429 sped up trial division by adding table of prime inverses
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

extern crate rand;

#[macro_use]
extern crate uucore;

use std::collections::HashMap;
use std::fmt;
use std::io::{stdin, BufRead};
use std::ops;

mod numeric;
mod rho;
mod table;

static SYNTAX: &str = "[OPTION] [NUMBER]...";
static SUMMARY: &str = "Print the prime factors of the given number(s).
 If none are specified, read from standard input.";
static LONG_HELP: &str = "";

struct Factors {
    f: HashMap<u64, u8>,
}

impl Factors {
    fn new() -> Factors {
        Factors { f: HashMap::new() }
    }

    fn add(&mut self, prime: u64, exp: u8) {
        assert!(exp > 0);
        self.f.insert(prime, exp + self.f.get(&prime).unwrap_or(&0));
    }

    fn push(&mut self, prime: u64) {
        self.add(prime, 1)
    }
}

impl ops::MulAssign<Factors> for Factors {
    fn mul_assign(&mut self, other: Factors) {
        for (prime, exp) in &other.f {
            self.add(*prime, *exp);
        }
    }
}

impl fmt::Display for Factors {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // TODO: Use a representation with efficient in-order iteration
        let mut primes: Vec<&u64> = self.f.keys().collect();
        primes.sort();

        for p in primes {
            for _ in 0..self.f[&p] {
                write!(f, " {}", p)?
            }
        }

        Ok(())
    }
}

fn factor(mut n: u64) -> Factors {
    let mut factors = Factors::new();

    if n < 2 {
        factors.push(n);
        return factors;
    }

    let z = n.trailing_zeros();
    if z > 0 {
        factors.add(2, z as u8);
        n = n >> z;
    }

    if n == 1 {
        return factors;
    }

    if numeric::is_prime(n) {
        factors.push(n);
        return factors;
    }

    let (f, n) = table::factor(n);
    factors *= f;

    if n >= table::NEXT_PRIME {
        factors *= rho::factor(n);
    }

    factors
}

fn print_factors(num: u64) {
    print!("{}:{}", num, factor(num));
    println!();
}

fn print_factors_str(num_str: &str) {
    if let Err(e) = num_str.parse::<u64>().and_then(|x| {
        print_factors(x);
        Ok(())
    }) {
        show_warning!("{}: {}", num_str, e);
    }
}

pub fn uumain(args: Vec<String>) -> i32 {
    let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP).parse(args);

    if matches.free.is_empty() {
        let stdin = stdin();
        for line in stdin.lock().lines() {
            for number in line.unwrap().split_whitespace() {
                print_factors_str(number);
            }
        }
    } else {
        for num_str in &matches.free {
            print_factors_str(num_str);
        }
    }
    0
}
<commit_msg>factor::factor: Remove extraneous call to the primality test<commit_after>#![crate_name = "uu_factor"]

/*
* This file is part of the uutils coreutils package.
*
* (c) T. Jameson Little <t.jameson.little@gmail.com>
* (c) Wiktor Kuropatwa <wiktor.kuropatwa@gmail.com>
*     20150223 added Pollard rho method implementation
* (c) kwantam <kwantam@gmail.com>
*     20150429 sped up trial division by adding table of prime inverses
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

extern crate rand;

#[macro_use]
extern crate uucore;

use std::collections::HashMap;
use std::fmt;
use std::io::{stdin, BufRead};
use std::ops;

mod numeric;
mod rho;
mod table;

static SYNTAX: &str = "[OPTION] [NUMBER]...";
static SUMMARY: &str = "Print the prime factors of the given number(s).
 If none are specified, read from standard input.";
static LONG_HELP: &str = "";

struct Factors {
    f: HashMap<u64, u8>,
}

impl Factors {
    fn new() -> Factors {
        Factors { f: HashMap::new() }
    }

    fn add(&mut self, prime: u64, exp: u8) {
        assert!(exp > 0);
        self.f.insert(prime, exp + self.f.get(&prime).unwrap_or(&0));
    }

    fn push(&mut self, prime: u64) {
        self.add(prime, 1)
    }
}

impl ops::MulAssign<Factors> for Factors {
    fn mul_assign(&mut self, other: Factors) {
        for (prime, exp) in &other.f {
            self.add(*prime, *exp);
        }
    }
}

impl fmt::Display for Factors {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // TODO: Use a representation with efficient in-order iteration
        let mut primes: Vec<&u64> = self.f.keys().collect();
        primes.sort();

        for p in primes {
            for _ in 0..self.f[&p] {
                write!(f, " {}", p)?
            }
        }

        Ok(())
    }
}

fn factor(mut n: u64) -> Factors {
    let mut factors = Factors::new();

    if n < 2 {
        factors.push(n);
        return factors;
    }

    let z = n.trailing_zeros();
    if z > 0 {
        factors.add(2, z as u8);
        n = n >> z;
    }

    if n == 1 {
        return factors;
    }

    let (f, n) = table::factor(n);
    factors *= f;

    if n >= table::NEXT_PRIME {
        factors *= rho::factor(n);
    }

    factors
}

fn print_factors(num: u64) {
    print!("{}:{}", num, factor(num));
    println!();
}

fn print_factors_str(num_str: &str) {
    if let Err(e) = num_str.parse::<u64>().and_then(|x| {
        print_factors(x);
        Ok(())
    }) {
        show_warning!("{}: {}", num_str, e);
    }
}

pub fn uumain(args: Vec<String>) -> i32 {
    let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP).parse(args);

    if matches.free.is_empty() {
        let stdin = stdin();
        for line in stdin.lock().lines() {
            for number in line.unwrap().split_whitespace() {
                print_factors_str(number);
            }
        }
    } else {
        for num_str in &matches.free {
            print_factors_str(num_str);
        }
    }
    0
}
<|endoftext|>


<commit_before>//! Endpoints for creating events.

use std::convert::{TryFrom, TryInto};

use bodyparser;
use diesel::{ExecuteDsl, insert};
use iron::{Chain, Handler, IronError, IronResult, Plugin, Request, Response, status};
use router::Router;
use ruma_identifiers::{EventId, RoomId, UserId};
use ruma_events::{CustomRoomEvent, EventType};
use ruma_events::call::answer::AnswerEvent;
use ruma_events::call::candidates::CandidatesEvent;
use ruma_events::call::hangup::HangupEvent;
use ruma_events::call::invite::InviteEvent;
use ruma_events::room::message::MessageEvent;
use serde_json::from_value;

use db::DB;
use config::Config;
use error::APIError;
use event::NewEvent;
use middleware::{AccessTokenAuth, JsonRequest};
use modifier::SerializableResponse;
use schema::events::table as events_table;
use user::User;

#[derive(Debug, Serialize)]
struct SendMessageEventResponse {
    event_id: String,
}

/// The /rooms/:room_id/send/:event_type/:transaction_id endpoint.
pub struct SendMessageEvent;

impl SendMessageEvent {
    /// Create a `SendMessageEvent` with all necessary middleware.
    pub fn chain() -> Chain {
        let mut chain = Chain::new(SendMessageEvent);

        chain.link_before(JsonRequest);
        chain.link_before(AccessTokenAuth);

        chain
    }
}

impl Handler for SendMessageEvent {
    fn handle(&self, request: &mut Request) -> IronResult<Response> {
        let params = request.extensions.get::<Router>().expect("Params object is missing").clone();

        let room_id = match params.find("room_id") {
            Some(room_id) => RoomId::try_from(room_id).map_err(APIError::from)?,
            None => {
                let error = APIError::missing_param("room_id");

                return Err(IronError::new(error.clone(), error));
            }
        };

        let event_type = params
            .find("event_type")
            .ok_or(APIError::missing_param("event_type"))
            .map(EventType::from)?;

        let transaction_id = params
            .find("transaction_id")
            .ok_or(APIError::missing_param("transaction_id"));

        let user = request.extensions.get::<User>()
            .expect("AccessTokenAuth should ensure a user").clone();

        let event_content = request
            .get::<bodyparser::Json>()
            .expect("JsonRequest verifies the Result is Ok")
            .expect("JsonRequest verifies the Option is Some");
        let config = Config::from_request(request)?;
        let event_id = EventId::new(&config.domain).map_err(APIError::from)?;
        let user_id = UserId::try_from(&format!("@{}:{}", user.id, config.domain))
            .map_err(APIError::from)?;

        let room_event: NewEvent = match event_type {
            EventType::CallAnswer => {
                AnswerEvent {
                    content: from_value(event_content).map_err(APIError::from)?,
                    event_id: event_id.clone(),
                    extra_content: (),
                    event_type: event_type,
                    room_id: room_id,
                    unsigned: None,
                    user_id: user_id,
                }.try_into().map_err(APIError::from)?
            }
            EventType::CallCandidates => {
                CandidatesEvent {
                    content: from_value(event_content).map_err(APIError::from)?,
                    event_id: event_id.clone(),
                    extra_content: (),
                    event_type: event_type,
                    room_id: room_id,
                    unsigned: None,
                    user_id: user_id,
                }.try_into().map_err(APIError::from)?
            }
            EventType::CallHangup => {
                HangupEvent {
                    content: from_value(event_content).map_err(APIError::from)?,
                    event_id: event_id.clone(),
                    extra_content: (),
                    event_type: event_type,
                    room_id: room_id,
                    unsigned: None,
                    user_id: user_id,
                }.try_into().map_err(APIError::from)?
            }
            EventType::CallInvite => {
                InviteEvent {
                    content: from_value(event_content).map_err(APIError::from)?,
                    event_id: event_id.clone(),
                    extra_content: (),
                    event_type: event_type,
                    room_id: room_id,
                    unsigned: None,
                    user_id: user_id,
                }.try_into().map_err(APIError::from)?
            }
            EventType::RoomMessage => {
                MessageEvent {
                    content: from_value(event_content).map_err(APIError::from)?,
                    event_id: event_id.clone(),
                    extra_content: (),
                    event_type: event_type,
                    room_id: room_id,
                    unsigned: None,
                    user_id: user_id,
                }.try_into().map_err(APIError::from)?
            }
            EventType::Custom(custom_event_type) => {
                CustomRoomEvent {
                    content: event_content,
                    event_id: event_id.clone(),
                    extra_content: (),
                    event_type: EventType::Custom(custom_event_type),
                    room_id: room_id,
                    unsigned: None,
                    user_id: user_id,
                }.try_into().map_err(APIError::from)?
            }
            _ => {
                let error = APIError::bad_event();

                return Err(IronError::new(error.clone(), error));
            }
        };

        let connection = DB::from_request(request)?;

        insert(&room_event)
            .into(events_table)
            .execute(&*connection)
            .map_err(APIError::from)?;

        let response = SendMessageEventResponse {
            event_id: event_id.opaque_id().to_string(),
        };

        Ok(Response::with((status::Ok, SerializableResponse(response))))
    }
}
<commit_msg>Ensure a room exists before creating a room event for it.<commit_after>//! Endpoints for creating events.

use std::convert::{TryFrom, TryInto};

use bodyparser;
use diesel::{Connection, ExecuteDsl, FindDsl, LoadDsl, insert};
use iron::{Chain, Handler, IronError, IronResult, Plugin, Request, Response, status};
use router::Router;
use ruma_identifiers::{EventId, RoomId, UserId};
use ruma_events::{CustomRoomEvent, EventType};
use ruma_events::call::answer::AnswerEvent;
use ruma_events::call::candidates::CandidatesEvent;
use ruma_events::call::hangup::HangupEvent;
use ruma_events::call::invite::InviteEvent;
use ruma_events::room::message::MessageEvent;
use serde_json::from_value;

use db::DB;
use config::Config;
use error::APIError;
use event::NewEvent;
use middleware::{AccessTokenAuth, JsonRequest};
use modifier::SerializableResponse;
use room::Room;
use schema::{events, rooms};
use user::User;

#[derive(Debug, Serialize)]
struct SendMessageEventResponse {
    event_id: String,
}

/// The /rooms/:room_id/send/:event_type/:transaction_id endpoint.
pub struct SendMessageEvent;

impl SendMessageEvent {
    /// Create a `SendMessageEvent` with all necessary middleware.
    pub fn chain() -> Chain {
        let mut chain = Chain::new(SendMessageEvent);

        chain.link_before(JsonRequest);
        chain.link_before(AccessTokenAuth);

        chain
    }
}

impl Handler for SendMessageEvent {
    fn handle(&self, request: &mut Request) -> IronResult<Response> {
        let params = request.extensions.get::<Router>().expect("Params object is missing").clone();

        let room_id = match params.find("room_id") {
            Some(room_id) => RoomId::try_from(room_id).map_err(APIError::from)?,
            None => {
                let error = APIError::missing_param("room_id");

                return Err(IronError::new(error.clone(), error));
            }
        };

        let event_type = params
            .find("event_type")
            .ok_or(APIError::missing_param("event_type"))
            .map(EventType::from)?;

        let transaction_id = params
            .find("transaction_id")
            .ok_or(APIError::missing_param("transaction_id"));

        let user = request.extensions.get::<User>()
            .expect("AccessTokenAuth should ensure a user").clone();

        let event_content = request
            .get::<bodyparser::Json>()
            .expect("JsonRequest verifies the Result is Ok")
            .expect("JsonRequest verifies the Option is Some");
        let config = Config::from_request(request)?;
        let event_id = EventId::new(&config.domain).map_err(APIError::from)?;
        let user_id = UserId::try_from(&format!("@{}:{}", user.id, config.domain))
            .map_err(APIError::from)?;

        let room_event: NewEvent = match event_type {
            EventType::CallAnswer => {
                AnswerEvent {
                    content: from_value(event_content).map_err(APIError::from)?,
                    event_id: event_id.clone(),
                    extra_content: (),
                    event_type: event_type,
                    room_id: room_id.clone(),
                    unsigned: None,
                    user_id: user_id,
                }.try_into().map_err(APIError::from)?
            }
            EventType::CallCandidates => {
                CandidatesEvent {
                    content: from_value(event_content).map_err(APIError::from)?,
                    event_id: event_id.clone(),
                    extra_content: (),
                    event_type: event_type,
                    room_id: room_id.clone(),
                    unsigned: None,
                    user_id: user_id,
                }.try_into().map_err(APIError::from)?
            }
            EventType::CallHangup => {
                HangupEvent {
                    content: from_value(event_content).map_err(APIError::from)?,
                    event_id: event_id.clone(),
                    extra_content: (),
                    event_type: event_type,
                    room_id: room_id.clone(),
                    unsigned: None,
                    user_id: user_id,
                }.try_into().map_err(APIError::from)?
            }
            EventType::CallInvite => {
                InviteEvent {
                    content: from_value(event_content).map_err(APIError::from)?,
                    event_id: event_id.clone(),
                    extra_content: (),
                    event_type: event_type,
                    room_id: room_id.clone(),
                    unsigned: None,
                    user_id: user_id,
                }.try_into().map_err(APIError::from)?
            }
            EventType::RoomMessage => {
                MessageEvent {
                    content: from_value(event_content).map_err(APIError::from)?,
                    event_id: event_id.clone(),
                    extra_content: (),
                    event_type: event_type,
                    room_id: room_id.clone(),
                    unsigned: None,
                    user_id: user_id,
                }.try_into().map_err(APIError::from)?
            }
            EventType::Custom(custom_event_type) => {
                CustomRoomEvent {
                    content: event_content,
                    event_id: event_id.clone(),
                    extra_content: (),
                    event_type: EventType::Custom(custom_event_type),
                    room_id: room_id.clone(),
                    unsigned: None,
                    user_id: user_id,
                }.try_into().map_err(APIError::from)?
            }
            _ => {
                let error = APIError::bad_event();

                return Err(IronError::new(error.clone(), error));
            }
        };

        let connection = DB::from_request(request)?;

        connection.transaction(|| {
            if let Err(_) = rooms::table.find(room_id.to_string()).first::<Room>(&*connection) {
                return Err(APIError::not_found());
            };

            insert(&room_event)
                .into(events::table)
                .execute(&*connection)
                .map_err(APIError::from)
        }).map_err(APIError::from)?;

        let response = SendMessageEventResponse {
            event_id: event_id.opaque_id().to_string(),
        };

        Ok(Response::with((status::Ok, SerializableResponse(response))))
    }
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::process::exit;

use chrono::naive::NaiveDateTime;

use libimagdiary::diaryid::DiaryId;
use libimagrt::runtime::Runtime;
use libimagerror::trace::trace_error_exit;
use libimagtimeui::datetime::DateTime;
use libimagtimeui::parse::Parse;
use libimagutil::warn_exit::warn_exit;
use libimagstore::storeid::IntoStoreId;

use util::get_diary_name;

pub fn delete(rt: &Runtime) {
    use libimaginteraction::ask::ask_bool;

    let diaryname = get_diary_name(rt)
        .unwrap_or_else(|| warn_exit("No diary selected. Use either the configuration file or the commandline option", 1));

    let datetime : Option<NaiveDateTime> = rt
        .cli()
        .subcommand_matches("delete")
        .unwrap()
        .value_of("datetime")
        .map(|dt| { debug!("DateTime = {:?}", dt); dt })
        .and_then(DateTime::parse)
        .map(|dt| dt.into());

    let to_del = match datetime {
        Some(dt) => {
            let id = match DiaryId::from_datetime(diaryname.clone(), dt).into_storeid() {
                Ok(id) => id,
                Err(e) => trace_error_exit(&e, 1),
            };
            Some(rt.store().retrieve(id))
        },
        None     => {
            warn!("Not deleting entries, because missing date/time specification");
            exit(1);
        },
    };

    let to_del = match to_del {
        Some(Ok(e)) => e,

        Some(Err(e)) => trace_error_exit(&e, 1),
        None => warn_exit("No entry", 1)
    };

    let location = to_del.get_location().clone();
    drop(to_del);

    if !ask_bool(&format!("Deleting {:?}", location), Some(true)) {
        info!("Aborting delete action");
        return;
    }

    if let Err(e) = rt.store().delete(location) {
        trace_error_exit(&e, 1)
    }

    info!("Ok!");
}

<commit_msg>Refactor, minify delete() impl<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::process::exit;

use chrono::naive::NaiveDateTime;

use libimagdiary::diaryid::DiaryId;
use libimagrt::runtime::Runtime;
use libimagerror::trace::trace_error_exit;
use libimagtimeui::datetime::DateTime;
use libimagtimeui::parse::Parse;
use libimagutil::warn_exit::warn_exit;
use libimagstore::storeid::IntoStoreId;

use util::get_diary_name;

pub fn delete(rt: &Runtime) {
    use libimaginteraction::ask::ask_bool;

    let diaryname = get_diary_name(rt)
        .unwrap_or_else(|| warn_exit("No diary selected. Use either the configuration file or the commandline option", 1));

    let to_del_location = rt
        .cli()
        .subcommand_matches("delete")
        .unwrap()
        .value_of("datetime")
        .map(|dt| { debug!("DateTime = {:?}", dt); dt })
        .and_then(DateTime::parse)
        .map(|dt| dt.into())
        .ok_or_else(|| {
            warn!("Not deleting entries, because missing date/time specification");
            exit(1);
        })
        .and_then(|dt: NaiveDateTime| {
            DiaryId::from_datetime(diaryname.clone(), dt)
                .into_storeid()
                .map(|id| rt.store().retrieve(id))
                .unwrap_or_else(|e| trace_error_exit(&e, 1))
        })
        .unwrap_or_else(|e| trace_error_exit(&e, 1))
        .get_location()
        .clone();

    if !ask_bool(&format!("Deleting {:?}", to_del_location), Some(true)) {
        info!("Aborting delete action");
        return;
    }

    if let Err(e) = rt.store().delete(to_del_location) {
        trace_error_exit(&e, 1)
    }

    info!("Ok!");
}

<|endoftext|>