<commit_before>use consts::*;
use entry::Entry;
use parse_error::ParseError;

use std::{fmt, slice, iter};
use std::io::BufRead;
use covers::Covers;

/// The main structure exposing all the functionality of the library
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Sudoku(Vec<u8>);

pub type Iter<'a> = iter::Map<slice::Iter<'a, u8>, fn(&u8)->Option<u8>>; // Iter over Sudoku cells

impl Sudoku {
	/// Creates a new sudoku based on a `&str`. See the crate documentation
	/// for an example of the expected format
	pub fn from_str(s: &str) -> Result<Sudoku, ParseError> {
		Sudoku::from_reader(s.as_bytes())
	}

	/// Creates a new sudoku based on a reader. See the crate documentation
	/// for an example of the expected format
	pub fn from_reader<T: BufRead>(reader: T) -> Result<Sudoku, ParseError> {
		let mut grid = Vec::with_capacity(N_SUDOKU_CELLS);

		// Read a row per line
		for (line_nr, line) in Iterator::zip(1..9+1, reader.lines().take(9)) {
			let line = line.ok().unwrap_or("".to_string());
			let trimmed_line = line.trim_right();
			if trimmed_line.chars().filter(|&c| c!= '|').count() != 9 {
				return Err(ParseError::InvalidLineLength(line_nr));
			}

			for ch in trimmed_line.chars().filter(|&c| c != '|') {
				match ch {
					'1'...'9' => grid.push( ch.to_digit(10).unwrap() as u8 ),
					'_'       => grid.push(0),
					_         => return Err(ParseError::InvalidNumber(line_nr, ch)),
				}
			}
		}

		if grid.len() < N_SUDOKU_CELLS {
			Err(ParseError::NotEnoughRows)
		} else {
			Ok(Sudoku(grid))
		}
	}

    fn into_solver(self) -> SudokuSolver {
        SudokuSolver::from_sudoku(self)
    }

	/// Try to find a solution to the sudoku and fill it in. Return true if a solution was found.
	/// This is a convenience interface. Use one of the other solver methods for better error handling
	pub fn solve(&mut self) -> bool {
		match self.clone().into_solver().solve_one() {
			Some(solution) => {
				*self = solution;
				true
			},
			None => false,
		}
	}

	/// Find a solution to the sudoku. If multiple solutions exist, it will not find them and just stop at the first.
	/// Return `None` if no solution exists.
    pub fn solve_one(self) -> Option<Sudoku> {
        self.into_solver().solve_one()
    }

    /// Solve sudoku and return solution if solution is unique.
	pub fn solve_unique(self) -> Option<Sudoku> {
		self.into_solver().solve_unique()
	}

	/// Solve sudoku and return the first `limit` solutions it finds. If less solutions exist, return only those. Return `None` if no solution exists.
	/// No specific ordering of solutions is promised. It can change across versions.
    pub fn solve_at_most(self, limit: usize) -> Option<Vec<Sudoku>> {
        let results = self.into_solver().solve_at_most(limit);
		if results.len() == 0 {
			None
		} else {
			Some(results)
		}
    }

	/// Check whether the sudoku is solved.
	pub fn is_solved(&self) -> bool {
		self.clone().into_solver().is_solved()
	}

    /// Returns an Iterator over sudoku, going from left to right, top to bottom
    pub fn iter(&self) -> Iter {
        self.0.iter().map(num_to_opt)
    }
}

fn num_to_opt(num: &u8) -> Option<u8> {
	if *num == 0 { None } else { Some(*num) }
}

impl fmt::Display for Sudoku {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		for entry in self.0.iter().enumerate().map(|(cell, &num)| Entry { cell: cell, num: num } ) {
			try!( match (entry.row(), entry.col()) {
				(_, 3) | (_, 6) => write!(f, " "),    // seperate fields in columns
				(3, 0) | (6, 0) => write!(f, "\n\n"), // separate fields in rows
				(_, 0)          => write!(f, "\n"),   // separate lines not between fields
				_ => Ok(()),
			});
			//try!(
            try!( match entry.num() {
                0 => write!(f, "_"),
                1...9 => write!(f, "{}", entry.num()),
                _ => unreachable!(),
            });
                //uwrite!(f, "{}", entry.num())
            //);
		}
		Ok(())
	}
}

// Solving happens by an exact cover algorithm
// There are a total of 729 (81 cells * 9 numbers) sudoku entry possibilities
//
// Every entry (cell-number-combination) satisfies 4 constraints
// 1. a row    needs to have 1 of each number (9 rows, 9 numbers each)
// 2. a column needs to have 1 of each number (9 cols, 9 numbers each)
// 3. a field  needs to have 1 of each number (9 fields, 9 numbers each)
// 4. a cell needs to be filled               (81 cells, 1 number each)
//
// For a total of 81*4 = 324 constraints
//
// The covers property in SudokuSolver contains the information what entries can
// be added at a certain point in the solving process, which constraints are
// already satisfied and how many possibilities still exist for a given constraint.
// See also the covers module.
//
// Solving happens by recursively walking the tree of possible sudokus
// If some constraint can only be satisfied by 1 entry, it will be entered immediately
// This is equivalent to finding naked singles and hidden singles
// If no entry can be deduced, a constraint with the least amount of possibilites
// is chosen and all possibilites tried out.

// Helper struct for recursive solving
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SudokuSolver {
	pub grid: Sudoku,
	pub covers: Covers,
}

impl SudokuSolver {
	pub fn from_sudoku(sudoku: Sudoku) -> SudokuSolver {
		SudokuSolver {
			covers: Covers::from_sudoku(&sudoku),
			grid: sudoku,
		}
	}

	#[inline]
	fn remove_impossible(&mut self, new_entry: Entry) {
		self.covers.remove_impossible(new_entry);
	}

	fn insert_entry(&mut self, entry: Entry) {
		self.grid.0[entry.cell()] = entry.num();
		self.remove_impossible(entry);
	}

	fn with_entry(&self, entry: Entry) -> Self {
		let mut sudoku = self.clone();
		sudoku.insert_entry(entry);
		sudoku
	}

	#[inline]
	pub fn is_solved(&self) -> bool {
		&self.covers.covered[..] == &[true; 324][..]
	}

	#[inline]
	fn is_impossible(&self) -> bool {
		Iterator::zip( self.covers.possibilities_count.iter(), self.covers.covered.iter() )
			.any(|(&poss, &covered)| !covered && poss == 0)
	}

	// return true if new entries were found
	fn insert_deduced_entries(&mut self) -> bool {
		let entries = self.covers.possibilities_count.iter()
			.enumerate()
			.filter(|&(_, &n_poss)| n_poss == 1)
			.map(|(idx, _)| self.matching_entry(idx) )//	self.covers.entries.iter().cloned().find(|e| e.constrains(idx))
			.collect::<Vec<_>>();

		let entries_added = entries.len() != 0;
		for entry in entries {
			self.insert_entry(entry);
		}
		entries_added
	}

	// may fail, but only if used incorrectly
	#[inline]
	fn matching_entry(&self, constraint_nr: usize) -> Entry {
		self.covers.entries.iter()
			.cloned()
			.find(|e| e.constrains(constraint_nr))
			.unwrap()
	}

	pub fn solve_one(self) -> Option<Sudoku> {
		let result = self.solve_at_most(1);
		if result.len() == 0 {
			None
		} else {
			result.into_iter().next() // just take one
		}
	}

	pub fn solve_unique(self) -> Option<Sudoku> {
		let result = self.solve_at_most(2);
		if result.len() == 1 {
			result.into_iter().next()
		} else {
			None
		}
	}

	pub fn solve_at_most(self, limit: usize) -> Vec<Sudoku> {
		let mut solutions = vec![];
		self._solve_at_most(limit, &mut solutions);
		solutions
	}

	fn _solve_at_most(mut self, limit: usize, solutions: &mut Vec<Sudoku>) {
		if solutions.len() == limit { return }

		// deduce entries, but check in between deductions if the sudoku is still possible
		while self.insert_deduced_entries() {
			if self.is_impossible() { return }
		}

		// impossible to insert another number
		// either solved or unsolvable
		if self.covers.is_empty() && self.is_solved() {
			if self.is_solved() {
				solutions.push(self.grid);
			}
			return
		}

		let (idx, _) = self.covers.possibilities_count.iter()
			.enumerate()
			.filter(|&(_, &n_poss)| n_poss != 0)
			.min_by_key(|&(_, n_poss)| n_poss)
			.unwrap();
		for trial_sudoku in self.covers.entries.iter()
			.filter(|e| e.constrains(idx))
			.map(|&new_entry| self.with_entry(new_entry))
		{
			trial_sudoku._solve_at_most(limit, solutions);
		}
	}
}
<commit_msg>Update sudoku.rs<commit_after>use consts::*;
use entry::Entry;
use parse_error::ParseError;

use std::{fmt, slice, iter};
use std::io::BufRead;
use covers::Covers;

/// The main structure exposing all the functionality of the library
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Sudoku(Vec<u8>);

pub type Iter<'a> = iter::Map<slice::Iter<'a, u8>, fn(&u8)->Option<u8>>; // Iter over Sudoku cells

impl Sudoku {
	/// Creates a new sudoku based on a `&str`. See the crate documentation
	/// for an example of the expected format
	pub fn from_str(s: &str) -> Result<Sudoku, ParseError> {
		Sudoku::from_reader(s.as_bytes())
	}

	/// Creates a new sudoku based on a reader. See the crate documentation
	/// for an example of the expected format
	pub fn from_reader<T: BufRead>(reader: T) -> Result<Sudoku, ParseError> {
		let mut grid = Vec::with_capacity(N_SUDOKU_CELLS);

		// Read a row per line
		for (line_nr, line) in Iterator::zip(1..9+1, reader.lines().take(9)) {
			let line = line.ok().unwrap_or("".to_string());
			let trimmed_line = line.trim_right();
			if trimmed_line.chars().filter(|&c| c!= '|').count() != 9 {
				return Err(ParseError::InvalidLineLength(line_nr));
			}

			for ch in trimmed_line.chars().filter(|&c| c != '|') {
				match ch {
					'1'...'9' => grid.push( ch.to_digit(10).unwrap() as u8 ),
					'_'       => grid.push(0),
					_         => return Err(ParseError::InvalidNumber(line_nr, ch)),
				}
			}
		}

		if grid.len() < N_SUDOKU_CELLS {
			Err(ParseError::NotEnoughRows)
		} else {
			Ok(Sudoku(grid))
		}
	}

    fn into_solver(self) -> SudokuSolver {
        SudokuSolver::from_sudoku(self)
    }

	/// Try to find a solution to the sudoku and fill it in. Return true if a solution was found.
	/// This is a convenience interface. Use one of the other solver methods for better error handling
	pub fn solve(&mut self) -> bool {
		match self.clone().into_solver().solve_one() {
			Some(solution) => {
				*self = solution;
				true
			},
			None => false,
		}
	}

	/// Find a solution to the sudoku. If multiple solutions exist, it will not find them and just stop at the first.
	/// Return `None` if no solution exists.
    pub fn solve_one(self) -> Option<Sudoku> {
        self.into_solver().solve_one()
    }

    /// Solve sudoku and return solution if solution is unique.
	pub fn solve_unique(self) -> Option<Sudoku> {
		self.into_solver().solve_unique()
	}

	/// Solve sudoku and return the first `limit` solutions it finds. If less solutions exist, return only those. Return `None` if no solution exists.
	/// No specific ordering of solutions is promised. It can change across versions.
    pub fn solve_at_most(self, limit: usize) -> Option<Vec<Sudoku>> {
        let results = self.into_solver().solve_at_most(limit);
		if results.len() == 0 {
			None
		} else {
			Some(results)
		}
    }

	/// Check whether the sudoku is solved.
	pub fn is_solved(&self) -> bool {
		self.clone().into_solver().is_solved()
	}

    /// Returns an Iterator over sudoku, going from left to right, top to bottom
    pub fn iter(&self) -> Iter {
        self.0.iter().map(num_to_opt)
    }
}

fn num_to_opt(num: &u8) -> Option<u8> {
	if *num == 0 { None } else { Some(*num) }
}

impl fmt::Display for Sudoku {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		for entry in self.0.iter().enumerate().map(|(cell, &num)| Entry { cell: cell, num: num } ) {
			try!( match (entry.row(), entry.col()) {
				(_, 3) | (_, 6) => write!(f, " "),    // seperate fields in columns
				(3, 0) | (6, 0) => write!(f, "\n\n"), // separate fields in rows
				(_, 0)          => write!(f, "\n"),   // separate lines not between fields
				_ => Ok(()),
			});
			//try!(
            try!( match entry.num() {
                0 => write!(f, "_"),
                1...9 => write!(f, "{}", entry.num()),
                _ => unreachable!(),
            });
                //uwrite!(f, "{}", entry.num())
            //);
		}
		Ok(())
	}
}

// Solving happens by an exact cover algorithm
// There are a total of 729 (81 cells * 9 numbers) sudoku entry possibilities
//
// Every entry (cell-number-combination) satisfies 4 constraints
// 1. a row    needs to have 1 of each number (9 rows, 9 numbers each)
// 2. a column needs to have 1 of each number (9 cols, 9 numbers each)
// 3. a field  needs to have 1 of each number (9 fields, 9 numbers each)
// 4. a cell needs to be filled               (81 cells, 1 number each)
//
// For a total of 81*4 = 324 constraints
//
// The covers property in SudokuSolver contains the information what entries can
// be added at a certain point in the solving process, which constraints are
// already satisfied and how many possibilities still exist for a given constraint.
// See also the covers module.
//
// Solving happens by recursively walking the tree of possible sudokus
// If some constraint can only be satisfied by 1 entry, it will be entered immediately
// This is equivalent to finding naked singles and hidden singles
// If no entry can be deduced, a constraint with the least amount of possibilites
// is chosen and all possibilites tried out.

// Helper struct for recursive solving
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SudokuSolver {
	pub grid: Sudoku,
	pub covers: Covers,
}

impl SudokuSolver {
	pub fn from_sudoku(sudoku: Sudoku) -> SudokuSolver {
		SudokuSolver {
			covers: Covers::from_sudoku(&sudoku),
			grid: sudoku,
		}
	}

	#[inline]
	fn remove_impossible(&mut self, new_entry: Entry) {
		self.covers.remove_impossible(new_entry);
	}

	fn insert_entry(&mut self, entry: Entry) {
		self.grid.0[entry.cell()] = entry.num();
		self.remove_impossible(entry);
	}

	fn with_entry(&self, entry: Entry) -> Self {
		let mut sudoku = self.clone();
		sudoku.insert_entry(entry);
		sudoku
	}

	#[inline]
	pub fn is_solved(&self) -> bool {
		&self.covers.covered[..] == &[true; 324][..]
	}

	#[inline]
	fn is_impossible(&self) -> bool {
		Iterator::zip( self.covers.possibilities_count.iter(), self.covers.covered.iter() )
			.any(|(&poss, &covered)| !covered && poss == 0)
	}

	// return true if new entries were found
	fn insert_deduced_entries(&mut self) -> bool {
		let entries = self.covers.possibilities_count.iter()
			.enumerate()
			.filter(|&(_, &n_poss)| n_poss == 1)
			.map(|(idx, _)| self.matching_entry(idx) )//	self.covers.entries.iter().cloned().find(|e| e.constrains(idx))
			.collect::<Vec<_>>();

		let entries_added = entries.len() != 0;
		for entry in entries {
			self.insert_entry(entry);
		}
		entries_added
	}

	// may fail, but only if used incorrectly
	#[inline]
	fn matching_entry(&self, constraint_nr: usize) -> Entry {
		self.covers.entries.iter()
			.cloned()
			.find(|e| e.constrains(constraint_nr))
			.unwrap()
	}

	pub fn solve_one(self) -> Option<Sudoku> {
		let result = self.solve_at_most(1);
		if result.len() == 0 {
			None
		} else {
			result.into_iter().next() // just take one
		}
	}

	pub fn solve_unique(self) -> Option<Sudoku> {
		let result = self.solve_at_most(2);
		if result.len() == 1 {
			result.into_iter().next()
		} else {
			None
		}
	}

	pub fn solve_at_most(self, limit: usize) -> Vec<Sudoku> {
		let mut solutions = vec![];
		self._solve_at_most(limit, &mut solutions);
		solutions
	}

	fn _solve_at_most(mut self, limit: usize, solutions: &mut Vec<Sudoku>) {
		if solutions.len() == limit { return }

		// deduce entries, but check in between deductions if the sudoku is still possible
		while self.insert_deduced_entries() {
			if self.is_impossible() { return }
		}

		// impossible to insert another number
		// either solved or unsolvable
		if self.covers.is_empty() && self.is_solved() {
			solutions.push(self.grid);
			return
		}

		let (idx, _) = self.covers.possibilities_count.iter()
			.enumerate()
			.filter(|&(_, &n_poss)| n_poss != 0)
			.min_by_key(|&(_, n_poss)| n_poss)
			.unwrap();
		for trial_sudoku in self.covers.entries.iter()
			.filter(|e| e.constrains(idx))
			.map(|&new_entry| self.with_entry(new_entry))
		{
			trial_sudoku._solve_at_most(limit, solutions);
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//! Raspberry Pi system-related tools.
//!
//! Use `DeviceInfo` to identify what Raspberry Pi model and SoC the software is
//! running on. This information is used internally to calculate the correct memory
//! locations for the various BCM283x peripherals.

use std::fmt;
use std::fs::File;
use std::io::{BufReader, BufRead};
use std::result;

const BCM2708_PERIPHERAL_BASE: u32 = 0x20000000;
const BCM2709_PERIPHERAL_BASE: u32 = 0x3f000000;
const BCM2710_PERIPHERAL_BASE: u32 = 0x3f000000;
const GPIO_OFFSET: u32 = 0x200000;

quick_error! {
    #[derive(Debug)]
/// Errors that can occur when trying to identify the Raspberry Pi hardware.
    pub enum Error {
/// Unknown SoC.
///
/// Based on the output of `/proc/cpuinfo`, it wasn't possible to identify the SoC used by the
/// Raspberry Pi. While running the library on an unknown Raspberry Pi model is acceptable,
/// identifying the SoC is required because the memory address for the GPIO peripheral
/// depends on it.
        UnknownSoC { description("unknown SoC") }
/// Can't access `/proc/cpuinfo`.
///
/// Unable to read the contents of `/proc/cpuinfo`. This could be an issue with permissions, or
/// a Linux distribution is used that doesn't provide access to this virtual file.
        CantAccessProcCPUInfo { description("can't access /proc/cpuinfo") }
    }
}

/// Result type returned from methods that can have `system::Error`s.
pub type Result<T> = result::Result<T, Error>;

#[derive(Debug, PartialEq, Copy, Clone)]
/// Identifiable Raspberry Pi models.
pub enum Model {
    RaspberryPiA,
    RaspberryPiAPlus,
    RaspberryPiB,
    RaspberryPiBPlus,
    RaspberryPi2B,
    RaspberryPi3B,
    RaspberryPiComputeModule,
    RaspberryPiComputeModule3,
    RaspberryPiZero,
    RaspberryPiZeroW,
    Unknown,
}

impl fmt::Display for Model {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Model::RaspberryPiA => write!(f, "Raspberry Pi A"),
            Model::RaspberryPiAPlus => write!(f, "Raspberry Pi A+"),
            Model::RaspberryPiB => write!(f, "Raspberry Pi B"),
            Model::RaspberryPiBPlus => write!(f, "Raspberry Pi B+"),
            Model::RaspberryPi2B => write!(f, "Raspberry Pi 2 B"),
            Model::RaspberryPi3B => write!(f, "Raspberry Pi 3 B"),
            Model::RaspberryPiComputeModule => write!(f, "Raspberry Pi Compute Module"),
            Model::RaspberryPiComputeModule3 => write!(f, "Raspberry Pi Compute Module 3"),
            Model::RaspberryPiZero => write!(f, "Raspberry Pi Zero"),
            Model::RaspberryPiZeroW => write!(f, "Raspberry Pi Zero W"),
            Model::Unknown => write!(f, "Unknown"),
        }
    }
}

#[derive(Debug, PartialEq, Copy, Clone)]
/// Identifiable Raspberry Pi SoCs.
pub enum SoC {
    BCM2835,
    BCM2836,
    BCM2837,
}

impl fmt::Display for SoC {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SoC::BCM2835 => write!(f, "BCM2835"),
            SoC::BCM2836 => write!(f, "BCM2836"),
            SoC::BCM2837 => write!(f, "BCM2837"),
        }
    }
}

/// Retrieves Raspberry Pi device information.
pub struct DeviceInfo {
    model: Model,
    soc: SoC,
    peripheral_base: u32,
    gpio_offset: u32,
}

impl DeviceInfo {
    /// Constructs a new `DeviceInfo`.
    pub fn new() -> Result<DeviceInfo> {
        // Parse hardware/revision from /proc/cpuinfo to figure out model/SoC
        let proc_cpuinfo = BufReader::new(match File::open("/proc/cpuinfo") {
            Err(_) => return Err(Error::CantAccessProcCPUInfo),
            Ok(file) => file,
        });

        let mut hardware: String = String::new();
        let mut revision: String = String::new();
        for line_result in proc_cpuinfo.lines() {
            if let Some(line) = line_result.ok() {
                if line.starts_with("Hardware\t: ") {
                    hardware = String::from(&line[11..]);
                } else if line.starts_with("Revision\t: ") {
                    revision = String::from(&line[11..]).to_lowercase();
                }
            }
        }

        let model = if revision.len() >= 6 {
            // Newer revisions consist of at least 6 characters
            match &revision[revision.len() - 3..revision.len() - 1] {
                "00" => Model::RaspberryPiA,
                "01" => Model::RaspberryPiB,
                "02" => Model::RaspberryPiAPlus,
                "03" => Model::RaspberryPiBPlus,
                "04" => Model::RaspberryPi2B,
                "06" => Model::RaspberryPiComputeModule,
                "08" => Model::RaspberryPi3B,
                "09" => Model::RaspberryPiZero,
                "0a" => Model::RaspberryPiComputeModule3,
                "0c" => Model::RaspberryPiZeroW,
                _ => Model::Unknown,
            }
        } else if revision.len() == 4 {
            // Older revisions are 4 characters long
            match &revision[..] {
                "0007" | "0008" | "0009" | "0015" => Model::RaspberryPiA,
                "Beta" | "0002" | "0003" | "0004" | "0005" | "0006" | "000d" | "000e" | "000f" => {
                    Model::RaspberryPiB
                }
                "0012" => Model::RaspberryPiAPlus,
                "0010" | "0013" => Model::RaspberryPiBPlus,
                "0011" | "0014" => Model::RaspberryPiComputeModule,
                _ => Model::Unknown,
            }
        } else {
            Model::Unknown
        };

        // Make sure we're actually running on a supported SoC
        match &hardware[..] {
            "BCM2708" | "BCM2835" => {
                Ok(DeviceInfo {
                    model: model,
                    soc: SoC::BCM2835,
                    peripheral_base: BCM2708_PERIPHERAL_BASE,
                    gpio_offset: GPIO_OFFSET,
                })
            }
            "BCM2709" | "BCM2836" => {
                Ok(DeviceInfo {
                    model: model,
                    soc: SoC::BCM2836,
                    peripheral_base: BCM2709_PERIPHERAL_BASE,
                    gpio_offset: GPIO_OFFSET,
                })
            }
            "BCM2710" | "BCM2837" => {
                Ok(DeviceInfo {
                    model: model,
                    soc: SoC::BCM2837,
                    peripheral_base: BCM2710_PERIPHERAL_BASE,
                    gpio_offset: GPIO_OFFSET,
                })
            }
            _ => return Err(Error::UnknownSoC),
        }
    }

    /// Returns a reference to the Raspberry Pi model identified by parsing the
    /// contents of `/proc/cpuinfo`.
    pub fn model(&self) -> &Model {
        &self.model
    }

    /// Returns a reference to the SoC identified by parsing the contents of `/proc/cpuinfo`.
    pub fn soc(&self) -> &SoC {
        &self.soc
    }

    /// Returns the base memory address for the BCM283x peripherals.
    pub fn peripheral_base(&self) -> u32 {
        self.peripheral_base
    }

    /// Returns the offset memory address for the GPIO section.
    pub fn gpio_offset(&self) -> u32 {
        self.gpio_offset
    }
}
<commit_msg>Refactor code (based on clippy suggestions)<commit_after>// Copyright (c) 2017 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//! Raspberry Pi system-related tools.
//!
//! Use `DeviceInfo` to identify what Raspberry Pi model and SoC the software is
//! running on. This information is used internally to calculate the correct memory
//! locations for the various BCM283x peripherals.

use std::fmt;
use std::fs::File;
use std::io::{BufReader, BufRead};
use std::result;

const BCM2708_PERIPHERAL_BASE: u32 = 0x20000000;
const BCM2709_PERIPHERAL_BASE: u32 = 0x3f000000;
const BCM2710_PERIPHERAL_BASE: u32 = 0x3f000000;
const GPIO_OFFSET: u32 = 0x200000;

quick_error! {
    #[derive(Debug)]
/// Errors that can occur when trying to identify the Raspberry Pi hardware.
    pub enum Error {
/// Unknown SoC.
///
/// Based on the output of `/proc/cpuinfo`, it wasn't possible to identify the SoC used by the
/// Raspberry Pi. While running the library on an unknown Raspberry Pi model is acceptable,
/// identifying the SoC is required because the memory address for the GPIO peripheral
/// depends on it.
        UnknownSoC { description("unknown SoC") }
/// Can't access `/proc/cpuinfo`.
///
/// Unable to read the contents of `/proc/cpuinfo`. This could be an issue with permissions, or
/// a Linux distribution is used that doesn't provide access to this virtual file.
        CantAccessProcCPUInfo { description("can't access /proc/cpuinfo") }
    }
}

/// Result type returned from methods that can have `system::Error`s.
pub type Result<T> = result::Result<T, Error>;

#[derive(Debug, PartialEq, Copy, Clone)]
/// Identifiable Raspberry Pi models.
pub enum Model {
    RaspberryPiA,
    RaspberryPiAPlus,
    RaspberryPiB,
    RaspberryPiBPlus,
    RaspberryPi2B,
    RaspberryPi3B,
    RaspberryPiComputeModule,
    RaspberryPiComputeModule3,
    RaspberryPiZero,
    RaspberryPiZeroW,
    Unknown,
}

impl fmt::Display for Model {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Model::RaspberryPiA => write!(f, "Raspberry Pi A"),
            Model::RaspberryPiAPlus => write!(f, "Raspberry Pi A+"),
            Model::RaspberryPiB => write!(f, "Raspberry Pi B"),
            Model::RaspberryPiBPlus => write!(f, "Raspberry Pi B+"),
            Model::RaspberryPi2B => write!(f, "Raspberry Pi 2 B"),
            Model::RaspberryPi3B => write!(f, "Raspberry Pi 3 B"),
            Model::RaspberryPiComputeModule => write!(f, "Raspberry Pi Compute Module"),
            Model::RaspberryPiComputeModule3 => write!(f, "Raspberry Pi Compute Module 3"),
            Model::RaspberryPiZero => write!(f, "Raspberry Pi Zero"),
            Model::RaspberryPiZeroW => write!(f, "Raspberry Pi Zero W"),
            Model::Unknown => write!(f, "Unknown"),
        }
    }
}

#[derive(Debug, PartialEq, Copy, Clone)]
/// Identifiable Raspberry Pi SoCs.
pub enum SoC {
    BCM2835,
    BCM2836,
    BCM2837,
}

impl fmt::Display for SoC {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SoC::BCM2835 => write!(f, "BCM2835"),
            SoC::BCM2836 => write!(f, "BCM2836"),
            SoC::BCM2837 => write!(f, "BCM2837"),
        }
    }
}

/// Retrieves Raspberry Pi device information.
pub struct DeviceInfo {
    model: Model,
    soc: SoC,
    peripheral_base: u32,
    gpio_offset: u32,
}

impl DeviceInfo {
    /// Constructs a new `DeviceInfo`.
    pub fn new() -> Result<DeviceInfo> {
        // Parse hardware/revision from /proc/cpuinfo to figure out model/SoC
        let proc_cpuinfo = BufReader::new(match File::open("/proc/cpuinfo") {
            Err(_) => return Err(Error::CantAccessProcCPUInfo),
            Ok(file) => file,
        });

        let mut hardware: String = String::new();
        let mut revision: String = String::new();
        for line_result in proc_cpuinfo.lines() {
            if let Ok(line) = line_result {
                if line.starts_with("Hardware\t: ") {
                    hardware = String::from(&line[11..]);
                } else if line.starts_with("Revision\t: ") {
                    revision = String::from(&line[11..]).to_lowercase();
                }
            }
        }

        let model = if revision.len() >= 6 {
            // Newer revisions consist of at least 6 characters
            match &revision[revision.len() - 3..revision.len() - 1] {
                "00" => Model::RaspberryPiA,
                "01" => Model::RaspberryPiB,
                "02" => Model::RaspberryPiAPlus,
                "03" => Model::RaspberryPiBPlus,
                "04" => Model::RaspberryPi2B,
                "06" => Model::RaspberryPiComputeModule,
                "08" => Model::RaspberryPi3B,
                "09" => Model::RaspberryPiZero,
                "0a" => Model::RaspberryPiComputeModule3,
                "0c" => Model::RaspberryPiZeroW,
                _ => Model::Unknown,
            }
        } else if revision.len() == 4 {
            // Older revisions are 4 characters long
            match &revision[..] {
                "0007" | "0008" | "0009" | "0015" => Model::RaspberryPiA,
                "Beta" | "0002" | "0003" | "0004" | "0005" | "0006" | "000d" | "000e" | "000f" => {
                    Model::RaspberryPiB
                }
                "0012" => Model::RaspberryPiAPlus,
                "0010" | "0013" => Model::RaspberryPiBPlus,
                "0011" | "0014" => Model::RaspberryPiComputeModule,
                _ => Model::Unknown,
            }
        } else {
            Model::Unknown
        };

        // Make sure we're actually running on a supported SoC
        match &hardware[..] {
            "BCM2708" | "BCM2835" => {
                Ok(DeviceInfo {
                    model: model,
                    soc: SoC::BCM2835,
                    peripheral_base: BCM2708_PERIPHERAL_BASE,
                    gpio_offset: GPIO_OFFSET,
                })
            }
            "BCM2709" | "BCM2836" => {
                Ok(DeviceInfo {
                    model: model,
                    soc: SoC::BCM2836,
                    peripheral_base: BCM2709_PERIPHERAL_BASE,
                    gpio_offset: GPIO_OFFSET,
                })
            }
            "BCM2710" | "BCM2837" => {
                Ok(DeviceInfo {
                    model: model,
                    soc: SoC::BCM2837,
                    peripheral_base: BCM2710_PERIPHERAL_BASE,
                    gpio_offset: GPIO_OFFSET,
                })
            }
            _ => Err(Error::UnknownSoC),
        }
    }

    /// Returns a reference to the Raspberry Pi model identified by parsing the
    /// contents of `/proc/cpuinfo`.
    pub fn model(&self) -> &Model {
        &self.model
    }

    /// Returns a reference to the SoC identified by parsing the contents of `/proc/cpuinfo`.
    pub fn soc(&self) -> &SoC {
        &self.soc
    }

    /// Returns the base memory address for the BCM283x peripherals.
    pub fn peripheral_base(&self) -> u32 {
        self.peripheral_base
    }

    /// Returns the offset memory address for the GPIO section.
    pub fn gpio_offset(&self) -> u32 {
        self.gpio_offset
    }
}
<|endoftext|>


<commit_before>
use ntpclient::retrieve_ntp_timestamp;
use std::sync::{Arc, Mutex, Condvar};
use std::sync::mpsc::{channel, Sender, Receiver, Iter};
use std::thread;
use time::{Timespec, Duration, precise_time_ns};

const BILLION: u64 = 1_000_000_000;

// NOTE: obsolete when Rust starts to support UDP receive timeout
struct NtpFetcher {
    server: String,
    last_sync: Arc<Mutex<(Timespec, u64)>>,
    poll: Duration,
    last_poll: u64,
    ntp_update: Arc<(Mutex<bool>, Condvar)>,
}

impl NtpFetcher {
    fn new(server: String,
           ntp_poll: Duration,
           ntp_update: Arc<(Mutex<bool>, Condvar)>) -> NtpFetcher {
        let mut ntp = NtpFetcher {
            server: server,
            last_sync: Arc::new(Mutex::new((Timespec::new(0,0), 0))),
            poll: ntp_poll,
            last_poll: 0,
            ntp_update: ntp_update,
        };

        ntp.consider_poll_ntp();
        ntp
    }

    fn consider_poll_ntp(&mut self) {
        if let Ok(ref lock) = self.last_sync.lock() {
            let (_, ref_time) = **lock;
            let poll_interval = if ref_time == 0 {
                // when never NTP timestamp was received, try again after 1 minute
                Duration::minutes(1)
            } else {
                self.poll
            };

            let curr = precise_time_ns();
            let must_poll = (self.last_poll == 0) ||
                (((curr - self.last_poll) / BILLION) >= poll_interval.num_seconds() as u64);

            if must_poll {
                self.last_poll = curr;
                let sync = self.last_sync.clone();
                let server = self.server.clone();
                let update = self.ntp_update.clone();

                let join = thread::spawn(move || {
                    if let Ok(ts) = retrieve_ntp_timestamp(&server[..]) {
                        if let Ok(ref mut lock) = sync.lock() {
                            let (_, ref_time) = **lock;
                            **lock = (ts, precise_time_ns());
                            if ref_time == 0 {
                                // notify ntp listener that a initial ntp result is known
                                let &(_, ref cvar) = &*update;
                                cvar.notify_all();
                            }
                        }
                    }
                });
                drop(join);
            }
        }
    }

    fn get_timespec(&mut self) -> Option<Timespec> {
        self.consider_poll_ntp();
        match self.last_sync.lock() {
            Ok(ref lock) => {
                let (sync_ts, ref_time) = **lock;

                match ref_time {
                    0 => None,
                    _ => {
                        let ns = precise_time_ns() - ref_time;
                        Some(sync_ts + Duration::nanoseconds(ns as i64))
                    }
                }
            },
            Err(_) => None,
        }
    }
}

pub struct Ticker<C> {
    rx: Receiver<(C, Option<Timespec>)>,
    tx: Sender<(C, Option<Timespec>)>,
    joiner: thread::JoinHandle<()>,
    leave_guard: Arc<(Mutex<bool>, Condvar)>,
}

impl<C> Ticker<C> where C: Send + Copy + 'static {
    pub fn spawn(server: &str, tick_interval: Duration, ntp_poll: Duration, event: C) -> Ticker<C> {
        let (tx, rx) = channel();
        let leave_guard = Arc::new((Mutex::new(true), Condvar::new()));
        let waiter = leave_guard.clone();
        let cloned_tx = tx.clone();
        let server = server.into();

        let joiner = thread::spawn(move || {
            let mut ntp = NtpFetcher::new(server, ntp_poll, waiter.clone());
            let &(ref lock, ref cvar) = &*waiter;
            let mut leaver = lock.lock().ok().expect("BUG: mutex cannot claimed inside thread");

            // this loop sends the NTP synchronized timestamp to receiving end of the channel
            while *leaver {
                let (new_leaver, _) =
                    cvar.wait_timeout_ms(leaver,
                                         tick_interval.num_milliseconds() as u32).ok().expect(
                                             "BUG: unexpected error during wait");

                leaver = new_leaver;

                if *leaver {
                    if let Some(ts) = ntp.get_timespec() {
                        tx.send((event, Some(ts))).ok().expect("BUG: cannot send timestamp");
                    }
                }
            }
        });

        Ticker {
            rx: rx,
            tx: cloned_tx,
            joiner: joiner,
            leave_guard: leave_guard,
        }
    }

    pub fn stop_ticker(self) {
        let &(ref lock, ref cvar) = &*(self.leave_guard);
        let mut leaver = lock.lock().ok().expect("BUG: cannot claim mutex during stop_ticker");
        *leaver = false;
        drop(leaver);
        cvar.notify_all();
        let _ = self.joiner.join();
    }

    pub fn get_sender(&self) -> Sender<(C, Option<Timespec>)> {
        self.tx.clone()
    }

    pub fn recv_iter(&self) -> Iter<(C, Option<Timespec>)> {
        self.rx.iter()
    }
}
<commit_msg>ticker: add logging<commit_after>
use ntpclient::retrieve_ntp_timestamp;
use std::sync::{Arc, Mutex, Condvar};
use std::sync::mpsc::{channel, Sender, Receiver, Iter};
use std::thread;
use time::{Timespec, Duration, precise_time_ns, at};

const BILLION: u64 = 1_000_000_000;

// NOTE: obsolete when Rust starts to support UDP receive timeout
struct NtpFetcher {
    server: String,
    last_sync: Arc<Mutex<(Timespec, u64)>>,
    poll: Duration,
    last_poll: u64,
    ntp_update: Arc<(Mutex<bool>, Condvar)>,
}

impl NtpFetcher {
    fn new(server: String,
           ntp_poll: Duration,
           ntp_update: Arc<(Mutex<bool>, Condvar)>) -> NtpFetcher {
        let mut ntp = NtpFetcher {
            server: server,
            last_sync: Arc::new(Mutex::new((Timespec::new(0,0), 0))),
            poll: ntp_poll,
            last_poll: 0,
            ntp_update: ntp_update,
        };

        ntp.consider_poll_ntp();
        ntp
    }

    fn consider_poll_ntp(&mut self) {
        if let Ok(ref lock) = self.last_sync.lock() {
            let (_, ref_time) = **lock;
            let poll_interval = if ref_time == 0 {
                // when never NTP timestamp was received, try again after 1 minute
                Duration::minutes(1)
            } else {
                self.poll
            };

            let curr = precise_time_ns();
            let must_poll = (self.last_poll == 0) ||
                (((curr - self.last_poll) / BILLION) >= poll_interval.num_seconds() as u64);

            if must_poll {
                self.last_poll = curr;
                let sync = self.last_sync.clone();
                let server = self.server.clone();
                let update = self.ntp_update.clone();

                let join = thread::spawn(move || {
                    if let Ok(ts) = retrieve_ntp_timestamp(&server[..]) {
                        if let Ok(ref mut lock) = sync.lock() {
                            debug!("updated internet time: {}", at(ts).asctime());
                            let (_, ref_time) = **lock;
                            **lock = (ts, precise_time_ns());
                            if ref_time == 0 {
                                // notify ntp listener that a initial ntp result is known
                                let &(_, ref cvar) = &*update;
                                cvar.notify_all();
                            }
                        }
                    }
                });
                drop(join);
            }
        }
    }

    fn get_timespec(&mut self) -> Option<Timespec> {
        self.consider_poll_ntp();
        match self.last_sync.lock() {
            Ok(ref lock) => {
                let (sync_ts, ref_time) = **lock;

                match ref_time {
                    0 => None,
                    _ => {
                        let ns = precise_time_ns() - ref_time;
                        Some(sync_ts + Duration::nanoseconds(ns as i64))
                    }
                }
            },
            Err(_) => None,
        }
    }
}

pub struct Ticker<C> {
    rx: Receiver<(C, Option<Timespec>)>,
    tx: Sender<(C, Option<Timespec>)>,
    joiner: thread::JoinHandle<()>,
    leave_guard: Arc<(Mutex<bool>, Condvar)>,
}

impl<C> Ticker<C> where C: Send + Copy + 'static {
    pub fn spawn(server: &str, tick_interval: Duration, ntp_poll: Duration, event: C) -> Ticker<C> {
        let (tx, rx) = channel();
        let leave_guard = Arc::new((Mutex::new(true), Condvar::new()));
        let waiter = leave_guard.clone();
        let cloned_tx = tx.clone();
        let server = server.into();

        let joiner = thread::spawn(move || {
            let mut ntp = NtpFetcher::new(server, ntp_poll, waiter.clone());
            let &(ref lock, ref cvar) = &*waiter;
            let mut leaver = lock.lock().ok().expect("BUG: mutex cannot claimed inside thread");

            // this loop sends the NTP synchronized timestamp to receiving end of the channel
            while *leaver {
                let (new_leaver, _) =
                    cvar.wait_timeout_ms(leaver,
                                         tick_interval.num_milliseconds() as u32).ok().expect(
                                             "BUG: unexpected error during wait");

                leaver = new_leaver;

                if *leaver {
                    if let Some(ts) = ntp.get_timespec() {
                        tx.send((event, Some(ts))).ok().expect("BUG: cannot send timestamp");
                    }
                }
            }
        });

        Ticker {
            rx: rx,
            tx: cloned_tx,
            joiner: joiner,
            leave_guard: leave_guard,
        }
    }

    pub fn stop_ticker(self) {
        let &(ref lock, ref cvar) = &*(self.leave_guard);
        let mut leaver = lock.lock().ok().expect("BUG: cannot claim mutex during stop_ticker");
        *leaver = false;
        drop(leaver);
        cvar.notify_all();
        let _ = self.joiner.join();
    }

    pub fn get_sender(&self) -> Sender<(C, Option<Timespec>)> {
        self.tx.clone()
    }

    pub fn recv_iter(&self) -> Iter<(C, Option<Timespec>)> {
        self.rx.iter()
    }
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;

/// The interface for the key-value map internal to an [`ArenaSet`].
///
/// The Entry API is not supported, because it can't be used as is, anyway:
/// the reference passed as a key to `entry(K)` would be to something outside
/// the arena_set, which we absolutely don't want to store in the map. The Entry
/// API would have to be extended to allow changing the key before insertion.
///
/// [`ArenaSet`]: struct.ArenaSet.html
pub trait Map {
    type Key;
    type Value;

    /// Create an empty map.
    ///
    /// This is required for `ArenaSet` to function properly.
    fn new() -> Self;

    /// Create an empty map with a capacity hint.
    ///
    /// Not all implementations may support this, making it equivalent to
    /// `Map::new`.
    fn with_capacity(usize) -> Self;

    /// Get the number of pairs in the map.
    fn len(&self) -> usize;

    /// Insert a key-value pair. If there was already an entry for the key,
    /// it gets replaced, and the previous returned.
    ///
    /// This is required for `ArenaSet` to function properly.
    fn insert(&mut self, Self::Key, Self::Value) -> Option<Self::Value>;

    /// Get a value by its key.
    ///
    /// This is required for `ArenaSet` to function properly.
    fn get(&self, Self::Key) -> Option<&Self::Value>;

    /// Remove a pair by its key.
    ///
    /// This is required for `ArenaSet` to function properly.
    fn remove(&mut self, Self::Key) -> Option<Self::Value>;

    /// Reduce memory usage as much as possible.
    ///
    /// Not all implementations may support this, making it a no-op.
    fn shrink_to_fit(&mut self);
}

impl<K: Eq + Hash, V> Map for HashMap<K, V> {
    type Key = K;
    type Value = V;

    fn new() -> Self {
        HashMap::new()
    }

    fn with_capacity(capacity: usize) -> Self {
        HashMap::with_capacity(capacity)
    }

    fn len(&self) -> usize {
        self.len()
    }

    fn insert(&mut self, k: K, v: V) -> Option<V> {
        self.insert(k, v)
    }

    fn get(&self, k: K) -> Option<&V> {
        self.get(&k)
    }

    fn remove(&mut self, k: K) -> Option<V> {
        self.remove(&k)
    }

    fn shrink_to_fit(&mut self) {
        self.shrink_to_fit();
    }
}

impl<K: Eq + Ord, V> Map for BTreeMap<K, V> {
    type Key = K;
    type Value = V;

    fn new() -> Self {
        BTreeMap::new()
    }

    fn with_capacity(_: usize) -> Self {
        BTreeMap::new()
    }

    fn len(&self) -> usize {
        self.len()
    }

    fn insert(&mut self, k: K, v: V) -> Option<V> {
        self.insert(k, v)
    }

    fn get(&self, k: K) -> Option<&V> {
        self.get(&k)
    }

    fn remove(&mut self, k: K) -> Option<V> {
        self.remove(&k)
    }

    fn shrink_to_fit(&mut self) {}
}
<commit_msg>Allow HashMap to have nonstandard hashers for Map<commit_after>use std::collections::{BTreeMap, HashMap};
use std::hash::{Hash, BuildHasher};

/// The interface for the key-value map internal to an [`ArenaSet`].
///
/// The Entry API is not supported, because it can't be used as is, anyway:
/// the reference passed as a key to `entry(K)` would be to something outside
/// the arena_set, which we absolutely don't want to store in the map. The Entry
/// API would have to be extended to allow changing the key before insertion.
///
/// [`ArenaSet`]: struct.ArenaSet.html
pub trait Map {
    type Key;
    type Value;

    /// Create an empty map.
    ///
    /// This is required for `ArenaSet` to function properly.
    fn new() -> Self;

    /// Create an empty map with a capacity hint.
    ///
    /// Not all implementations may support this, making it equivalent to
    /// `Map::new`.
    fn with_capacity(usize) -> Self;

    /// Get the number of pairs in the map.
    fn len(&self) -> usize;

    /// Insert a key-value pair. If there was already an entry for the key,
    /// it gets replaced, and the previous returned.
    ///
    /// This is required for `ArenaSet` to function properly.
    fn insert(&mut self, Self::Key, Self::Value) -> Option<Self::Value>;

    /// Get a value by its key.
    ///
    /// This is required for `ArenaSet` to function properly.
    fn get(&self, Self::Key) -> Option<&Self::Value>;

    /// Remove a pair by its key.
    ///
    /// This is required for `ArenaSet` to function properly.
    fn remove(&mut self, Self::Key) -> Option<Self::Value>;

    /// Reduce memory usage as much as possible.
    ///
    /// Not all implementations may support this, making it a no-op.
    fn shrink_to_fit(&mut self);
}

impl<K: Eq + Hash, V, H: Default + BuildHasher> Map for HashMap<K, V, H> {
    type Key = K;
    type Value = V;

    fn new() -> Self {
        HashMap::default()
    }

    fn with_capacity(capacity: usize) -> Self {
        HashMap::with_capacity_and_hasher(capacity, Default::default())
    }

    fn len(&self) -> usize {
        self.len()
    }

    fn insert(&mut self, k: K, v: V) -> Option<V> {
        self.insert(k, v)
    }

    fn get(&self, k: K) -> Option<&V> {
        self.get(&k)
    }

    fn remove(&mut self, k: K) -> Option<V> {
        self.remove(&k)
    }

    fn shrink_to_fit(&mut self) {
        self.shrink_to_fit();
    }
}

impl<K: Eq + Ord, V> Map for BTreeMap<K, V> {
    type Key = K;
    type Value = V;

    fn new() -> Self {
        BTreeMap::new()
    }

    fn with_capacity(_: usize) -> Self {
        BTreeMap::new()
    }

    fn len(&self) -> usize {
        self.len()
    }

    fn insert(&mut self, k: K, v: V) -> Option<V> {
        self.insert(k, v)
    }

    fn get(&self, k: K) -> Option<&V> {
        self.get(&k)
    }

    fn remove(&mut self, k: K) -> Option<V> {
        self.remove(&k)
    }

    fn shrink_to_fit(&mut self) {}
}
<|endoftext|>


<commit_before>
use ndarray::{RcArray, Dimension};

/// calculate right hand side (rhs) of equation of motion from current state
pub trait RHS<D: Dimension> {
    fn rhs(&self, RcArray<f64, D>) -> RcArray<f64, D>;
}

/// calculate next step by integrating the equation of motion
pub trait TimeEvolution<D: Dimension> {
    fn iterate(&self, RcArray<f64, D>) -> RcArray<f64, D>;
    fn get_dt(&self) -> f64;
}
<commit_msg>Associated type Dim<commit_after>
use ndarray::RcArray;

/// calculate right hand side (rhs) of equation of motion from current state
pub trait RHS {
    type Dim;
    fn rhs(&self, RcArray<f64, Self::Dim>) -> RcArray<f64, Self::Dim>;
}

/// calculate next step by integrating the equation of motion
pub trait TimeEvolution {
    type Dim;
    fn iterate(&self, RcArray<f64, Self::Dim>) -> RcArray<f64, Self::Dim>;
    fn get_dt(&self) -> f64;
}
<|endoftext|>


<commit_before>use std::collections::vec_deque::IntoIter as VecDequeIter;
use std::default::Default;

use Api;
use BuilderAttribs;
use CreationError;
use Event;
use GlRequest;
use MouseCursor;

use gl_common;
use libc;

use winimpl;

/// Object that allows you to build windows.
pub struct WindowBuilder<'a> {
    attribs: BuilderAttribs<'a>
}

impl<'a> WindowBuilder<'a> {
    /// Initializes a new `WindowBuilder` with default values.
    pub fn new() -> WindowBuilder<'a> {
        WindowBuilder {
            attribs: BuilderAttribs::new(),
        }
    }

    /// Requests the window to be of specific dimensions.
    ///
    /// Width and height are in pixels.
    pub fn with_dimensions(mut self, width: u32, height: u32) -> WindowBuilder<'a> {
        self.attribs.dimensions = Some((width, height));
        self
    }

    /// Requests a specific title for the window.
    pub fn with_title(mut self, title: String) -> WindowBuilder<'a> {
        self.attribs.title = title;
        self
    }

    /// Requests fullscreen mode.
    ///
    /// If you don't specify dimensions for the window, it will match the monitor's.
    pub fn with_fullscreen(mut self, monitor: MonitorID) -> WindowBuilder<'a> {
        let MonitorID(monitor) = monitor;
        self.attribs.monitor = Some(monitor);
        self
    }

    /// The created window will share all its OpenGL objects with the window in the parameter.
    ///
    /// There are some exceptions, like FBOs or VAOs. See the OpenGL documentation.
    pub fn with_shared_lists(mut self, other: &'a Window) -> WindowBuilder<'a> {
        self.attribs.sharing = Some(&other.window);
        self
    }

    /// THIS FUNCTION IS DEPRECATED
    #[deprecated = "Use with_gl instead"]
    pub fn with_gl_version(mut self, version: (u32, u32)) -> WindowBuilder<'a> {
        self.attribs.gl_version = GlRequest::Specific(::Api::OpenGl, (version.0 as u8, version.1 as u8));
        self
    }

    /// Sets how the backend should choose the OpenGL API and version.
    pub fn with_gl(mut self, request: GlRequest) -> WindowBuilder<'a> {
        self.attribs.gl_version = request;
        self
    }

    /// Sets the *debug* flag for the OpenGL context.
    ///
    /// The default value for this flag is `cfg!(ndebug)`, which means that it's enabled
    /// when you run `cargo build` and disabled when you run `cargo build --release`.
    pub fn with_gl_debug_flag(mut self, flag: bool) -> WindowBuilder<'a> {
        self.attribs.gl_debug = flag;
        self
    }

    /// Requests that the window has vsync enabled.
    pub fn with_vsync(mut self) -> WindowBuilder<'a> {
        self.attribs.vsync = true;
        self
    }

    /// Sets whether the window will be initially hidden or visible.
    pub fn with_visibility(mut self, visible: bool) -> WindowBuilder<'a> {
        self.attribs.visible = visible;
        self
    }

    /// Sets the multisampling level to request.
    ///
    /// # Panic
    ///
    /// Will panic if `samples` is not a power of two.
    pub fn with_multisampling(mut self, samples: u16) -> WindowBuilder<'a> {
        use std::num::UnsignedInt;
        assert!(samples.is_power_of_two());
        self.attribs.multisampling = Some(samples);
        self
    }

    /// Sets the number of bits in the depth buffer.
    pub fn with_depth_buffer(mut self, bits: u8) -> WindowBuilder<'a> {
        self.attribs.depth_bits = Some(bits);
        self
    }

    /// Sets the number of bits in the stencil buffer.
    pub fn with_stencil_buffer(mut self, bits: u8) -> WindowBuilder<'a> {
        self.attribs.stencil_bits = Some(bits);
        self
    }

    /// Sets the number of bits in the color buffer.
    pub fn with_pixel_format(mut self, color_bits: u8, alpha_bits: u8) -> WindowBuilder<'a> {
        self.attribs.color_bits = Some(color_bits);
        self.attribs.alpha_bits = Some(alpha_bits);
        self
    }

    /// Request the backend to be stereoscopic.
    pub fn with_stereoscopy(mut self) -> WindowBuilder<'a> {
        self.attribs.stereoscopy = true;
        self
    }

    /// Builds the window.
    ///
    /// Error should be very rare and only occur in case of permission denied, incompatible system,
    ///  out of memory, etc.
    pub fn build(mut self) -> Result<Window, CreationError> {
        // resizing the window to the dimensions of the monitor when fullscreen
        if self.attribs.dimensions.is_none() && self.attribs.monitor.is_some() {
            self.attribs.dimensions = Some(self.attribs.monitor.as_ref().unwrap().get_dimensions())
        }

        // default dimensions
        if self.attribs.dimensions.is_none() {
            self.attribs.dimensions = Some((1024, 768));
        }

        // building
        winimpl::Window::new(self.attribs).map(|w| Window { window: w })
    }

    /// Builds the window.
    ///
    /// The context is build in a *strict* way. That means that if the backend couldn't give
    /// you what you requested, an `Err` will be returned.
    pub fn build_strict(mut self) -> Result<Window, CreationError> {
        self.attribs.strict = true;
        self.build()
    }
}

/// Represents an OpenGL context and the Window or environment around it.
///
/// # Example
///
/// ```ignore
/// let window = Window::new().unwrap();
///
/// unsafe { window.make_current() };
///
/// loop {
///     for event in window.poll_events() {
///             // process events here
///             _ => ()
///         }
///     }
///
///     // draw everything here
///
///     window.swap_buffers();
///     std::old_io::timer::sleep(17);
/// }
/// ```
pub struct Window {
    window: winimpl::Window,
}

impl Default for Window {
    fn default() -> Window {
        Window::new().unwrap()
    }
}

impl Window {
    /// Creates a new OpenGL context, and a Window for platforms where this is appropriate.
    ///
    /// This function is equivalent to `WindowBuilder::new().build()`.
    ///
    /// Error should be very rare and only occur in case of permission denied, incompatible system,
    ///  out of memory, etc.
    #[inline]
    pub fn new() -> Result<Window, CreationError> {
        let builder = WindowBuilder::new();
        builder.build()
    }

    /// Returns true if the window has previously been closed by the user.
    #[inline]
    pub fn is_closed(&self) -> bool {
        self.window.is_closed()
    }

    /// Returns true if the window has previously been closed by the user.
    #[inline]
    #[deprecated = "Use is_closed instead"]
    pub fn should_close(&self) -> bool {
        self.is_closed()
    }

    /// Modifies the title of the window.
    ///
    /// This is a no-op if the window has already been closed.
    #[inline]
    pub fn set_title(&self, title: &str) {
        self.window.set_title(title)
    }

    /// Shows the window if it was hidden.
    ///
    /// ## Platform-specific
    ///
    /// - Has no effect on Android
    ///
    #[inline]
    pub fn show(&self) {
        self.window.show()
    }

    /// Hides the window if it was visible.
    ///
    /// ## Platform-specific
    ///
    /// - Has no effect on Android
    ///
    #[inline]
    pub fn hide(&self) {
        self.window.hide()
    }

    /// Returns the position of the top-left hand corner of the window relative to the
    ///  top-left hand corner of the desktop.
    ///
    /// Note that the top-left hand corner of the desktop is not necessarly the same as
    ///  the screen. If the user uses a desktop with multiple monitors, the top-left hand corner
    ///  of the desktop is the top-left hand corner of the monitor at the top-left of the desktop.
    ///
    /// The coordinates can be negative if the top-left hand corner of the window is outside
    ///  of the visible screen region.
    ///
    /// Returns `None` if the window no longer exists.
    #[inline]
    pub fn get_position(&self) -> Option<(i32, i32)> {
        self.window.get_position()
    }

    /// Modifies the position of the window.
    ///
    /// See `get_position` for more informations about the coordinates.
    ///
    /// This is a no-op if the window has already been closed.
    #[inline]
    pub fn set_position(&self, x: i32, y: i32) {
        self.window.set_position(x, y)
    }

    /// Returns the size in pixels of the client area of the window.
    ///
    /// The client area is the content of the window, excluding the title bar and borders.
    /// These are the dimensions of the frame buffer, and the dimensions that you should use
    ///  when you call `glViewport`.
    ///
    /// Returns `None` if the window no longer exists.
    #[inline]
    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        self.window.get_inner_size()
    }

    /// Returns the size in pixels of the window.
    ///
    /// These dimensions include title bar and borders. If you don't want these, you should use
    ///  use `get_inner_size` instead.
    ///
    /// Returns `None` if the window no longer exists.
    #[inline]
    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        self.window.get_outer_size()
    }

    /// Modifies the inner size of the window.
    ///
    /// See `get_inner_size` for more informations about the values.
    ///
    /// This is a no-op if the window has already been closed.
    #[inline]
    pub fn set_inner_size(&self, x: u32, y: u32) {
        self.window.set_inner_size(x, y)
    }

    /// Returns an iterator that poll for the next event in the window's events queue.
    /// Returns `None` if there is no event in the queue.
    ///
    /// Contrary to `wait_events`, this function never blocks.
    #[inline]
    pub fn poll_events(&self) -> PollEventsIterator {
        PollEventsIterator(self.window.poll_events())
    }

    /// Returns an iterator that returns events one by one, blocking if necessary until one is
    /// available.
    ///
    /// The iterator never returns `None`.
    #[inline]
    pub fn wait_events(&self) -> WaitEventsIterator {
        WaitEventsIterator(self.window.wait_events())
    }

    /// Sets the context as the current context.
    #[inline]
    pub unsafe fn make_current(&self) {
        self.window.make_current()
    }

    /// Returns the address of an OpenGL function.
    ///
    /// Contrary to `wglGetProcAddress`, all available OpenGL functions return an address.
    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const libc::c_void {
        self.window.get_proc_address(addr) as *const libc::c_void
    }

    /// Swaps the buffers in case of double or triple buffering.
    ///
    /// You should call this function every time you have finished rendering, or the image
    ///  may not be displayed on the screen.
    ///
    /// **Warning**: if you enabled vsync, this function will block until the next time the screen
    /// is refreshed. However drivers can choose to override your vsync settings, which means that
    /// you can't know in advance whether `swap_buffers` will block or not.
    #[inline]
    pub fn swap_buffers(&self) {
        self.window.swap_buffers()
    }

    /// Gets the native platform specific display for this window.
    /// This is typically only required when integrating with
    /// other libraries that need this information.
    #[inline]
    pub unsafe fn platform_display(&self) -> *mut libc::c_void {
        self.window.platform_display()
    }

    /// Gets the native platform specific window handle. This is
    /// typically only required when integrating with other libraries
    /// that need this information.
    #[inline]
    pub unsafe fn platform_window(&self) -> *mut libc::c_void {
        self.window.platform_window()
    }

    /// Returns the API that is currently provided by this window.
    ///
    /// - On Windows and OS/X, this always returns `OpenGl`.
    /// - On Android, this always returns `OpenGlEs`.
    /// - On Linux, it must be checked at runtime.
    pub fn get_api(&self) -> Api {
        self.window.get_api()
    }

    /// Create a window proxy for this window, that can be freely
    /// passed to different threads.
    #[inline]
    pub fn create_window_proxy(&self) -> WindowProxy {
        WindowProxy {
            proxy: self.window.create_window_proxy()
        }
    }

    /// Sets a resize callback that is called by Mac (and potentially other
    /// operating systems) during resize operations. This can be used to repaint
    /// during window resizing.
    pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
        self.window.set_window_resize_callback(callback);
    }

    /// Modifies the mouse cursor of the window.
    /// Has no effect on Android.
    pub fn set_cursor(&self, cursor: MouseCursor) {
        self.window.set_cursor(cursor);
    }

    /// Returns the ratio between the backing framebuffer resolution and the
    /// window size in screen pixels. This is typically one for a normal display
    /// and two for a retina display.
    pub fn hidpi_factor(&self) -> f32 {
        self.window.hidpi_factor()
    }
}

impl gl_common::GlFunctionsSource for Window {
    fn get_proc_addr(&self, addr: &str) -> *const libc::c_void {
        self.get_proc_address(addr)
    }
}

/// Represents a thread safe subset of operations that can be called
/// on a window. This structure can be safely cloned and sent between
/// threads.
#[derive(Clone)]
pub struct WindowProxy {
    proxy: winimpl::WindowProxy,
}

impl WindowProxy {

    /// Triggers a blocked event loop to wake up. This is
    /// typically called when another thread wants to wake
    /// up the blocked rendering thread to cause a refresh.
    #[inline]
    pub fn wakeup_event_loop(&self) {
        self.proxy.wakeup_event_loop();
    }
}
/// An iterator for the `poll_events` function.
pub struct PollEventsIterator<'a>(winimpl::PollEventsIterator<'a>);

impl<'a> Iterator for PollEventsIterator<'a> {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        self.0.next()
    }
}

/// An iterator for the `wait_events` function.
pub struct WaitEventsIterator<'a>(winimpl::WaitEventsIterator<'a>);

impl<'a> Iterator for WaitEventsIterator<'a> {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        self.0.next()
    }
}

/// An iterator for the list of available monitors.
// Implementation note: we retreive the list once, then serve each element by one by one.
// This may change in the future.
pub struct AvailableMonitorsIter {
    data: VecDequeIter<winimpl::MonitorID>,
}

impl Iterator for AvailableMonitorsIter {
    type Item = MonitorID;
    fn next(&mut self) -> Option<MonitorID> {
        self.data.next().map(|id| MonitorID(id))
    }
}

/// Returns the list of all available monitors.
pub fn get_available_monitors() -> AvailableMonitorsIter {
    let data = winimpl::get_available_monitors();
    AvailableMonitorsIter{ data: data.into_iter() }
}

/// Returns the primary monitor of the system.
pub fn get_primary_monitor() -> MonitorID {
    MonitorID(winimpl::get_primary_monitor())
}

/// Identifier for a monitor.
pub struct MonitorID(winimpl::MonitorID);

impl MonitorID {
    /// Returns a human-readable name of the monitor.
    pub fn get_name(&self) -> Option<String> {
        let &MonitorID(ref id) = self;
        id.get_name()
    }

    /// Returns the number of pixels currently displayed on the monitor.
    pub fn get_dimensions(&self) -> (u32, u32) {
        let &MonitorID(ref id) = self;
        id.get_dimensions()
    }
}
<commit_msg>Fix doc<commit_after>use std::collections::vec_deque::IntoIter as VecDequeIter;
use std::default::Default;

use Api;
use BuilderAttribs;
use CreationError;
use Event;
use GlRequest;
use MouseCursor;

use gl_common;
use libc;

use winimpl;

/// Object that allows you to build windows.
pub struct WindowBuilder<'a> {
    attribs: BuilderAttribs<'a>
}

impl<'a> WindowBuilder<'a> {
    /// Initializes a new `WindowBuilder` with default values.
    pub fn new() -> WindowBuilder<'a> {
        WindowBuilder {
            attribs: BuilderAttribs::new(),
        }
    }

    /// Requests the window to be of specific dimensions.
    ///
    /// Width and height are in pixels.
    pub fn with_dimensions(mut self, width: u32, height: u32) -> WindowBuilder<'a> {
        self.attribs.dimensions = Some((width, height));
        self
    }

    /// Requests a specific title for the window.
    pub fn with_title(mut self, title: String) -> WindowBuilder<'a> {
        self.attribs.title = title;
        self
    }

    /// Requests fullscreen mode.
    ///
    /// If you don't specify dimensions for the window, it will match the monitor's.
    pub fn with_fullscreen(mut self, monitor: MonitorID) -> WindowBuilder<'a> {
        let MonitorID(monitor) = monitor;
        self.attribs.monitor = Some(monitor);
        self
    }

    /// The created window will share all its OpenGL objects with the window in the parameter.
    ///
    /// There are some exceptions, like FBOs or VAOs. See the OpenGL documentation.
    pub fn with_shared_lists(mut self, other: &'a Window) -> WindowBuilder<'a> {
        self.attribs.sharing = Some(&other.window);
        self
    }

    /// THIS FUNCTION IS DEPRECATED
    #[deprecated = "Use with_gl instead"]
    pub fn with_gl_version(mut self, version: (u32, u32)) -> WindowBuilder<'a> {
        self.attribs.gl_version = GlRequest::Specific(::Api::OpenGl, (version.0 as u8, version.1 as u8));
        self
    }

    /// Sets how the backend should choose the OpenGL API and version.
    pub fn with_gl(mut self, request: GlRequest) -> WindowBuilder<'a> {
        self.attribs.gl_version = request;
        self
    }

    /// Sets the *debug* flag for the OpenGL context.
    ///
    /// The default value for this flag is `cfg!(ndebug)`, which means that it's enabled
    /// when you run `cargo build` and disabled when you run `cargo build --release`.
    pub fn with_gl_debug_flag(mut self, flag: bool) -> WindowBuilder<'a> {
        self.attribs.gl_debug = flag;
        self
    }

    /// Requests that the window has vsync enabled.
    pub fn with_vsync(mut self) -> WindowBuilder<'a> {
        self.attribs.vsync = true;
        self
    }

    /// Sets whether the window will be initially hidden or visible.
    pub fn with_visibility(mut self, visible: bool) -> WindowBuilder<'a> {
        self.attribs.visible = visible;
        self
    }

    /// Sets the multisampling level to request.
    ///
    /// # Panic
    ///
    /// Will panic if `samples` is not a power of two.
    pub fn with_multisampling(mut self, samples: u16) -> WindowBuilder<'a> {
        use std::num::UnsignedInt;
        assert!(samples.is_power_of_two());
        self.attribs.multisampling = Some(samples);
        self
    }

    /// Sets the number of bits in the depth buffer.
    pub fn with_depth_buffer(mut self, bits: u8) -> WindowBuilder<'a> {
        self.attribs.depth_bits = Some(bits);
        self
    }

    /// Sets the number of bits in the stencil buffer.
    pub fn with_stencil_buffer(mut self, bits: u8) -> WindowBuilder<'a> {
        self.attribs.stencil_bits = Some(bits);
        self
    }

    /// Sets the number of bits in the color buffer.
    pub fn with_pixel_format(mut self, color_bits: u8, alpha_bits: u8) -> WindowBuilder<'a> {
        self.attribs.color_bits = Some(color_bits);
        self.attribs.alpha_bits = Some(alpha_bits);
        self
    }

    /// Request the backend to be stereoscopic.
    pub fn with_stereoscopy(mut self) -> WindowBuilder<'a> {
        self.attribs.stereoscopy = true;
        self
    }

    /// Builds the window.
    ///
    /// Error should be very rare and only occur in case of permission denied, incompatible system,
    ///  out of memory, etc.
    pub fn build(mut self) -> Result<Window, CreationError> {
        // resizing the window to the dimensions of the monitor when fullscreen
        if self.attribs.dimensions.is_none() && self.attribs.monitor.is_some() {
            self.attribs.dimensions = Some(self.attribs.monitor.as_ref().unwrap().get_dimensions())
        }

        // default dimensions
        if self.attribs.dimensions.is_none() {
            self.attribs.dimensions = Some((1024, 768));
        }

        // building
        winimpl::Window::new(self.attribs).map(|w| Window { window: w })
    }

    /// Builds the window.
    ///
    /// The context is build in a *strict* way. That means that if the backend couldn't give
    /// you what you requested, an `Err` will be returned.
    pub fn build_strict(mut self) -> Result<Window, CreationError> {
        self.attribs.strict = true;
        self.build()
    }
}

/// Represents an OpenGL context and the Window or environment around it.
///
/// # Example
///
/// ```ignore
/// let window = Window::new().unwrap();
///
/// unsafe { window.make_current() };
///
/// loop {
///     for event in window.poll_events() {
///         match(event) {
///             // process events here
///             _ => ()
///         }
///     }
///
///     // draw everything here
///
///     window.swap_buffers();
///     std::old_io::timer::sleep(17);
/// }
/// ```
pub struct Window {
    window: winimpl::Window,
}

impl Default for Window {
    fn default() -> Window {
        Window::new().unwrap()
    }
}

impl Window {
    /// Creates a new OpenGL context, and a Window for platforms where this is appropriate.
    ///
    /// This function is equivalent to `WindowBuilder::new().build()`.
    ///
    /// Error should be very rare and only occur in case of permission denied, incompatible system,
    ///  out of memory, etc.
    #[inline]
    pub fn new() -> Result<Window, CreationError> {
        let builder = WindowBuilder::new();
        builder.build()
    }

    /// Returns true if the window has previously been closed by the user.
    #[inline]
    pub fn is_closed(&self) -> bool {
        self.window.is_closed()
    }

    /// Returns true if the window has previously been closed by the user.
    #[inline]
    #[deprecated = "Use is_closed instead"]
    pub fn should_close(&self) -> bool {
        self.is_closed()
    }

    /// Modifies the title of the window.
    ///
    /// This is a no-op if the window has already been closed.
    #[inline]
    pub fn set_title(&self, title: &str) {
        self.window.set_title(title)
    }

    /// Shows the window if it was hidden.
    ///
    /// ## Platform-specific
    ///
    /// - Has no effect on Android
    ///
    #[inline]
    pub fn show(&self) {
        self.window.show()
    }

    /// Hides the window if it was visible.
    ///
    /// ## Platform-specific
    ///
    /// - Has no effect on Android
    ///
    #[inline]
    pub fn hide(&self) {
        self.window.hide()
    }

    /// Returns the position of the top-left hand corner of the window relative to the
    ///  top-left hand corner of the desktop.
    ///
    /// Note that the top-left hand corner of the desktop is not necessarly the same as
    ///  the screen. If the user uses a desktop with multiple monitors, the top-left hand corner
    ///  of the desktop is the top-left hand corner of the monitor at the top-left of the desktop.
    ///
    /// The coordinates can be negative if the top-left hand corner of the window is outside
    ///  of the visible screen region.
    ///
    /// Returns `None` if the window no longer exists.
    #[inline]
    pub fn get_position(&self) -> Option<(i32, i32)> {
        self.window.get_position()
    }

    /// Modifies the position of the window.
    ///
    /// See `get_position` for more informations about the coordinates.
    ///
    /// This is a no-op if the window has already been closed.
    #[inline]
    pub fn set_position(&self, x: i32, y: i32) {
        self.window.set_position(x, y)
    }

    /// Returns the size in pixels of the client area of the window.
    ///
    /// The client area is the content of the window, excluding the title bar and borders.
    /// These are the dimensions of the frame buffer, and the dimensions that you should use
    ///  when you call `glViewport`.
    ///
    /// Returns `None` if the window no longer exists.
    #[inline]
    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        self.window.get_inner_size()
    }

    /// Returns the size in pixels of the window.
    ///
    /// These dimensions include title bar and borders. If you don't want these, you should use
    ///  use `get_inner_size` instead.
    ///
    /// Returns `None` if the window no longer exists.
    #[inline]
    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        self.window.get_outer_size()
    }

    /// Modifies the inner size of the window.
    ///
    /// See `get_inner_size` for more informations about the values.
    ///
    /// This is a no-op if the window has already been closed.
    #[inline]
    pub fn set_inner_size(&self, x: u32, y: u32) {
        self.window.set_inner_size(x, y)
    }

    /// Returns an iterator that poll for the next event in the window's events queue.
    /// Returns `None` if there is no event in the queue.
    ///
    /// Contrary to `wait_events`, this function never blocks.
    #[inline]
    pub fn poll_events(&self) -> PollEventsIterator {
        PollEventsIterator(self.window.poll_events())
    }

    /// Returns an iterator that returns events one by one, blocking if necessary until one is
    /// available.
    ///
    /// The iterator never returns `None`.
    #[inline]
    pub fn wait_events(&self) -> WaitEventsIterator {
        WaitEventsIterator(self.window.wait_events())
    }

    /// Sets the context as the current context.
    #[inline]
    pub unsafe fn make_current(&self) {
        self.window.make_current()
    }

    /// Returns the address of an OpenGL function.
    ///
    /// Contrary to `wglGetProcAddress`, all available OpenGL functions return an address.
    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const libc::c_void {
        self.window.get_proc_address(addr) as *const libc::c_void
    }

    /// Swaps the buffers in case of double or triple buffering.
    ///
    /// You should call this function every time you have finished rendering, or the image
    ///  may not be displayed on the screen.
    ///
    /// **Warning**: if you enabled vsync, this function will block until the next time the screen
    /// is refreshed. However drivers can choose to override your vsync settings, which means that
    /// you can't know in advance whether `swap_buffers` will block or not.
    #[inline]
    pub fn swap_buffers(&self) {
        self.window.swap_buffers()
    }

    /// Gets the native platform specific display for this window.
    /// This is typically only required when integrating with
    /// other libraries that need this information.
    #[inline]
    pub unsafe fn platform_display(&self) -> *mut libc::c_void {
        self.window.platform_display()
    }

    /// Gets the native platform specific window handle. This is
    /// typically only required when integrating with other libraries
    /// that need this information.
    #[inline]
    pub unsafe fn platform_window(&self) -> *mut libc::c_void {
        self.window.platform_window()
    }

    /// Returns the API that is currently provided by this window.
    ///
    /// - On Windows and OS/X, this always returns `OpenGl`.
    /// - On Android, this always returns `OpenGlEs`.
    /// - On Linux, it must be checked at runtime.
    pub fn get_api(&self) -> Api {
        self.window.get_api()
    }

    /// Create a window proxy for this window, that can be freely
    /// passed to different threads.
    #[inline]
    pub fn create_window_proxy(&self) -> WindowProxy {
        WindowProxy {
            proxy: self.window.create_window_proxy()
        }
    }

    /// Sets a resize callback that is called by Mac (and potentially other
    /// operating systems) during resize operations. This can be used to repaint
    /// during window resizing.
    pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
        self.window.set_window_resize_callback(callback);
    }

    /// Modifies the mouse cursor of the window.
    /// Has no effect on Android.
    pub fn set_cursor(&self, cursor: MouseCursor) {
        self.window.set_cursor(cursor);
    }

    /// Returns the ratio between the backing framebuffer resolution and the
    /// window size in screen pixels. This is typically one for a normal display
    /// and two for a retina display.
    pub fn hidpi_factor(&self) -> f32 {
        self.window.hidpi_factor()
    }
}

impl gl_common::GlFunctionsSource for Window {
    fn get_proc_addr(&self, addr: &str) -> *const libc::c_void {
        self.get_proc_address(addr)
    }
}

/// Represents a thread safe subset of operations that can be called
/// on a window. This structure can be safely cloned and sent between
/// threads.
#[derive(Clone)]
pub struct WindowProxy {
    proxy: winimpl::WindowProxy,
}

impl WindowProxy {

    /// Triggers a blocked event loop to wake up. This is
    /// typically called when another thread wants to wake
    /// up the blocked rendering thread to cause a refresh.
    #[inline]
    pub fn wakeup_event_loop(&self) {
        self.proxy.wakeup_event_loop();
    }
}
/// An iterator for the `poll_events` function.
pub struct PollEventsIterator<'a>(winimpl::PollEventsIterator<'a>);

impl<'a> Iterator for PollEventsIterator<'a> {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        self.0.next()
    }
}

/// An iterator for the `wait_events` function.
pub struct WaitEventsIterator<'a>(winimpl::WaitEventsIterator<'a>);

impl<'a> Iterator for WaitEventsIterator<'a> {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        self.0.next()
    }
}

/// An iterator for the list of available monitors.
// Implementation note: we retreive the list once, then serve each element by one by one.
// This may change in the future.
pub struct AvailableMonitorsIter {
    data: VecDequeIter<winimpl::MonitorID>,
}

impl Iterator for AvailableMonitorsIter {
    type Item = MonitorID;
    fn next(&mut self) -> Option<MonitorID> {
        self.data.next().map(|id| MonitorID(id))
    }
}

/// Returns the list of all available monitors.
pub fn get_available_monitors() -> AvailableMonitorsIter {
    let data = winimpl::get_available_monitors();
    AvailableMonitorsIter{ data: data.into_iter() }
}

/// Returns the primary monitor of the system.
pub fn get_primary_monitor() -> MonitorID {
    MonitorID(winimpl::get_primary_monitor())
}

/// Identifier for a monitor.
pub struct MonitorID(winimpl::MonitorID);

impl MonitorID {
    /// Returns a human-readable name of the monitor.
    pub fn get_name(&self) -> Option<String> {
        let &MonitorID(ref id) = self;
        id.get_name()
    }

    /// Returns the number of pixels currently displayed on the monitor.
    pub fn get_dimensions(&self) -> (u32, u32) {
        let &MonitorID(ref id) = self;
        id.get_dimensions()
    }
}
<|endoftext|>


<commit_before>//! This module implements `LzmaWriter`.
//!
//! `LzmaWriter` implements the LZMA (XZ) compression/decompression algorithm as a generic
//! Writer.  In other words, it behaves similar to BufWriter.  Instead of buffering the `Write`
//! object passed to it, `LzmaWriter` applies compression or decompression to it as it's write.
//!
//!
//! # Examples
//!
//! ```no_run
//! use lzma::LzmaWriter;
//! use std::io::prelude::*;
//! use std::fs::File;
//!
//! let f = File::create("foo.xz").unwrap();
//! let mut f = LzmaWriter::new_compressor(f, 6).unwrap();
//!
//! write!(f, "It's a small world!").unwrap();
//! f.finish().unwrap();
//! ```

use std::io::{self, Write};
use std::ops::Drop;
use lzma_sys::*;
use std;
use error::LzmaError;
use ::Direction;
use lzma_stream_wrapper::LzmaStreamWrapper;

const DEFAULT_BUF_SIZE: usize = 4 * 1024;

pub struct LzmaWriter<T> {
	inner: T,
	stream: LzmaStreamWrapper,
	buffer: Vec<u8>,
	direction: Direction,
}

impl<T: Write> LzmaWriter<T> {
	pub fn new_compressor(inner: T, preset: u32) -> Result<LzmaWriter<T>, LzmaError> {
		LzmaWriter::with_capacity(DEFAULT_BUF_SIZE, inner, Direction::Compress, preset)
	}

	pub fn new_decompressor(inner: T) -> Result<LzmaWriter<T>, LzmaError> {
		LzmaWriter::with_capacity(DEFAULT_BUF_SIZE, inner, Direction::Decompress, 0)
	}

	pub fn with_capacity(capacity: usize, inner: T, direction: Direction, preset: u32) -> Result<LzmaWriter<T>, LzmaError> {
		let mut writer = LzmaWriter {
			inner: inner,
			stream: LzmaStreamWrapper::new(),
			buffer: vec![0; capacity],
			direction: direction,
		};

		match writer.direction {
			Direction::Compress => {
				try!(writer.stream.easy_encoder(preset, lzma_check::LzmaCheckCrc64))
			},
			Direction::Decompress => {
				try!(writer.stream.stream_decoder(std::u64::MAX, 0))
			},
		}

		Ok(writer)
	}
}

impl<T> Drop for LzmaWriter<T> {
	fn drop(&mut self) {
		self.stream.end()
	}
}

impl<W: Write> LzmaWriter<W> {
	/// Finalizes the LZMA stream so that it finishes compressing or decompressing.
	///
	/// This *must* be called after all writing is done to ensure the last pieces of the compressed
	/// or decompressed stream get written out.
	pub fn finish(&mut self) -> Result<(), LzmaError> {
		loop {
			match self.lzma_code_and_write(&[], lzma_action::LzmaFinish) {
				Ok((lzma_ret::LzmaStreamEnd,_)) => break,
				Ok(_) => (),
				Err(err) => return Err(err),
			}
		}

		Ok(())
	}

	fn lzma_code_and_write(&mut self, input: &[u8], action: lzma_action) -> Result<(lzma_ret, usize), LzmaError> {
		let result = self.stream.code(input, &mut self.buffer, action);
		let ret = try!(result.ret);

		if result.bytes_written > 0 {
			try!(Write::write_all(&mut self.inner, &self.buffer[..result.bytes_written]));
		}

		Ok((ret, result.bytes_read))
	}
}

impl<W: Write> Write for LzmaWriter<W> {
	fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
		match self.lzma_code_and_write(buf, lzma_action::LzmaRun) {
			Ok((_,bytes_read)) => Ok(bytes_read),
			Err(LzmaError::Io(err)) => return Err(err),
			Err(err) => return Err(io::Error::new(io::ErrorKind::Other, err)),
		}
	}

	fn flush(&mut self) -> io::Result<()> {
		self.inner.flush()
	}
}
<commit_msg>Repair merge conflict<commit_after>//! This module implements `LzmaWriter`.
//!
//! `LzmaWriter` implements the LZMA (XZ) compression/decompression algorithm as a generic
//! Writer.  In other words, it behaves similar to BufWriter.  Instead of buffering the `Write`
//! object passed to it, `LzmaWriter` applies compression or decompression to it as it's write.
//!
//!
//! # Examples
//!
//! ```no_run
//! use lzma::LzmaWriter;
//! use std::io::prelude::*;
//! use std::fs::File;
//!
//! let f = File::create("foo.xz").unwrap();
//! let mut f = LzmaWriter::new_compressor(f, 6).unwrap();
//!
//! write!(f, "It's a small world!").unwrap();
//! f.finish().unwrap();
//! ```

use std::io::{self, Write};
use std::ops::Drop;
use lzma_sys::*;
use std;
use error::LzmaError;
use ::Direction;
use lzma_stream_wrapper::{LzmaStreamWrapper, LzmaCodeResult};

const DEFAULT_BUF_SIZE: usize = 4 * 1024;

pub struct LzmaWriter<T> {
	inner: T,
	stream: LzmaStreamWrapper,
	buffer: Vec<u8>,
	direction: Direction,
}

impl<T: Write> LzmaWriter<T> {
	pub fn new_compressor(inner: T, preset: u32) -> Result<LzmaWriter<T>, LzmaError> {
		LzmaWriter::with_capacity(DEFAULT_BUF_SIZE, inner, Direction::Compress, preset)
	}

	pub fn new_decompressor(inner: T) -> Result<LzmaWriter<T>, LzmaError> {
		LzmaWriter::with_capacity(DEFAULT_BUF_SIZE, inner, Direction::Decompress, 0)
	}

	pub fn with_capacity(capacity: usize, inner: T, direction: Direction, preset: u32) -> Result<LzmaWriter<T>, LzmaError> {
		let mut writer = LzmaWriter {
			inner: inner,
			stream: LzmaStreamWrapper::new(),
			buffer: vec![0; capacity],
			direction: direction,
		};

		match writer.direction {
			Direction::Compress => {
				try!(writer.stream.easy_encoder(preset, lzma_check::LzmaCheckCrc64))
			},
			Direction::Decompress => {
				try!(writer.stream.stream_decoder(std::u64::MAX, 0))
			},
		}

		Ok(writer)
	}
}

impl<T> Drop for LzmaWriter<T> {
	fn drop(&mut self) {
		self.stream.end()
	}
}

impl<W: Write> LzmaWriter<W> {
	/// Finalizes the LZMA stream so that it finishes compressing or decompressing.
	///
	/// This *must* be called after all writing is done to ensure the last pieces of the compressed
	/// or decompressed stream get written out.
	pub fn finish(&mut self) -> Result<(), LzmaError> {
		loop {
			match self.lzma_code_and_write(&[], lzma_action::LzmaFinish) {
				Ok(LzmaCodeResult {
					ret: Ok(lzma_ret::LzmaStreamEnd),
					bytes_read: _,
					bytes_written: _,
				}) => break,
				Ok(_) => continue,
				Err(err) => return Err(err),
			}
		}

		Ok(())
	}

	fn lzma_code_and_write(&mut self, input: &[u8], action: lzma_action) -> Result<LzmaCodeResult, LzmaError> {
		let result = self.stream.code(input, &mut self.buffer, action);
		let _ = try!(result.ret);

		if result.bytes_written > 0 {
			try!(Write::write_all(&mut self.inner, &self.buffer[..result.bytes_written]));
		}

		Ok(result)
	}
}

impl<W: Write> Write for LzmaWriter<W> {
	fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
		// Loop until at least one byte from buf was consumed in order to be
		// compliant with std::io::Write trait API.
		loop {
			match self.lzma_code_and_write(buf, lzma_action::LzmaRun) {
				Ok(result) => if result.bytes_read == 0 && result.bytes_written > 0 {
					continue
				} else {
					// If result.bytes_read is zero, then neither was something
					// written nor read. This indicates, something went wrong.
					return Ok(result.bytes_read)
				},
				Err(LzmaError::Io(err)) => return Err(err),
				Err(err) => return Err(io::Error::new(io::ErrorKind::Other, err)),
			}
		}
	}

	fn flush(&mut self) -> io::Result<()> {
		self.inner.flush()
	}
}
<|endoftext|>


<commit_before>pub use std::libc::*;
pub use std::libc::types::os::arch::extra::*;

pub type ATOM = WORD;
pub type UINT = c_uint;
pub type LONG = c_long;

// 32-bit specific
pub type UINT_PTR = c_uint;
pub type LONG_PTR = c_long;
pub type ULONG_PTR = c_ulong;

pub type HANDLE = PVOID;

pub type HBRUSH = HANDLE;
pub type HCURSOR = HICON;
pub type HMENU = HANDLE;
pub type HICON = HANDLE;
pub type HINSTANCE = HANDLE;
pub type HWND = HANDLE;
pub type HDC = HANDLE;

pub type WPARAM = UINT_PTR;
pub type LPARAM = LONG_PTR;

pub type PVOID = *c_void;

// extern fn(HWND, UINT, WPARAM, LPARAM) -> LRESULT
pub type WNDPROC = *u8;

pub struct SECURITY_ATTRIBUTES {
    nLength: DWORD,
    lpSecurityDescriptor: LPVOID,
    bInheritHandle: BOOL,
}

pub struct PROCESS_INFORMATION {
    hProcess: HANDLE,
    hTread: HANDLE,
    dwProcessId: DWORD,
    dwThreadId: DWORD,
}

pub struct STARTUPINFO {
    cb: DWORD,
    lpReserved: LPWSTR,
    lpDesktop: LPWSTR,
    lpTitle: LPWSTR,
    dwX: DWORD,
    dwY: DWORD,
    dwXSize: DWORD,
    dwYSize: DWORD,
    dwXCountChars: DWORD,
    dwYCountChars: DWORD,
    dwFillAttribute: DWORD,
    dwFlags: DWORD,
    wShowWindow: WORD,
    cbReserved2: WORD,
    lpReserved2: LPBYTE,
    hStdInput: HANDLE,
    hStdOutput: HANDLE,
    hStdError: HANDLE,
}

pub struct WNDCLASSEX {
    cbSize: UINT,
    style: UINT,
    lpfnWndProc: WNDPROC,
    cbClsExtra: c_int,
    cbWndExtra: c_int,
    hInstance: HINSTANCE,
    hIcon: HICON,
    hCursor: HCURSOR,
    hbrBackground: HBRUSH,
    lpszMenuName: LPCWSTR,
    lpszClassName: LPCWSTR,
    hIconSm: HICON,
}

pub struct CREATESTRUCT {
    lpCreateParams: LPVOID,
    hInstance: HINSTANCE,
    hMenu: HMENU,
    hwndParent: HWND,
    cy: c_int,
    cx: c_int,
    y: c_int,
    x: c_int,
    style: LONG,
    lpszName: LPCWSTR,
    lpszClass: LPCWSTR,
    dwExStyle: DWORD,
}

pub struct POINT {
    x: LONG,
    y: LONG,
}

pub struct MSG {
    hwnd: HWND,
    message: UINT,
    wParam: WPARAM,
    lParam: LPARAM,
    time: DWORD,
    pt: POINT,
}

pub struct RECT {
    left: LONG,
    top: LONG,
    right: LONG,
    bottom: LONG,
}

pub struct PAINTSTRUCT {
    hdc: HDC,
    fErase: BOOL,
    rcPaint: RECT,
    fRestore: BOOL,
    fIncUpdate: BOOL,
    rgbReserved: *[BYTE, ..32],
}

pub mod kernel32 {
    use ll::*;
    extern "stdcall" {
        unsafe fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;

        unsafe fn CreateProcessW(
            lpApplicationName: LPCWSTR, lpCommandLine: LPWSTR,
            lpProcessAttributes: *SECURITY_ATTRIBUTES,
            lpThreadAttributes: *SECURITY_ATTRIBUTES,
            bInheritHandles: BOOL,
            dwCreationFlags: DWORD,
            lpEnvironment: LPVOID,
            lpCurrentDirectory: LPCWSTR,
            lpStartupInfo: LPSTARTUPINFO,
            lpProcessInformation: LPPROCESS_INFORMATION
        ) -> BOOL;
    }
}

pub mod user32 {
    use ll::*;
    extern "stdcall" {
        unsafe fn CreateWindowExW(extrastyle: DWORD, classname: LPCWSTR,
                windowname: LPCWSTR, style: DWORD,
                x: c_int, y: c_int, width: c_int, height: c_int,
                parent: HWND, menu: HMENU, instance: HINSTANCE, param: LPVOID
        ) -> HWND;

        unsafe fn ShowWindow(hwnd: HWND, nCmdShow: c_int) -> BOOL;

        unsafe fn UpdateWindow(hwnd: HWND) -> BOOL;

        unsafe fn BeginPaint(hwnd: HWND, lpPaint: *PAINTSTRUCT) -> HDC;

        unsafe fn EndPaint(hwnd: HWND, lpPaint: *PAINTSTRUCT) -> BOOL;

        unsafe fn MessageBoxW(
                hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT
        ) -> c_int;

        unsafe fn RegisterClassExW(lpwcx: *WNDCLASSEX) -> ATOM;

        unsafe fn DefWindowProcW(
                hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM
        ) -> LRESULT;

        unsafe fn GetMessageW(
                lpMsg: *MSG, hWnd: HWND,
                wMsgFilterMin: UINT, wMsgFilterMAx: UINT
        ) -> BOOL;

        unsafe fn PeekMessageW(
                lpMsg: *MSG, hWnd: HWND,
                wMsgFilterMin: UINT, wMsgFilterMAx: UINT, wRemoveMsg: UINT
        ) -> BOOL;

        unsafe fn TranslateMessage(lpMsg: *MSG) -> BOOL;

        unsafe fn DispatchMessageW(lpMsg: *MSG) -> LRESULT;

        // 32-bit only
        unsafe fn GetClassLongW(hwnd: HWND, nIndex: c_int) -> DWORD;

        // 32-bit only
        unsafe fn SetClassLongW(
                hwnd: HWND, nIndex: c_int, dwNewLong: LONG
        ) -> DWORD;
    }
}
<commit_msg>ll: PostMessageW, PostQuitMessage<commit_after>pub use std::libc::*;
pub use std::libc::types::os::arch::extra::*;

pub type ATOM = WORD;
pub type UINT = c_uint;
pub type LONG = c_long;

// 32-bit specific
pub type UINT_PTR = c_uint;
pub type LONG_PTR = c_long;
pub type ULONG_PTR = c_ulong;

pub type HANDLE = PVOID;

pub type HBRUSH = HANDLE;
pub type HCURSOR = HICON;
pub type HMENU = HANDLE;
pub type HICON = HANDLE;
pub type HINSTANCE = HANDLE;
pub type HWND = HANDLE;
pub type HDC = HANDLE;

pub type WPARAM = UINT_PTR;
pub type LPARAM = LONG_PTR;

pub type PVOID = *c_void;

// extern fn(HWND, UINT, WPARAM, LPARAM) -> LRESULT
pub type WNDPROC = *u8;

pub struct SECURITY_ATTRIBUTES {
    nLength: DWORD,
    lpSecurityDescriptor: LPVOID,
    bInheritHandle: BOOL,
}

pub struct PROCESS_INFORMATION {
    hProcess: HANDLE,
    hTread: HANDLE,
    dwProcessId: DWORD,
    dwThreadId: DWORD,
}

pub struct STARTUPINFO {
    cb: DWORD,
    lpReserved: LPWSTR,
    lpDesktop: LPWSTR,
    lpTitle: LPWSTR,
    dwX: DWORD,
    dwY: DWORD,
    dwXSize: DWORD,
    dwYSize: DWORD,
    dwXCountChars: DWORD,
    dwYCountChars: DWORD,
    dwFillAttribute: DWORD,
    dwFlags: DWORD,
    wShowWindow: WORD,
    cbReserved2: WORD,
    lpReserved2: LPBYTE,
    hStdInput: HANDLE,
    hStdOutput: HANDLE,
    hStdError: HANDLE,
}

pub struct WNDCLASSEX {
    cbSize: UINT,
    style: UINT,
    lpfnWndProc: WNDPROC,
    cbClsExtra: c_int,
    cbWndExtra: c_int,
    hInstance: HINSTANCE,
    hIcon: HICON,
    hCursor: HCURSOR,
    hbrBackground: HBRUSH,
    lpszMenuName: LPCWSTR,
    lpszClassName: LPCWSTR,
    hIconSm: HICON,
}

pub struct CREATESTRUCT {
    lpCreateParams: LPVOID,
    hInstance: HINSTANCE,
    hMenu: HMENU,
    hwndParent: HWND,
    cy: c_int,
    cx: c_int,
    y: c_int,
    x: c_int,
    style: LONG,
    lpszName: LPCWSTR,
    lpszClass: LPCWSTR,
    dwExStyle: DWORD,
}

pub struct POINT {
    x: LONG,
    y: LONG,
}

pub struct MSG {
    hwnd: HWND,
    message: UINT,
    wParam: WPARAM,
    lParam: LPARAM,
    time: DWORD,
    pt: POINT,
}

pub struct RECT {
    left: LONG,
    top: LONG,
    right: LONG,
    bottom: LONG,
}

pub struct PAINTSTRUCT {
    hdc: HDC,
    fErase: BOOL,
    rcPaint: RECT,
    fRestore: BOOL,
    fIncUpdate: BOOL,
    rgbReserved: *[BYTE, ..32],
}

pub mod kernel32 {
    use ll::*;
    extern "stdcall" {
        unsafe fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;

        unsafe fn CreateProcessW(
            lpApplicationName: LPCWSTR, lpCommandLine: LPWSTR,
            lpProcessAttributes: *SECURITY_ATTRIBUTES,
            lpThreadAttributes: *SECURITY_ATTRIBUTES,
            bInheritHandles: BOOL,
            dwCreationFlags: DWORD,
            lpEnvironment: LPVOID,
            lpCurrentDirectory: LPCWSTR,
            lpStartupInfo: LPSTARTUPINFO,
            lpProcessInformation: LPPROCESS_INFORMATION
        ) -> BOOL;
    }
}

pub mod user32 {
    use ll::*;
    extern "stdcall" {
        unsafe fn CreateWindowExW(extrastyle: DWORD, classname: LPCWSTR,
                windowname: LPCWSTR, style: DWORD,
                x: c_int, y: c_int, width: c_int, height: c_int,
                parent: HWND, menu: HMENU, instance: HINSTANCE, param: LPVOID
        ) -> HWND;

        unsafe fn ShowWindow(hwnd: HWND, nCmdShow: c_int) -> BOOL;

        unsafe fn UpdateWindow(hwnd: HWND) -> BOOL;

        unsafe fn BeginPaint(hwnd: HWND, lpPaint: *PAINTSTRUCT) -> HDC;

        unsafe fn EndPaint(hwnd: HWND, lpPaint: *PAINTSTRUCT) -> BOOL;

        unsafe fn MessageBoxW(
                hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT
        ) -> c_int;

        unsafe fn RegisterClassExW(lpwcx: *WNDCLASSEX) -> ATOM;

        unsafe fn DefWindowProcW(
                hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM
        ) -> LRESULT;

        unsafe fn GetMessageW(
                lpMsg: *MSG, hWnd: HWND,
                wMsgFilterMin: UINT, wMsgFilterMAx: UINT
        ) -> BOOL;

        unsafe fn PeekMessageW(
                lpMsg: *MSG, hWnd: HWND,
                wMsgFilterMin: UINT, wMsgFilterMAx: UINT, wRemoveMsg: UINT
        ) -> BOOL;

        unsafe fn PostMessageW(
                hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM
        ) -> BOOL;

        unsafe fn PostQuitMessage(nExitCode: c_int);

        unsafe fn TranslateMessage(lpMsg: *MSG) -> BOOL;

        unsafe fn DispatchMessageW(lpMsg: *MSG) -> LRESULT;

        // 32-bit only
        unsafe fn GetClassLongW(hwnd: HWND, nIndex: c_int) -> DWORD;

        // 32-bit only
        unsafe fn SetClassLongW(
                hwnd: HWND, nIndex: c_int, dwNewLong: LONG
        ) -> DWORD;
    }
}
<|endoftext|>