<commit_before>use std::os::unix::io;

use byteorder::{LittleEndian, WriteBytesExt};
use nix;
use nix::fcntl;
use nix::sys::stat::Mode;
use nix::unistd;

mod hid_ioctl {
    const HID_IOC_MAGIC: u8 = 'H' as u8;
    const HID_IOC_NR_SFEATURE: u8 = 0x06;
    const HID_IOC_NR_GFEATURE: u8 = 0x07;

    ioctl!(readwrite buf sfeature with HID_IOC_MAGIC, HID_IOC_NR_SFEATURE; u8);
    ioctl!(readwrite buf gfeature with HID_IOC_MAGIC, HID_IOC_NR_GFEATURE; u8);
}

const DA2013_CMD_SET: u16 = 0x0300;
const DA2013_REQ_DPI: u16 = 0x0104;
const DA2013_REQ_LED: u16 = 0x0003;
const DA2013_REQ_FREQ: u16 = 0x0500;

pub struct Da2013 {
    fd: io::RawFd,
}

pub enum Led {
    Logo,
    Wheel,
}

impl Da2013 {
    pub fn open<P: nix::NixPath>(path: P) -> Result<Da2013, nix::Error> {
        let fd = fcntl::open(&path, fcntl::O_RDWR, Mode::empty())?;
        Ok(Da2013 {
            fd: fd,
        })
    }

    fn do_cmd(&self, command: u16, request: u16, arg0: u16, arg1: u16, footer: u8) {
        let mut buf = Vec::with_capacity(91);

        // HID report number
        buf.write_u8(0).unwrap();
        // Status
        buf.write_u8(0).unwrap();
        // Padding
        for _ in 0..3 { buf.write_u8(0).unwrap(); }
        buf.write_u16::<LittleEndian>(command).unwrap();
        buf.write_u16::<LittleEndian>(request).unwrap();
        buf.write_u16::<LittleEndian>(arg0).unwrap();
        buf.write_u16::<LittleEndian>(arg1).unwrap();
        // Padding
        for _ in 0..76 { buf.write_u8(0).unwrap(); }
        buf.write_u8(footer).unwrap();
        // Padding
        buf.write_u8(0).unwrap();

        // Errors here are considered non-critical
        // We try multiple times to make sure the device has registered the command, sometimes it
        // doesn't
        for _ in 0..3 {
            unsafe {
                match hid_ioctl::sfeature(self.fd, buf.as_mut_ptr(), buf.len()) {
                    Ok(_) => match hid_ioctl::gfeature(self.fd, buf.as_mut_ptr(), buf.len()) {
                        // Status field of the response
                        Ok(_) => match buf[1] {
                            // We expect the same values as librazer/razercfg does
                            0 | 1 | 2 | 3 => {},
                            e => println!("Command {:#X}/{:#X} failed with {:#X}",
                                          command, request, e),
                        },
                        Err(e) => println!("HIDIOCGFEATURE: {}", e.to_string()),
                    },
                    Err(e) => println!("HIDIOCGFEATURE: {}", e.to_string()),
                }
            }
        }
    }

    pub fn set_res(&self, res: i32) {
        let res = (res / 100 - 1) * 4;
        let arg0 = (res | (res << 8)) as u16;
        self.do_cmd(DA2013_CMD_SET, DA2013_REQ_DPI, arg0, 0, 0x06);
    }

    pub fn set_freq(&self, freq: i32) {
        let (arg0, footer) = match freq {
            125 => (8, 0x0C),
            500 => (2, 0x06),
            1000 => (1, 0x05),
            _ => unreachable!(),
        };
        self.do_cmd(DA2013_CMD_SET, DA2013_REQ_FREQ, arg0, 0, footer);
    }

    pub fn set_led(&self, led: Led, state: bool) {
        let (arg0, arg1, footer) = match (led, state) {
            (Led::Logo, true) => (0x0401, 1, 0x04),
            (Led::Logo, false) => (0x0401, 0, 0x05),
            (Led::Wheel, true) => (0x0101, 1, 0x01),
            (Led::Wheel, false) => (0x0101, 0, 0x00),
        };
        self.do_cmd(DA2013_CMD_SET, DA2013_REQ_LED, arg0, arg1, footer);
    }
}

impl Drop for Da2013 {
    fn drop(&mut self) {
        unistd::close(self.fd).expect("Failed to close device");
    }
}
<commit_msg>Avoid the character cast<commit_after>use std::os::unix::io;

use byteorder::{LittleEndian, WriteBytesExt};
use nix;
use nix::fcntl;
use nix::sys::stat::Mode;
use nix::unistd;

mod hid_ioctl {
    const HID_IOC_MAGIC: u8 = b'H';
    const HID_IOC_NR_SFEATURE: u8 = 0x06;
    const HID_IOC_NR_GFEATURE: u8 = 0x07;

    ioctl!(readwrite buf sfeature with HID_IOC_MAGIC, HID_IOC_NR_SFEATURE; u8);
    ioctl!(readwrite buf gfeature with HID_IOC_MAGIC, HID_IOC_NR_GFEATURE; u8);
}

const DA2013_CMD_SET: u16 = 0x0300;
const DA2013_REQ_DPI: u16 = 0x0104;
const DA2013_REQ_LED: u16 = 0x0003;
const DA2013_REQ_FREQ: u16 = 0x0500;

pub struct Da2013 {
    fd: io::RawFd,
}

pub enum Led {
    Logo,
    Wheel,
}

impl Da2013 {
    pub fn open<P: nix::NixPath>(path: P) -> Result<Da2013, nix::Error> {
        let fd = fcntl::open(&path, fcntl::O_RDWR, Mode::empty())?;
        Ok(Da2013 {
            fd: fd,
        })
    }

    fn do_cmd(&self, command: u16, request: u16, arg0: u16, arg1: u16, footer: u8) {
        let mut buf = Vec::with_capacity(91);

        // HID report number
        buf.write_u8(0).unwrap();
        // Status
        buf.write_u8(0).unwrap();
        // Padding
        for _ in 0..3 { buf.write_u8(0).unwrap(); }
        buf.write_u16::<LittleEndian>(command).unwrap();
        buf.write_u16::<LittleEndian>(request).unwrap();
        buf.write_u16::<LittleEndian>(arg0).unwrap();
        buf.write_u16::<LittleEndian>(arg1).unwrap();
        // Padding
        for _ in 0..76 { buf.write_u8(0).unwrap(); }
        buf.write_u8(footer).unwrap();
        // Padding
        buf.write_u8(0).unwrap();

        // Errors here are considered non-critical
        // We try multiple times to make sure the device has registered the command, sometimes it
        // doesn't
        for _ in 0..3 {
            unsafe {
                match hid_ioctl::sfeature(self.fd, buf.as_mut_ptr(), buf.len()) {
                    Ok(_) => match hid_ioctl::gfeature(self.fd, buf.as_mut_ptr(), buf.len()) {
                        // Status field of the response
                        Ok(_) => match buf[1] {
                            // We expect the same values as librazer/razercfg does
                            0 | 1 | 2 | 3 => {},
                            e => println!("Command {:#X}/{:#X} failed with {:#X}",
                                          command, request, e),
                        },
                        Err(e) => println!("HIDIOCGFEATURE: {}", e.to_string()),
                    },
                    Err(e) => println!("HIDIOCGFEATURE: {}", e.to_string()),
                }
            }
        }
    }

    pub fn set_res(&self, res: i32) {
        let res = (res / 100 - 1) * 4;
        let arg0 = (res | (res << 8)) as u16;
        self.do_cmd(DA2013_CMD_SET, DA2013_REQ_DPI, arg0, 0, 0x06);
    }

    pub fn set_freq(&self, freq: i32) {
        let (arg0, footer) = match freq {
            125 => (8, 0x0C),
            500 => (2, 0x06),
            1000 => (1, 0x05),
            _ => unreachable!(),
        };
        self.do_cmd(DA2013_CMD_SET, DA2013_REQ_FREQ, arg0, 0, footer);
    }

    pub fn set_led(&self, led: Led, state: bool) {
        let (arg0, arg1, footer) = match (led, state) {
            (Led::Logo, true) => (0x0401, 1, 0x04),
            (Led::Logo, false) => (0x0401, 0, 0x05),
            (Led::Wheel, true) => (0x0101, 1, 0x01),
            (Led::Wheel, false) => (0x0101, 0, 0x00),
        };
        self.do_cmd(DA2013_CMD_SET, DA2013_REQ_LED, arg0, arg1, footer);
    }
}

impl Drop for Da2013 {
    fn drop(&mut self) {
        unistd::close(self.fd).expect("Failed to close device");
    }
}
<|endoftext|>


<commit_before>use platform::vga::{Color, COLS, ROWS};
use platform::vga;

pub struct StdioWriter
{
	pub xpos: u32,
	pub ypos: u32,
	pub fg: Color,
	pub bg: Color
}

impl Copy for StdioWriter {}
impl Clone for StdioWriter { fn clone(&self) -> Self { *self } }

impl StdioWriter
{
	pub fn new() -> StdioWriter
	{
		StdioWriter
		{
			xpos: 0,
			ypos: 0,
			fg: Color::White,
			bg: Color::Black
		}
	}

	pub fn clear_screen(&mut self)
	{
		for y in (0u32 .. ROWS)
		{
			for x in (0u32 .. COLS)
			{
				vga::putc(x, y, 0);
				vga::setfg(x, y, self.fg);
				vga::setbg(x, y, self.bg);
			}
		}
		self.go_to(0, 0);
	}

	pub fn go_to(&mut self, x: u32, y: u32)
	{
		self.move_coords(x, y);
		self.set_cursor();
	}

	pub fn backspace(&mut self)
	{
		self.go_left();
		self.raw_print_char(' ' as u8);
		self.set_cursor();
	}

	pub fn tab(&mut self)
	{
		let x = self.xpos;
		for _ in (0 .. 4 - (x % 4))
		{
			self.raw_print_char(' ' as u8);
			self.go_right();
		}
		self.set_cursor();
	}

	pub fn crlf(&mut self)
	{
		self.xpos = 0;
		self.ypos = if self.ypos == ROWS - 1 { 0 } else { self.ypos + 1 };
		self.set_cursor();
	}

	fn go_right(&mut self)
	{
		if self.xpos == COLS - 1
		{
			self.xpos = 0;
			self.ypos = (self.ypos + ROWS + 1) % ROWS;
		}
		else
		{
			self.xpos += 1;
		}
	}

	fn go_left(&mut self)
	{
		if self.xpos == 0
		{
			self.xpos = COLS - 1;
			self.ypos = (self.ypos + ROWS - 1) % ROWS;
		}
		else
		{
			self.xpos -= 1;
		}
	}

	fn move_coords(&mut self, x: u32, y: u32)
	{
		let mut newx = x;
		let mut newy = y;
		if newx >= COLS { newx = 0; newy += 1; }
		if newy >= ROWS { newy = 0; }
		self.xpos = newx;
		self.ypos = newy;
	}

	fn set_cursor(&self)
	{
		vga::move_cursor(self.xpos, self.ypos);
	}

	pub fn print_dec(&mut self, v: u32)
	{
		if v == 0
		{
			self.print_char('0');
			return;
		}

		let mut fac = 1;
		let mut nv = v;
		while fac <= v { fac *= 10; }
		fac /= 10;
		while fac > 0
		{
			let n = nv / fac;
			let c = n as u8 + '0' as u8;
			self.raw_print_char(c);
			self.go_right();
			nv -= n * fac;
			fac /= 10;
		}
		self.set_cursor();
	}

	pub fn print_bin(&mut self, v: u32, sz: u32)
	{
		self.print_screen("0b");

		let mut i = (sz - 1) as i32;
		while i >= 0
		{
			let c = match (v >> (i as u32)) & 0x1
			{
				0 => '0',
				_ => '1',
			} as u8;
			self.raw_print_char(c);
			self.go_right();
			i -= 1;
		}
		self.set_cursor();
	}

	pub fn print_hex(&mut self, v: u32, sz: u32)
	{
		self.print_screen("0x");

		let mut i = (sz - 4) as i32;
		while i >= 0
		{
			let c = match (v >> (i as u32)) & 0xF
			{
				c if c <= 9 => c + '0' as u32,
				c => c - 10 + 'A' as u32,
			} as u8;
			self.raw_print_char(c);
			self.go_right();
			i -= 4;
		}
		self.set_cursor();
	}

	pub fn print_char(&mut self, value: char)
	{
		self.raw_print_char(value as u8);
		self.go_right();
		self.set_cursor();
	}

	fn raw_print_char(&self, value: u8)
	{
		vga::putc(self.xpos, self.ypos, value);
		vga::setfg(self.xpos, self.ypos, self.fg);
		vga::setbg(self.xpos, self.ypos, self.bg);
	}

	pub fn print_screen(&mut self, value: &str)
	{
		for c in value.bytes()
		{
			self.raw_print_char(c);
			self.go_right();
		}
		self.set_cursor();
	}
}

impl ::core::fmt::Write for StdioWriter
{
	fn write_str(&mut self, s: &str) -> ::core::fmt::Result
	{
		for b in s.bytes()
		{
			self.raw_print_char(b);
			self.go_right();
		}
		self.set_cursor();
		Ok(())
	}
}
<commit_msg>Remove superfluous parentheses<commit_after>use platform::vga::{Color, COLS, ROWS};
use platform::vga;

pub struct StdioWriter
{
	pub xpos: u32,
	pub ypos: u32,
	pub fg: Color,
	pub bg: Color
}

impl Copy for StdioWriter {}
impl Clone for StdioWriter { fn clone(&self) -> Self { *self } }

impl StdioWriter
{
	pub fn new() -> StdioWriter
	{
		StdioWriter
		{
			xpos: 0,
			ypos: 0,
			fg: Color::White,
			bg: Color::Black
		}
	}

	pub fn clear_screen(&mut self)
	{
		for y in 0u32 .. ROWS
		{
			for x in 0u32 .. COLS
			{
				vga::putc(x, y, 0);
				vga::setfg(x, y, self.fg);
				vga::setbg(x, y, self.bg);
			}
		}
		self.go_to(0, 0);
	}

	pub fn go_to(&mut self, x: u32, y: u32)
	{
		self.move_coords(x, y);
		self.set_cursor();
	}

	pub fn backspace(&mut self)
	{
		self.go_left();
		self.raw_print_char(' ' as u8);
		self.set_cursor();
	}

	pub fn tab(&mut self)
	{
		let x = self.xpos;
		for _ in 0 .. 4 - (x % 4)
		{
			self.raw_print_char(' ' as u8);
			self.go_right();
		}
		self.set_cursor();
	}

	pub fn crlf(&mut self)
	{
		self.xpos = 0;
		self.ypos = if self.ypos == ROWS - 1 { 0 } else { self.ypos + 1 };
		self.set_cursor();
	}

	fn go_right(&mut self)
	{
		if self.xpos == COLS - 1
		{
			self.xpos = 0;
			self.ypos = (self.ypos + ROWS + 1) % ROWS;
		}
		else
		{
			self.xpos += 1;
		}
	}

	fn go_left(&mut self)
	{
		if self.xpos == 0
		{
			self.xpos = COLS - 1;
			self.ypos = (self.ypos + ROWS - 1) % ROWS;
		}
		else
		{
			self.xpos -= 1;
		}
	}

	fn move_coords(&mut self, x: u32, y: u32)
	{
		let mut newx = x;
		let mut newy = y;
		if newx >= COLS { newx = 0; newy += 1; }
		if newy >= ROWS { newy = 0; }
		self.xpos = newx;
		self.ypos = newy;
	}

	fn set_cursor(&self)
	{
		vga::move_cursor(self.xpos, self.ypos);
	}

	pub fn print_dec(&mut self, v: u32)
	{
		if v == 0
		{
			self.print_char('0');
			return;
		}

		let mut fac = 1;
		let mut nv = v;
		while fac <= v { fac *= 10; }
		fac /= 10;
		while fac > 0
		{
			let n = nv / fac;
			let c = n as u8 + '0' as u8;
			self.raw_print_char(c);
			self.go_right();
			nv -= n * fac;
			fac /= 10;
		}
		self.set_cursor();
	}

	pub fn print_bin(&mut self, v: u32, sz: u32)
	{
		self.print_screen("0b");

		let mut i = (sz - 1) as i32;
		while i >= 0
		{
			let c = match (v >> (i as u32)) & 0x1
			{
				0 => '0',
				_ => '1',
			} as u8;
			self.raw_print_char(c);
			self.go_right();
			i -= 1;
		}
		self.set_cursor();
	}

	pub fn print_hex(&mut self, v: u32, sz: u32)
	{
		self.print_screen("0x");

		let mut i = (sz - 4) as i32;
		while i >= 0
		{
			let c = match (v >> (i as u32)) & 0xF
			{
				c if c <= 9 => c + '0' as u32,
				c => c - 10 + 'A' as u32,
			} as u8;
			self.raw_print_char(c);
			self.go_right();
			i -= 4;
		}
		self.set_cursor();
	}

	pub fn print_char(&mut self, value: char)
	{
		self.raw_print_char(value as u8);
		self.go_right();
		self.set_cursor();
	}

	fn raw_print_char(&self, value: u8)
	{
		vga::putc(self.xpos, self.ypos, value);
		vga::setfg(self.xpos, self.ypos, self.fg);
		vga::setbg(self.xpos, self.ypos, self.bg);
	}

	pub fn print_screen(&mut self, value: &str)
	{
		for c in value.bytes()
		{
			self.raw_print_char(c);
			self.go_right();
		}
		self.set_cursor();
	}
}

impl ::core::fmt::Write for StdioWriter
{
	fn write_str(&mut self, s: &str) -> ::core::fmt::Result
	{
		for b in s.bytes()
		{
			self.raw_print_char(b);
			self.go_right();
		}
		self.set_cursor();
		Ok(())
	}
}
<|endoftext|>


<commit_before><commit_msg>update<commit_after>extern crate soio;

pub use ports::localhost;

mod ports {
    use std::net::SocketAddr;
    use std::str::FromStr;
    use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
    use std::sync::atomic::Ordering::SeqCst;

    // Helper for getting a unique port for the task run
    // TODO: Reuse ports to not spam the system
    static mut NEXT_PORT: AtomicUsize = ATOMIC_USIZE_INIT;
    const FIRST_PORT: usize = 18080;

    fn next_port() -> usize {
        unsafe {
            // If the atomic was never used, set it to the initial port
            NEXT_PORT.compare_and_swap(0, FIRST_PORT, SeqCst);

            // Get and increment the port list
            NEXT_PORT.fetch_add(1, SeqCst)
        }
    }

    pub fn localhost() -> SocketAddr {
        let s = format!("127.0.0.1:{}", next_port());
        FromStr::from_str(&s).unwrap()
    }
}

pub fn sleep_ms(ms: u64) {
    use std::thread;
    use std::time::Duration;
    thread::sleep(Duration::from_millis(ms));
}
<|endoftext|>


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

//!
//! # Regular language
//!
//! This provides a data structure representing a regular language. This is a more generalised form of a regular
//! expression (it supports symbol types other than simple strings). A regular language using the `u8` symbol forms
//! a simple regular expression.
//!

use super::phrase::*;
use std::ops::Range;

///
/// A Pattern represents a matching pattern in a regular language
///
#[derive(Clone)]
pub enum Pattern<Symbol> {
    ///
    /// Matches nothing
    ///
    Nothing,

    ///
    /// Matches a specific literal phrase
    ///
    Phrase(Vec<Symbol>),

    ///
    /// Matches at least a particular number of repetitions of a pattern
    ///
    /// `RepeatInfinite(0, X)` is the equivalent of the regular expression `X*`, `RepeatInfinite(1, X)` is the equivalent of the regular expression `X+`
    ///
    RepeatInfinite(u32, Box<Pattern<Symbol>>),

    ///
    /// Matches a range of repetitions of a pattern
    ///
    Repeat(Range<u32>, Box<Pattern<Symbol>>),

    ///
    /// Matches 0 or 1 instances of a pattern
    ///
    Optional(Box<Pattern<Symbol>>),

    ///
    /// Matches a set of sub-patterns in order
    ///
    And(Vec<Pattern<Symbol>>),

    ///
    /// Matches any one of a set of patterns
    ///
    Or(Vec<Pattern<Symbol>>)
}
<commit_msg>Optional is sugar for Repeat(0,1) so just use that<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! # Regular language
//!
//! This provides a data structure representing a regular language. This is a more generalised form of a regular
//! expression (it supports symbol types other than simple strings). A regular language using the `u8` symbol forms
//! a simple regular expression.
//!

use super::phrase::*;
use std::ops::Range;

///
/// A Pattern represents a matching pattern in a regular language
///
#[derive(Clone)]
pub enum Pattern<Symbol> {
    ///
    /// Matches nothing
    ///
    Nothing,

    ///
    /// Matches a specific literal phrase
    ///
    Phrase(Vec<Symbol>),

    ///
    /// Matches at least a particular number of repetitions of a pattern
    ///
    /// `RepeatInfinite(0, X)` is the equivalent of the regular expression `X*`, `RepeatInfinite(1, X)` is the equivalent of the regular expression `X+`
    ///
    RepeatInfinite(u32, Box<Pattern<Symbol>>),

    ///
    /// Matches a range of repetitions of a pattern
    ///
    Repeat(Range<u32>, Box<Pattern<Symbol>>),

    ///
    /// Matches a set of sub-patterns in order
    ///
    And(Vec<Pattern<Symbol>>),

    ///
    /// Matches any one of a set of patterns
    ///
    Or(Vec<Pattern<Symbol>>)
}
<|endoftext|>


<commit_before>// Copyright 2014-2016 Johannes Köster, Martin Larralde.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! One-way orf finder algorithm.
//!
//! Complexity: O(n).
//!
//! # Example
//!
//! ```
//! use bio::seq_analysis::orf::{Finder, Orf};
//! let start_codons = vec!(b"ATG");
//! let stop_codons  = vec!(b"TGA", b"TAG", b"TAA");
//! let min_len = 50;
//! let finder = Finder::new(start_codons, stop_codons, min_len);
//!
//! let sequence = b"ACGGCTAGAAAAGGCTAGAAAA";
//!
//! for Orf{start, end, offset} in finder.find_all(sequence) {
//!    let orf = &sequence[start..end];
//!    //...do something with orf sequence...
//! }
//! ```
//!
//! Right now the only way to check the reverse strand for orf is to use
//! the `alphabet::dna::RevComp` struct and to check for both sequences.
//! But that's not so performance friendly, as the reverse complementation and the orf research
//! could go on at the same time.

use std::borrow::Borrow;
use std::collections::VecDeque;
use std::iter;

/// An implementation of a naive algorithm finder
pub struct Finder {
    start_codons: Vec<VecDeque<u8>>,
    stop_codons: Vec<VecDeque<u8>>,
    min_len: usize,
}

impl Finder {
    /// Create a new instance of a finder for the given start and stop codons and a particular length
    pub fn new<'a>(
        start_codons: Vec<&'a [u8; 3]>,
        stop_codons: Vec<&'a [u8; 3]>,
        min_len: usize,
    ) -> Self {
        Finder {
            start_codons: start_codons
                .iter() // Convert start_ and
                .map(|x| {
                    // stop_codons from
                    x.iter() // Vec<&[u8;3]> to
                        .map(|&x| x as u8) // Vec<VecDeque<u8>>
                        .collect::<VecDeque<u8>>() // so they can be
                }) // easily compared
                .collect(), // with codon built
            stop_codons: stop_codons
                .iter() // from IntoTextIterator
                .map(|x| {
                    // object.
                    x.iter().map(|&x| x as u8).collect::<VecDeque<u8>>()
                })
                .collect(),
            min_len,
        }
    }

    /// Find all orfs in the given sequence
    pub fn find_all<C, T>(&self, seq: T) -> Matches<'_, C, T::IntoIter>
    where
        C: Borrow<u8>,
        T: IntoIterator<Item = C>,
    {
        Matches {
            finder: self,
            state: State::new(),
            seq: seq.into_iter().enumerate(),
        }
    }
}

/// An orf representation with start and end position of said orf,
/// as well as offset of the reading frame (1,2,3) and strand location
// (current: +, reverse complementary: -).
#[derive(Debug, PartialEq)]
pub struct Orf {
    pub start: usize,
    pub end: usize,
    pub offset: i8,
}

/// The current algorithm state.
struct State {
    start_pos: [Option<usize>; 3],
    codon: VecDeque<u8>,
}

impl State {
    /// Create new state.
    pub fn new() -> Self {
        State {
            start_pos: [None, None, None],
            codon: VecDeque::new(),
        }
    }
}

/// Iterator over offset, start position, end position and sequence of matched orfs.
pub struct Matches<'a, C, T>
where
    C: Borrow<u8>,
    T: Iterator<Item = C>,
{
    finder: &'a Finder,
    state: State,
    seq: iter::Enumerate<T>,
}

impl<'a, C, T> Iterator for Matches<'a, C, T>
where
    C: Borrow<u8>,
    T: Iterator<Item = C>,
{
    type Item = Orf;

    fn next(&mut self) -> Option<Orf> {
        let mut result: Option<Orf> = None;
        let mut offset: usize;

        for (index, nuc) in self.seq.by_ref() {
            // update the codon
            if self.state.codon.len() >= 3 {
                self.state.codon.pop_front();
            }
            self.state.codon.push_back(*nuc.borrow());
            offset = (index + 1) % 3;

            // inside orf
            if self.state.start_pos[offset].is_some() {
                // check if leaving orf
                if self.finder.stop_codons.contains(&self.state.codon) {
                    // check if length is sufficient
                    if index + 1 - self.state.start_pos[offset].unwrap() > self.finder.min_len {
                        // build results
                        result = Some(Orf {
                            start: self.state.start_pos[offset].unwrap() - 2,
                            end: index + 1,
                            offset: offset as i8,
                        });
                    }
                    // reinitialize
                    self.state.start_pos[offset] = None;
                }
            // check if entering orf
            } else if self.finder.start_codons.contains(&self.state.codon) {
                self.state.start_pos[offset] = Some(index);
            }
            if result.is_some() {
                return result;
            }
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn basic_finder() -> Finder {
        let start_codons = vec![b"ATG"];
        let stop_codons = vec![b"TGA", b"TAG", b"TAA"];
        let min_len = 5;
        Finder::new(start_codons, stop_codons, min_len)
    }

    #[test]
    fn test_no_orf() {
        let finder = basic_finder();
        let sequence = b"ACGGCTAGAAAAGGCTAGAAAA";
        assert!(finder.find_all(sequence).collect::<Vec<Orf>>().is_empty());
    }

    #[test]
    fn test_one_orf_no_offset() {
        let finder = basic_finder();
        let sequence = b"GGGATGGGGTGAGGG";
        let expected = vec![Orf {
            start: 3,
            end: 12,
            offset: 0,
        }];
        assert_eq!(expected, finder.find_all(sequence).collect::<Vec<Orf>>());
    }

    #[test]
    fn test_one_orf_with_offset() {
        let finder = basic_finder();
        let sequence = b"AGGGATGGGGTGAGGG";
        let expected = vec![Orf {
            start: 4,
            end: 13,
            offset: 1,
        }];
        assert_eq!(expected, finder.find_all(sequence).collect::<Vec<Orf>>());
    }

    #[test]
    fn test_two_orfs_different_offsets() {
        let finder = basic_finder();
        let sequence = b"ATGGGGTGAGGGGGATGGAAAAATAAG";
        let expected = vec![
            Orf {
                start: 0,
                end: 9,
                offset: 0,
            },
            Orf {
                start: 14,
                end: 26,
                offset: 2,
            },
        ];
        assert_eq!(expected, finder.find_all(sequence).collect::<Vec<Orf>>());
    }
}
<commit_msg>Improve documentation for open reading frame (#310)<commit_after>// Copyright 2014-2016 Johannes Köster, Martin Larralde.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! One-way open reading frame (ORF) finder algorithm.
//!
//! Complexity: O(n).
//!
//! # Example
//!
//! ```
//! use bio::seq_analysis::orf::{Finder, Orf};
//! let start_codons = vec!(b"ATG");
//! let stop_codons  = vec!(b"TGA", b"TAG", b"TAA");
//! let min_len = 50;
//! let finder = Finder::new(start_codons, stop_codons, min_len);
//!
//! let sequence = b"ACGGCTAGAAAAGGCTAGAAAA";
//!
//! for Orf{start, end, offset} in finder.find_all(sequence) {
//!    let orf = &sequence[start..end];
//!    //...do something with orf sequence...
//! }
//! ```
//!
//! Right now the only way to check the reverse strand for ORF is to use
//! the `alphabet::dna::RevComp` struct and to check for both sequences.
//! But that's not so performance friendly, as the reverse complementation and the ORF research
//! could go on at the same time.

use std::borrow::Borrow;
use std::collections::VecDeque;
use std::iter;

/// An implementation of a naive algorithm finder
// Implementation note:
//
// VecDeque is used rather than the obvious [u8; 3] to represent
// codons because a VecDeque<u8> is used to represent a sliding codon
// (see: State.codon) window which unfortunately, cannot be compared
// to [u8; 3].
pub struct Finder {
    start_codons: Vec<VecDeque<u8>>,
    stop_codons: Vec<VecDeque<u8>>,
    min_len: usize,
}

impl Finder {
    /// Create a new instance of a finder for the given start and stop codons and the minimum
    /// length of an ORF.
    pub fn new<'a>(
        start_codons: Vec<&'a [u8; 3]>,
        stop_codons: Vec<&'a [u8; 3]>,
        min_len: usize,
    ) -> Self {
        Finder {
            start_codons: start_codons
                .iter()
                .map(|x| x.iter().map(|&x| x as u8).collect::<VecDeque<u8>>())
                .collect(),
            stop_codons: stop_codons
                .iter()
                .map(|x| x.iter().map(|&x| x as u8).collect::<VecDeque<u8>>())
                .collect(),
            min_len,
        }
    }

    /// Find all ORFs in the given sequence
    pub fn find_all<C, T>(&self, seq: T) -> Matches<'_, C, T::IntoIter>
    where
        C: Borrow<u8>,
        T: IntoIterator<Item = C>,
    {
        Matches {
            finder: self,
            state: State::new(),
            seq: seq.into_iter().enumerate(),
        }
    }
}

/// An ORF representation with start and end position of said ORF,
/// as well as offset of the reading frame (1,2,3) and strand location
// (current: +, reverse complementary: -).
#[derive(Debug, PartialEq)]
pub struct Orf {
    pub start: usize,
    pub end: usize,
    pub offset: i8,
}

/// The current algorithm state.
struct State {
    start_pos: [Option<usize>; 3],
    codon: VecDeque<u8>,
}

impl State {
    /// Create new state.
    pub fn new() -> Self {
        State {
            start_pos: [None, None, None],
            codon: VecDeque::new(),
        }
    }
}

/// Iterator over offset, start position, end position and sequence of matched ORFs.
pub struct Matches<'a, C, T>
where
    C: Borrow<u8>,
    T: Iterator<Item = C>,
{
    finder: &'a Finder,
    state: State,
    seq: iter::Enumerate<T>,
}

impl<'a, C, T> Iterator for Matches<'a, C, T>
where
    C: Borrow<u8>,
    T: Iterator<Item = C>,
{
    type Item = Orf;

    fn next(&mut self) -> Option<Orf> {
        let mut result: Option<Orf> = None;
        let mut offset: usize;

        for (index, nuc) in self.seq.by_ref() {
            // update the codon
            if self.state.codon.len() >= 3 {
                self.state.codon.pop_front();
            }
            self.state.codon.push_back(*nuc.borrow());
            offset = (index + 1) % 3;

            // inside orf
            if self.state.start_pos[offset].is_some() {
                // check if leaving orf
                if self.finder.stop_codons.contains(&self.state.codon) {
                    // check if length is sufficient
                    if index + 1 - self.state.start_pos[offset].unwrap() > self.finder.min_len {
                        // build results
                        result = Some(Orf {
                            start: self.state.start_pos[offset].unwrap() - 2,
                            end: index + 1,
                            offset: offset as i8,
                        });
                    }
                    // reinitialize
                    self.state.start_pos[offset] = None;
                }
            // check if entering orf
            } else if self.finder.start_codons.contains(&self.state.codon) {
                self.state.start_pos[offset] = Some(index);
            }
            if result.is_some() {
                return result;
            }
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn basic_finder() -> Finder {
        let start_codons = vec![b"ATG"];
        let stop_codons = vec![b"TGA", b"TAG", b"TAA"];
        let min_len = 5;
        Finder::new(start_codons, stop_codons, min_len)
    }

    #[test]
    fn test_no_orf() {
        let finder = basic_finder();
        let sequence = b"ACGGCTAGAAAAGGCTAGAAAA";
        assert!(finder.find_all(sequence).collect::<Vec<Orf>>().is_empty());
    }

    #[test]
    fn test_one_orf_no_offset() {
        let finder = basic_finder();
        let sequence = b"GGGATGGGGTGAGGG";
        let expected = vec![Orf {
            start: 3,
            end: 12,
            offset: 0,
        }];
        assert_eq!(expected, finder.find_all(sequence).collect::<Vec<Orf>>());
    }

    #[test]
    fn test_one_orf_with_offset() {
        let finder = basic_finder();
        let sequence = b"AGGGATGGGGTGAGGG";
        let expected = vec![Orf {
            start: 4,
            end: 13,
            offset: 1,
        }];
        assert_eq!(expected, finder.find_all(sequence).collect::<Vec<Orf>>());
    }

    #[test]
    fn test_two_orfs_different_offsets() {
        let finder = basic_finder();
        let sequence = b"ATGGGGTGAGGGGGATGGAAAAATAAG";
        let expected = vec![
            Orf {
                start: 0,
                end: 9,
                offset: 0,
            },
            Orf {
                start: 14,
                end: 26,
                offset: 2,
            },
        ];
        assert_eq!(expected, finder.find_all(sequence).collect::<Vec<Orf>>());
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::thread;
use std::thread::JoinHandle;
use std::net::TcpStream;
use std::ops::DerefMut;
use std::os::unix::io::RawFd;
use std::collections::LinkedList;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{
    channel,
    Sender,
    Receiver,
    TryRecvError
};

use super::types::*;
use super::epoll;
use super::epoll::util::*;
use super::epoll::EpollEvent;
use super::socket::Socket;
use super::simple_stream::nbetstream::NbetStream;

#[allow(dead_code)]
pub struct EventLoop {
    /// Handle to event loop process
    prox: JoinHandle<()>,
    /// Sender<T> to proc
    prox_tx: Sender<TcpStream>
}

impl EventLoop {

    /// Returns a new EventLoop
    pub fn new(server_tx: Sender<EventTuple>) -> EventLoop {
        let (tx, rx): (Sender<TcpStream>, Receiver<TcpStream>) = channel();
        let prox = thread::Builder::new()
            .name("EventLoop".to_string())
            .spawn(move || {
                EventLoop::start(rx, server_tx);
            }).unwrap();

        EventLoop {
            prox: prox,
            prox_tx: tx
        }
    }

    /// Returns a clone of this EventLoop's Sender<TcpStream> channel
    pub fn sender(&self) -> Sender<TcpStream> {
        self.prox_tx.clone()
    }

    /// Main event loop
    fn start(rx: Receiver<TcpStream>, uspace_tx: Sender<EventTuple>) {
        // Master socket list
        let sockets = Arc::new(Mutex::new(LinkedList::<Socket>::new()));

        // Our error handler for this thread and it's children
        let (err_tx, err_rx): (Sender<()>, Receiver<()>) = channel();

        // Create an epoll instance
        let result = epoll::create1(0);
        if result.is_err() {
            let err = result.unwrap_err();
            panic!("Unable to create epoll instance: {}", err)
        }
        let epoll_instance = result.unwrap();

        // Start the epoll thread
        let c_sockets = sockets.clone();
        let c_epoll_instance = epoll_instance.clone();
        let epoll_prox = thread::Builder::new()
            .name("EpollLoop".to_string())
            .spawn(move || {
                EventLoop::epoll_loop(uspace_tx, c_sockets, c_epoll_instance, err_rx);
            }).unwrap();

        for new_stream in rx.iter() {
            match NbetStream::new(new_stream) {
                Ok(s_stream) => {
                    // Add to master list
                    let socket = Socket::new(s_stream);

                    // TODO - Replace with recoverable version once into_inner() is stable
                    // Unfortunately, this is the only stable way to use mutexes at the moment
                    // Hopefully recovering from poisoning will be in 1.2
                    // let mut s_guard = match sockets.lock() {
                    //     Ok(guard) => guard,
                    //     Err(poisoned) => poisoned.into_inner()
                    // };
                    let mut s_guard = sockets.lock().unwrap();
                    let s_list = s_guard.deref_mut();
                    let s_fd = socket.raw_fd();
                    s_list.push_back(socket);

                    // Add to epoll
                    let event = Box::new(EpollEvent {
                        data: s_fd as u64,
                        events: (event_type::EPOLLIN | event_type::EPOLLET)
                    });
                    match epoll::ctl(epoll_instance, ctl_op::ADD, s_fd, event) {
                        Ok(()) => println!("New socket added to epoll list"),
                        Err(e) => println!("Epoll CtrlError during add: {}", e)
                    };
                }
                Err(e) => {
                    // TODO - write error to log file
                    println!("Error: {}", e);
                }
            };
        }

        // If we get here, shit is real bad. It means we have lost our
        // channel to the outside world.
        // Kill off event loop, so unwinding can begin
        println!("Rust.EventLoop.start - thread finished");
        let _ = err_tx.send(());
    }

    /// Calls epoll_wait forever waiting for events to be fired up from kernel
    fn epoll_loop(uspace_tx: Sender<EventTuple>,
                  sockets: SocketList,
                  epoll_instance: RawFd,
                  err_rx: Receiver<()>) {

        // This is the maximum number of events we want to be notified of at one time
        let mut events = Vec::<EpollEvent>::with_capacity(100);
        unsafe { events.set_len(100); }

        loop {
            // Wait for epoll events
            match epoll::wait(epoll_instance, &mut events[..], -1) {
                Ok(num_events) => {
                    println!("{} epoll event(s) received", num_events);
                    for x in 0..num_events {
                        let tx_clone = uspace_tx.clone();
                        let s_clone = sockets.clone();
                        let epfd_clone = epoll_instance.clone();

                        EventLoop::handle_epoll_event(epfd_clone,
                            &events[x as usize], s_clone, tx_clone);
                    }
                }
                Err(e) => {
                    panic!("Error on epoll::wait(): {}", e)
                }
            }

            // If we receive anything on this end or lose communication, we need to halt,
            // because we have no where to send up events, our "user space" channel is
            // gone
            match err_rx.try_recv() {
                Ok(_) => {
                    println!("Error, terminating epoll_loop");
                    break;
                }
                Err(e) => {
                    match e {
                        TryRecvError::Empty => {}
                        _ => {
                            println!("Error, terminating epoll_loo");
                            break;
                        }
                    }
                }
            }
        }
        println!("Rust.EventLoop.epoll_loop - thread finished");
    }

    /// Processes a read on the socket that is ready for reading
    ///
    /// An epoll event is passed to this function, with the fd that is ready to be read
    /// A traversal through the list of sockets is then performed in order to locate the
    /// NbetStream instance that is wrapping that file descriptor.
    /// After a read is performed on that socket, it's data will be passed back to the
    /// "user-space" section of the Server to process the payload however it needs to.
    ///
    /// TODO - Create a faster way to gain a safe reference to the NbetStream wrapping
    /// the fd instead of an O(n) lookup for every event. Currently lookup time is
    /// O(n) * MAX_EPOLL_EVENTS, where MAX_EPOLL_EVENTS is user defined in this function's
    /// caller.
    fn handle_epoll_event(epoll_instance: RawFd,
                          event: &EpollEvent,
                          sockets: SocketList,
                          uspace_tx: Sender<EventTuple>) {

        println!("Rust.EventLoop.handle_epoll_event");

        // The fd we are traversing the list for
        let fd = event.data;

        // We need a handle before the list gets locked and used
        let s_list_clone = sockets.clone();

        // TODO - Replace with recoverable version once into_inner() is stable
        // Unfortunately, this is the only stable way to use mutexes at the moment
        // Hopefully recovering from poisoning will be in 1.2
        // let mut s_guard = match sockets.lock() {
        //     Ok(guard) => guard,
        //     Err(poisoned) => poisoned.into_inner()
        // };
        let mut s_guard = sockets.lock().unwrap();
        let s_list = s_guard.deref_mut();
        for socket in s_list.iter_mut() {
            if socket.raw_fd() as u64 == fd {
                // We've found the socket for the event passed from epoll
                // Lets attempt to read from it
                match socket.read() {
                    Ok(()) => {
                        println!("Rust.EventLoop.handle_epoll_event.socket.read.Ok()");
                        for msg in socket.buffer().iter() {
                            let msg_for_debug = msg.clone();
                            match String::from_utf8(msg_for_debug) {
                                Ok(msg_str) => {
                                    println!("Rust.EventLoop.handle_epoll_event.socket.read.ok.msg_as_string: {}", msg_str);
                                }
                                Err(e) => {
                                    println!("Rust.EventLoop.handle_epoll_event.socket.read.ok.msg_as_string.Err: {}", e);
                                }
                            };

                            let list_handle = s_list_clone.clone();
                            let socket_clone = socket.clone();
                            let msg_clone = msg.clone();
                            let _ = uspace_tx.send((list_handle, socket_clone, msg_clone));
                        }
                    }
                    Err(e) => {
                        println!("Rust.EventLoop.handle_epoll_event.socket.read.Err(e): {}", e);
                        // We really don't care what happened, it all results in the same
                        // outcome - remove the socket from system...
                        let s_clone = socket.clone();
                        let epfd_clone = epoll_instance.clone();
                        EventLoop::remove_socket_from_epoll(s_clone, epfd_clone);

                        let s_id = socket.id();
                        let list_clone = s_list_clone.clone();
                        EventLoop::remove_socket_from_list(s_id, list_clone);
                    }
                }
            }
        }
    }

    /// Removes socket from the epoll watch list
    fn remove_socket_from_epoll(socket: Socket, epoll_instance: RawFd) {
        // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required
        // a non-null pointer in event, even though this argument is ignored.
        // Since Linux 2.6.9, event can be specified as NULL when using
        // EPOLL_CTL_DEL.  Applications that need to be portable to kernels
        // before 2.6.9 should specify a non-null pointer in event.
        let event = Box::new(EpollEvent {
            data: 0 as u32,
            events: 0 as u32
        });
        let s_fd = socket.raw_fd();
        match epoll::ctl(epoll_instance, ctl_op::DEL, s_fd, event) {
            Ok(()) => println!("Socket removed from epoll watch list"),
            Err(e) => println!("Epoll CtrlError during del: {}", e)
        };
    }

    /// Removes socket from master list
    fn remove_socket_from_list(socket_id: u32, sockets: SocketList) {
        // TODO - Replace with recoverable version once into_inner() is stable
        // Unfortunately, this is the only stable way to use mutexes at the moment
        // Hopefully recovering from poisoning will be in 1.2
        // let mut s_guard = match sockets.lock() {
        //     Ok(guard) => guard,
        //     Err(poisoned) => poisoned.into_inner()
        // };
        let mut s_guard = sockets.lock().unwrap();
        let s_list = s_guard.deref_mut();

        let mut socket_found = false;
        let mut index: usize = 1;
        for socket in s_list.iter() {
            if socket.id() == socket_id {
                socket_found = true;
                break;
            }
            index += 1;
        }

        if !socket_found {
            println!("Socket not found in list...?");
            return;
        }

        if index == 1 {
            s_list.pop_front();
        } else {
            let mut split = s_list.split_off(index - 1);
            split.pop_front();
            s_list.append(&mut split);
        }

        println!("Socket removed sucessfully");
    }
}
<commit_msg>I thought rustc was better than that<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::thread;
use std::thread::JoinHandle;
use std::net::TcpStream;
use std::ops::DerefMut;
use std::os::unix::io::RawFd;
use std::collections::LinkedList;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{
    channel,
    Sender,
    Receiver,
    TryRecvError
};

use super::types::*;
use super::epoll;
use super::epoll::util::*;
use super::epoll::EpollEvent;
use super::socket::Socket;
use super::simple_stream::nbetstream::NbetStream;

#[allow(dead_code)]
pub struct EventLoop {
    /// Handle to event loop process
    prox: JoinHandle<()>,
    /// Sender<T> to proc
    prox_tx: Sender<TcpStream>
}

impl EventLoop {

    /// Returns a new EventLoop
    pub fn new(server_tx: Sender<EventTuple>) -> EventLoop {
        let (tx, rx): (Sender<TcpStream>, Receiver<TcpStream>) = channel();
        let prox = thread::Builder::new()
            .name("EventLoop".to_string())
            .spawn(move || {
                EventLoop::start(rx, server_tx);
            }).unwrap();

        EventLoop {
            prox: prox,
            prox_tx: tx
        }
    }

    /// Returns a clone of this EventLoop's Sender<TcpStream> channel
    pub fn sender(&self) -> Sender<TcpStream> {
        self.prox_tx.clone()
    }

    /// Main event loop
    fn start(rx: Receiver<TcpStream>, uspace_tx: Sender<EventTuple>) {
        // Master socket list
        let sockets = Arc::new(Mutex::new(LinkedList::<Socket>::new()));

        // Our error handler for this thread and it's children
        let (err_tx, err_rx): (Sender<()>, Receiver<()>) = channel();

        // Create an epoll instance
        let result = epoll::create1(0);
        if result.is_err() {
            let err = result.unwrap_err();
            panic!("Unable to create epoll instance: {}", err)
        }
        let epoll_instance = result.unwrap();

        // Start the epoll thread
        let c_sockets = sockets.clone();
        let c_epoll_instance = epoll_instance.clone();
        let epoll_prox = thread::Builder::new()
            .name("EpollLoop".to_string())
            .spawn(move || {
                EventLoop::epoll_loop(uspace_tx, c_sockets, c_epoll_instance, err_rx);
            }).unwrap();

        for new_stream in rx.iter() {
            match NbetStream::new(new_stream) {
                Ok(s_stream) => {
                    // Add to master list
                    let socket = Socket::new(s_stream);

                    // TODO - Replace with recoverable version once into_inner() is stable
                    // Unfortunately, this is the only stable way to use mutexes at the moment
                    // Hopefully recovering from poisoning will be in 1.2
                    // let mut s_guard = match sockets.lock() {
                    //     Ok(guard) => guard,
                    //     Err(poisoned) => poisoned.into_inner()
                    // };
                    let mut s_guard = sockets.lock().unwrap();
                    let s_list = s_guard.deref_mut();
                    let s_fd = socket.raw_fd();
                    s_list.push_back(socket);

                    // Add to epoll
                    let event = Box::new(EpollEvent {
                        data: s_fd as u64,
                        events: (event_type::EPOLLIN | event_type::EPOLLET)
                    });
                    match epoll::ctl(epoll_instance, ctl_op::ADD, s_fd, event) {
                        Ok(()) => println!("New socket added to epoll list"),
                        Err(e) => println!("Epoll CtrlError during add: {}", e)
                    };
                }
                Err(e) => {
                    // TODO - write error to log file
                    println!("Error: {}", e);
                }
            };
        }

        // If we get here, shit is real bad. It means we have lost our
        // channel to the outside world.
        // Kill off event loop, so unwinding can begin
        println!("Rust.EventLoop.start - thread finished");
        let _ = err_tx.send(());
    }

    /// Calls epoll_wait forever waiting for events to be fired up from kernel
    fn epoll_loop(uspace_tx: Sender<EventTuple>,
                  sockets: SocketList,
                  epoll_instance: RawFd,
                  err_rx: Receiver<()>) {

        // This is the maximum number of events we want to be notified of at one time
        let mut events = Vec::<EpollEvent>::with_capacity(100);
        unsafe { events.set_len(100); }

        loop {
            // Wait for epoll events
            match epoll::wait(epoll_instance, &mut events[..], -1) {
                Ok(num_events) => {
                    println!("{} epoll event(s) received", num_events);
                    for x in 0..num_events {
                        let tx_clone = uspace_tx.clone();
                        let s_clone = sockets.clone();
                        let epfd_clone = epoll_instance.clone();

                        EventLoop::handle_epoll_event(epfd_clone,
                            &events[x as usize], s_clone, tx_clone);
                    }
                }
                Err(e) => {
                    panic!("Error on epoll::wait(): {}", e)
                }
            }

            // If we receive anything on this end or lose communication, we need to halt,
            // because we have no where to send up events, our "user space" channel is
            // gone
            match err_rx.try_recv() {
                Ok(_) => {
                    println!("Error, terminating epoll_loop");
                    break;
                }
                Err(e) => {
                    match e {
                        TryRecvError::Empty => {}
                        _ => {
                            println!("Error, terminating epoll_loo");
                            break;
                        }
                    }
                }
            }
        }
        println!("Rust.EventLoop.epoll_loop - thread finished");
    }

    /// Processes a read on the socket that is ready for reading
    ///
    /// An epoll event is passed to this function, with the fd that is ready to be read
    /// A traversal through the list of sockets is then performed in order to locate the
    /// NbetStream instance that is wrapping that file descriptor.
    /// After a read is performed on that socket, it's data will be passed back to the
    /// "user-space" section of the Server to process the payload however it needs to.
    ///
    /// TODO - Create a faster way to gain a safe reference to the NbetStream wrapping
    /// the fd instead of an O(n) lookup for every event. Currently lookup time is
    /// O(n) * MAX_EPOLL_EVENTS, where MAX_EPOLL_EVENTS is user defined in this function's
    /// caller.
    fn handle_epoll_event(epoll_instance: RawFd,
                          event: &EpollEvent,
                          sockets: SocketList,
                          uspace_tx: Sender<EventTuple>) {

        println!("Rust.EventLoop.handle_epoll_event");

        // The fd we are traversing the list for
        let fd = event.data;

        // We need a handle before the list gets locked and used
        let s_list_clone = sockets.clone();

        // TODO - Replace with recoverable version once into_inner() is stable
        // Unfortunately, this is the only stable way to use mutexes at the moment
        // Hopefully recovering from poisoning will be in 1.2
        // let mut s_guard = match sockets.lock() {
        //     Ok(guard) => guard,
        //     Err(poisoned) => poisoned.into_inner()
        // };
        let mut s_guard = sockets.lock().unwrap();
        let s_list = s_guard.deref_mut();
        for socket in s_list.iter_mut() {
            if socket.raw_fd() as u64 == fd {
                // We've found the socket for the event passed from epoll
                // Lets attempt to read from it
                match socket.read() {
                    Ok(()) => {
                        println!("Rust.EventLoop.handle_epoll_event.socket.read.Ok()");
                        for msg in socket.buffer().iter() {
                            let msg_for_debug = msg.clone();
                            match String::from_utf8(msg_for_debug) {
                                Ok(msg_str) => {
                                    println!("Rust.EventLoop.handle_epoll_event.socket.read.ok.msg_as_string: {}", msg_str);
                                }
                                Err(e) => {
                                    println!("Rust.EventLoop.handle_epoll_event.socket.read.ok.msg_as_string.Err: {}", e);
                                }
                            };

                            let list_handle = s_list_clone.clone();
                            let socket_clone = socket.clone();
                            let msg_clone = msg.clone();
                            let _ = uspace_tx.send((list_handle, socket_clone, msg_clone));
                        }
                    }
                    Err(e) => {
                        println!("Rust.EventLoop.handle_epoll_event.socket.read.Err(e): {}", e);
                        // We really don't care what happened, it all results in the same
                        // outcome - remove the socket from system...
                        let s_clone = socket.clone();
                        let epfd_clone = epoll_instance.clone();
                        EventLoop::remove_socket_from_epoll(s_clone, epfd_clone);

                        let s_id = socket.id();
                        let list_clone = s_list_clone.clone();
                        EventLoop::remove_socket_from_list(s_id, list_clone);
                    }
                }
            }
        }
    }

    /// Removes socket from the epoll watch list
    fn remove_socket_from_epoll(socket: Socket, epoll_instance: RawFd) {
        // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required
        // a non-null pointer in event, even though this argument is ignored.
        // Since Linux 2.6.9, event can be specified as NULL when using
        // EPOLL_CTL_DEL.  Applications that need to be portable to kernels
        // before 2.6.9 should specify a non-null pointer in event.
        let event = Box::new(EpollEvent {
            data: 0 as u64,
            events: 0 as u32
        });
        let s_fd = socket.raw_fd();
        match epoll::ctl(epoll_instance, ctl_op::DEL, s_fd, event) {
            Ok(()) => println!("Socket removed from epoll watch list"),
            Err(e) => println!("Epoll CtrlError during del: {}", e)
        };
    }

    /// Removes socket from master list
    fn remove_socket_from_list(socket_id: u32, sockets: SocketList) {
        // TODO - Replace with recoverable version once into_inner() is stable
        // Unfortunately, this is the only stable way to use mutexes at the moment
        // Hopefully recovering from poisoning will be in 1.2
        // let mut s_guard = match sockets.lock() {
        //     Ok(guard) => guard,
        //     Err(poisoned) => poisoned.into_inner()
        // };
        let mut s_guard = sockets.lock().unwrap();
        let s_list = s_guard.deref_mut();

        let mut socket_found = false;
        let mut index: usize = 1;
        for socket in s_list.iter() {
            if socket.id() == socket_id {
                socket_found = true;
                break;
            }
            index += 1;
        }

        if !socket_found {
            println!("Socket not found in list...?");
            return;
        }

        if index == 1 {
            s_list.pop_front();
        } else {
            let mut split = s_list.split_off(index - 1);
            split.pop_front();
            s_list.append(&mut split);
        }

        println!("Socket removed sucessfully");
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use error::{Error, Result};
use file::FileOwner;
use regex::Regex;
use std::{process, str};
use std::path::Path;
use super::default_base as default;
use host::telemetry::Netif;

pub fn file_get_owner<P: AsRef<Path>>(path: P) -> Result<FileOwner> {
    Ok(FileOwner {
        user_name: try!(default::file_stat(path.as_ref(), vec!["-f", "%Su"])),
        user_uid: try!(default::file_stat(path.as_ref(), vec!["-f", "%u"])).parse::<u64>().unwrap(),
        group_name: try!(default::file_stat(path.as_ref(), vec!["-f", "%Sg"])),
        group_gid: try!(default::file_stat(path.as_ref(), vec!["-f", "%g"])).parse::<u64>().unwrap()
    })
}

pub fn file_get_mode<P: AsRef<Path>>(path: P) -> Result<u16> {
    Ok(try!(default::file_stat(path, vec!["-f", "%Lp"])).parse::<u16>().unwrap())
}

pub fn version() -> Result<String> {
    let output = try!(process::Command::new("uname").arg("-r").output());
    Ok(str::from_utf8(&output.stdout).unwrap().trim().to_string())
}

pub fn net() -> Result<Vec<Netif>> {
    let if_pattern = r"(?m)^(?P<if>[a-z0-9]+): flags=(?P<content>.+\n(?:^\s+.+\n)+)";
    let kv_pattern = r"^\s+(?P<key>[a-z0-9]+)(?:\s|:\s|=)(?P<value>.+)";
    let ipv4_pattern = r"^(?P<ip>(?:[0-9]{1,3}\.){3}[0-9]{1,3}) netmask (?P<mask>0x[a-f0-9]{8})";
    let ipv6_pattern = r"^(?P<ip>(?:[a-f0-9]{4}::(?:[a-f0-9]{1,4}:){3}[a-f0-9]{1,4})|::1)(?:%[a-z]+[0-9]+)? prefixlen (?P<prefix>[0-9]+)(?: scopeid (?P<scope>[a-z0-9]+))?\s*$";
    default::parse_net(if_pattern, kv_pattern, ipv4_pattern, ipv6_pattern)
}

pub fn get_sysctl_item(item: &str) -> Result<String> {
    // XXX This result should be cached
    let sysctl_out = try!(process::Command::new("sysctl").arg("-a").output());
    let sysctl = String::from_utf8(sysctl_out.stdout).unwrap();

    let exp = format!("{}: (.+)", item);
    let regex = Regex::new(&exp).unwrap();

    if let Some(cap) = regex.captures(&sysctl) {
        Ok(cap.at(1).unwrap().to_string())
    } else {
        Err(Error::Generic("Could not match sysctl item".to_string()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_net() {
        // XXX Not a proper test. Requires mocking.
        assert!(net().is_ok());
    }

    #[test]
    fn test_get_sysctl_item_err() {
        assert!(super::get_sysctl_item("moo").is_err());
    }
}
<commit_msg>Trivial cleanup or use order<commit_after>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use error::{Error, Result};
use file::FileOwner;
use host::telemetry::Netif;
use regex::Regex;
use std::{process, str};
use std::path::Path;
use super::default_base as default;

pub fn file_get_owner<P: AsRef<Path>>(path: P) -> Result<FileOwner> {
    Ok(FileOwner {
        user_name: try!(default::file_stat(path.as_ref(), vec!["-f", "%Su"])),
        user_uid: try!(default::file_stat(path.as_ref(), vec!["-f", "%u"])).parse::<u64>().unwrap(),
        group_name: try!(default::file_stat(path.as_ref(), vec!["-f", "%Sg"])),
        group_gid: try!(default::file_stat(path.as_ref(), vec!["-f", "%g"])).parse::<u64>().unwrap()
    })
}

pub fn file_get_mode<P: AsRef<Path>>(path: P) -> Result<u16> {
    Ok(try!(default::file_stat(path, vec!["-f", "%Lp"])).parse::<u16>().unwrap())
}

pub fn version() -> Result<String> {
    let output = try!(process::Command::new("uname").arg("-r").output());
    Ok(str::from_utf8(&output.stdout).unwrap().trim().to_string())
}

pub fn net() -> Result<Vec<Netif>> {
    let if_pattern = r"(?m)^(?P<if>[a-z0-9]+): flags=(?P<content>.+\n(?:^\s+.+\n)+)";
    let kv_pattern = r"^\s+(?P<key>[a-z0-9]+)(?:\s|:\s|=)(?P<value>.+)";
    let ipv4_pattern = r"^(?P<ip>(?:[0-9]{1,3}\.){3}[0-9]{1,3}) netmask (?P<mask>0x[a-f0-9]{8})";
    let ipv6_pattern = r"^(?P<ip>(?:[a-f0-9]{4}::(?:[a-f0-9]{1,4}:){3}[a-f0-9]{1,4})|::1)(?:%[a-z]+[0-9]+)? prefixlen (?P<prefix>[0-9]+)(?: scopeid (?P<scope>[a-z0-9]+))?\s*$";
    default::parse_net(if_pattern, kv_pattern, ipv4_pattern, ipv6_pattern)
}

pub fn get_sysctl_item(item: &str) -> Result<String> {
    // XXX This result should be cached
    let sysctl_out = try!(process::Command::new("sysctl").arg("-a").output());
    let sysctl = String::from_utf8(sysctl_out.stdout).unwrap();

    let exp = format!("{}: (.+)", item);
    let regex = Regex::new(&exp).unwrap();

    if let Some(cap) = regex.captures(&sysctl) {
        Ok(cap.at(1).unwrap().to_string())
    } else {
        Err(Error::Generic("Could not match sysctl item".to_string()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_net() {
        // XXX Not a proper test. Requires mocking.
        assert!(net().is_ok());
    }

    #[test]
    fn test_get_sysctl_item_err() {
        assert!(super::get_sysctl_item("moo").is_err());
    }
}
<|endoftext|>


<commit_before>
use std::io::prelude::*;
use std::io::BufReader;
use std::fs;
use std::path::PathBuf;
use rustc_serialize::json::Json;
use errors::*;

fn crates_from_file<F>(path: &PathBuf, func: &mut F) -> Result<()>
    where F: FnMut(&str, &str) -> () {

    let reader = try!(fs::File::open(path)
                      .map(|f| BufReader::new(f)));

    let mut name = String::new();
    let mut versions = Vec::new();

    for line in reader.lines() {
        // some crates have invalid UTF-8 (nanny-sys-0.0.7)
        // skip them
        let line = match line {
            Ok(l) => l,
            Err(_) => continue
        };
        let data = match Json::from_str(line.trim()) {
            Ok(d) => d,
            Err(_) => continue
        };

        let obj = try!(data.as_object().ok_or("Not a JSON object"));
        let crate_name = try!(obj.get("name")
                              .and_then(|n| n.as_string())
                              .ok_or("`name` not found in JSON object"));
        let vers = try!(obj.get("vers")
                        .and_then(|n| n.as_string())
                        .ok_or("`vers` not found in JSON object"));

        name.clear();
        name.push_str(crate_name);
        versions.push(format!("{}", vers));
    }

    if !name.is_empty() {
        versions.reverse();
        for version in versions {
            func(&name[..], &version[..]);
        }
    }

    Ok(())
}

pub fn crates_from_path<F>(path: &PathBuf, func: &mut F) -> Result<()>
    where F: FnMut(&str, &str) -> () {

    if !path.is_dir() {
        return Err("Not a directory".into());
    }

    for file in try!(path.read_dir()) {
        let file = try!(file);
        let path = file.path();
        // skip files under .git and config.json
        if path.to_str().unwrap().contains(".git") ||
            path.file_name().unwrap() == "config.json" {
                continue;
            }

        if path.is_dir() {
            try!(crates_from_path(&path, func));
        } else {
            try!(crates_from_file(&path, func));
        }
    }

    Ok(())
}
<commit_msg>Skip yanked crates when building world<commit_after>
use std::io::prelude::*;
use std::io::BufReader;
use std::fs;
use std::path::PathBuf;
use rustc_serialize::json::Json;
use errors::*;

fn crates_from_file<F>(path: &PathBuf, func: &mut F) -> Result<()>
    where F: FnMut(&str, &str) -> () {

    let reader = try!(fs::File::open(path)
                      .map(|f| BufReader::new(f)));

    let mut name = String::new();
    let mut versions = Vec::new();

    for line in reader.lines() {
        // some crates have invalid UTF-8 (nanny-sys-0.0.7)
        // skip them
        let line = match line {
            Ok(l) => l,
            Err(_) => continue
        };
        let data = match Json::from_str(line.trim()) {
            Ok(d) => d,
            Err(_) => continue
        };

        let obj = try!(data.as_object().ok_or("Not a JSON object"));
        let crate_name = try!(obj.get("name")
                              .and_then(|n| n.as_string())
                              .ok_or("`name` not found in JSON object"));
        let vers = try!(obj.get("vers")
                        .and_then(|n| n.as_string())
                        .ok_or("`vers` not found in JSON object"));

        let yanked = try!(obj.get("yanked")
                          .and_then(|n| n.as_boolean())
                          .ok_or("`vers` not found in JSON object"));

        // Skip yanked crates
        if yanked {
            continue;
        }

        name.clear();
        name.push_str(crate_name);
        versions.push(format!("{}", vers));
    }

    if !name.is_empty() {
        versions.reverse();
        for version in versions {
            func(&name[..], &version[..]);
        }
    }

    Ok(())
}

pub fn crates_from_path<F>(path: &PathBuf, func: &mut F) -> Result<()>
    where F: FnMut(&str, &str) -> () {

    if !path.is_dir() {
        return Err("Not a directory".into());
    }

    for file in try!(path.read_dir()) {
        let file = try!(file);
        let path = file.path();
        // skip files under .git and config.json
        if path.to_str().unwrap().contains(".git") ||
            path.file_name().unwrap() == "config.json" {
                continue;
            }

        if path.is_dir() {
            try!(crates_from_path(&path, func));
        } else {
            try!(crates_from_file(&path, func));
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use rand::os::OsRng;
use rand::XorShiftRng;
use rand::Rand;
use rand::Rng;

use tile::Faction;

use util::{Error, Direction};

use level::{Level, add_isize_to_usize};

pub struct FactionGen {
    rand: XorShiftRng,
}

impl FactionGen {
    pub fn new() -> FactionGen {
        FactionGen {
            rand: XorShiftRng::rand(&mut OsRng::new().unwrap()),
        }
    }

    pub fn generate(&mut self, level: &mut Level<Faction>) {
        let mut delta = Vec::new();
        for x in 0..level.get_width() {
            for y in 0..level.get_height() {
                let mut deck = Vec::new();
                match level.get_mut_tile(x, y) {
                    Ok(tile) => {
                        match *tile {
                            Faction::Faction(_) => {
                                deck.push(tile.clone());
                            },
                            Faction::Void => continue,
                            _ => {},
                        }

                    },
                    Err(Error::IndexOutOfBounds) => {
                        panic!("Generate method indexed out of bounds while simulating a step. This should never happen unless the programmer is not very bright.");
                    }
                }
                Self::get_faction_neighbours(x, y, &mut deck, level);
                self.rand.shuffle(&mut deck);
                match deck.pop() {
                    Some(f) => {
                        delta.push(((x,y), f));
                    },
                    None => continue,
                }
            }
        }
        Self::apply_changes(level, delta);
    }

    fn get_faction_neighbours(x: usize, y: usize, deck: &mut Vec<Faction>, level: &mut Level<Faction>) {
        for d in Direction::get_dirs() {
            let (ix, iy) = d.get_tuple();
            let coord = match (add_isize_to_usize(ix, x), add_isize_to_usize(iy, y)) {
                (Some(x), Some(y)) => (x,y),
                _ => continue,
            };
            match level.get_tile_with_tuple(coord) {
                Ok(f @ &Faction::Faction(_)) => deck.push(f.clone()),
                _ => {},
            }
        }
    }

    fn apply_changes(level: &mut Level<Faction>, delta: Vec<((usize, usize), Faction)>) {
        for ((x, y), f) in delta {
            if let Ok(tile) = level.get_mut_tile(x, y) {
                *tile = f;
            }
        }
    }
}
<commit_msg>the shuffling of the deck and then poping has been replaced with rand.choose<commit_after>use rand::os::OsRng;
use rand::XorShiftRng;
use rand::Rand;
use rand::Rng;

use tile::Faction;

use util::{Error, Direction};

use level::{Level, add_isize_to_usize};

pub struct FactionGen {
    rand: XorShiftRng,
}

impl FactionGen {
    pub fn new() -> FactionGen {
        FactionGen {
            rand: XorShiftRng::rand(&mut OsRng::new().unwrap()),
        }
    }

    pub fn generate(&mut self, level: &mut Level<Faction>) {
        let mut delta = Vec::new();
        for x in 0..level.get_width() {
            for y in 0..level.get_height() {
                let mut deck = Vec::new();
                match level.get_mut_tile(x, y) {
                    Ok(tile) => {
                        match *tile {
                            Faction::Faction(_) => {
                                deck.push(tile.clone());
                            },
                            Faction::Void => continue,
                            _ => {},
                        }

                    },
                    Err(Error::IndexOutOfBounds) => {
                        panic!("Generate method indexed out of bounds while simulating a step. This should never happen unless the programmer is not very bright.");
                    }
                }
                Self::get_faction_neighbours(x, y, &mut deck, level);
                match self.rand.choose(&deck) {
                    Some(f) => {
                        delta.push(((x,y), f.clone()));
                    },
                    None => continue,
                }
            }
        }
        Self::apply_changes(level, delta);
    }

    fn get_faction_neighbours(x: usize, y: usize, deck: &mut Vec<Faction>, level: &mut Level<Faction>) {
        for d in Direction::get_dirs() {
            let (ix, iy) = d.get_tuple();
            let coord = match (add_isize_to_usize(ix, x), add_isize_to_usize(iy, y)) {
                (Some(x), Some(y)) => (x,y),
                _ => continue,
            };
            match level.get_tile_with_tuple(coord) {
                Ok(f @ &Faction::Faction(_)) => deck.push(f.clone()),
                _ => {},
            }
        }
    }

    fn apply_changes(level: &mut Level<Faction>, delta: Vec<((usize, usize), Faction)>) {
        for ((x, y), f) in delta {
            if let Ok(tile) = level.get_mut_tile(x, y) {
                *tile = f;
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! GdkDevice — Object representing an input device

use glib::translate::*;
use glib::types;
use cursor::Cursor;
use display::Display;
use object::Object;
use screen::Screen;
use window::Window;
use ffi;

pub type Type = ffi::GdkDeviceType;

pub type Device = Object<ffi::GdkDevice>;

impl types::StaticType for Device {
    fn static_type() -> types::Type { unsafe { from_glib(ffi::gdk_device_get_type()) } }
}

impl Device {
    pub fn get_name(&self) -> Option<String> {
        unsafe {
            from_glib_none(ffi::gdk_device_get_name(self.to_glib_none().0))
        }
    }

    pub fn get_source(&self) -> ::InputSource {
        unsafe { ffi::gdk_device_get_source(self.to_glib_none().0) }
    }

    pub fn set_mode(&self, mode: ::InputMode) {
        unsafe { ffi::gdk_device_set_mode(self.to_glib_none().0, mode); }
    }

    pub fn get_mode(&self) -> ::InputMode {
        unsafe { ffi::gdk_device_get_mode(self.to_glib_none().0) }
    }

    pub fn set_key(&self, index_: u32, keyval: u32, modifiers: ::ModifierType) {
        unsafe { ffi::gdk_device_set_key(self.to_glib_none().0, index_, keyval, modifiers) }
    }

    pub fn get_key(&self, index_: u32, keyval: &mut u32, modifiers: &mut ::ModifierType) -> bool {
        unsafe { from_glib(ffi::gdk_device_get_key(self.to_glib_none().0, index_, keyval, modifiers)) }
    }

    pub fn set_axis_use(&self, index_: u32, use_: ::AxisUse) {
        unsafe { ffi::gdk_device_set_axis_use(self.to_glib_none().0, index_, use_) }
    }

    pub fn get_axis_use(&self, index_: u32) -> ::AxisUse {
        unsafe { ffi::gdk_device_get_axis_use(self.to_glib_none().0, index_) }
    }

    pub fn get_associated_device(&self) -> Option<Device> {
        unsafe { from_glib_none(ffi::gdk_device_get_associated_device(self.to_glib_none().0)) }
    }

    pub fn get_device_type(&self) -> Type {
        unsafe { ffi::gdk_device_get_device_type(self.to_glib_none().0) }
    }

    pub fn get_display(&self) -> Display {
        unsafe { from_glib_none(ffi::gdk_device_get_display(self.to_glib_none().0)) }
    }

    pub fn get_has_cursor(&self) -> bool {
        unsafe { from_glib(ffi::gdk_device_get_has_cursor(self.to_glib_none().0)) }
    }

    pub fn get_n_axes(&self) -> i32 {
        unsafe { ffi::gdk_device_get_n_axes(self.to_glib_none().0) }
    }

    pub fn get_n_keys(&self) -> i32 {
        unsafe { ffi::gdk_device_get_n_keys(self.to_glib_none().0) }
    }

    pub fn warp(&self, screen: &Screen, x: i32, y: i32) {
        unsafe { ffi::gdk_device_warp(self.to_glib_none().0, screen.to_glib_none().0, x, y) }
    }

    pub fn grab(&self, window: &Window, grab_ownership: ::GrabOwnership, owner_events: bool,
                event_mask: ::EventMask, cursor: &Cursor, time_: u32) -> ::GrabStatus {
        unsafe {
            ffi::gdk_device_grab(self.to_glib_none().0, window.to_glib_none().0, grab_ownership,
                owner_events.to_glib(), event_mask, cursor.to_glib_none().0, time_)
        }
    }

    pub fn ungrab(&self, time_: u32) {
        unsafe { ffi::gdk_device_ungrab(self.to_glib_none().0, time_) }
    }

    /*pub fn get_state(&self, window: &::Window, axes: &mut [f64], mask: &mut gdk;:ModifierType) {
        unsafe { ffi::gdk_device_get_state(self.to_glib_none().0, window.unwrap_pointer(), axes.as_mut_ptr(), mask) }
    }

    pub fn get_position(&self, x: &mut i32, y: &mut i32) -> Option<::Screen> {
        let mut ptr = ::std::ptr::null_mut();

        unsafe { ffi::gdk_device_get_position(self.to_glib_none().0, &mut ptr, x as *mut c_int, y as *mut c_int) };
        if ptr.is_null() {
            None
        } else {
            Some(::Screen::wrap_pointer(ptr))
        }
    }

    pub fn get_position_double(&self, x: &mut f64, y: &mut f64) -> Option<::Screen> {
        let mut ptr = ::std::ptr::null_mut();

        unsafe { ffi::gdk_device_get_position_double(self.to_glib_none().0, &mut ptr, x as *mut c_double, y as *mut c_double) };
        if ptr.is_null() {
            None
        } else {
            Some(::Screen::wrap_pointer(ptr))
        }
    }

    pub fn get_window_at_position(&self, x: &mut i32, y: &mut i32) -> Option<::Window> {
        let mut ptr = ::std::ptr::null_mut();

        unsafe { ffi::gdk_device_get_window_at_position(self.to_glib_none().0, &mut ptr, x as *mut c_int, y as *mut c_int) };
        if ptr.is_null() {
            None
        } else {
            Some(::Window::wrap_pointer(ptr))
        }
    }

    pub fn get_window_at_position_double(&self, x: &mut f64, y: &mut f64) -> Option<::Window> {
        let mut ptr = ::std::ptr::null_mut();

        unsafe { ffi::gdk_device_get_window_at_position_double(self.to_glib_none().0, &mut ptr, x as *mut c_double, y as *mut c_double) };
        if ptr.is_null() {
            None
        } else {
            Some(::Window::wrap_pointer(ptr))
        }
    }

    pub fn get_history(&self, window: &::Window, start: u32, stop: u32) -> Vec<::TimeCoord> {
        let mut ptr = ::std::ptr::null_mut();
        let mut n_events : c_int = 0;

        unsafe { ffi::gdk_device_get_history(self.to_glib_none().0, window.unwrap_pointer(), start, stop, &mut ptr, &mut n_events) };

        let mut ret = Vec::with_capacity(n_events as uint);

        for i in range(0, n_events) {
            ret.push(::TimeCoord::wrap_pointer(::std::ptr::read(ptr.offset(i))));
        }
        ret
    }

    pub fn free_history(events: &[::TimeCoord]) {
        let mut tmp = Vec::with_capacity(events.len());

        for i in range(0, events.len()) {
            tmp.push(events[i].unwrap_pointer());
        }
        unsafe { ffi::gdk_device_free_history(events.as_mut_ptr(), events.len()) }
    }*/

    pub fn get_axis(&self, axes: &mut [f64], use_: ::AxisUse, value: &mut f64) -> bool {
        unsafe { from_glib(ffi::gdk_device_get_axis(self.to_glib_none().0, axes.as_mut_ptr(), use_, value)) }
    }

    /*pub fn get_axis_value(&self, axes: &mut [f64], label: &mut ::Atom, value: &mut f64) -> bool {
        unsafe { from_glib(ffi::gdk_device_get_axis_value(self.to_glib_none().0, axes.as_mut_ptr(), label.unwrap_pointer(), value)) }
    }*/

    /*pub fn get_last_event_window(&self) -> Option<::Window> {
        let ptr = unsafe { ffi::gdk_device_get_last_event_window(self.to_glib_none().0) };

        if ptr.is_null() {
            None
        } else {
            Some(::Window::wrap_pointer(ptr))
        }
    }*/
}
<commit_msg>Add Device documentation<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! GdkDevice — Object representing an input device

use glib::translate::*;
use glib::types;
use cursor::Cursor;
use display::Display;
use object::Object;
use screen::Screen;
use window::Window;
use ffi;

pub type Type = ffi::GdkDeviceType;

pub type Device = Object<ffi::GdkDevice>;

impl types::StaticType for Device {
    fn static_type() -> types::Type { unsafe { from_glib(ffi::gdk_device_get_type()) } }
}

impl Device {
    /// Determines the name of the device.
    pub fn get_name(&self) -> Option<String> {
        unsafe {
            from_glib_none(ffi::gdk_device_get_name(self.to_glib_none().0))
        }
    }

    /// Returns the vendor ID of this device, or NULL if this information couldn't be obtained. This
    /// ID is retrieved from the device, and is thus constant for it.
    ///
    /// This function, together with gdk_device_get_product_id(), can be used to eg. compose GSettings
    /// paths to store settings for this device.
    ///
    /// ```ignore
    /// fn get_device_settings(device: &Device) -> GSettings {
    ///     GSettings *settings;
    ///     GdkDevice *device;
    ///     gchar *path;
    ///
    ///     let vendor = device.get_vendor_id().unwrap();
    ///     let product = device.get_product_id().unwrap();
    ///
    ///     let path = format!("/org/example/app/devices/{}:{}/", vendor, product);
    ///     g_settings_new_with_path(DEVICE_SCHEMA, path);
    /// }
    /// ```
    #[cfg(feature = "gdk_3_16")]
    pub fn get_vendor_id(&self) -> Option<String> {
        unsafe {
            from_glib_none(ffi::gdk_device_get_vendor_id(self.to_glib_none().0))
        }
    }

    /// Returns the product ID of this device, or None if this information couldn't be obtained. This
    /// ID is retrieved from the device, and is thus constant for it. See Device::get_vendor_id() for
    /// more information.
    #[cfg(feature = "gdk_3_16")]
    pub fn get_vendor_id(&self) -> Option<String> {
        unsafe {
            from_glib_none(ffi::gdk_device_get_vendor_id(self.to_glib_none().0))
        }
    }

    /// Determines the type of the device.
    pub fn get_source(&self) -> ::InputSource {
        unsafe { ffi::gdk_device_get_source(self.to_glib_none().0) }
    }

    /// Sets a the mode of an input device. The mode controls if the device is active and whether the
    /// device’s range is mapped to the entire screen or to a single window.
    ///
    /// Note: This is only meaningful for floating devices, master devices (and slaves connected to
    /// these) drive the pointer cursor, which is not limited by the input mode.
    pub fn set_mode(&self, mode: ::InputMode) {
        unsafe { ffi::gdk_device_set_mode(self.to_glib_none().0, mode); }
    }

    /// Determines the mode of the device.
    pub fn get_mode(&self) -> ::InputMode {
        unsafe { ffi::gdk_device_get_mode(self.to_glib_none().0) }
    }

    /// Specifies the X key event to generate when a macro button of a device is pressed.
    pub fn set_key(&self, index_: u32, keyval: u32, modifiers: ::ModifierType) {
        unsafe { ffi::gdk_device_set_key(self.to_glib_none().0, index_, keyval, modifiers) }
    }

    /// If `index_` has a valid keyval, this function will return true and fill in `keyval` and
    /// `modifiers` with the keyval settings.
    pub fn get_key(&self, index_: u32, keyval: &mut u32, modifiers: &mut ::ModifierType) -> bool {
        unsafe { from_glib(ffi::gdk_device_get_key(self.to_glib_none().0, index_, keyval, modifiers)) }
    }

    /// Specifies how an axis of a device is used.
    pub fn set_axis_use(&self, index_: u32, use_: ::AxisUse) {
        unsafe { ffi::gdk_device_set_axis_use(self.to_glib_none().0, index_, use_) }
    }

    /// Returns the axis use for `index_`.
    pub fn get_axis_use(&self, index_: u32) -> ::AxisUse {
        unsafe { ffi::gdk_device_get_axis_use(self.to_glib_none().0, index_) }
    }

    /// Returns the associated `self` to `self` , if `self` is of type DeviceType::Master, it
    /// will return the paired pointer or keyboard.
    ///
    /// If `self` is of type DeviceType::Slave, it will return the master device to which `self`
    /// is attached to.
    ///
    /// If `self` is of type DeviceType::Floating, None will be returned, as there is no
    /// associated device.
    pub fn get_associated_device(&self) -> Option<Device> {
        unsafe { from_glib_none(ffi::gdk_device_get_associated_device(self.to_glib_none().0)) }
    }

    /// Returns the device type for `self`.
    pub fn get_device_type(&self) -> Type {
        unsafe { ffi::gdk_device_get_device_type(self.to_glib_none().0) }
    }

    /// Returns the Display to which `self` pertains.
    pub fn get_display(&self) -> Display {
        unsafe { from_glib_none(ffi::gdk_device_get_display(self.to_glib_none().0)) }
    }

    /// Determines whether the pointer follows device motion. This is not meaningful for
    /// keyboard devices, which don't have a pointer.
    pub fn get_has_cursor(&self) -> bool {
        unsafe { from_glib(ffi::gdk_device_get_has_cursor(self.to_glib_none().0)) }
    }

    /// Returns the number of axes the device currently has.
    pub fn get_n_axes(&self) -> i32 {
        unsafe { ffi::gdk_device_get_n_axes(self.to_glib_none().0) }
    }

    /// Returns the number of keys the device currently has.
    pub fn get_n_keys(&self) -> i32 {
        unsafe { ffi::gdk_device_get_n_keys(self.to_glib_none().0) }
    }

    /// Warps `self` in display to the point `x`, `y` on the screen `screen`, unless the device
    /// is confined to a window by a grab, in which case it will be moved as far as allowed by
    /// the grab. Warping the pointer creates events as if the user had moved the mouse
    /// instantaneously to the destination.
    ///
    /// Note that the pointer should normally be under the control of the user. This function
    /// was added to cover some rare use cases like keyboard navigation support for the color
    /// picker in the gtk::ColorSelectionDialog.
    pub fn warp(&self, screen: &Screen, x: i32, y: i32) {
        unsafe { ffi::gdk_device_warp(self.to_glib_none().0, screen.to_glib_none().0, x, y) }
    }

    /// Grabs the device so that all events coming from this device are passed to this
    /// application until the device is ungrabbed with Device::ungrab(), or the window becomes
    /// unviewable. This overrides any previous grab on the device by this client.
    ///
    /// Note that `self` and `window` need to be on the same display.
    ///
    /// Device grabs are used for operations which need complete control over the given device
    /// events (either pointer or keyboard). For example in GTK+ this is used for Drag and Drop
    /// operations, popup menus and such.
    ///
    /// Note that if the event mask of an X window has selected both button press and button
    /// release events, then a button press event will cause an automatic pointer grab until
    /// the button is released. X does this automatically since most applications expect to
    /// receive button press and release events in pairs. It is equivalent to a pointer grab
    /// on the window with `owner_events` set to true.
    ///
    /// If you set up anything at the time you take the grab that needs to be cleaned up when
    /// the grab ends, you should handle the GdkEventGrabBroken events that are emitted when
    /// the grab ends unvoluntarily.
    pub fn grab(&self, window: &Window, grab_ownership: ::GrabOwnership, owner_events: bool,
                event_mask: ::EventMask, cursor: &Cursor, time_: u32) -> ::GrabStatus {
        unsafe {
            ffi::gdk_device_grab(self.to_glib_none().0, window.to_glib_none().0, grab_ownership,
                owner_events.to_glib(), event_mask, cursor.to_glib_none().0, time_)
        }
    }

    /// Release any grab on `self`.
    pub fn ungrab(&self, time_: u32) {
        unsafe { ffi::gdk_device_ungrab(self.to_glib_none().0, time_) }
    }

    /*pub fn get_state(&self, window: &::Window, axes: &mut [f64], mask: &mut gdk;:ModifierType) {
        unsafe { ffi::gdk_device_get_state(self.to_glib_none().0, window.unwrap_pointer(), axes.as_mut_ptr(), mask) }
    }

    pub fn get_position(&self, x: &mut i32, y: &mut i32) -> Option<::Screen> {
        let mut ptr = ::std::ptr::null_mut();

        unsafe { ffi::gdk_device_get_position(self.to_glib_none().0, &mut ptr, x as *mut c_int, y as *mut c_int) };
        if ptr.is_null() {
            None
        } else {
            Some(::Screen::wrap_pointer(ptr))
        }
    }

    pub fn get_position_double(&self, x: &mut f64, y: &mut f64) -> Option<::Screen> {
        let mut ptr = ::std::ptr::null_mut();

        unsafe { ffi::gdk_device_get_position_double(self.to_glib_none().0, &mut ptr, x as *mut c_double, y as *mut c_double) };
        if ptr.is_null() {
            None
        } else {
            Some(::Screen::wrap_pointer(ptr))
        }
    }

    pub fn get_window_at_position(&self, x: &mut i32, y: &mut i32) -> Option<::Window> {
        let mut ptr = ::std::ptr::null_mut();

        unsafe { ffi::gdk_device_get_window_at_position(self.to_glib_none().0, &mut ptr, x as *mut c_int, y as *mut c_int) };
        if ptr.is_null() {
            None
        } else {
            Some(::Window::wrap_pointer(ptr))
        }
    }

    pub fn get_window_at_position_double(&self, x: &mut f64, y: &mut f64) -> Option<::Window> {
        let mut ptr = ::std::ptr::null_mut();

        unsafe { ffi::gdk_device_get_window_at_position_double(self.to_glib_none().0, &mut ptr, x as *mut c_double, y as *mut c_double) };
        if ptr.is_null() {
            None
        } else {
            Some(::Window::wrap_pointer(ptr))
        }
    }

    pub fn get_history(&self, window: &::Window, start: u32, stop: u32) -> Vec<::TimeCoord> {
        let mut ptr = ::std::ptr::null_mut();
        let mut n_events : c_int = 0;

        unsafe { ffi::gdk_device_get_history(self.to_glib_none().0, window.unwrap_pointer(), start, stop, &mut ptr, &mut n_events) };

        let mut ret = Vec::with_capacity(n_events as uint);

        for i in range(0, n_events) {
            ret.push(::TimeCoord::wrap_pointer(::std::ptr::read(ptr.offset(i))));
        }
        ret
    }

    pub fn free_history(events: &[::TimeCoord]) {
        let mut tmp = Vec::with_capacity(events.len());

        for i in range(0, events.len()) {
            tmp.push(events[i].unwrap_pointer());
        }
        unsafe { ffi::gdk_device_free_history(events.as_mut_ptr(), events.len()) }
    }*/

    /// Interprets an array of double as axis values for a given device, and locates the value
    /// in the array for a given axis use.
    pub fn get_axis(&self, axes: &mut [f64], use_: ::AxisUse, value: &mut f64) -> bool {
        unsafe { from_glib(ffi::gdk_device_get_axis(self.to_glib_none().0, axes.as_mut_ptr(), use_, value)) }
    }

    /*pub fn get_axis_value(&self, axes: &mut [f64], label: &mut ::Atom, value: &mut f64) -> bool {
        unsafe { from_glib(ffi::gdk_device_get_axis_value(self.to_glib_none().0, axes.as_mut_ptr(), label.unwrap_pointer(), value)) }
    }*/

    /*pub fn get_last_event_window(&self) -> Option<::Window> {
        let ptr = unsafe { ffi::gdk_device_get_last_event_window(self.to_glib_none().0) };

        if ptr.is_null() {
            None
        } else {
            Some(::Window::wrap_pointer(ptr))
        }
    }*/
}
<|endoftext|>