<commit_before>use std::io::{self, Read, Write};

use IntoRawMode;

/// A key.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Key {
    /// Backspace.
    Backspace,
    /// Left arrow.
    Left,
    /// Right arrow.
    Right,
    /// Up arrow.
    Up,
    /// Down arrow.
    Down,
    /// Normal character.
    Char(char),
    /// Alt modified character.
    Alt(char),
    /// Ctrl modified character.
    ///
    /// Note that certain keys may not be modifiable with `ctrl`, due to limitations of terminals.
    Ctrl(char),
    /// Invalid character code.
    Invalid,
    /// Null byte.
    Null,

    #[allow(missing_docs)]
    #[doc(hidden)]
    __IsNotComplete
}

/// An iterator over input keys.
#[cfg(feature = "nightly")]
pub struct Keys<I> {
    chars: I,
}

#[cfg(feature = "nightly")]
impl<I: Iterator<Item = Result<char, io::CharsError>>> Iterator for Keys<I> {
    type Item = Result<Key, io::CharsError>;

    fn next(&mut self) -> Option<Result<Key, io::CharsError>> {
        Some(match self.chars.next() {
            Some(Ok('\x1B')) => Ok(match self.chars.next() {
                Some(Ok('[')) => match self.chars.next() {
                    Some(Ok('D')) => Key::Left,
                    Some(Ok('C')) => Key::Right,
                    Some(Ok('A')) => Key::Up,
                    Some(Ok('B')) => Key::Down,
                    _ => Key::Invalid,
                },
                Some(Ok(c)) => Key::Alt(c),
                Some(Err(_)) | None => Key::Invalid,
            }),
            Some(Ok('\n')) | Some(Ok('\r')) => Ok(Key::Char('\n')),
            Some(Ok('\t')) => Ok(Key::Char('\t')),
            Some(Ok('\x7F')) => Ok(Key::Backspace),
            Some(Ok(c @ '\x01' ... '\x1A')) => Ok(Key::Ctrl((c as u8 - 0x1  + b'a') as char)),
            Some(Ok(c @ '\x1C' ... '\x1F')) => Ok(Key::Ctrl((c as u8 - 0x1C + b'4') as char)),
            Some(Ok('\0')) => Ok(Key::Null),
            Some(Ok(c)) => Ok(Key::Char(c)),
            Some(Err(e)) => Err(e),
            None => return None,
        })
    }
}

/// Extension to `Read` trait.
pub trait TermRead {
    /// An iterator over key inputs.
    #[cfg(feature = "nightly")]
    fn keys(self) -> Keys<io::Chars<Self>> where Self: Sized;

    /// Read a line.
    ///
    /// EOT and ETX will abort the prompt, returning `None`. Newline or carriage return will
    /// complete the input.
    fn read_line(&mut self) -> io::Result<Option<String>>;

    /// Read a password.
    ///
    /// EOT and ETX will abort the prompt, returning `None`. Newline or carriage return will
    /// complete the input.
    fn read_passwd<W: Write>(&mut self, writer: &mut W) -> io::Result<Option<String>> {
        let _raw = try!(writer.into_raw_mode());
        self.read_line()
    }
}

impl<R: Read> TermRead for R {
    #[cfg(feature = "nightly")]
    fn keys(self) -> Keys<io::Chars<R>> {
        Keys {
            chars: self.chars(),
        }
    }

    fn read_line(&mut self) -> io::Result<Option<String>> {
        let mut buf = Vec::with_capacity(30);

        for c in self.bytes() {
            match c {
                Err(e) => return Err(e),
                Ok(0) | Ok(3) | Ok(4) => return Ok(None),
                Ok(0x7f) => { buf.pop(); },
                Ok(b'\n') | Ok(b'\r') => break,
                Ok(c) => buf.push(c),
            }
        }

        let string = try!(String::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)));
        Ok(Some(string))
    }
}

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

    #[cfg(feature = "nightly")]
    #[test]
    fn test_keys() {
        let mut i = b"\x1Bayo\x7F\x1B[D".keys();

        assert_eq!(i.next().unwrap().unwrap(), Key::Alt('a'));
        assert_eq!(i.next().unwrap().unwrap(), Key::Char('y'));
        assert_eq!(i.next().unwrap().unwrap(), Key::Char('o'));
        assert_eq!(i.next().unwrap().unwrap(), Key::Backspace);
        assert_eq!(i.next().unwrap().unwrap(), Key::Left);
        assert!(i.next().is_none());
    }

    fn line_match(a: &str, b: Option<&str>) {
        let mut sink = io::sink();

        let line = a.as_bytes().read_line().unwrap();
        let pass = a.as_bytes().read_passwd(&mut sink).unwrap();

        // godammit rustc

        assert_eq!(line, pass);

        if let Some(l) = line {
            assert_eq!(Some(l.as_str()), b);
        } else {
            assert!(b.is_none());
        }
    }

    #[test]
    fn test_read() {
        let test1 = "this is the first test";
        let test2 = "this is the second test";

        line_match(test1, Some(test1));
        line_match(test2, Some(test2));
    }

    #[test]
    fn test_backspace() {
        line_match("this is the\x7f first\x7f\x7f test", Some("this is th fir test"));
        line_match("this is the seco\x7fnd test\x7f", Some("this is the secnd tes"));
    }

    #[test]
    fn test_end() {
        line_match("abc\nhttps://www.youtube.com/watch?v=dQw4w9WgXcQ", Some("abc"));
        line_match("hello\rhttps://www.youtube.com/watch?v=yPYZpwSpKmA", Some("hello"));
    }

    #[test]
    fn test_abort() {
        line_match("abc\x03https://www.youtube.com/watch?v=dQw4w9WgXcQ", None);
        line_match("hello\x04https://www.youtube.com/watch?v=yPYZpwSpKmA", None);
    }
}
<commit_msg>added more special keys<commit_after>use std::io::{self, Read, Write};

use IntoRawMode;

/// A key.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Key {
    /// Backspace.
    Backspace,
    /// Left arrow.
    Left,
    /// Right arrow.
    Right,
    /// Up arrow.
    Up,
    /// Down arrow.
    Down,
    /// Home key.
    Home,
    /// End key.
    End,
    /// Page Up key.
    PageUp,
    /// Page Down key.
    PageDown,
    /// Delete key.
    Delete,
    /// Insert key.
    Insert,
    /// Function keys.
    F(u8),
    /// Normal character.
    Char(char),
    /// Alt modified character.
    Alt(char),
    /// Ctrl modified character.
    ///
    /// Note that certain keys may not be modifiable with `ctrl`, due to limitations of terminals.
    Ctrl(char),
    /// Invalid character code.
    Invalid,
    /// Null byte.
    Null,

    #[allow(missing_docs)]
    #[doc(hidden)]
    __IsNotComplete
}

/// An iterator over input keys.
#[cfg(feature = "nightly")]
pub struct Keys<I> {
    chars: I,
}

#[cfg(feature = "nightly")]
impl<I: Iterator<Item = Result<char, io::CharsError>>> Iterator for Keys<I> {
    type Item = Result<Key, io::CharsError>;

    fn next(&mut self) -> Option<Result<Key, io::CharsError>> {
        Some(match self.chars.next() {
            Some(Ok('\x1B')) => Ok(match self.chars.next() {
                Some(Ok('O')) => match self.chars.next() {
                    Some(Ok('P')) => Key::F(1),
                    Some(Ok('Q')) => Key::F(2),
                    Some(Ok('R')) => Key::F(3),
                    Some(Ok('S')) => Key::F(4),
                    _ => Key::Invalid,
                },
                Some(Ok('[')) => match self.chars.next() {
                    Some(Ok('D')) => Key::Left,
                    Some(Ok('C')) => Key::Right,
                    Some(Ok('A')) => Key::Up,
                    Some(Ok('B')) => Key::Down,
                    Some(Ok('H')) => Key::Home,
                    Some(Ok('F')) => Key::End,
                    Some(Ok(c @ '1' ... '6')) => match self.chars.next() {
                        Some(Ok('~')) => match c {
                            '1' => Key::Home,
                            '2' => Key::Insert,
                            '3' => Key::Delete,
                            '4' => Key::End,
                            '5' => Key::PageUp,
                            '6' => Key::PageDown,
                            _ => Key::Invalid,
                        },
                        Some(Ok(k @ '0' ... '9')) => match self.chars.next() {
                            Some(Ok('~')) => match (c, k) {
                                ('1', '1') => Key::F(1),
                                ('1', '2') => Key::F(2),
                                ('1', '3') => Key::F(3),
                                ('1', '4') => Key::F(4),
                                ('1', '5') => Key::F(5),
                                ('1', '7') => Key::F(6),
                                ('1', '8') => Key::F(7),
                                ('1', '9') => Key::F(8),
                                ('2', '0') => Key::F(9),
                                ('2', '1') => Key::F(10),
                                ('2', '3') => Key::F(11),
                                ('2', '4') => Key::F(12),
                                _ => Key::Invalid,
                            },
                            _ => Key::Invalid,
                        },
                        _ => Key::Invalid,
                    },
                    _ => Key::Invalid,
                },
                Some(Ok(c)) => Key::Alt(c),
                Some(Err(_)) | None => Key::Invalid,
            }),
            Some(Ok('\n')) | Some(Ok('\r')) => Ok(Key::Char('\n')),
            Some(Ok('\t')) => Ok(Key::Char('\t')),
            Some(Ok('\x7F')) => Ok(Key::Backspace),
            Some(Ok(c @ '\x01' ... '\x1A')) => Ok(Key::Ctrl((c as u8 - 0x1  + b'a') as char)),
            Some(Ok(c @ '\x1C' ... '\x1F')) => Ok(Key::Ctrl((c as u8 - 0x1C + b'4') as char)),
            Some(Ok('\0')) => Ok(Key::Null),
            Some(Ok(c)) => Ok(Key::Char(c)),
            Some(Err(e)) => Err(e),
            None => return None,
        })
    }
}

/// Extension to `Read` trait.
pub trait TermRead {
    /// An iterator over key inputs.
    #[cfg(feature = "nightly")]
    fn keys(self) -> Keys<io::Chars<Self>> where Self: Sized;

    /// Read a line.
    ///
    /// EOT and ETX will abort the prompt, returning `None`. Newline or carriage return will
    /// complete the input.
    fn read_line(&mut self) -> io::Result<Option<String>>;

    /// Read a password.
    ///
    /// EOT and ETX will abort the prompt, returning `None`. Newline or carriage return will
    /// complete the input.
    fn read_passwd<W: Write>(&mut self, writer: &mut W) -> io::Result<Option<String>> {
        let _raw = try!(writer.into_raw_mode());
        self.read_line()
    }
}

impl<R: Read> TermRead for R {
    #[cfg(feature = "nightly")]
    fn keys(self) -> Keys<io::Chars<R>> {
        Keys {
            chars: self.chars(),
        }
    }

    fn read_line(&mut self) -> io::Result<Option<String>> {
        let mut buf = Vec::with_capacity(30);

        for c in self.bytes() {
            match c {
                Err(e) => return Err(e),
                Ok(0) | Ok(3) | Ok(4) => return Ok(None),
                Ok(0x7f) => { buf.pop(); },
                Ok(b'\n') | Ok(b'\r') => break,
                Ok(c) => buf.push(c),
            }
        }

        let string = try!(String::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)));
        Ok(Some(string))
    }
}

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

    #[cfg(feature = "nightly")]
    #[test]
    fn test_keys() {
        let mut i = b"\x1Bayo\x7F\x1B[D".keys();

        assert_eq!(i.next().unwrap().unwrap(), Key::Alt('a'));
        assert_eq!(i.next().unwrap().unwrap(), Key::Char('y'));
        assert_eq!(i.next().unwrap().unwrap(), Key::Char('o'));
        assert_eq!(i.next().unwrap().unwrap(), Key::Backspace);
        assert_eq!(i.next().unwrap().unwrap(), Key::Left);
        assert!(i.next().is_none());
    }

    fn line_match(a: &str, b: Option<&str>) {
        let mut sink = io::sink();

        let line = a.as_bytes().read_line().unwrap();
        let pass = a.as_bytes().read_passwd(&mut sink).unwrap();

        // godammit rustc

        assert_eq!(line, pass);

        if let Some(l) = line {
            assert_eq!(Some(l.as_str()), b);
        } else {
            assert!(b.is_none());
        }
    }

    #[test]
    fn test_read() {
        let test1 = "this is the first test";
        let test2 = "this is the second test";

        line_match(test1, Some(test1));
        line_match(test2, Some(test2));
    }

    #[test]
    fn test_backspace() {
        line_match("this is the\x7f first\x7f\x7f test", Some("this is th fir test"));
        line_match("this is the seco\x7fnd test\x7f", Some("this is the secnd tes"));
    }

    #[test]
    fn test_end() {
        line_match("abc\nhttps://www.youtube.com/watch?v=dQw4w9WgXcQ", Some("abc"));
        line_match("hello\rhttps://www.youtube.com/watch?v=yPYZpwSpKmA", Some("hello"));
    }

    #[test]
    fn test_abort() {
        line_match("abc\x03https://www.youtube.com/watch?v=dQw4w9WgXcQ", None);
        line_match("hello\x04https://www.youtube.com/watch?v=yPYZpwSpKmA", None);
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use {KeyboardControllable, Key, MouseControllable, MouseButton};

use self::libc::{c_ulong, c_int, c_char, c_void};
use std::borrow::Cow;
use std::ffi::CString;
use std::ptr;

const CURRENT_WINDOW: c_int = 0;
type Window  = c_int;
type Xdo     = *const c_void;

#[link(name = "xdo")]
extern "C" {
    fn xdo_free(xdo: Xdo);
    fn xdo_new(display: *const c_char) -> Xdo;

    fn xdo_click_window(xdo: Xdo, window: Window, button: c_int) -> c_int;
    fn xdo_mouse_down(xdo: Xdo, window: Window, button: c_int) -> c_int;
    fn xdo_mouse_up(xdo: Xdo, window: Window, button: c_int) -> c_int;
    fn xdo_move_mouse(xdo: Xdo, x: c_int, y: c_int, screen: c_int) -> c_int;
    fn xdo_move_mouse_relative(xdo: Xdo, x: c_int, y: c_int) -> c_int;

    fn xdo_enter_text_window(xdo: Xdo, window: Window, string: *const c_char, delay: c_ulong);
    fn xdo_send_keysequence_window(xdo: Xdo, window: Window, string: *const c_char, delay: c_ulong);
    fn xdo_send_keysequence_window_down(xdo: Xdo, window: Window, string: *const c_char, delay: c_ulong);
    fn xdo_send_keysequence_window_up(xdo: Xdo, window: Window, string: *const c_char, delay: c_ulong);
}

fn mousebutton(button: MouseButton) -> i32 {
    match button {
        MouseButton::Left => 1,
        MouseButton::Middle => 2,
        MouseButton::Right => 3,
        MouseButton::ScrollUp => 4,
        MouseButton::ScrollDown => 5,
        MouseButton::ScrollLeft => 6,
        MouseButton::ScrollRight => 7
    }
}

/// The main struct for handling the event emitting
pub struct Enigo {
    xdo: Xdo
}
impl Enigo {
    /// Create a new Enigo instance
    pub fn new() -> Enigo {
        Enigo {
            xdo: unsafe { xdo_new(ptr::null()) }
        }
    }
}
impl Drop for Enigo {
    fn drop(&mut self) {
        unsafe {
            xdo_free(self.xdo);
        }
    }
}
impl MouseControllable for Enigo {
    fn mouse_move_to(&mut self, x: i32, y: i32) {
        unsafe {
            xdo_move_mouse(self.xdo, x, y, 0);
        }
    }
    fn mouse_move_relative(&mut self, x: i32, y: i32) {
        unsafe {
            xdo_move_mouse_relative(self.xdo, x, y);
        }
    }
    fn mouse_down(&mut self, button: MouseButton) {
        unsafe {
            xdo_mouse_down(self.xdo, CURRENT_WINDOW, mousebutton(button));
        }
    }
    fn mouse_up(&mut self, button: MouseButton) {
        unsafe {
            xdo_mouse_up(self.xdo, CURRENT_WINDOW, mousebutton(button));
        }
    }
    fn mouse_click(&mut self, button: MouseButton) {
        unsafe {
            xdo_click_window(self.xdo, CURRENT_WINDOW, mousebutton(button));
        }
    }
    fn mouse_scroll_x(&mut self, length: i32) {
        let button;
        let mut length = length;

        if length < 0 {
            button = MouseButton::ScrollLeft;
        } else {
            button = MouseButton::ScrollRight;
        }

        if length < 0 {
            length = -length;
        }

        for _ in 0..length {
            self.mouse_click(button);
        }
    }
    fn mouse_scroll_y(&mut self, length: i32) {
        let button;
        let mut length = length;

        if length < 0 {
            button = MouseButton::ScrollUp;
        } else {
            button = MouseButton::ScrollDown;
        }

        if length < 0 {
            length = -length;
        }

        for _ in 0..length {
            self.mouse_click(button);
        }
    }
}
fn keysequence<'a>(key: Key) -> Cow<'a, str> {
    if let Key::Layout(c) = key {
        return Cow::from(c.to_string());
    }
    Cow::from(match key {
        Key::Alt => "Alt",
        Key::Backspace => "Backspace",
        Key::CapsLock => "CapsLock",
        Key::Command => "Command",
        Key::Control => "Control",
        Key::DownArrow => "DownArrow",
        Key::Escape => "Escape",
        Key::F1 => "F1",
        Key::F2 => "F2",
        Key::F3 => "F3",
        Key::F4 => "F4",
        Key::F5 => "F5",
        Key::F6 => "F6",
        Key::F7 => "F7",
        Key::F8 => "F8",
        Key::F9 => "F9",
        Key::F10 => "F10",
        Key::F11 => "F11",
        Key::F12 => "F12",
        Key::Home => "Home",
        Key::Layout(_) => unreachable!(),
        Key::LeftArrow => "Left",
        Key::Option => "Option",
        Key::PageDown => "PageDown",
        Key::PageUp => "PageUp",
        Key::Raw(_) => unimplemented!(),
        Key::Return => "Return",
        Key::RightArrow => "Right",
        Key::Shift => "Shift",
        Key::Space => "Space",
        Key::Super => "Super",
        Key::Tab => "Tab",
        Key::UpArrow => "Up",
        Key::Windows => "Windows"
    })
}
impl KeyboardControllable for Enigo {
    fn key_sequence(&mut self, sequence: &str) {
        let string = CString::new(sequence).unwrap();
        unsafe {
            xdo_enter_text_window(self.xdo, CURRENT_WINDOW, string.as_ptr(), 0);
        }
    }
    fn key_down(&mut self, key: Key) {
        let string = CString::new(&*keysequence(key)).unwrap();
        unsafe {
            xdo_send_keysequence_window_down(self.xdo, CURRENT_WINDOW, string.as_ptr(), 0);
        }
    }
    fn key_up(&mut self, key: Key) {
        let string = CString::new(&*keysequence(key)).unwrap();
        unsafe {
            xdo_send_keysequence_window_up(self.xdo, CURRENT_WINDOW, string.as_ptr(), 0);
        }
    }
    fn key_click(&mut self, key: Key) {
        let string = CString::new(&*keysequence(key)).unwrap();
        unsafe {
            xdo_send_keysequence_window(self.xdo, CURRENT_WINDOW, string.as_ptr(), 0);
        }
    }
}
<commit_msg>Change delay (for now)<commit_after>extern crate libc;

use {KeyboardControllable, Key, MouseControllable, MouseButton};

use self::libc::{c_ulong, c_int, c_char, c_void};
use std::borrow::Cow;
use std::ffi::CString;
use std::ptr;

const CURRENT_WINDOW: c_int = 0;
type Window  = c_int;
type Xdo     = *const c_void;

#[link(name = "xdo")]
extern "C" {
    fn xdo_free(xdo: Xdo);
    fn xdo_new(display: *const c_char) -> Xdo;

    fn xdo_click_window(xdo: Xdo, window: Window, button: c_int) -> c_int;
    fn xdo_mouse_down(xdo: Xdo, window: Window, button: c_int) -> c_int;
    fn xdo_mouse_up(xdo: Xdo, window: Window, button: c_int) -> c_int;
    fn xdo_move_mouse(xdo: Xdo, x: c_int, y: c_int, screen: c_int) -> c_int;
    fn xdo_move_mouse_relative(xdo: Xdo, x: c_int, y: c_int) -> c_int;

    fn xdo_enter_text_window(xdo: Xdo, window: Window, string: *const c_char, delay: c_ulong);
    fn xdo_send_keysequence_window(xdo: Xdo, window: Window, string: *const c_char, delay: c_ulong);
    fn xdo_send_keysequence_window_down(xdo: Xdo, window: Window, string: *const c_char, delay: c_ulong);
    fn xdo_send_keysequence_window_up(xdo: Xdo, window: Window, string: *const c_char, delay: c_ulong);
}

fn mousebutton(button: MouseButton) -> i32 {
    match button {
        MouseButton::Left => 1,
        MouseButton::Middle => 2,
        MouseButton::Right => 3,
        MouseButton::ScrollUp => 4,
        MouseButton::ScrollDown => 5,
        MouseButton::ScrollLeft => 6,
        MouseButton::ScrollRight => 7
    }
}

/// The main struct for handling the event emitting
pub struct Enigo {
    xdo: Xdo
}
impl Enigo {
    /// Create a new Enigo instance
    pub fn new() -> Enigo {
        Enigo {
            xdo: unsafe { xdo_new(ptr::null()) }
        }
    }
}
impl Drop for Enigo {
    fn drop(&mut self) {
        unsafe {
            xdo_free(self.xdo);
        }
    }
}
impl MouseControllable for Enigo {
    fn mouse_move_to(&mut self, x: i32, y: i32) {
        unsafe {
            xdo_move_mouse(self.xdo, x, y, 0);
        }
    }
    fn mouse_move_relative(&mut self, x: i32, y: i32) {
        unsafe {
            xdo_move_mouse_relative(self.xdo, x, y);
        }
    }
    fn mouse_down(&mut self, button: MouseButton) {
        unsafe {
            xdo_mouse_down(self.xdo, CURRENT_WINDOW, mousebutton(button));
        }
    }
    fn mouse_up(&mut self, button: MouseButton) {
        unsafe {
            xdo_mouse_up(self.xdo, CURRENT_WINDOW, mousebutton(button));
        }
    }
    fn mouse_click(&mut self, button: MouseButton) {
        unsafe {
            xdo_click_window(self.xdo, CURRENT_WINDOW, mousebutton(button));
        }
    }
    fn mouse_scroll_x(&mut self, length: i32) {
        let button;
        let mut length = length;

        if length < 0 {
            button = MouseButton::ScrollLeft;
        } else {
            button = MouseButton::ScrollRight;
        }

        if length < 0 {
            length = -length;
        }

        for _ in 0..length {
            self.mouse_click(button);
        }
    }
    fn mouse_scroll_y(&mut self, length: i32) {
        let button;
        let mut length = length;

        if length < 0 {
            button = MouseButton::ScrollUp;
        } else {
            button = MouseButton::ScrollDown;
        }

        if length < 0 {
            length = -length;
        }

        for _ in 0..length {
            self.mouse_click(button);
        }
    }
}
fn keysequence<'a>(key: Key) -> Cow<'a, str> {
    if let Key::Layout(c) = key {
        return Cow::from(c.to_string());
    }
    Cow::from(match key {
        Key::Alt => "Alt",
        Key::Backspace => "Backspace",
        Key::CapsLock => "CapsLock",
        Key::Command => "Command",
        Key::Control => "Control",
        Key::DownArrow => "DownArrow",
        Key::Escape => "Escape",
        Key::F1 => "F1",
        Key::F2 => "F2",
        Key::F3 => "F3",
        Key::F4 => "F4",
        Key::F5 => "F5",
        Key::F6 => "F6",
        Key::F7 => "F7",
        Key::F8 => "F8",
        Key::F9 => "F9",
        Key::F10 => "F10",
        Key::F11 => "F11",
        Key::F12 => "F12",
        Key::Home => "Home",
        Key::Layout(_) => unreachable!(),
        Key::LeftArrow => "Left",
        Key::Option => "Option",
        Key::PageDown => "PageDown",
        Key::PageUp => "PageUp",
        Key::Raw(_) => unimplemented!(),
        Key::Return => "Return",
        Key::RightArrow => "Right",
        Key::Shift => "Shift",
        Key::Space => "Space",
        Key::Super => "Super",
        Key::Tab => "Tab",
        Key::UpArrow => "Up",
        Key::Windows => "Windows"
    })
}
impl KeyboardControllable for Enigo {
    fn key_sequence(&mut self, sequence: &str) {
        let string = CString::new(sequence).unwrap();
        unsafe {
            xdo_enter_text_window(self.xdo, CURRENT_WINDOW, string.as_ptr(), 12000);
        }
    }
    fn key_down(&mut self, key: Key) {
        let string = CString::new(&*keysequence(key)).unwrap();
        unsafe {
            xdo_send_keysequence_window_down(self.xdo, CURRENT_WINDOW, string.as_ptr(), 12000);
        }
    }
    fn key_up(&mut self, key: Key) {
        let string = CString::new(&*keysequence(key)).unwrap();
        unsafe {
            xdo_send_keysequence_window_up(self.xdo, CURRENT_WINDOW, string.as_ptr(), 12000);
        }
    }
    fn key_click(&mut self, key: Key) {
        let string = CString::new(&*keysequence(key)).unwrap();
        unsafe {
            xdo_send_keysequence_window(self.xdo, CURRENT_WINDOW, string.as_ptr(), 12000);
        }
    }
}
<|endoftext|>


<commit_before>use var::Var;
use parse::{IR, Def};
use eval::Eval;

/// Expect Types for Composites
#[derive(Debug,PartialEq)]
pub enum Expect {
    All,
    Any,
    None,

    /// References env variable
    Ref(String)  // NOTE: may be renamed to Sym
}

impl Expect {
    pub fn parse(s: String) -> Expect {
        match &s[..] {
            "all" => Expect::All,
            "any" => Expect::Any,
            "none" => Expect::None,
            _ => Expect::Ref(s),
        }
    }
}

/// Logic Variants
///
/// These are each to be delimited by a new line
/// Always should resolve to boolean
#[derive(Debug,PartialEq)]
pub enum Logic {
    /// Greater Than, eg: weight > 1
    GT(Var,Var),
    /// Lesser Than
    LT(Var,Var),

    /// Boolean: True
    Is(String),
    /// Boolean: False
    IsNot(String),
}

pub struct LogicFn(Box<Fn(&Def) -> Option<bool>>);

// NOTE: we don't actually impl this, but satisfy checker
impl PartialEq for LogicFn {
    fn eq(&self, _other: &LogicFn) -> bool {
        false
    }
}

use std::fmt;
// NOTE: we don't actually impl this, but satisfy checker
impl fmt::Debug for LogicFn {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,"")
    }
}

impl Logic {
    pub fn parse(mut exp: Vec<IR>) -> Result<Logic,&'static str> {
        let len = exp.len();

        if len == 1 {
            let mut exp: String = exp.pop().unwrap().into();
            let inv = exp.remove(0);
            if inv == '!' {
                Ok(Logic::IsNot(exp))
            }
            else {
                exp.insert(0,inv);
                Ok(Logic::Is(exp))
            }
        }
        else if len == 3 {
            let var = exp.pop().unwrap();
            let var = try!(Var::parse(var));

            let sym: String = exp.pop().unwrap().into();
            let key = exp.pop().unwrap();
            let key = try!(Var::parse(key));

            if sym == ">" {
                Ok(Logic::GT(key,var))
            }
            else if sym == "<" {
                Ok(Logic::LT(key,var))
            }
            else { Err("Invalid Logic Syntax") }
        }
        else { Err("Unbalanced Logic Syntax") }
    }

    /// Evaluate Logic into Functions
    pub fn eval (&self) -> LogicFn {
        //eg: let lfn: Box<LogicFn<D>> = Box::new(|| { Some(false) });

        match self {
            &Logic::Is(ref lookup) => {
                let lookup = lookup.clone();
                let lfn = Box::new(move |data: &Def| {
                    if let Some(r) = data.get_path(&lookup) {
                        match r {
                            Var::Bool(v) => {
                                 Some(v)
                            },
                            _ => { //if exists?
                                Some(true)
                            },
                        }
                    }
                    else { None }
                });

                LogicFn(lfn)
            },
            &Logic::IsNot(ref lookup) => { //inverse state
                let lookup = lookup.clone();
                let lfn = Box::new(move |data: &Def| {
                    if let Some(r) = data.get_path(&lookup) {
                        match r {
                            Var::Bool(v) => {
                                Some(!v)
                            },
                            _ => {
                                Some(false)
                            },
                        }
                    }
                    else { None }
                });

                LogicFn(lfn)
            },

            &Logic::GT(ref left, ref right) => {
                let left = left.clone();
                let right = right.clone();
                let lfn = Box::new(move |data: &Def| {
                    let right = Var::get_num::<Def>(&right,data);
                    let left = Var::get_num::<Def>(&left,data);

                    if left.is_ok() && right.is_ok() {
                        Some(left.unwrap() > right.unwrap())
                    }
                    else { None }
                });

                LogicFn(lfn)
            },
            &Logic::LT(ref left, ref right) => {
                let left = left.clone();
                let right = right.clone();
                let lfn = Box::new(move |data: &Def| {
                    let right = Var::get_num::<Def>(&right,data);
                    let left = Var::get_num::<Def>(&left,data);

                    if left.is_ok() && right.is_ok() {
                        Some(left.unwrap() < right.unwrap())
                    }
                    else { None }
                });

                LogicFn(lfn)
            },
        }

    }
}
<commit_msg>remove eg<commit_after>use var::Var;
use parse::{IR, Def};
use eval::Eval;

/// Expect Types for Composites
#[derive(Debug,PartialEq)]
pub enum Expect {
    All,
    Any,
    None,

    /// References env variable
    Ref(String)  // NOTE: may be renamed to Sym
}

impl Expect {
    pub fn parse(s: String) -> Expect {
        match &s[..] {
            "all" => Expect::All,
            "any" => Expect::Any,
            "none" => Expect::None,
            _ => Expect::Ref(s),
        }
    }
}

/// Logic Variants
///
/// These are each to be delimited by a new line
/// Always should resolve to boolean
#[derive(Debug,PartialEq)]
pub enum Logic {
    /// Greater Than, eg: weight > 1
    GT(Var,Var),
    /// Lesser Than
    LT(Var,Var),

    /// Boolean: True
    Is(String),
    /// Boolean: False
    IsNot(String),
}

pub struct LogicFn(Box<Fn(&Def) -> Option<bool>>);

// NOTE: we don't actually impl this, but satisfy checker
impl PartialEq for LogicFn {
    fn eq(&self, _other: &LogicFn) -> bool {
        false
    }
}

use std::fmt;
// NOTE: we don't actually impl this, but satisfy checker
impl fmt::Debug for LogicFn {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,"")
    }
}

impl Logic {
    pub fn parse(mut exp: Vec<IR>) -> Result<Logic,&'static str> {
        let len = exp.len();

        if len == 1 {
            let mut exp: String = exp.pop().unwrap().into();
            let inv = exp.remove(0);
            if inv == '!' {
                Ok(Logic::IsNot(exp))
            }
            else {
                exp.insert(0,inv);
                Ok(Logic::Is(exp))
            }
        }
        else if len == 3 {
            let var = exp.pop().unwrap();
            let var = try!(Var::parse(var));

            let sym: String = exp.pop().unwrap().into();
            let key = exp.pop().unwrap();
            let key = try!(Var::parse(key));

            if sym == ">" {
                Ok(Logic::GT(key,var))
            }
            else if sym == "<" {
                Ok(Logic::LT(key,var))
            }
            else { Err("Invalid Logic Syntax") }
        }
        else { Err("Unbalanced Logic Syntax") }
    }

    /// Evaluate Logic into Functions
    pub fn eval (&self) -> LogicFn {
        match self {
            &Logic::Is(ref lookup) => {
                let lookup = lookup.clone();
                let lfn = Box::new(move |data: &Def| {
                    if let Some(r) = data.get_path(&lookup) {
                        match r {
                            Var::Bool(v) => {
                                 Some(v)
                            },
                            _ => { //if exists?
                                Some(true)
                            },
                        }
                    }
                    else { None }
                });

                LogicFn(lfn)
            },
            &Logic::IsNot(ref lookup) => { //inverse state
                let lookup = lookup.clone();
                let lfn = Box::new(move |data: &Def| {
                    if let Some(r) = data.get_path(&lookup) {
                        match r {
                            Var::Bool(v) => {
                                Some(!v)
                            },
                            _ => {
                                Some(false)
                            },
                        }
                    }
                    else { None }
                });

                LogicFn(lfn)
            },

            &Logic::GT(ref left, ref right) => {
                let left = left.clone();
                let right = right.clone();
                let lfn = Box::new(move |data: &Def| {
                    let right = Var::get_num::<Def>(&right,data);
                    let left = Var::get_num::<Def>(&left,data);

                    if left.is_ok() && right.is_ok() {
                        Some(left.unwrap() > right.unwrap())
                    }
                    else { None }
                });

                LogicFn(lfn)
            },
            &Logic::LT(ref left, ref right) => {
                let left = left.clone();
                let right = right.clone();
                let lfn = Box::new(move |data: &Def| {
                    let right = Var::get_num::<Def>(&right,data);
                    let left = Var::get_num::<Def>(&left,data);

                    if left.is_ok() && right.is_ok() {
                        Some(left.unwrap() < right.unwrap())
                    }
                    else { None }
                });

                LogicFn(lfn)
            },
        }

    }
}
<|endoftext|>


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

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Ben Hirsch <benhirsch24@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate collections;

use collections::string::String;
use std::io::File;

#[deriving(Show)]
enum Radix { Decimal, Hexadecimal, Octal, Binary }

pub fn uumain(args: Vec<String>) -> isize {
    let opts = [
        getopts::optopt("A", "address-radix",
                        "Select the base in which file offsets are printed.", "RADIX"),
        getopts::optopt("j", "skip-bytes",
                        "Skip bytes input bytes before formatting and writing.", "BYTES"),
        getopts::optopt("N", "read-bytes",
                        "limit dump to BYTES input bytes", "BYTES"),
        getopts::optopt("S", "strings",
                        ("output strings of at least BYTES graphic chars. 3 is assumed when \
                          BYTES is not specified."),
                        "BYTES"),
        getopts::optopt("t", "format", "select output format or formats", "TYPE"),
        getopts::optflag("v", "output-duplicates", "do not use * to mark line suppression"),
        getopts::optopt("w", "width",
                        ("output BYTES bytes per output line. 32 is implied when BYTES is not \
                          specified."),
                        "BYTES"),
        getopts::optflag("h", "help", "display this help and exit."),
        getopts::optflag("v", "version", "output version information and exit."),
        ];

    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => panic!("Invalid options\n{}", f)
    };

    let mut rad = Radix::Octal;
    if matches.opt_present("A") {
        rad = parse_radix(matches.opt_str("A"));
    } else {
        println!("{}", getopts::usage("od", &opts));
    }

    let mut fname;
    match args.last() {
        Some(n) => fname = n,
        None    => { panic!("Need fname for now") ; }
    };

    main(rad, fname.clone());

    0
}

fn main(radix: Radix, fname: String) {
    let mut f = match File::open(&Path::new(fname)) {
        Ok(f) => f,
        Err(e) => panic!("file error: {}", e)
    };

    let mut addr = 0;
    let bytes = &mut [b'\x00'; 16];
    loop {
        match f.read(bytes) {
            Ok(n) => {
                print!("{:07o}", addr);
                match radix {
                    Radix::Decimal => {
                    },
                    Radix::Octal => {
                        for b in range(0, n/std::u16::BYTES) {
                            let bs = bytes.slice(2*b, 2*b+2);
                            let p: u16 = (bs[1] as u16) << 8 | bs[0] as u16;
                            print!(" {:06o}", p);
                        }
                        if n % std::u16::BYTES == 1 {
                            print!(" {:06o}", bytes[n-1]);
                        }
                    }
                    _ => { }
                };
                print!("\n");
                addr += n;
            },
            Err(_) => { println!("{:07o}", addr); break; }
        };
    };
}

fn parse_radix(radix_str: Option<String>) -> Radix {
    let rad = match radix_str {
        Some(s) => {
            let st = s.into_bytes();
            if st.len() != 1 {
                panic!("Radix must be one of [d, o, b, x]\n");
            }

            let radix: char = *(st.get(0)
                                .expect("byte string of length 1 lacks a 0th elem")) as char;
            if radix == 'd' {
                Radix::Decimal
            } else if radix == 'x' {
                Radix::Hexadecimal
            } else if radix == 'o' {
                Radix::Octal
            } else if radix == 'b' {
                Radix::Binary
            } else {
                panic!("Radix must be one of [d, o, b, x]\n");
            }
        },
        None => Radix::Octal
    };

    rad
}
<commit_msg>od: fix warnings<commit_after>#![crate_name = "od"]
#![allow(unstable)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Ben Hirsch <benhirsch24@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate collections;

use collections::string::String;
use std::io::File;

#[derive(Show)]
enum Radix { Decimal, Hexadecimal, Octal, Binary }

pub fn uumain(args: Vec<String>) -> isize {
    let opts = [
        getopts::optopt("A", "address-radix",
                        "Select the base in which file offsets are printed.", "RADIX"),
        getopts::optopt("j", "skip-bytes",
                        "Skip bytes input bytes before formatting and writing.", "BYTES"),
        getopts::optopt("N", "read-bytes",
                        "limit dump to BYTES input bytes", "BYTES"),
        getopts::optopt("S", "strings",
                        ("output strings of at least BYTES graphic chars. 3 is assumed when \
                          BYTES is not specified."),
                        "BYTES"),
        getopts::optopt("t", "format", "select output format or formats", "TYPE"),
        getopts::optflag("v", "output-duplicates", "do not use * to mark line suppression"),
        getopts::optopt("w", "width",
                        ("output BYTES bytes per output line. 32 is implied when BYTES is not \
                          specified."),
                        "BYTES"),
        getopts::optflag("h", "help", "display this help and exit."),
        getopts::optflag("v", "version", "output version information and exit."),
        ];

    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => panic!("Invalid options\n{}", f)
    };

    let mut rad = Radix::Octal;
    if matches.opt_present("A") {
        rad = parse_radix(matches.opt_str("A"));
    } else {
        println!("{}", getopts::usage("od", &opts));
    }

    let mut fname;
    match args.last() {
        Some(n) => fname = n,
        None    => { panic!("Need fname for now") ; }
    };

    main(rad, fname.clone());

    0
}

fn main(radix: Radix, fname: String) {
    let mut f = match File::open(&Path::new(fname)) {
        Ok(f) => f,
        Err(e) => panic!("file error: {}", e)
    };

    let mut addr = 0;
    let bytes = &mut [b'\x00'; 16];
    loop {
        match f.read(bytes) {
            Ok(n) => {
                print!("{:07o}", addr);
                match radix {
                    Radix::Decimal => {
                    },
                    Radix::Octal => {
                        for b in range(0, n/std::u16::BYTES) {
                            let bs = &bytes[2*b .. 2*b+2];
                            let p: u16 = (bs[1] as u16) << 8 | bs[0] as u16;
                            print!(" {:06o}", p);
                        }
                        if n % std::u16::BYTES == 1 {
                            print!(" {:06o}", bytes[n-1]);
                        }
                    }
                    _ => { }
                };
                print!("\n");
                addr += n;
            },
            Err(_) => { println!("{:07o}", addr); break; }
        };
    };
}

fn parse_radix(radix_str: Option<String>) -> Radix {
    let rad = match radix_str {
        Some(s) => {
            let st = s.into_bytes();
            if st.len() != 1 {
                panic!("Radix must be one of [d, o, b, x]\n");
            }

            let radix: char = *(st.get(0)
                                .expect("byte string of length 1 lacks a 0th elem")) as char;
            if radix == 'd' {
                Radix::Decimal
            } else if radix == 'x' {
                Radix::Hexadecimal
            } else if radix == 'o' {
                Radix::Octal
            } else if radix == 'b' {
                Radix::Binary
            } else {
                panic!("Radix must be one of [d, o, b, x]\n");
            }
        },
        None => Radix::Octal
    };

    rad
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Panic handling and stack unwinding

use core::fmt;
use core::fmt::{Arguments, Write};
use super::io::term;

#[lang = "panic_fmt"]
#[no_mangle] #[inline(never)] #[cold]
pub extern fn panic_fmt( args: Arguments
                       , file: &'static str
                       , line: usize ) -> !
{
    write!( term::CONSOLE.lock()
          , "{}: {} {}"
          , file, line, args
          );
    loop { }
}

/// Required for Rust stack unwinding
#[lang = "eh_personality"]
#[no_mangle] #[inline(never)] #[cold]
pub extern fn eh_personality() {
    // TODO: add support for stack unwinding
}

#[lang = "stack_exhausted"]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn __morestack() -> ! {
    loop { }
}

#[allow(non_snake_case)]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn _Unwind_Resume() -> ! {
    loop { }
}

#[lang = "begin_unwind"]
#[no_mangle] #[inline(never)] #[cold]
pub fn begin_unwind<M: Send>(msg: M
                            , file_line: &(&'static str, usize))  -> !
{ loop { } }
<commit_msg>Maybe THIS will fix the panic handling issue<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Panic handling and stack unwinding

use core::fmt::{Arguments, Write};
use super::io::term;

#[lang = "panic_fmt"]
#[no_mangle] #[inline(never)] #[cold]
pub extern fn rust_begin_unwind( args: Arguments
                               , file: &'static str
                               , line: usize ) -> !
{
    write!( term::CONSOLE.lock()
          , "{}: {} {}"
          , file, line, args
          );
    loop { }
}

/// Required for Rust stack unwinding
#[lang = "eh_personality"]
#[no_mangle] #[inline(never)] #[cold]
pub extern fn eh_personality() {
    // TODO: add support for stack unwinding
}

#[lang = "stack_exhausted"]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn __morestack() -> ! {
    loop { }
}

#[allow(non_snake_case)]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn _Unwind_Resume() -> ! {
    loop { }
}

// #[lang = "begin_unwind"]
// #[no_mangle] #[inline(never)] #[cold]
// pub fn begin_unwind<M: Send>(msg: M
//                             , file_line: &(&'static str, usize))  -> !
// { loop { } }
<|endoftext|>


<commit_before>use common::math::lcm;

/// Returns the smallest number than can divided by all numbers between one and `target`
fn smallest_multiple(target: uint) -> uint {
    range(1, target).fold(1, |a, b| { lcm(a, b) })
}

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

    #[test]
    fn provided_example() {
        assert_eq!(smallest_multiple(10), 2520);
    }

    #[test]
    fn expected_result() {
        assert_eq!(smallest_multiple(20), 232792560);
    }
}
<commit_msg>Add benchmark for problem 5<commit_after>use common::math::lcm;

/// Returns the smallest number than can divided by all numbers between one and `target`
fn smallest_multiple(target: uint) -> uint {
    range(1, target).fold(1, |a, b| { lcm(a, b) })
}

#[cfg(test)]
mod test {
    extern crate test;

    use super::smallest_multiple;
    use self::test::Bencher;

    #[test]
    fn provided_example() {
        assert_eq!(smallest_multiple(10), 2520);
    }

    #[test]
    fn expected_result() {
        assert_eq!(smallest_multiple(20), 232792560);
    }

    #[bench]
    fn bench_smallest_multiple(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(smallest_multiple(20), 232792560);
        });
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate helix;
extern crate csv;

use helix::sys;
use helix::sys::VALUE;
use helix::{UncheckedValue, CheckResult, CheckedValue, ToRust};

struct VecWrap<T>(Vec<T>);

impl<T> UncheckedValue<VecWrap<T>> for VALUE
    where VALUE: UncheckedValue<T>
{
    fn to_checked(self) -> CheckResult<VecWrap<T>> {
        if unsafe { sys::RB_TYPE_P(self, sys::T_ARRAY) } {
            let len = unsafe { sys::RARRAY_LEN(self) };
            let ptr = unsafe { sys::RARRAY_PTR(self) };
            for i in 0..len {
                let val = unsafe { *ptr.offset(i) };
                if let Err(error) = val.to_checked() {
                    return Err(format!("Failed to convert value for Vec<T>: {}", error));
                }
            }
            Ok(unsafe { CheckedValue::<VecWrap<T>>::new(self) })
        } else {
            let val = unsafe { CheckedValue::<String>::new(sys::rb_inspect(self)) };
            Err(format!("No implicit conversion of {} into Vec<String>",
                        val.to_rust()))
        }
    }
}

impl ToRust<VecWrap<String>> for CheckedValue<VecWrap<String>>
    where VALUE: UncheckedValue<String>,
          CheckedValue<String>: ToRust<String>
{
    fn to_rust(self) -> VecWrap<String> {
        let len = unsafe { sys::RARRAY_LEN(self.inner) };
        let ptr = unsafe { sys::RARRAY_PTR(self.inner) };
        let mut vec: Vec<String> = Vec::with_capacity(len as usize);
        for i in 0..len {
            let val = unsafe { *ptr.offset(i) };
            let checked = val.to_checked().unwrap();
            vec.push(checked.to_rust());
        }
        return VecWrap(vec);
    }
}

impl ToRust<VecWrap<VecWrap<String>>> for CheckedValue<VecWrap<VecWrap<String>>>
    where VALUE: UncheckedValue<VecWrap<String>>,
          CheckedValue<VecWrap<String>>: ToRust<VecWrap<String>>
{
    fn to_rust(self) -> VecWrap<VecWrap<String>> {
        let len = unsafe { sys::RARRAY_LEN(self.inner) };
        let ptr = unsafe { sys::RARRAY_PTR(self.inner) };
        let mut vec: Vec<VecWrap<String>> = Vec::with_capacity(len as usize);
        for i in 0..len {
            let val = unsafe { *ptr.offset(i) };
            let checked = val.to_checked().unwrap();
            vec.push(checked.to_rust());
        }
        return VecWrap(vec);
    }
}

ruby! {
    class RscsvWriter {
        def generate_line(row: VecWrap<String>) -> String {
            let mut writer = csv::Writer::from_memory();
            writer.write(row.0.into_iter()).unwrap();
            let result = writer.as_string();
            return result.to_owned();
        }

        def generate_lines(rows: VecWrap<VecWrap<String>>) -> String {
            let mut writer = csv::Writer::from_memory();
            let vec = rows.0;

            for row in vec.into_iter() {
                writer.write(row.0.into_iter()).unwrap();
            }

            let result = writer.as_string();
            return result.to_owned();
        }
    }
}
<commit_msg>Avoid copying array of array before writing<commit_after>#[macro_use]
extern crate helix;
extern crate csv;

use helix::sys;
use helix::sys::VALUE;
use helix::{UncheckedValue, CheckResult, CheckedValue, ToRust};

struct VecWrap<T>(Vec<T>);

impl<T> UncheckedValue<VecWrap<T>> for VALUE
    where VALUE: UncheckedValue<T>
{
    fn to_checked(self) -> CheckResult<VecWrap<T>> {
        if unsafe { sys::RB_TYPE_P(self, sys::T_ARRAY) } {
            let len = unsafe { sys::RARRAY_LEN(self) };
            let ptr = unsafe { sys::RARRAY_PTR(self) };
            for i in 0..len {
                let val = unsafe { *ptr.offset(i) };
                if let Err(error) = val.to_checked() {
                    return Err(format!("Failed to convert value for Vec<T>: {}", error));
                }
            }
            Ok(unsafe { CheckedValue::<VecWrap<T>>::new(self) })
        } else {
            let val = unsafe { CheckedValue::<String>::new(sys::rb_inspect(self)) };
            Err(format!("No implicit conversion of {} into Vec<String>",
                        val.to_rust()))
        }
    }
}

impl ToRust<VecWrap<String>> for CheckedValue<VecWrap<String>>
    where VALUE: UncheckedValue<String>,
          CheckedValue<String>: ToRust<String>
{
    fn to_rust(self) -> VecWrap<String> {
        let len = unsafe { sys::RARRAY_LEN(self.inner) };
        let ptr = unsafe { sys::RARRAY_PTR(self.inner) };
        let mut vec: Vec<String> = Vec::with_capacity(len as usize);
        for i in 0..len {
            let val = unsafe { *ptr.offset(i) };
            let checked = val.to_checked().unwrap();
            vec.push(checked.to_rust());
        }
        return VecWrap(vec);
    }
}

impl ToRust<VecWrap<VecWrap<String>>> for CheckedValue<VecWrap<VecWrap<String>>>
    where VALUE: UncheckedValue<VecWrap<String>>,
          CheckedValue<VecWrap<String>>: ToRust<VecWrap<String>>
{
    fn to_rust(self) -> VecWrap<VecWrap<String>> {
        let len = unsafe { sys::RARRAY_LEN(self.inner) };
        let ptr = unsafe { sys::RARRAY_PTR(self.inner) };
        let mut vec: Vec<VecWrap<String>> = Vec::with_capacity(len as usize);
        for i in 0..len {
            let val = unsafe { *ptr.offset(i) };
            let checked = val.to_checked().unwrap();
            vec.push(checked.to_rust());
        }
        return VecWrap(vec);
    }
}

ruby! {
    class RscsvWriter {
        def generate_line(row: VecWrap<String>) -> String {
            let mut writer = csv::Writer::from_memory();
            writer.write(row.0.into_iter()).unwrap();
            let result = writer.as_string();
            return result.to_owned();
        }

        def generate_lines(rows: VecWrap<VecWrap<String>>) -> String {
            let mut writer = csv::Writer::from_memory();
            let vec = rows.0;

            for row in vec {
                writer.write(row.0.into_iter()).unwrap();
            }

            let result = writer.as_string();
            return result.to_owned();
        }
    }
}
<|endoftext|>


<commit_before>use nom::IResult;
use unicode_xid::UnicodeXID;

pub fn whitespace(input: &str) -> IResult<&str, ()> {
    if input.is_empty() {
        return IResult::Error;
    }

    let bytes = input.as_bytes();
    let mut i = 0;
    while i < bytes.len() {
        let s = &input[i..];
        if bytes[i] == b'/' {
            if s.starts_with("//") && (!s.starts_with("///") || s.starts_with("////")) &&
               !s.starts_with("//!") {
                if let Some(len) = s.find('\n') {
                    i += len + 1;
                    continue;
                }
                break;
            } else if s.starts_with("/*") && (!s.starts_with("/**") || s.starts_with("/***")) && !s.starts_with("/*!") {
                match block_comment(s) {
                    IResult::Done(_, com) => {
                        i += com.len();
                        continue;
                    }
                    IResult::Error => {
                        return IResult::Error;
                    }
                }
            }
        }
        match bytes[i] {
            b' ' | 0x09...0x0d => {
                i += 1;
                continue;
            }
            b if b <= 0x7f => {}
            _ => {
                let ch = s.chars().next().unwrap();
                if ch.is_whitespace() {
                    i += ch.len_utf8();
                    continue;
                }
            }
        }
        return if i > 0 {
            IResult::Done(s, ())
        } else {
            IResult::Error
        };
    }
    IResult::Done("", ())
}

pub fn block_comment(input: &str) -> IResult<&str, &str> {
    if !input.starts_with("/*") {
        return IResult::Error;
    }

    let mut depth = 0;
    let bytes = input.as_bytes();
    let mut i = 0;
    let upper = bytes.len() - 1;
    while i < upper {
        if bytes[i] == b'/' && bytes[i + 1] == b'*' {
            depth += 1;
            i += 1; // eat '*'
        } else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
            depth -= 1;
            if depth == 0 {
                return IResult::Done(&input[i + 2..], &input[..i + 2]);
            }
            i += 1; // eat '/'
        }
        i += 1;
    }
    IResult::Error
}

pub fn word_break(input: &str) -> IResult<&str, ()> {
    match input.chars().next() {
        Some(ch) if UnicodeXID::is_xid_continue(ch) => IResult::Error,
        Some(_) | None => IResult::Done(input, ()),
    }
}

pub fn skip_whitespace(input: &str) -> &str {
    match whitespace(input) {
        IResult::Done(rest, _) => rest,
        IResult::Error => input,
    }
}
<commit_msg>Allow left-to-right mark and right-to-left mark as whitespace<commit_after>use nom::IResult;
use unicode_xid::UnicodeXID;

pub fn whitespace(input: &str) -> IResult<&str, ()> {
    if input.is_empty() {
        return IResult::Error;
    }

    let bytes = input.as_bytes();
    let mut i = 0;
    while i < bytes.len() {
        let s = &input[i..];
        if bytes[i] == b'/' {
            if s.starts_with("//") && (!s.starts_with("///") || s.starts_with("////")) &&
               !s.starts_with("//!") {
                if let Some(len) = s.find('\n') {
                    i += len + 1;
                    continue;
                }
                break;
            } else if s.starts_with("/*") && (!s.starts_with("/**") || s.starts_with("/***")) && !s.starts_with("/*!") {
                match block_comment(s) {
                    IResult::Done(_, com) => {
                        i += com.len();
                        continue;
                    }
                    IResult::Error => {
                        return IResult::Error;
                    }
                }
            }
        }
        match bytes[i] {
            b' ' | 0x09...0x0d => {
                i += 1;
                continue;
            }
            b if b <= 0x7f => {}
            _ => {
                let ch = s.chars().next().unwrap();
                if is_whitespace(ch) {
                    i += ch.len_utf8();
                    continue;
                }
            }
        }
        return if i > 0 {
            IResult::Done(s, ())
        } else {
            IResult::Error
        };
    }
    IResult::Done("", ())
}

pub fn block_comment(input: &str) -> IResult<&str, &str> {
    if !input.starts_with("/*") {
        return IResult::Error;
    }

    let mut depth = 0;
    let bytes = input.as_bytes();
    let mut i = 0;
    let upper = bytes.len() - 1;
    while i < upper {
        if bytes[i] == b'/' && bytes[i + 1] == b'*' {
            depth += 1;
            i += 1; // eat '*'
        } else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
            depth -= 1;
            if depth == 0 {
                return IResult::Done(&input[i + 2..], &input[..i + 2]);
            }
            i += 1; // eat '/'
        }
        i += 1;
    }
    IResult::Error
}

pub fn word_break(input: &str) -> IResult<&str, ()> {
    match input.chars().next() {
        Some(ch) if UnicodeXID::is_xid_continue(ch) => IResult::Error,
        Some(_) | None => IResult::Done(input, ()),
    }
}

pub fn skip_whitespace(input: &str) -> &str {
    match whitespace(input) {
        IResult::Done(rest, _) => rest,
        IResult::Error => input,
    }
}

fn is_whitespace(ch: char) -> bool {
    // Rust treats left-to-right mark and right-to-left mark as whitespace
    ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}'
}
<|endoftext|>


<commit_before>//! Small tracked parts of the application state. Includes [**window**](mod.window.html),
//! [**keys**](mod.keys.html), [**mouse**](mod.mouse.html), [**time**](mod.mouse.html) - each of
//! which are stored in the **App**.

pub use self::keys::Keys;
pub use self::mouse::Mouse;
pub use self::time::Time;
pub use self::window::Window;

/// Tracked state related to the focused window.
pub mod window {
    use crate::geom;
    use crate::window;

    /// The default scalar value used for window positioning and sizing.
    pub type DefaultScalar = geom::scalar::Default;

    /// State of the window in focus.
    #[derive(Copy, Clone, Debug, PartialEq)]
    pub struct Window {
        /// ID of the window currently in focus.
        pub id: Option<window::Id>,
    }

    impl Window {
        /// Initialise the window state.
        pub fn new() -> Self {
            Window { id: None }
        }

        /// Expects that there will be a `window::Id` (the common case) and **panic!**s otherwise.
        pub fn id(&self) -> window::Id {
            self.id.unwrap()
        }
    }
}

/// Tracked state related to the keyboard.
pub mod keys {
    use crate::event::{Key, ModifiersState};
    use std::collections::HashSet;
    use std::ops::Deref;

    /// The state of the keyboard.
    #[derive(Clone, Debug, Default)]
    pub struct Keys {
        /// The state of the modifier keys as last indicated by winit.
        pub mods: ModifiersState,
        /// The state of all keys as tracked via the nannou App event handling.
        pub down: Down,
    }

    /// The set of keys that are currently pressed.
    #[derive(Clone, Debug, Default)]
    pub struct Down {
        pub(crate) keys: HashSet<Key>,
    }

    impl Deref for Down {
        type Target = HashSet<Key>;
        fn deref(&self) -> &Self::Target {
            &self.keys
        }
    }
}

/// Tracked state related to the mouse.
pub mod mouse {
    use crate::geom::{self, Point2};
    use crate::math::BaseFloat;
    use crate::window;
    use std;

    /// The default scalar value used for positions.
    pub type DefaultScalar = geom::scalar::Default;

    #[doc(inline)]
    pub use crate::event::MouseButton as Button;

    /// The max total number of buttons on a mouse.
    pub const NUM_BUTTONS: usize = 9;

    /// The state of the `Mouse` at a single moment in time.
    #[derive(Copy, Clone, Debug, PartialEq)]
    pub struct Mouse<S = DefaultScalar> {
        /// The ID of the last window currently in focus.
        pub window: Option<window::Id>,
        /// *x* position relative to the middle of `window`.
        pub x: S,
        /// *y* position relative to the middle of `window`.
        pub y: S,
        /// A map describing the state of each mouse button.
        pub buttons: ButtonMap,
    }

    /// Whether the button is up or down.
    #[derive(Copy, Clone, Debug, PartialEq)]
    pub enum ButtonPosition<S = DefaultScalar> {
        /// The button is up (i.e. pressed).
        Up,
        /// The button is down and was originally pressed down at the given `Point2`.
        Down(Point2<S>),
    }

    /// Stores the state of all mouse buttons.
    ///
    /// If the mouse button is down, it stores the position of the mouse when the button was pressed
    #[derive(Copy, Clone, Debug, PartialEq)]
    pub struct ButtonMap<S = DefaultScalar> {
        buttons: [ButtonPosition<S>; NUM_BUTTONS],
    }

    /// An iterator yielding all pressed buttons.
    #[derive(Clone)]
    pub struct PressedButtons<'a, S: 'a = DefaultScalar> {
        buttons: std::iter::Enumerate<std::slice::Iter<'a, ButtonPosition<S>>>,
    }

    impl<S> Mouse<S>
    where
        S: BaseFloat,
    {
        /// Construct a new default `Mouse`.
        pub fn new() -> Self {
            Mouse {
                window: None,
                buttons: ButtonMap::new(),
                x: S::zero(),
                y: S::zero(),
            }
        }

        /// The position of the mouse relative to the middle of the window in focus..
        pub fn position(&self) -> Point2<S> {
            Point2 {
                x: self.x,
                y: self.y,
            }
        }
    }

    impl<S> ButtonPosition<S>
    where
        S: BaseFloat,
    {
        /// If the mouse button is down, return a new one with position relative to the given `xy`.
        pub fn relative_to(self, xy: Point2<S>) -> Self {
            match self {
                ButtonPosition::Down(pos) => {
                    let rel_p = pos - xy;
                    ButtonPosition::Down(Point2 {
                        x: rel_p.x,
                        y: rel_p.y,
                    })
                }
                button_pos => button_pos,
            }
        }

        /// Is the `ButtonPosition` down.
        pub fn is_down(&self) -> bool {
            match *self {
                ButtonPosition::Down(_) => true,
                _ => false,
            }
        }

        /// Is the `ButtonPosition` up.
        pub fn is_up(&self) -> bool {
            match *self {
                ButtonPosition::Up => true,
                _ => false,
            }
        }

        /// Returns the position at which the button was pressed.
        pub fn if_down(&self) -> Option<Point2<S>> {
            match *self {
                ButtonPosition::Down(xy) => Some(xy),
                _ => None,
            }
        }
    }

    impl<S> ButtonMap<S>
    where
        S: BaseFloat,
    {
        /// Returns a new button map with all states set to `None`
        pub fn new() -> Self {
            ButtonMap {
                buttons: [ButtonPosition::Up; NUM_BUTTONS],
            }
        }

        /// Returns a copy of the ButtonMap relative to the given `Point`
        pub fn relative_to(self, xy: Point2<S>) -> Self {
            self.buttons
                .iter()
                .enumerate()
                .fold(ButtonMap::new(), |mut map, (idx, button_pos)| {
                    map.buttons[idx] = button_pos.relative_to(xy);
                    map
                })
        }

        /// The state of the left mouse button.
        pub fn left(&self) -> &ButtonPosition<S> {
            &self[Button::Left]
        }

        /// The state of the middle mouse button.
        pub fn middle(&self) -> &ButtonPosition<S> {
            &self[Button::Middle]
        }

        /// The state of the right mouse button.
        pub fn right(&self) -> &ButtonPosition<S> {
            &self[Button::Right]
        }

        /// Sets the `Button` in the `Down` position.
        pub fn press(&mut self, button: Button, xy: Point2<S>) {
            self.buttons[button_to_idx(button)] = ButtonPosition::Down(xy);
        }

        /// Set's the `Button` in the `Up` position.
        pub fn release(&mut self, button: Button) {
            self.buttons[button_to_idx(button)] = ButtonPosition::Up;
        }

        /// An iterator yielding all pressed mouse buttons along with the location at which they
        /// were originally pressed.
        pub fn pressed(&self) -> PressedButtons<S> {
            PressedButtons {
                buttons: self.buttons.iter().enumerate(),
            }
        }
    }

    impl<S> std::ops::Index<Button> for ButtonMap<S> {
        type Output = ButtonPosition<S>;
        fn index(&self, button: Button) -> &Self::Output {
            &self.buttons[button_to_idx(button)]
        }
    }

    impl<'a, S> Iterator for PressedButtons<'a, S>
    where
        S: BaseFloat,
    {
        type Item = (Button, Point2<S>);
        fn next(&mut self) -> Option<Self::Item> {
            while let Some((idx, button_pos)) = self.buttons.next() {
                if let ButtonPosition::Down(xy) = *button_pos {
                    return Some((idx_to_button(idx), xy));
                }
            }
            None
        }
    }

    fn idx_to_button(i: usize) -> Button {
        match i {
            n @ 0...5 => Button::Other(n as u8),
            6 => Button::Left,
            7 => Button::Right,
            8 => Button::Middle,
            _ => Button::Other(std::u8::MAX),
        }
    }

    fn button_to_idx(button: Button) -> usize {
        match button {
            Button::Other(n) => n as usize,
            Button::Left => 6,
            Button::Right => 7,
            Button::Middle => 8,
        }
    }
}

/// Tracked durations related to the App.
pub mod time {
    /// The state of time tracked by the App.
    #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
    pub struct Time {
        /// The duration since the app started running.
        pub since_start: std::time::Duration,
        /// The duration since the previous update.
        pub since_prev_update: std::time::Duration,
    }

    impl Time {
        /// The number of updates per second if `since_prev_update` were to remain constant
        pub fn updates_per_second(&self) -> f32 {
            if self.since_prev_update.as_secs() > 0 {
                return 0.0
            }

            let millis = self.since_prev_update.subsec_millis() as f32;

            if millis == 0.0 {
                return std::f32::MAX;
            }

            1000.0 / millis
        }
    }
}
<commit_msg>Format code<commit_after>//! Small tracked parts of the application state. Includes [**window**](mod.window.html),
//! [**keys**](mod.keys.html), [**mouse**](mod.mouse.html), [**time**](mod.mouse.html) - each of
//! which are stored in the **App**.

pub use self::keys::Keys;
pub use self::mouse::Mouse;
pub use self::time::Time;
pub use self::window::Window;

/// Tracked state related to the focused window.
pub mod window {
    use crate::geom;
    use crate::window;

    /// The default scalar value used for window positioning and sizing.
    pub type DefaultScalar = geom::scalar::Default;

    /// State of the window in focus.
    #[derive(Copy, Clone, Debug, PartialEq)]
    pub struct Window {
        /// ID of the window currently in focus.
        pub id: Option<window::Id>,
    }

    impl Window {
        /// Initialise the window state.
        pub fn new() -> Self {
            Window { id: None }
        }

        /// Expects that there will be a `window::Id` (the common case) and **panic!**s otherwise.
        pub fn id(&self) -> window::Id {
            self.id.unwrap()
        }
    }
}

/// Tracked state related to the keyboard.
pub mod keys {
    use crate::event::{Key, ModifiersState};
    use std::collections::HashSet;
    use std::ops::Deref;

    /// The state of the keyboard.
    #[derive(Clone, Debug, Default)]
    pub struct Keys {
        /// The state of the modifier keys as last indicated by winit.
        pub mods: ModifiersState,
        /// The state of all keys as tracked via the nannou App event handling.
        pub down: Down,
    }

    /// The set of keys that are currently pressed.
    #[derive(Clone, Debug, Default)]
    pub struct Down {
        pub(crate) keys: HashSet<Key>,
    }

    impl Deref for Down {
        type Target = HashSet<Key>;
        fn deref(&self) -> &Self::Target {
            &self.keys
        }
    }
}

/// Tracked state related to the mouse.
pub mod mouse {
    use crate::geom::{self, Point2};
    use crate::math::BaseFloat;
    use crate::window;
    use std;

    /// The default scalar value used for positions.
    pub type DefaultScalar = geom::scalar::Default;

    #[doc(inline)]
    pub use crate::event::MouseButton as Button;

    /// The max total number of buttons on a mouse.
    pub const NUM_BUTTONS: usize = 9;

    /// The state of the `Mouse` at a single moment in time.
    #[derive(Copy, Clone, Debug, PartialEq)]
    pub struct Mouse<S = DefaultScalar> {
        /// The ID of the last window currently in focus.
        pub window: Option<window::Id>,
        /// *x* position relative to the middle of `window`.
        pub x: S,
        /// *y* position relative to the middle of `window`.
        pub y: S,
        /// A map describing the state of each mouse button.
        pub buttons: ButtonMap,
    }

    /// Whether the button is up or down.
    #[derive(Copy, Clone, Debug, PartialEq)]
    pub enum ButtonPosition<S = DefaultScalar> {
        /// The button is up (i.e. pressed).
        Up,
        /// The button is down and was originally pressed down at the given `Point2`.
        Down(Point2<S>),
    }

    /// Stores the state of all mouse buttons.
    ///
    /// If the mouse button is down, it stores the position of the mouse when the button was pressed
    #[derive(Copy, Clone, Debug, PartialEq)]
    pub struct ButtonMap<S = DefaultScalar> {
        buttons: [ButtonPosition<S>; NUM_BUTTONS],
    }

    /// An iterator yielding all pressed buttons.
    #[derive(Clone)]
    pub struct PressedButtons<'a, S: 'a = DefaultScalar> {
        buttons: std::iter::Enumerate<std::slice::Iter<'a, ButtonPosition<S>>>,
    }

    impl<S> Mouse<S>
    where
        S: BaseFloat,
    {
        /// Construct a new default `Mouse`.
        pub fn new() -> Self {
            Mouse {
                window: None,
                buttons: ButtonMap::new(),
                x: S::zero(),
                y: S::zero(),
            }
        }

        /// The position of the mouse relative to the middle of the window in focus..
        pub fn position(&self) -> Point2<S> {
            Point2 {
                x: self.x,
                y: self.y,
            }
        }
    }

    impl<S> ButtonPosition<S>
    where
        S: BaseFloat,
    {
        /// If the mouse button is down, return a new one with position relative to the given `xy`.
        pub fn relative_to(self, xy: Point2<S>) -> Self {
            match self {
                ButtonPosition::Down(pos) => {
                    let rel_p = pos - xy;
                    ButtonPosition::Down(Point2 {
                        x: rel_p.x,
                        y: rel_p.y,
                    })
                }
                button_pos => button_pos,
            }
        }

        /// Is the `ButtonPosition` down.
        pub fn is_down(&self) -> bool {
            match *self {
                ButtonPosition::Down(_) => true,
                _ => false,
            }
        }

        /// Is the `ButtonPosition` up.
        pub fn is_up(&self) -> bool {
            match *self {
                ButtonPosition::Up => true,
                _ => false,
            }
        }

        /// Returns the position at which the button was pressed.
        pub fn if_down(&self) -> Option<Point2<S>> {
            match *self {
                ButtonPosition::Down(xy) => Some(xy),
                _ => None,
            }
        }
    }

    impl<S> ButtonMap<S>
    where
        S: BaseFloat,
    {
        /// Returns a new button map with all states set to `None`
        pub fn new() -> Self {
            ButtonMap {
                buttons: [ButtonPosition::Up; NUM_BUTTONS],
            }
        }

        /// Returns a copy of the ButtonMap relative to the given `Point`
        pub fn relative_to(self, xy: Point2<S>) -> Self {
            self.buttons
                .iter()
                .enumerate()
                .fold(ButtonMap::new(), |mut map, (idx, button_pos)| {
                    map.buttons[idx] = button_pos.relative_to(xy);
                    map
                })
        }

        /// The state of the left mouse button.
        pub fn left(&self) -> &ButtonPosition<S> {
            &self[Button::Left]
        }

        /// The state of the middle mouse button.
        pub fn middle(&self) -> &ButtonPosition<S> {
            &self[Button::Middle]
        }

        /// The state of the right mouse button.
        pub fn right(&self) -> &ButtonPosition<S> {
            &self[Button::Right]
        }

        /// Sets the `Button` in the `Down` position.
        pub fn press(&mut self, button: Button, xy: Point2<S>) {
            self.buttons[button_to_idx(button)] = ButtonPosition::Down(xy);
        }

        /// Set's the `Button` in the `Up` position.
        pub fn release(&mut self, button: Button) {
            self.buttons[button_to_idx(button)] = ButtonPosition::Up;
        }

        /// An iterator yielding all pressed mouse buttons along with the location at which they
        /// were originally pressed.
        pub fn pressed(&self) -> PressedButtons<S> {
            PressedButtons {
                buttons: self.buttons.iter().enumerate(),
            }
        }
    }

    impl<S> std::ops::Index<Button> for ButtonMap<S> {
        type Output = ButtonPosition<S>;
        fn index(&self, button: Button) -> &Self::Output {
            &self.buttons[button_to_idx(button)]
        }
    }

    impl<'a, S> Iterator for PressedButtons<'a, S>
    where
        S: BaseFloat,
    {
        type Item = (Button, Point2<S>);
        fn next(&mut self) -> Option<Self::Item> {
            while let Some((idx, button_pos)) = self.buttons.next() {
                if let ButtonPosition::Down(xy) = *button_pos {
                    return Some((idx_to_button(idx), xy));
                }
            }
            None
        }
    }

    fn idx_to_button(i: usize) -> Button {
        match i {
            n @ 0...5 => Button::Other(n as u8),
            6 => Button::Left,
            7 => Button::Right,
            8 => Button::Middle,
            _ => Button::Other(std::u8::MAX),
        }
    }

    fn button_to_idx(button: Button) -> usize {
        match button {
            Button::Other(n) => n as usize,
            Button::Left => 6,
            Button::Right => 7,
            Button::Middle => 8,
        }
    }
}

/// Tracked durations related to the App.
pub mod time {
    /// The state of time tracked by the App.
    #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
    pub struct Time {
        /// The duration since the app started running.
        pub since_start: std::time::Duration,
        /// The duration since the previous update.
        pub since_prev_update: std::time::Duration,
    }

    impl Time {
        /// The number of updates per second if `since_prev_update` were to remain constant
        pub fn updates_per_second(&self) -> f32 {
            if self.since_prev_update.as_secs() > 0 {
                return 0.0;
            }

            let millis = self.since_prev_update.subsec_millis() as f32;

            if millis == 0.0 {
                return std::f32::MAX;
            }

            1000.0 / millis
        }
    }
}
<|endoftext|>


<commit_before>//! This mod specifies and implements the Distributed Lock Manager Redlock object, as well
//! as the necessary functions lock() and unlock(). It also declares the struct Lock which
//! is used to hold necessary information about each lock a client acquires.

use redis::{Client, Connection};
use types::{RedlockResult, Error};
use time::precise_time_s;

/// Distributed Lock Manager class object
pub struct Redlock {
    /// list of connections with Master Nodes
    servers: Vec<Connection>,
    /// no. of retries to secure locks
    retry_count: i32,
    /// time delay between each retry
    retry_delay: f32,
    /// number of locks needed
    quorum: i32,
    /// clock drift factor
    clock_drift_factor: f32,
}

/// Represents the Lock a client holds
pub struct Lock {
    /// an integer representing the number of milliseconds the lock will be valid
    validity: i32,
    /// the name of the locked resource as specified by the user.
    resource: String,
    /// a random value which is used to safely reclaim the lock.
    key: String,
}

impl Redlock {
    /// instantialize a lock manager with a vector of URLs (format: redis://host:port/db)
    /// for each Redis master node, and optionally specify a retry count and delay between
    /// each retry. If None is given, the default will be 3 and 0.2s respectively
    pub fn dlm(urls : Vec<String>, retry_count: Option<i32>, retry_delay: Option<f32>)
        -> RedlockResult<Redlock> {
        let mut servers = Vec::new();
        let quorum = urls.len() as i32;
        let mut num_errors = 0;
        for u in urls {
            let client_res = Client::open(&*u);
            if client_res.is_err() {
                num_errors += 1;
            }
            let con_res = client_res.unwrap().get_connection();
            if con_res.is_err() {
                num_errors += 1;
            }
            servers.push(con_res.unwrap());
        }
        if (servers.len() as i32) < quorum {
            return Err(Error::NotEnoughMasters);
        }
        let rc = match retry_count {
            Some(x) => x,
            None => 3,
        };
        let rd = match retry_delay {
            Some(x) => x,
            None => 0.2,
        };
        let cdf = 0.01;
        Ok(Redlock {
            servers: servers,
            retry_count: rc,
            retry_delay: rd,
            quorum: quorum,
            clock_drift_factor: cdf,
        })
    }

    /// generates unique id for lock key
    fn get_unique_id(&self) -> String {
        unimplemented!()
    }

    fn lock_instance(&self, server : &Connection, res_name : &str, val : &str,
                     ttl: i32) -> RedlockResult<()> {
        Ok(())
    }

    /// locks resource specified by res_name for ttl in miliseconds
    pub fn lock(&self, res_name: String, ttl: i32) -> RedlockResult<Lock> {
        let retry = 0;
        let val = self.get_unique_id();
        let drift : i32 = (((ttl as f32) * self.clock_drift_factor) as i32) + 2;
        while retry < self.retry_count {
            let mut n = 0;
            let start_time : i32 = (precise_time_s() * 1000.0) as i32;
            for ref mut server in self.servers {
                let res = self.lock_instance(server, &res_name, &val, ttl);
            }

        }
        Err(Error::CannotObtainLock)
    }
    /// unlocks resource held by Lock
    pub fn unlock(lock: Lock) -> RedlockResult<()> {
        unimplemented!()
    }
}

impl Lock {
    /// instantialize a Lock with validity, resource name, and key
    pub fn new(validity: i32, res: String, key: String) -> Self {
        Lock { validity: validity, resource: res, key: key }
    }
}
<commit_msg>most of implementation, need to fill out helper functions and test<commit_after>//! This mod specifies and implements the Distributed Lock Manager Redlock object, as well
//! as the necessary functions lock() and unlock(). It also declares the struct Lock which
//! is used to hold necessary information about each lock a client acquires.

use redis::{Client, Connection};
use types::{RedlockResult, Error};
use time::precise_time_s;

/// Distributed Lock Manager class object
pub struct Redlock {
    /// list of connections with Master Nodes
    servers: Vec<Connection>,
    /// no. of retries to secure locks
    retry_count: i32,
    /// time delay between each retry
    retry_delay: f32,
    /// number of locks needed
    quorum: i32,
    /// clock drift factor
    clock_drift_factor: f32,
}

/// Represents the Lock a client holds
pub struct Lock {
    /// an integer representing the number of milliseconds the lock will be valid
    validity: i32,
    /// the name of the locked resource as specified by the user.
    resource: String,
    /// a random value which is used to safely reclaim the lock.
    key: String,
}

impl Redlock {
    /// instantialize a lock manager with a vector of URLs (format: redis://host:port/db)
    /// for each Redis master node, and optionally specify a retry count and delay between
    /// each retry. If None is given, the default will be 3 and 0.2s respectively
    pub fn dlm(urls : Vec<String>, retry_count: Option<i32>, retry_delay: Option<f32>)
        -> RedlockResult<Redlock> {
        let mut servers = Vec::new();
        let quorum = urls.len() as i32;
        for u in urls {
            let client_res = Client::open(&*u);
            if client_res.is_ok() {
                let con_res = client_res.unwrap().get_connection();
                if con_res.is_ok() {
                    servers.push(con_res.unwrap());
                }
            }
        }
        if (servers.len() as i32) < quorum {
            return Err(Error::NotEnoughMasters);
        }
        let rc = match retry_count {
            Some(x) => x,
            None => 3,
        };
        let rd = match retry_delay {
            Some(x) => x,
            None => 0.2,
        };
        let cdf = 0.01;
        Ok(Redlock {
            servers: servers,
            retry_count: rc,
            retry_delay: rd,
            quorum: quorum,
            clock_drift_factor: cdf,
        })
    }

    /// generates unique id for lock key
    fn get_unique_id(&self) -> String {
        unimplemented!()
    }

    /// acquire lock from one server
    fn lock_instance(&self, server : &Connection, res_name : &str, val : &str,
                     ttl: i32) -> RedlockResult<()> {
        Ok(())
    }

    /// release lock from one server
    fn unlock_instance(&self, server : Connection, res_name : &str,
                       val : &str) -> () {
    }

    /// locks resource specified by res_name for ttl in miliseconds
    pub fn lock(&self, res_name: String, ttl: i32) -> RedlockResult<Lock> {
        let mut retry = 0;
        let val = self.get_unique_id();
        let drift : i32 = (((ttl as f32) * self.clock_drift_factor) as i32) + 2;
        while retry < self.retry_count {
            let mut n = 0;
            let start_time : i32 = (precise_time_s() * 1000.0) as i32;
            for server in self.servers {
                let res = self.lock_instance(server, &res_name, &val, ttl);
                if res.is_ok() {
                    n = n + 1;
                }
            }
            let elapsed_time : i32 = ((precise_time_s() * 1000.0) as i32) - start_time;
            let validity = ttl - elapsed_time - drift;
            if validity > 0 && n >= self.quorum {
                // lock successful!
                return Ok(Lock::new(validity, res_name, val));
            }  else {
                for server in self.servers {
                    self.unlock_instance(server, &res_name, &val);
                }
                retry = retry + 1;
                //TODO: sleep for retry_delay
            }
        }
        Err(Error::CannotObtainLock)
    }
    /// unlocks resource held by Lock
    pub fn unlock(lock: Lock) -> RedlockResult<()> {
        for server in self.servers {
            let res = self.unlock_instance(server, lock.resource, lock.key);
            if res.is_err() {
                Err(Error::MultipleRedlock)
            }
        }
        Ok(())
    }
}

impl Lock {
    /// instantialize a Lock with validity, resource name, and key
    pub fn new(validity: i32, res: String, key: String) -> Self {
        Lock { validity: validity, resource: res, key: key }
    }
}
<|endoftext|>


<commit_before>//!
//! https://tools.ietf.org/html/rfc4315
//!
//! The IMAP UIDPLUS Extension
//!

use nom::{
    branch::alt,
    bytes::streaming::{tag, tag_no_case},
    combinator::map,
    multi::separated_list1,
    sequence::{preceded, tuple},
    IResult,
};

use crate::parser::core::number;
use crate::types::*;

/// Extends resp-text-code as follows:
///
///     resp-text-code =/ resp-code-apnd
///     resp-code-apnd = "APPENDUID" SP nz-number SP append-uid
///     append-uid      =/ uid-set
///                       ; only permitted if client uses [MULTIAPPEND]
///                       ; to append multiple messages.
///
/// [RFC4315 - 3 Additional Response Codes](https://tools.ietf.org/html/rfc4315#section-3)
pub(crate) fn resp_text_code_append_uid(i: &[u8]) -> IResult<&[u8], ResponseCode> {
    map(
        preceded(
            tag_no_case(b"APPENDUID "),
            tuple((number, tag(" "), uid_set)),
        ),
        |(fst, _, snd)| ResponseCode::AppendUid(fst, snd),
    )(i)
}

/// Extends resp-text-code as follows:
///
///     resp-text-code =/ resp-code-copy
///     resp-code-copy = "COPYUID" SP nz-number SP uid-set
///
/// [RFC4315 - 3 Additional Response Codes](https://tools.ietf.org/html/rfc4315#section-3)
pub(crate) fn resp_text_code_copy_uid(i: &[u8]) -> IResult<&[u8], ResponseCode> {
    map(
        preceded(
            tag_no_case(b"COPYUID "),
            tuple((number, tag(" "), uid_set, tag(" "), uid_set)),
        ),
        |(fst, _, snd, _, trd)| ResponseCode::CopyUid(fst, snd, trd),
    )(i)
}

/// Extends resp-text-code as follows:
///
///     resp-text-code =/ "UIDNOTSTICKY"
///
/// [RFC4315 - 3 Additional Response Codes](https://tools.ietf.org/html/rfc4315#section-3)
pub(crate) fn resp_text_code_uid_not_sticky(i: &[u8]) -> IResult<&[u8], ResponseCode> {
    map(tag_no_case(b"UIDNOTSTICKY"), |_| ResponseCode::UidNotSticky)(i)
}

/// Parses the uid-set nonterminal:
///
///     uid-set = (uniqueid / uid-range) *("," uid-set)
///
/// [RFC4315 - 4 Formal Syntax](https://tools.ietf.org/html/rfc4315#section-4)
fn uid_set(i: &[u8]) -> IResult<&[u8], Vec<UidSetMember>> {
    separated_list1(tag(","), alt((uid_range, map(number, From::from))))(i)
}

/// Parses the uid-set nonterminal:
///
///    uid-range = (uniqueid ":" uniqueid)
///                ; two uniqueid values and all values
///                ; between these two regards of order.
///                ; Example: 2:4 and 4:2 are equivalent.
///
/// [RFC4315 - 4 Formal Syntax](https://tools.ietf.org/html/rfc4315#section-4)
fn uid_range(i: &[u8]) -> IResult<&[u8], UidSetMember> {
    map(
        nom::sequence::separated_pair(number, tag(":"), number),
        |(fst, snd)| if fst <= snd { fst..=snd } else { snd..=fst }.into(),
    )(i)
}
<commit_msg>Fix up doctest failures<commit_after>//!
//! https://tools.ietf.org/html/rfc4315
//!
//! The IMAP UIDPLUS Extension
//!

use nom::{
    branch::alt,
    bytes::streaming::{tag, tag_no_case},
    combinator::map,
    multi::separated_list1,
    sequence::{preceded, tuple},
    IResult,
};

use crate::parser::core::number;
use crate::types::*;

/// Extends resp-text-code as follows:
///
/// ```ignore
///     resp-text-code =/ resp-code-apnd
///     resp-code-apnd = "APPENDUID" SP nz-number SP append-uid
///     append-uid      =/ uid-set
///                       ; only permitted if client uses [MULTIAPPEND]
///                       ; to append multiple messages.
/// ```
///
/// [RFC4315 - 3 Additional Response Codes](https://tools.ietf.org/html/rfc4315#section-3)
pub(crate) fn resp_text_code_append_uid(i: &[u8]) -> IResult<&[u8], ResponseCode> {
    map(
        preceded(
            tag_no_case(b"APPENDUID "),
            tuple((number, tag(" "), uid_set)),
        ),
        |(fst, _, snd)| ResponseCode::AppendUid(fst, snd),
    )(i)
}

/// Extends resp-text-code as follows:
///
/// ```ignore
///     resp-text-code =/ resp-code-copy
///     resp-code-copy = "COPYUID" SP nz-number SP uid-set
/// ```
///
/// [RFC4315 - 3 Additional Response Codes](https://tools.ietf.org/html/rfc4315#section-3)
pub(crate) fn resp_text_code_copy_uid(i: &[u8]) -> IResult<&[u8], ResponseCode> {
    map(
        preceded(
            tag_no_case(b"COPYUID "),
            tuple((number, tag(" "), uid_set, tag(" "), uid_set)),
        ),
        |(fst, _, snd, _, trd)| ResponseCode::CopyUid(fst, snd, trd),
    )(i)
}

/// Extends resp-text-code as follows:
///
/// ```ignore
///     resp-text-code =/ "UIDNOTSTICKY"
/// ```
///
/// [RFC4315 - 3 Additional Response Codes](https://tools.ietf.org/html/rfc4315#section-3)
pub(crate) fn resp_text_code_uid_not_sticky(i: &[u8]) -> IResult<&[u8], ResponseCode> {
    map(tag_no_case(b"UIDNOTSTICKY"), |_| ResponseCode::UidNotSticky)(i)
}

/// Parses the uid-set nonterminal:
///
/// ```ignore
///     uid-set = (uniqueid / uid-range) *("," uid-set)
/// ```
///
/// [RFC4315 - 4 Formal Syntax](https://tools.ietf.org/html/rfc4315#section-4)
fn uid_set(i: &[u8]) -> IResult<&[u8], Vec<UidSetMember>> {
    separated_list1(tag(","), alt((uid_range, map(number, From::from))))(i)
}

/// Parses the uid-set nonterminal:
///
/// ```ignore
///    uid-range = (uniqueid ":" uniqueid)
///                ; two uniqueid values and all values
///                ; between these two regards of order.
///                ; Example: 2:4 and 4:2 are equivalent.
/// ```
///
/// [RFC4315 - 4 Formal Syntax](https://tools.ietf.org/html/rfc4315#section-4)
fn uid_range(i: &[u8]) -> IResult<&[u8], UidSetMember> {
    map(
        nom::sequence::separated_pair(number, tag(":"), number),
        |(fst, snd)| if fst <= snd { fst..=snd } else { snd..=fst }.into(),
    )(i)
}
<|endoftext|>