<commit_before>#![deny(missing_docs)]

//! A GLFW window back-end for the Piston game engine.

extern crate glfw;
extern crate collections;
extern crate gl;
extern crate event;
extern crate shader_version;
extern crate input;

// External crates.
use collections::RingBuf;
use glfw::Context;
use input::{
    keyboard,
    mouse,
    InputEvent,
};
use event::{
    Window,
    WindowSettings,
};
use event::window::{
    PollEvent,
    SwapBuffers,
};
use shader_version::opengl::OpenGL;

/// Contains stuff for game window.
pub struct GlfwWindow {
    /// The window.
    pub window: glfw::Window,
    /// Receives events from window.
    events: Receiver<(f64, glfw::WindowEvent)>,
    /// GLFW context.
    pub glfw: glfw::Glfw,
    /// Game window settings.
    settings: WindowSettings,
    event_queue: RingBuf<input::InputEvent>,
    // Used to compute relative mouse movement.
    last_mouse_pos: Option<(f64, f64)>,
}

impl GlfwWindow {
    /// Create a new game window from an existing GLFW window.
    pub fn from_pieces(win: glfw::Window, glfw: glfw::Glfw,
                       events: Receiver<(f64, glfw::WindowEvent)>,
                       exit_on_esc: bool) -> GlfwWindow {
        win.set_all_polling(true);
        win.make_current();

        let (w, h) = win.get_framebuffer_size();
        let fullscreen = win.with_window_mode(|m| match m { glfw::Windowed => true, _ => false });

        GlfwWindow {
            window: win,
            events: events,
            glfw: glfw,
            settings: WindowSettings {
                title: "<unknown window title, created with from_pieces>".to_string(),
                size: [w as u32, h as u32],
                samples: 0, //unknown
                fullscreen: fullscreen,
                exit_on_esc: exit_on_esc,
            },
            event_queue: RingBuf::new(),
            last_mouse_pos: None,
        }
    }

    /// Creates a new game window for GLFW.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> GlfwWindow {
        use glfw::Context;

        // Initialize GLFW.
        let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

        let (major, minor) = opengl.get_major_minor();

        // Make sure we have the right GL version.
        glfw.window_hint(glfw::ContextVersion(major as u32, minor as u32));
        glfw.window_hint(glfw::OpenglForwardCompat(true));
        glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));
        glfw.window_hint(glfw::Samples(settings.samples as u32));

        // Create GLFW window.
        let (window, events) = glfw.create_window(
            settings.size[0],
            settings.size[1],
            settings.title.as_slice(), glfw::Windowed
        ).expect("Failed to create GLFW window.");
        window.set_all_polling(true);
        window.make_current();

        // Load the OpenGL function pointers
        gl::load_with(|s| window.get_proc_address(s));

        GlfwWindow {
            window: window,
            events: events,
            glfw: glfw,
            settings: settings,
            event_queue: RingBuf::new(),
            last_mouse_pos: None,
        }
    }

    fn flush_messages(&mut self) {
        if self.event_queue.len() != 0 {
            return;
        }

        self.glfw.poll_events();
        for (_, event) in glfw::flush_messages(&self.events) {
            match event {
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _)
                if self.settings.exit_on_esc => {
                    self.window.set_should_close(true);
                }
                glfw::CharEvent(ch) => {
                    self.event_queue.push(input::Text(ch.to_string()));
                }
                glfw::KeyEvent(key, _, glfw::Press, _) => {
                    self.event_queue.push(
                        input::Press(input::Keyboard(glfw_map_key(key)))
                    );
                }
                glfw::KeyEvent(key, _, glfw::Release, _) => {
                    self.event_queue.push(
                        input::Release(input::Keyboard(glfw_map_key(key)))
                    );
                }
                glfw::MouseButtonEvent(button, glfw::Press, _) => {
                    self.event_queue.push(
                        input::Press(input::Mouse(glfw_map_mouse(button)))
                    );
                }
                glfw::MouseButtonEvent(button, glfw::Release, _) => {
                    self.event_queue.push(
                        input::Release(input::Mouse(glfw_map_mouse(button)))
                    );
                }
                glfw::CursorPosEvent(x, y) => {
                    self.event_queue.push(input::Move(input::MouseCursor(x, y)));
                    match self.last_mouse_pos {
                        Some((lx, ly)) => {
                            self.event_queue.push(
                                input::Move(input::MouseRelative(x - lx, y - ly))
                            )
                        }
                        None => {}
                    };
                    self.last_mouse_pos = Some((x, y));
                }
                glfw::ScrollEvent(x, y) => {
                    self.event_queue.push(input::Move(input::MouseScroll(x, y)));
                }
                glfw::SizeEvent(w, h) => {
                    self.event_queue.push(input::Resize(w as u32, h as u32));
                }
                glfw::FocusEvent(focus) => {
                    self.event_queue.push(input::Focus(focus));
                }
                _ => {}
            }
        }
    }
}

impl PollEvent<InputEvent> for GlfwWindow {
    fn poll_event(&mut self) -> Option<input::InputEvent> {
        self.flush_messages();

        if self.event_queue.len() != 0 {
            self.event_queue.pop_front()
        } else {
            None
        }
    }
}

impl SwapBuffers for GlfwWindow {
    fn swap_buffers(&mut self) {
        use glfw::Context;

        self.window.swap_buffers();
    }
}

impl Window for GlfwWindow {
    fn get_settings<'a>(&'a self) -> &'a WindowSettings {
        &self.settings
    }

    fn get_draw_size(&self) -> (u32, u32) {
        let (w, h) = self.window.get_framebuffer_size();
        (w as u32, h as u32)
    }

    fn get_size(&self) -> (u32, u32) {
        let (w, h) = self.window.get_size();
        (w as u32, h as u32)
    }

    fn should_close(&self) -> bool {
        self.window.should_close()
    }

    fn close(&mut self) {
        self.window.set_should_close(true);
    }

    fn capture_cursor(&mut self, enabled: bool) {
        if enabled {
            self.window.set_cursor_mode(glfw::CursorDisabled)
        } else {
            self.window.set_cursor_mode(glfw::CursorNormal);
            self.last_mouse_pos = None;
        }
    }
}

fn glfw_map_key(keycode: glfw::Key) -> keyboard::Key {
    match keycode {
        glfw::Key0 => keyboard::D0,
        glfw::Key1 => keyboard::D1,
        glfw::Key2 => keyboard::D2,
        glfw::Key3 => keyboard::D3,
        glfw::Key4 => keyboard::D4,
        glfw::Key5 => keyboard::D5,
        glfw::Key6 => keyboard::D6,
        glfw::Key7 => keyboard::D7,
        glfw::Key8 => keyboard::D8,
        glfw::Key9 => keyboard::D9,
        glfw::KeyA => keyboard::A,
        glfw::KeyB => keyboard::B,
        glfw::KeyC => keyboard::C,
        glfw::KeyD => keyboard::D,
        glfw::KeyE => keyboard::E,
        glfw::KeyF => keyboard::F,
        glfw::KeyG => keyboard::G,
        glfw::KeyH => keyboard::H,
        glfw::KeyI => keyboard::I,
        glfw::KeyJ => keyboard::J,
        glfw::KeyK => keyboard::K,
        glfw::KeyL => keyboard::L,
        glfw::KeyM => keyboard::M,
        glfw::KeyN => keyboard::N,
        glfw::KeyO => keyboard::O,
        glfw::KeyP => keyboard::P,
        glfw::KeyQ => keyboard::Q,
        glfw::KeyR => keyboard::R,
        glfw::KeyS => keyboard::S,
        glfw::KeyT => keyboard::T,
        glfw::KeyU => keyboard::U,
        glfw::KeyV => keyboard::V,
        glfw::KeyW => keyboard::W,
        glfw::KeyX => keyboard::X,
        glfw::KeyY => keyboard::Y,
        glfw::KeyZ => keyboard::Z,
        glfw::KeyApostrophe => keyboard::Unknown,
        glfw::KeyBackslash => keyboard::Backslash,
        glfw::KeyBackspace => keyboard::Backspace,
        glfw::KeyCapsLock => keyboard::CapsLock,
        glfw::KeyDelete => keyboard::Delete,
        glfw::KeyComma => keyboard::Comma,
        glfw::KeyDown => keyboard::Down,
        glfw::KeyEnd => keyboard::End,
        glfw::KeyEnter => keyboard::Return,
        glfw::KeyEqual => keyboard::Equals,
        glfw::KeyEscape => keyboard::Escape,
        glfw::KeyF1 => keyboard::F1,
        glfw::KeyF2 => keyboard::F2,
        glfw::KeyF3 => keyboard::F3,
        glfw::KeyF4 => keyboard::F4,
        glfw::KeyF5 => keyboard::F5,
        glfw::KeyF6 => keyboard::F6,
        glfw::KeyF7 => keyboard::F7,
        glfw::KeyF8 => keyboard::F8,
        glfw::KeyF9 => keyboard::F9,
        glfw::KeyF10 => keyboard::F10,
        glfw::KeyF11 => keyboard::F11,
        glfw::KeyF12 => keyboard::F12,
        glfw::KeyF13 => keyboard::F13,
        glfw::KeyF14 => keyboard::F14,
        glfw::KeyF15 => keyboard::F15,
        glfw::KeyF16 => keyboard::F16,
        glfw::KeyF17 => keyboard::F17,
        glfw::KeyF18 => keyboard::F18,
        glfw::KeyF19 => keyboard::F19,
        glfw::KeyF20 => keyboard::F20,
        glfw::KeyF21 => keyboard::F21,
        glfw::KeyF22 => keyboard::F22,
        glfw::KeyF23 => keyboard::F23,
        glfw::KeyF24 => keyboard::F24,
        // Possibly next code.
        glfw::KeyF25 => keyboard::Unknown,
        glfw::KeyKp0 => keyboard::NumPad0,
        glfw::KeyKp1 => keyboard::NumPad1,
        glfw::KeyKp2 => keyboard::NumPad2,
        glfw::KeyKp3 => keyboard::NumPad3,
        glfw::KeyKp4 => keyboard::NumPad4,
        glfw::KeyKp5 => keyboard::NumPad5,
        glfw::KeyKp6 => keyboard::NumPad6,
        glfw::KeyKp7 => keyboard::NumPad7,
        glfw::KeyKp8 => keyboard::NumPad8,
        glfw::KeyKp9 => keyboard::NumPad9,
        glfw::KeyKpDecimal => keyboard::NumPadDecimal,
        glfw::KeyKpDivide => keyboard::NumPadDivide,
        glfw::KeyKpMultiply => keyboard::NumPadMultiply,
        glfw::KeyKpSubtract => keyboard::NumPadMinus,
        glfw::KeyKpAdd => keyboard::NumPadPlus,
        glfw::KeyKpEnter => keyboard::NumPadEnter,
        glfw::KeyKpEqual => keyboard::NumPadEquals,
        glfw::KeyLeftShift => keyboard::LShift,
        glfw::KeyLeftControl => keyboard::LCtrl,
        glfw::KeyLeftAlt => keyboard::LAlt,
        glfw::KeyLeftSuper => keyboard::LGui,
        glfw::KeyRightShift => keyboard::RShift,
        glfw::KeyRightControl => keyboard::RCtrl,
        glfw::KeyRightAlt => keyboard::RAlt,
        glfw::KeyRightSuper => keyboard::RGui,
        // Map to backslash?
        glfw::KeyGraveAccent => keyboard::Unknown,
        glfw::KeyHome => keyboard::Home,
        glfw::KeyInsert => keyboard::Insert,
        glfw::KeyLeft => keyboard::Left,
        glfw::KeyLeftBracket => keyboard::LeftBracket,
        glfw::KeyMenu => keyboard::Menu,
        glfw::KeyMinus => keyboard::Minus,
        glfw::KeyNumLock => keyboard::NumLockClear,
        glfw::KeyPageDown => keyboard::PageDown,
        glfw::KeyPageUp => keyboard::PageUp,
        glfw::KeyPause => keyboard::Pause,
        glfw::KeyPeriod => keyboard::Period,
        glfw::KeyPrintScreen => keyboard::PrintScreen,
        glfw::KeyRight => keyboard::Right,
        glfw::KeyRightBracket => keyboard::RightBracket,
        glfw::KeyScrollLock => keyboard::ScrollLock,
        glfw::KeySemicolon => keyboard::Semicolon,
        glfw::KeySlash => keyboard::Slash,
        glfw::KeySpace => keyboard::Space,
        glfw::KeyTab => keyboard::Tab,
        glfw::KeyUp => keyboard::Up,
        glfw::KeyWorld1 => keyboard::Unknown,
        glfw::KeyWorld2 => keyboard::Unknown,
        // _ => keyboard::Unknown,
    }
}

fn glfw_map_mouse(mouse_button: glfw::MouseButton) -> mouse::Button {
    match mouse_button {
        glfw::MouseButton1 => mouse::Left,
        glfw::MouseButton2 => mouse::Right,
        glfw::MouseButton3 => mouse::Middle,
        glfw::MouseButton4 => mouse::X1,
        glfw::MouseButton5 => mouse::X2,
        glfw::MouseButton6 => mouse::Button6,
        glfw::MouseButton7 => mouse::Button7,
        glfw::MouseButton8 => mouse::Button8,
    }
}
<commit_msg>Upgraded to latest Rust + piston-event<commit_after>#![deny(missing_docs)]

//! A GLFW window back-end for the Piston game engine.

extern crate glfw;
extern crate collections;
extern crate gl;
extern crate event;
extern crate shader_version;
extern crate input;
extern crate current;

// External crates.
use current::{ Get };
use collections::RingBuf;
use glfw::Context;
use input::{
    keyboard,
    mouse,
    InputEvent,
};
use event::{
    Window,
    WindowSettings,
};
use event::window::{
    ShouldClose,
    Size,
};
use event::window::{
    PollEvent,
    SwapBuffers,
};
use shader_version::opengl::OpenGL;

/// Contains stuff for game window.
pub struct GlfwWindow {
    /// The window.
    pub window: glfw::Window,
    /// Receives events from window.
    events: Receiver<(f64, glfw::WindowEvent)>,
    /// GLFW context.
    pub glfw: glfw::Glfw,
    /// Game window settings.
    settings: WindowSettings,
    event_queue: RingBuf<input::InputEvent>,
    // Used to compute relative mouse movement.
    last_mouse_pos: Option<(f64, f64)>,
}

impl GlfwWindow {
    /// Create a new game window from an existing GLFW window.
    pub fn from_pieces(win: glfw::Window, glfw: glfw::Glfw,
                       events: Receiver<(f64, glfw::WindowEvent)>,
                       exit_on_esc: bool) -> GlfwWindow {
        win.set_all_polling(true);
        win.make_current();

        let (w, h) = win.get_framebuffer_size();
        let fullscreen = win.with_window_mode(|m| match m { glfw::Windowed => true, _ => false });

        GlfwWindow {
            window: win,
            events: events,
            glfw: glfw,
            settings: WindowSettings {
                title: "<unknown window title, created with from_pieces>".to_string(),
                size: [w as u32, h as u32],
                samples: 0, //unknown
                fullscreen: fullscreen,
                exit_on_esc: exit_on_esc,
            },
            event_queue: RingBuf::new(),
            last_mouse_pos: None,
        }
    }

    /// Creates a new game window for GLFW.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> GlfwWindow {
        use glfw::Context;

        // Initialize GLFW.
        let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

        let (major, minor) = opengl.get_major_minor();

        // Make sure we have the right GL version.
        glfw.window_hint(glfw::ContextVersion(major as u32, minor as u32));
        glfw.window_hint(glfw::OpenglForwardCompat(true));
        glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));
        glfw.window_hint(glfw::Samples(settings.samples as u32));

        // Create GLFW window.
        let (window, events) = glfw.create_window(
            settings.size[0],
            settings.size[1],
            settings.title.as_slice(), glfw::Windowed
        ).expect("Failed to create GLFW window.");
        window.set_all_polling(true);
        window.make_current();

        // Load the OpenGL function pointers
        gl::load_with(|s| window.get_proc_address(s));

        GlfwWindow {
            window: window,
            events: events,
            glfw: glfw,
            settings: settings,
            event_queue: RingBuf::new(),
            last_mouse_pos: None,
        }
    }

    fn flush_messages(&mut self) {
        if self.event_queue.len() != 0 {
            return;
        }

        self.glfw.poll_events();
        for (_, event) in glfw::flush_messages(&self.events) {
            match event {
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _)
                if self.settings.exit_on_esc => {
                    self.window.set_should_close(true);
                }
                glfw::CharEvent(ch) => {
                    self.event_queue.push_back(input::Text(ch.to_string()));
                }
                glfw::KeyEvent(key, _, glfw::Press, _) => {
                    self.event_queue.push_back(
                        input::Press(input::Keyboard(glfw_map_key(key)))
                    );
                }
                glfw::KeyEvent(key, _, glfw::Release, _) => {
                    self.event_queue.push_back(
                        input::Release(input::Keyboard(glfw_map_key(key)))
                    );
                }
                glfw::MouseButtonEvent(button, glfw::Press, _) => {
                    self.event_queue.push_back(
                        input::Press(input::Mouse(glfw_map_mouse(button)))
                    );
                }
                glfw::MouseButtonEvent(button, glfw::Release, _) => {
                    self.event_queue.push_back(
                        input::Release(input::Mouse(glfw_map_mouse(button)))
                    );
                }
                glfw::CursorPosEvent(x, y) => {
                    self.event_queue.push_back(input::Move(input::MouseCursor(x, y)));
                    match self.last_mouse_pos {
                        Some((lx, ly)) => {
                            self.event_queue.push_back(
                                input::Move(input::MouseRelative(x - lx, y - ly))
                            )
                        }
                        None => {}
                    };
                    self.last_mouse_pos = Some((x, y));
                }
                glfw::ScrollEvent(x, y) => {
                    self.event_queue.push_back(input::Move(input::MouseScroll(x, y)));
                }
                glfw::SizeEvent(w, h) => {
                    self.event_queue.push_back(input::Resize(w as u32, h as u32));
                }
                glfw::FocusEvent(focus) => {
                    self.event_queue.push_back(input::Focus(focus));
                }
                _ => {}
            }
        }
    }
}

impl Get<Size> for GlfwWindow {
    fn get(&self) -> Size {
        let (w, h) = self.window.get_size();
        Size([w as u32, h as u32])
    }
}

impl Get<ShouldClose> for GlfwWindow {
    fn get(&self) -> ShouldClose {
        ShouldClose(self.window.should_close())
    }
}

impl PollEvent<InputEvent> for GlfwWindow {
    fn poll_event(&mut self) -> Option<input::InputEvent> {
        self.flush_messages();

        if self.event_queue.len() != 0 {
            self.event_queue.pop_front()
        } else {
            None
        }
    }
}

impl SwapBuffers for GlfwWindow {
    fn swap_buffers(&mut self) {
        use glfw::Context;

        self.window.swap_buffers();
    }
}

impl Window for GlfwWindow {
    fn get_settings<'a>(&'a self) -> &'a WindowSettings {
        &self.settings
    }

    fn get_draw_size(&self) -> (u32, u32) {
        let (w, h) = self.window.get_framebuffer_size();
        (w as u32, h as u32)
    }

    fn close(&mut self) {
        self.window.set_should_close(true);
    }

    fn capture_cursor(&mut self, enabled: bool) {
        if enabled {
            self.window.set_cursor_mode(glfw::CursorDisabled)
        } else {
            self.window.set_cursor_mode(glfw::CursorNormal);
            self.last_mouse_pos = None;
        }
    }
}

fn glfw_map_key(keycode: glfw::Key) -> keyboard::Key {
    match keycode {
        glfw::Key0 => keyboard::D0,
        glfw::Key1 => keyboard::D1,
        glfw::Key2 => keyboard::D2,
        glfw::Key3 => keyboard::D3,
        glfw::Key4 => keyboard::D4,
        glfw::Key5 => keyboard::D5,
        glfw::Key6 => keyboard::D6,
        glfw::Key7 => keyboard::D7,
        glfw::Key8 => keyboard::D8,
        glfw::Key9 => keyboard::D9,
        glfw::KeyA => keyboard::A,
        glfw::KeyB => keyboard::B,
        glfw::KeyC => keyboard::C,
        glfw::KeyD => keyboard::D,
        glfw::KeyE => keyboard::E,
        glfw::KeyF => keyboard::F,
        glfw::KeyG => keyboard::G,
        glfw::KeyH => keyboard::H,
        glfw::KeyI => keyboard::I,
        glfw::KeyJ => keyboard::J,
        glfw::KeyK => keyboard::K,
        glfw::KeyL => keyboard::L,
        glfw::KeyM => keyboard::M,
        glfw::KeyN => keyboard::N,
        glfw::KeyO => keyboard::O,
        glfw::KeyP => keyboard::P,
        glfw::KeyQ => keyboard::Q,
        glfw::KeyR => keyboard::R,
        glfw::KeyS => keyboard::S,
        glfw::KeyT => keyboard::T,
        glfw::KeyU => keyboard::U,
        glfw::KeyV => keyboard::V,
        glfw::KeyW => keyboard::W,
        glfw::KeyX => keyboard::X,
        glfw::KeyY => keyboard::Y,
        glfw::KeyZ => keyboard::Z,
        glfw::KeyApostrophe => keyboard::Unknown,
        glfw::KeyBackslash => keyboard::Backslash,
        glfw::KeyBackspace => keyboard::Backspace,
        glfw::KeyCapsLock => keyboard::CapsLock,
        glfw::KeyDelete => keyboard::Delete,
        glfw::KeyComma => keyboard::Comma,
        glfw::KeyDown => keyboard::Down,
        glfw::KeyEnd => keyboard::End,
        glfw::KeyEnter => keyboard::Return,
        glfw::KeyEqual => keyboard::Equals,
        glfw::KeyEscape => keyboard::Escape,
        glfw::KeyF1 => keyboard::F1,
        glfw::KeyF2 => keyboard::F2,
        glfw::KeyF3 => keyboard::F3,
        glfw::KeyF4 => keyboard::F4,
        glfw::KeyF5 => keyboard::F5,
        glfw::KeyF6 => keyboard::F6,
        glfw::KeyF7 => keyboard::F7,
        glfw::KeyF8 => keyboard::F8,
        glfw::KeyF9 => keyboard::F9,
        glfw::KeyF10 => keyboard::F10,
        glfw::KeyF11 => keyboard::F11,
        glfw::KeyF12 => keyboard::F12,
        glfw::KeyF13 => keyboard::F13,
        glfw::KeyF14 => keyboard::F14,
        glfw::KeyF15 => keyboard::F15,
        glfw::KeyF16 => keyboard::F16,
        glfw::KeyF17 => keyboard::F17,
        glfw::KeyF18 => keyboard::F18,
        glfw::KeyF19 => keyboard::F19,
        glfw::KeyF20 => keyboard::F20,
        glfw::KeyF21 => keyboard::F21,
        glfw::KeyF22 => keyboard::F22,
        glfw::KeyF23 => keyboard::F23,
        glfw::KeyF24 => keyboard::F24,
        // Possibly next code.
        glfw::KeyF25 => keyboard::Unknown,
        glfw::KeyKp0 => keyboard::NumPad0,
        glfw::KeyKp1 => keyboard::NumPad1,
        glfw::KeyKp2 => keyboard::NumPad2,
        glfw::KeyKp3 => keyboard::NumPad3,
        glfw::KeyKp4 => keyboard::NumPad4,
        glfw::KeyKp5 => keyboard::NumPad5,
        glfw::KeyKp6 => keyboard::NumPad6,
        glfw::KeyKp7 => keyboard::NumPad7,
        glfw::KeyKp8 => keyboard::NumPad8,
        glfw::KeyKp9 => keyboard::NumPad9,
        glfw::KeyKpDecimal => keyboard::NumPadDecimal,
        glfw::KeyKpDivide => keyboard::NumPadDivide,
        glfw::KeyKpMultiply => keyboard::NumPadMultiply,
        glfw::KeyKpSubtract => keyboard::NumPadMinus,
        glfw::KeyKpAdd => keyboard::NumPadPlus,
        glfw::KeyKpEnter => keyboard::NumPadEnter,
        glfw::KeyKpEqual => keyboard::NumPadEquals,
        glfw::KeyLeftShift => keyboard::LShift,
        glfw::KeyLeftControl => keyboard::LCtrl,
        glfw::KeyLeftAlt => keyboard::LAlt,
        glfw::KeyLeftSuper => keyboard::LGui,
        glfw::KeyRightShift => keyboard::RShift,
        glfw::KeyRightControl => keyboard::RCtrl,
        glfw::KeyRightAlt => keyboard::RAlt,
        glfw::KeyRightSuper => keyboard::RGui,
        // Map to backslash?
        glfw::KeyGraveAccent => keyboard::Unknown,
        glfw::KeyHome => keyboard::Home,
        glfw::KeyInsert => keyboard::Insert,
        glfw::KeyLeft => keyboard::Left,
        glfw::KeyLeftBracket => keyboard::LeftBracket,
        glfw::KeyMenu => keyboard::Menu,
        glfw::KeyMinus => keyboard::Minus,
        glfw::KeyNumLock => keyboard::NumLockClear,
        glfw::KeyPageDown => keyboard::PageDown,
        glfw::KeyPageUp => keyboard::PageUp,
        glfw::KeyPause => keyboard::Pause,
        glfw::KeyPeriod => keyboard::Period,
        glfw::KeyPrintScreen => keyboard::PrintScreen,
        glfw::KeyRight => keyboard::Right,
        glfw::KeyRightBracket => keyboard::RightBracket,
        glfw::KeyScrollLock => keyboard::ScrollLock,
        glfw::KeySemicolon => keyboard::Semicolon,
        glfw::KeySlash => keyboard::Slash,
        glfw::KeySpace => keyboard::Space,
        glfw::KeyTab => keyboard::Tab,
        glfw::KeyUp => keyboard::Up,
        glfw::KeyWorld1 => keyboard::Unknown,
        glfw::KeyWorld2 => keyboard::Unknown,
        // _ => keyboard::Unknown,
    }
}

fn glfw_map_mouse(mouse_button: glfw::MouseButton) -> mouse::Button {
    match mouse_button {
        glfw::MouseButton1 => mouse::Left,
        glfw::MouseButton2 => mouse::Right,
        glfw::MouseButton3 => mouse::Middle,
        glfw::MouseButton4 => mouse::X1,
        glfw::MouseButton5 => mouse::X2,
        glfw::MouseButton6 => mouse::Button6,
        glfw::MouseButton7 => mouse::Button7,
        glfw::MouseButton8 => mouse::Button8,
    }
}
<|endoftext|>


<commit_before>#[allow(non_snake_case, dead_code, non_camel_case_types)]
mod geodesic;

pub struct Geodesic {
    g: geodesic::Struct_geod_geodesic,
}

impl Geodesic {
    pub fn new(a: f64, f: f64) -> Geodesic {
        let mut g = geodesic::Struct_geod_geodesic::default();
        unsafe {
            geodesic::geod_init(&mut g, a, f);
        }
        Geodesic { g: g }
    }
    pub fn direct(&self, lat1: f64, lon1: f64, azi1: f64, s12: f64) -> (f64, f64, f64) {
        let mut lat2 = std::f64::NAN;
        let mut lon2 = std::f64::NAN;
        let mut azi2 = std::f64::NAN;
        unsafe {
            geodesic::geod_direct(&self.g,
                                  lat1,
                                  lon1,
                                  azi1,
                                  s12,
                                  &mut lat2,
                                  &mut lon2,
                                  &mut azi2);
        }
        (lat2, lon2, azi2)
    }
    pub fn inverse(&self, lat1: f64, lon1: f64, lat2: f64, lon2: f64) -> (f64, f64, f64) {
        let mut s12 = std::f64::NAN;
        let mut azi1 = std::f64::NAN;
        let mut azi2 = std::f64::NAN;
        unsafe {
            geodesic::geod_inverse(&self.g,
                                   lat1,
                                   lon1,
                                   lat2,
                                   lon2,
                                   &mut s12,
                                   &mut azi1,
                                   &mut azi2);
        }
        (s12, azi1, azi2)
    }
}
<commit_msg>Add WGS84 geoid<commit_after>#[allow(non_snake_case, dead_code, non_camel_case_types)]
mod geodesic;

pub struct Geodesic {
    g: geodesic::Struct_geod_geodesic,
}

impl Geodesic {
    pub fn new(a: f64, f: f64) -> Geodesic {
        let mut g = geodesic::Struct_geod_geodesic::default();
        unsafe {
            geodesic::geod_init(&mut g, a, f);
        }
        Geodesic { g: g }
    }
    pub fn wgs84() -> Geodesic {
        Geodesic::new(6378137.0, 1.0 / 298.257223563)
    }
    pub fn direct(&self, lat1: f64, lon1: f64, azi1: f64, s12: f64) -> (f64, f64, f64) {
        let mut lat2 = std::f64::NAN;
        let mut lon2 = std::f64::NAN;
        let mut azi2 = std::f64::NAN;
        unsafe {
            geodesic::geod_direct(&self.g,
                                  lat1,
                                  lon1,
                                  azi1,
                                  s12,
                                  &mut lat2,
                                  &mut lon2,
                                  &mut azi2);
        }
        (lat2, lon2, azi2)
    }
    pub fn inverse(&self, lat1: f64, lon1: f64, lat2: f64, lon2: f64) -> (f64, f64, f64) {
        let mut s12 = std::f64::NAN;
        let mut azi1 = std::f64::NAN;
        let mut azi2 = std::f64::NAN;
        unsafe {
            geodesic::geod_inverse(&self.g,
                                   lat1,
                                   lon1,
                                   lat2,
                                   lon2,
                                   &mut s12,
                                   &mut azi1,
                                   &mut azi2);
        }
        (s12, azi1, azi2)
    }
}
<|endoftext|>


<commit_before>#![feature(trace_macros)]
#![feature(log_syntax)]

extern crate num;
extern crate rand;
extern crate rutorch;
#[macro_use]
extern crate modparse_derive;
extern crate linked_hash_map;

pub mod nn;
use rutorch::*;
use std::ops::{Index, IndexMut};
//use std::convert::From;
use std::cmp::max;
use std::slice;

trait Storage {
    fn new() -> Self;
    fn sized(len: isize) -> Self;
}

pub struct FloatStorage {
    t: *mut THFloatStorage,
}

impl Storage for FloatStorage {
    fn new() -> Self {
        unsafe { FloatStorage { t: THFloatStorage_new() } }
    }
    fn sized(size: isize) -> Self {
        unsafe { FloatStorage { t: THFloatStorage_newWithSize(size) } }
    }
}
// XXX annotate with lifetime for safety's sake
impl FloatStorage {
    fn into_slice(&self) -> &[f32] {
        unsafe { slice::from_raw_parts((*self.t).data, (*self.t).size as usize) }
    }
    fn into_slice_mut(&mut self) -> &mut [f32] {
        unsafe { slice::from_raw_parts_mut((*self.t).data, (*self.t).size as usize) }
    }
    pub fn iter(&self) -> slice::Iter<f32> {
        self.into_slice().iter()
    }
    pub fn iter_mut(&mut self) -> slice::IterMut<f32> {
        self.into_slice_mut().iter_mut()
    }
}

impl Index<isize> for FloatStorage {
    type Output = f32;

    fn index(&self, idx: isize) -> &f32 {
        unsafe { &*(*self.t).data.offset(idx) }
    }
}

impl IndexMut<isize> for FloatStorage {
    fn index_mut(&mut self, idx: isize) -> &mut f32 {
        unsafe { &mut *(*self.t).data.offset(idx) }
    }
}

//fn from(args: &ArgsArray<T>) -> Self;

trait Tensor {
	 fn _dummy(&self);
}

pub struct FloatTensor {
    t: *mut THFloatTensor,
    storage: FloatStorage,
    dims: Vec<isize>,
}

pub struct Parameter {
	data: Tensor,
}

impl FloatTensor {
    fn new() -> Self {
        unsafe {
            FloatTensor {
                t: THFloatTensor_new(),
                storage: FloatStorage::new(),
                dims: Vec::new(),
            }
        }
    }

    fn sized(dims: & [isize]) -> Self {
        let size = dims.iter().product();
        let storage = FloatStorage::sized(size);
        let strides = vec![1; dims.len()];
        let mut t = THFloatTensor {
            size: dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
            stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
            nDimension: dims.len() as i32,
            storage: storage.t,
            storageOffset: 0,
            refcount: 1,
            flag: TH_TENSOR_REFCOUNTED as i8,
        };
        FloatTensor {
            t: &mut t,
            storage: storage,
            dims: Vec::from(dims),
        }
    }
    fn randn(dims: & [isize]) -> Self {
        /* XXX */
        let mut t = FloatTensor::sized(dims);
        for x in t.storage.iter_mut() {
            *x = rand::random::<f32>()
        }
        t
    }
}

impl<'a> Index<&'a [isize]> for FloatTensor {
    type Output = f32;

    fn index(&self, idx: &'a [isize]) -> &f32 {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &self.storage[index]
    }
}

impl<'a> IndexMut<&'a [isize]> for FloatTensor {
    fn index_mut(&mut self, idx: &'a [isize]) -> &mut f32 {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &mut self.storage[index]
    }
}

/*
    def __init__(self):
        self._backend = thnn_backend
        self._parameters = OrderedDict()
        self._buffers = OrderedDict()
        self._backward_hooks = OrderedDict()
        self._forward_hooks = OrderedDict()
        self._modules = OrderedDict()
        self.training = True
*/

/*
impl fmt::Display for FloatTensor {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match (*self.t).size
		write!(f, "[torchrs.FloatTensor of size ]")
	}
}
*/
#[cfg(test)]
mod tests {
    use super::*;
    use nn::*;

#[derive(ModParse)]

pub struct MyModSmallA<'a> {
	delegate: Module<'a>,
}

impl <'a>MyModSmallA<'a> {
	pub fn new() -> Self {
		let mut t = MyModSmallA {delegate: Module::new()};
		t.init_module();
		t
	}
}

#[derive(ModParse)]
pub struct MyModBig<'a> {
	delegate: Module<'a>,
	#[module]
	a: Linear<'a> ,
	#[module]
	b: MyModSmallA<'a>
}

impl <'a>ModIntf<'a> for MyModBig<'a> {
	fn delegate(&mut self) -> &mut Module<'a> {
				&mut self.delegate

	}
	fn forward(&mut self /* Tensor */ ) /* -> Tensor */{}
}
impl <'a>ModIntf<'a> for MyModSmallA<'a> {
	fn delegate(&mut self) -> &mut Module<'a> {
				&mut self.delegate

	}
	fn forward(&mut self /* Tensor */ ) /* -> Tensor */{}
}
impl <'a> MyModBig<'a> {
	pub fn new() -> MyModBig<'a>  {
		let mut t = MyModBig {delegate: Module::new(),
			a: Linear::new(), b: MyModSmallA::new()} ;
		t.init_module();
		t
	}
}

    #[test]
    fn it_works() {
    	let x = MyModBig::new();
    }
}
<commit_msg> make Tensor trait public<commit_after>#![feature(trace_macros)]
#![feature(log_syntax)]

extern crate num;
extern crate rand;
extern crate rutorch;
#[macro_use]
extern crate modparse_derive;
extern crate linked_hash_map;

pub mod nn;
use rutorch::*;
use std::ops::{Index, IndexMut};
//use std::convert::From;
use std::cmp::max;
use std::slice;

trait Storage {
    fn new() -> Self;
    fn sized(len: isize) -> Self;
}

pub struct FloatStorage {
    t: *mut THFloatStorage,
}

impl Storage for FloatStorage {
    fn new() -> Self {
        unsafe { FloatStorage { t: THFloatStorage_new() } }
    }
    fn sized(size: isize) -> Self {
        unsafe { FloatStorage { t: THFloatStorage_newWithSize(size) } }
    }
}
// XXX annotate with lifetime for safety's sake
impl FloatStorage {
    fn into_slice(&self) -> &[f32] {
        unsafe { slice::from_raw_parts((*self.t).data, (*self.t).size as usize) }
    }
    fn into_slice_mut(&mut self) -> &mut [f32] {
        unsafe { slice::from_raw_parts_mut((*self.t).data, (*self.t).size as usize) }
    }
    pub fn iter(&self) -> slice::Iter<f32> {
        self.into_slice().iter()
    }
    pub fn iter_mut(&mut self) -> slice::IterMut<f32> {
        self.into_slice_mut().iter_mut()
    }
}

impl Index<isize> for FloatStorage {
    type Output = f32;

    fn index(&self, idx: isize) -> &f32 {
        unsafe { &*(*self.t).data.offset(idx) }
    }
}

impl IndexMut<isize> for FloatStorage {
    fn index_mut(&mut self, idx: isize) -> &mut f32 {
        unsafe { &mut *(*self.t).data.offset(idx) }
    }
}

//fn from(args: &ArgsArray<T>) -> Self;

pub trait Tensor {
	 fn _dummy(&self);
}

pub struct FloatTensor {
    t: *mut THFloatTensor,
    storage: FloatStorage,
    dims: Vec<isize>,
}

pub struct Parameter {
	data: Tensor,
}

impl FloatTensor {
    fn new() -> Self {
        unsafe {
            FloatTensor {
                t: THFloatTensor_new(),
                storage: FloatStorage::new(),
                dims: Vec::new(),
            }
        }
    }

    fn sized(dims: & [isize]) -> Self {
        let size = dims.iter().product();
        let storage = FloatStorage::sized(size);
        let strides = vec![1; dims.len()];
        let mut t = THFloatTensor {
            size: dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
            stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
            nDimension: dims.len() as i32,
            storage: storage.t,
            storageOffset: 0,
            refcount: 1,
            flag: TH_TENSOR_REFCOUNTED as i8,
        };
        FloatTensor {
            t: &mut t,
            storage: storage,
            dims: Vec::from(dims),
        }
    }
    fn randn(dims: & [isize]) -> Self {
        /* XXX */
        let mut t = FloatTensor::sized(dims);
        for x in t.storage.iter_mut() {
            *x = rand::random::<f32>()
        }
        t
    }
}

impl<'a> Index<&'a [isize]> for FloatTensor {
    type Output = f32;

    fn index(&self, idx: &'a [isize]) -> &f32 {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &self.storage[index]
    }
}

impl<'a> IndexMut<&'a [isize]> for FloatTensor {
    fn index_mut(&mut self, idx: &'a [isize]) -> &mut f32 {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &mut self.storage[index]
    }
}

/*
    def __init__(self):
        self._backend = thnn_backend
        self._parameters = OrderedDict()
        self._buffers = OrderedDict()
        self._backward_hooks = OrderedDict()
        self._forward_hooks = OrderedDict()
        self._modules = OrderedDict()
        self.training = True
*/

/*
impl fmt::Display for FloatTensor {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match (*self.t).size
		write!(f, "[torchrs.FloatTensor of size ]")
	}
}
*/
#[cfg(test)]
mod tests {
    use super::*;
    use nn::*;

#[derive(ModParse)]

pub struct MyModSmallA<'a> {
	delegate: Module<'a>,
}

impl <'a>MyModSmallA<'a> {
	pub fn new() -> Self {
		let mut t = MyModSmallA {delegate: Module::new()};
		t.init_module();
		t
	}
}

#[derive(ModParse)]
pub struct MyModBig<'a> {
	delegate: Module<'a>,
	#[module]
	a: Linear<'a> ,
	#[module]
	b: MyModSmallA<'a>
}

impl <'a>ModIntf<'a> for MyModBig<'a> {
	fn delegate(&mut self) -> &mut Module<'a> {
				&mut self.delegate

	}
	fn forward(&mut self /* Tensor */ ) /* -> Tensor */{}
}
impl <'a>ModIntf<'a> for MyModSmallA<'a> {
	fn delegate(&mut self) -> &mut Module<'a> {
				&mut self.delegate

	}
	fn forward(&mut self /* Tensor */ ) /* -> Tensor */{}
}
impl <'a> MyModBig<'a> {
	pub fn new() -> MyModBig<'a>  {
		let mut t = MyModBig {delegate: Module::new(),
			a: Linear::new(), b: MyModSmallA::new()} ;
		t.init_module();
		t
	}
}

    #[test]
    fn it_works() {
    	let x = MyModBig::new();
    }
}
<|endoftext|>


<commit_before>#![feature(alloc_system)]

extern crate alloc_system;
extern crate num;
extern crate fnv;
#[macro_use]
extern crate nock;

use std::rc::Rc;
use std::collections::HashMap;
use nock::{Nock, Noun, NockError, NockResult, Shape, FromNoun};
use jet::Jet;

mod jet;
mod jets;

/// An Urbit virtual machine.
pub struct VM {
    jets: HashMap<Noun, jet::Jet>,
}

impl Nock for VM {
    fn call(&mut self, subject: &Noun, formula: &Noun) -> Option<NockResult> {
        if let Some(jet) = self.jets.get_mut(formula) {
            jet.calls += 1;

            if let Some(f) = jet.jet {
                return Some(f(subject));
            }
        }
        None
    }

    fn hint(&mut self, subject: &Noun, hint: &Noun, c: &Noun) -> Result<(), NockError> {
        let (id, clue) = match hint.get() {
            Shape::Cell(ref p, ref q) => {
                (*p, try!(self.nock_on((*subject).clone(), (*q).clone())))
            }
            Shape::Atom(_) => (hint, Noun::from(0u32)),
        };

        // TODO: Handle other hint types than %fast.
        if String::from_noun(id).unwrap() == "fast" {
            let core = try!(self.nock_on((*subject).clone(), (*c).clone()));
            if let Ok((name, axis, hooks)) = parse_fast_clue(&clue) {
                if let Shape::Cell(ref battery, _) = core.get() {
                    if !self.jets.contains_key(battery) {
                        let jet = Jet::new(name, (*battery).clone(), axis, hooks);
                        self.jets.insert((*battery).clone(), jet);
                    }
                } else {
                    return Err(NockError(format!("hint")));
                }
            } else {
                // println!("Unparseable clue...");
            }
        }
        Ok(())
    }
}

impl VM {
    pub fn new() -> VM {
        VM { jets: HashMap::new() }
    }

    pub fn print_status(&self) {
        let mut total_count = 0;
        let mut jets: Vec<&Jet> = self.jets.iter().map(|(_, x)| x).collect();
        jets.sort_by(|a, b| b.calls.cmp(&a.calls));
        for jet in &jets {
            if jet.calls < 100 || (jet.calls as f32) / (total_count as f32) < 1e-6 {
                // Don't care about the little things
                println!(" ...");
                break;
            }
            println!("{}{} called {} times",
                     if jet.jet.is_some() {
                         '*'
                     } else {
                         ' '
                     },
                     jet.name,
                     jet.calls);
            total_count += jet.calls;
        }
    }
}

fn parse_fast_clue(clue: &Noun) -> Result<(String, u32, Vec<(String, Noun)>), NockError> {
    if let Some((ref name, ref axis_formula, ref hooks)) = clue.get_122() {
        let chum = try!(String::from_noun(name).map_err(|_| NockError(format!("hint"))));

        let axis = if let Shape::Cell(ref a, ref b) = axis_formula.get() {
            if let (Some(1), Some(0)) = (a.as_u32(), b.as_u32()) {
                0
            } else if let (Some(0), Some(axis)) = (a.as_u32(), b.as_u32()) {
                axis
            } else {
                return Err(NockError(format!("hint")));
            }
        } else {
            return Err(NockError(format!("hint")));
        };

        let hooks: Vec<(String, Noun)> = try!(FromNoun::from_noun(hooks)
                                                  .map_err(|_| NockError(format!("hint"))));

        Ok((chum, axis, hooks))
    } else {
        Err(NockError(format!("hint")))
    }
}

/// A human-readable hash version.
pub fn symhash(noun: &Noun) -> String {
    fn proquint(buf: &mut String, mut b: u16) {
        const C: [char; 16] = ['b', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's',
                               't', 'v', 'z'];
        const V: [char; 4] = ['a', 'i', 'o', 'u'];
        buf.push(C[(b % 16) as usize]);
        b >>= 4;
        buf.push(V[(b % 4) as usize]);
        b >>= 2;
        buf.push(C[(b % 16) as usize]);
        b >>= 4;
        buf.push(V[(b % 4) as usize]);
        b >>= 2;
        buf.push(C[(b % 16) as usize]);
    }

    let mut hash = noun.mug();
    let mut ret = String::new();
    proquint(&mut ret, (hash % 0xFFFF) as u16);
    hash >>= 16;
    ret.push('-');
    proquint(&mut ret, (hash % 0xFFFF) as u16);

    ret
}

/// Unpack the data of an Urbit pillfile into a Nock noun.
pub fn unpack_pill(mut buf: Vec<u8>) -> jet::JetResult<Noun> {
    // Guarantee that the buffer is made of 32-bit chunks.
    while buf.len() % 4 != 0 {
        buf.push(0);
    }

    jets::cue(Rc::new(buf))
}

#[cfg(test)]
mod test {
    use nock::Noun;

    #[test]
    fn test_read_pill() {
        use super::unpack_pill;

        let noun: Noun = "[18.446.744.073.709.551.616 8 [1 0] 8 [1 6 [5 [0 7] 4 0 6] [0 6] 9 2 [0 \
                          2] [4 0 6] 0 7] 9 2 0 1]"
                             .parse()
                             .expect("Nock parse error");
        let pill: &[u8] = &[0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
                            0xc1, 0x62, 0x83, 0x60, 0x71, 0xd8, 0x85, 0x5b, 0xe2, 0x87, 0x99,
                            0xd8, 0x0d, 0xc1, 0x1a, 0x24, 0x43, 0x96, 0xc8, 0x86, 0x10, 0x1d,
                            0xc2, 0x32, 0x48, 0x86, 0x4c, 0x06];
        let unpacked = unpack_pill(pill.to_vec()).expect("Pill unpack failed");
        assert_eq!(noun, unpacked);
    }

    #[test]
    fn test_cue_stack() {
        use super::unpack_pill;

        let noun: Noun = "[1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]"
                             .parse()
                             .expect("Nock parse error");
        let pill: &[u8] = "qffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
                           fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
                           fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffj"
                              .as_bytes();
        let unpacked = unpack_pill(pill.to_vec()).expect("Pill unpack failed");
        assert_eq!(noun, unpacked);
    }
}
<commit_msg>Remove the unstable rust requiring alloc bit<commit_after>extern crate num;
extern crate fnv;
extern crate nock;

use std::rc::Rc;
use std::collections::HashMap;
use nock::{Nock, Noun, NockError, NockResult, Shape, FromNoun};
use jet::Jet;

mod jet;
mod jets;

/// An Urbit virtual machine.
pub struct VM {
    jets: HashMap<Noun, jet::Jet>,
}

impl Nock for VM {
    fn call(&mut self, subject: &Noun, formula: &Noun) -> Option<NockResult> {
        if let Some(jet) = self.jets.get_mut(formula) {
            jet.calls += 1;

            if let Some(f) = jet.jet {
                return Some(f(subject));
            }
        }
        None
    }

    fn hint(&mut self, subject: &Noun, hint: &Noun, c: &Noun) -> Result<(), NockError> {
        let (id, clue) = match hint.get() {
            Shape::Cell(ref p, ref q) => {
                (*p, try!(self.nock_on((*subject).clone(), (*q).clone())))
            }
            Shape::Atom(_) => (hint, Noun::from(0u32)),
        };

        // TODO: Handle other hint types than %fast.
        if String::from_noun(id).unwrap() == "fast" {
            let core = try!(self.nock_on((*subject).clone(), (*c).clone()));
            if let Ok((name, axis, hooks)) = parse_fast_clue(&clue) {
                if let Shape::Cell(ref battery, _) = core.get() {
                    if !self.jets.contains_key(battery) {
                        let jet = Jet::new(name, (*battery).clone(), axis, hooks);
                        self.jets.insert((*battery).clone(), jet);
                    }
                } else {
                    return Err(NockError(format!("hint")));
                }
            } else {
                // println!("Unparseable clue...");
            }
        }
        Ok(())
    }
}

impl VM {
    pub fn new() -> VM {
        VM { jets: HashMap::new() }
    }

    pub fn print_status(&self) {
        let mut total_count = 0;
        let mut jets: Vec<&Jet> = self.jets.iter().map(|(_, x)| x).collect();
        jets.sort_by(|a, b| b.calls.cmp(&a.calls));
        for jet in &jets {
            if jet.calls < 100 || (jet.calls as f32) / (total_count as f32) < 1e-6 {
                // Don't care about the little things
                println!(" ...");
                break;
            }
            println!("{}{} called {} times",
                     if jet.jet.is_some() {
                         '*'
                     } else {
                         ' '
                     },
                     jet.name,
                     jet.calls);
            total_count += jet.calls;
        }
    }
}

fn parse_fast_clue(clue: &Noun) -> Result<(String, u32, Vec<(String, Noun)>), NockError> {
    if let Some((ref name, ref axis_formula, ref hooks)) = clue.get_122() {
        let chum = try!(String::from_noun(name).map_err(|_| NockError(format!("hint"))));

        let axis = if let Shape::Cell(ref a, ref b) = axis_formula.get() {
            if let (Some(1), Some(0)) = (a.as_u32(), b.as_u32()) {
                0
            } else if let (Some(0), Some(axis)) = (a.as_u32(), b.as_u32()) {
                axis
            } else {
                return Err(NockError(format!("hint")));
            }
        } else {
            return Err(NockError(format!("hint")));
        };

        let hooks: Vec<(String, Noun)> = try!(FromNoun::from_noun(hooks)
                                                  .map_err(|_| NockError(format!("hint"))));

        Ok((chum, axis, hooks))
    } else {
        Err(NockError(format!("hint")))
    }
}

/// A human-readable hash version.
pub fn symhash(noun: &Noun) -> String {
    fn proquint(buf: &mut String, mut b: u16) {
        const C: [char; 16] = ['b', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's',
                               't', 'v', 'z'];
        const V: [char; 4] = ['a', 'i', 'o', 'u'];
        buf.push(C[(b % 16) as usize]);
        b >>= 4;
        buf.push(V[(b % 4) as usize]);
        b >>= 2;
        buf.push(C[(b % 16) as usize]);
        b >>= 4;
        buf.push(V[(b % 4) as usize]);
        b >>= 2;
        buf.push(C[(b % 16) as usize]);
    }

    let mut hash = noun.mug();
    let mut ret = String::new();
    proquint(&mut ret, (hash % 0xFFFF) as u16);
    hash >>= 16;
    ret.push('-');
    proquint(&mut ret, (hash % 0xFFFF) as u16);

    ret
}

/// Unpack the data of an Urbit pillfile into a Nock noun.
pub fn unpack_pill(mut buf: Vec<u8>) -> jet::JetResult<Noun> {
    // Guarantee that the buffer is made of 32-bit chunks.
    while buf.len() % 4 != 0 {
        buf.push(0);
    }

    jets::cue(Rc::new(buf))
}

#[cfg(test)]
mod test {
    use nock::Noun;

    #[test]
    fn test_read_pill() {
        use super::unpack_pill;

        let noun: Noun = "[18.446.744.073.709.551.616 8 [1 0] 8 [1 6 [5 [0 7] 4 0 6] [0 6] 9 2 [0 \
                          2] [4 0 6] 0 7] 9 2 0 1]"
                             .parse()
                             .expect("Nock parse error");
        let pill: &[u8] = &[0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
                            0xc1, 0x62, 0x83, 0x60, 0x71, 0xd8, 0x85, 0x5b, 0xe2, 0x87, 0x99,
                            0xd8, 0x0d, 0xc1, 0x1a, 0x24, 0x43, 0x96, 0xc8, 0x86, 0x10, 0x1d,
                            0xc2, 0x32, 0x48, 0x86, 0x4c, 0x06];
        let unpacked = unpack_pill(pill.to_vec()).expect("Pill unpack failed");
        assert_eq!(noun, unpacked);
    }

    #[test]
    fn test_cue_stack() {
        use super::unpack_pill;

        let noun: Noun = "[1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \
                          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]"
                             .parse()
                             .expect("Nock parse error");
        let pill: &[u8] = "qffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
                           fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
                           fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffj"
                              .as_bytes();
        let unpacked = unpack_pill(pill.to_vec()).expect("Pill unpack failed");
        assert_eq!(noun, unpacked);
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::cell::RefCell;

pub mod io;

thread_local!(static EVENT_LOOP: RefCell<Option<EventLoop>> = RefCell::new(None));

fn with_current_event_loop<F, R>(f: F) -> R
    where F: FnOnce(&mut EventLoop) -> R {
        EVENT_LOOP.with(|maybe_event_loop| {
            match &mut *maybe_event_loop.borrow_mut() {
                &mut None => panic!("current thread has no event loop"),
                &mut Some(ref mut event_loop) => f(event_loop),
            }
        })
    }

pub type Error = Box<::std::error::Error>;
pub type Result<T> = ::std::result::Result<T, Error>;

pub struct Promise<T> where T: 'static {
    pub node : Box<PromiseNode<T>>,
}

impl <T> Promise <T> where T: 'static {
    pub fn then<F, R>(self, func: F) -> Promise<R>
        where F: 'static + FnOnce(T) -> Result<Promise<R>>,
              R: 'static {
                  self.then_else(func, |e| { return Err(e); })
        }

    pub fn then_else<F, G, R>(self, _func: F, _error_handler: G) -> Promise<R>
        where F: 'static + FnOnce(T) -> Result<Promise<R>>,
              G: 'static + FnOnce(Error) -> Result<R>,
              R: 'static {
                  unimplemented!();
        }

    pub fn map<F, R>(self, func: F) -> Promise<R>
        where F: 'static + FnOnce(T) -> Result<R>,
              R: 'static {
            self.map_else(func, |e| { return Err(e); })
        }

    pub fn map_else<F, G, R>(self, func: F, error_handler: G) -> Promise<R>
        where F: 'static + FnOnce(T) -> Result<R>,
              G: 'static + FnOnce(Error) -> Result<R>,
              R: 'static {
            let node : Box<PromiseNode<R>> = Box::new(TransformPromiseNode::new(self.node, func, error_handler));
            Promise { node: node }
        }

    pub fn wait(mut self) -> Result<T> {
        with_current_event_loop(move |event_loop| {
            let fired = ::std::rc::Rc::new(::std::cell::Cell::new(false));
            let done_event = BoolEvent { fired: fired.clone()};
            self.node.on_ready(Box::new(done_event), event_loop);

            event_loop.running = true;

            while !fired.get() {
                if !event_loop.turn() {
                    // No events in the queue.
                    panic!("need to implement EventPort");
                }
            }

            self.node.get()
        })
    }

    pub fn fulfilled(value: T) -> Promise<T> {
        return Promise { node: Box::new(ImmediatePromiseNode { result: Ok(value) }) };
    }

    pub fn rejected(error: Error) -> Promise<T> {
        return Promise { node: Box::new(ImmediatePromiseNode { result: Err(error) }) };
    }
}

pub trait Event {
    fn fire(&mut self);

    /* TODO why doesn't this worked? Something about Sized?
    fn arm_breadth_first(self: Box<Self>) {
        with_current_event_loop(|event_loop| {
     //       event_loop.borrow_mut().arm_breadth_first(self);
        });
    } */
}

struct BoolEvent {
    fired: ::std::rc::Rc<::std::cell::Cell<bool>>,
}

impl Event for BoolEvent {
    fn fire(&mut self) {
        self.fired.set(true);
    }
}

pub trait PromiseNode<T> {
    /// Arms the given event when the promised value is ready.
    fn on_ready(&mut self, event: Box<Event>, event_loop: &mut EventLoop);

    fn set_self_pointer(&mut self) {}
    fn get(self: Box<Self>) -> Result<T>;
}

/// A PromiseNode that transforms the result of another PromiseNode through an application-provided
/// function (implements `then()`).
pub struct TransformPromiseNode<T, DepT, Func, ErrorFunc>
where Func: FnOnce(DepT) -> Result<T>, ErrorFunc: FnOnce(Error) -> Result<T> {
    dependency: Box<PromiseNode<DepT>>,
    func: Func,
    error_handler: ErrorFunc,
}

impl <T, DepT, Func, ErrorFunc> TransformPromiseNode<T, DepT, Func, ErrorFunc>
where Func: FnOnce(DepT) -> Result<T>, ErrorFunc: FnOnce(Error) -> Result<T> {
    fn new(dependency: Box<PromiseNode<DepT>>, func: Func, error_handler: ErrorFunc)
           -> TransformPromiseNode<T, DepT, Func, ErrorFunc> {
        TransformPromiseNode { dependency : dependency,
                               func: func, error_handler: error_handler }
    }
}

impl <T, DepT, Func, ErrorFunc> PromiseNode<T> for TransformPromiseNode<T, DepT, Func, ErrorFunc>
where Func: FnOnce(DepT) -> Result<T>, ErrorFunc: FnOnce(Error) -> Result<T> {
    fn on_ready(&mut self, event: Box<Event>, event_loop: &mut EventLoop) {
        self.dependency.on_ready(event, event_loop);
    }
    fn get(self: Box<Self>) -> Result<T> {
        let tmp = *self;
        let TransformPromiseNode {dependency, func, error_handler} = tmp;
        match dependency.get() {
            Ok(value) => {
                func(value)
            }
            Err(e) => {
                error_handler(e)
            }
        }
    }
}

/// A promise that has already been resolved to an immediate value or error.
pub struct ImmediatePromiseNode<T> {
    result: Result<T>,
}

impl <T> PromiseNode<T> for ImmediatePromiseNode<T> {

    fn on_ready(&mut self, event: Box<Event>, event_loop: &mut EventLoop) {
        event_loop.arm_breadth_first(event);
    }
    fn get(self: Box<Self>) -> Result<T> {
        self.result
    }
}

trait ErrorHandler {
    fn task_failed(error: Error);
}

struct TaskSetImpl {
    error_handler: Box<ErrorHandler>,
}

/// A queue of events being executed in a loop.
pub struct EventLoop {
//    daemons: TaskSetImpl,
    running: bool,
    last_runnable_state: bool,
    events: ::std::collections::VecDeque<Box<Event>>,
    depth_first_events: ::std::collections::VecDeque<Box<Event>>,
}

impl EventLoop {
    pub fn init() {
        EVENT_LOOP.with(|maybe_event_loop| {
            let event_loop = EventLoop { running: false,
                                         last_runnable_state: false,
                                         events: ::std::collections::VecDeque::new(),
                                         depth_first_events: ::std::collections::VecDeque::new() };

            *maybe_event_loop.borrow_mut() = Some(event_loop);
        });
    }

    fn arm_depth_first(&mut self, event: Box<Event>) {
        self.depth_first_events.push_front(event);
    }

    fn arm_breadth_first(&mut self, event: Box<Event>) {
        self.events.push_back(event);
    }

    /// Run the event loop for `max_turn_count` turns or until there is nothing left to be done,
    /// whichever comes first. This never calls the `EventPort`'s `sleep()` or `poll()`. It will
    /// call the `EventPort`'s `set_runnable(false)` if the queue becomes empty.
    pub fn run(&mut self, max_turn_count : u32) {
        self.running = true;

        for _ in 0..max_turn_count {
            if !self.turn() {
                break;
            }
        }
    }

    fn turn(&mut self) -> bool {
        assert!(self.depth_first_events.is_empty());
        match self.events.pop_front() {
            None => return false,
            Some(mut event) => {
                // event->firing = true ?
                event.fire();
            }
        }
        while !self.depth_first_events.is_empty() {
            self.events.push_front(self.depth_first_events.pop_back().unwrap());
        }
        return true;
    }
}

/// A callback which can be used to fulfill a promise.
pub trait PromiseFulfiller<T> where T: 'static {
    fn fulfill(&mut self, value: T);
    fn reject(&mut self, error: Error);
}

pub enum OnReadyEvent {
    Empty,
    AlreadyReady,
    Full(Box<Event>),
}

impl OnReadyEvent {
    fn is_already_ready(&self) -> bool {
        match self {
            &OnReadyEvent::AlreadyReady => return true,
            _ => return false,
        }
    }

    fn is_empty(&self) -> bool {
        match self {
            &OnReadyEvent::Empty => return true,
            _ => return false,
        }
    }

    fn init(&mut self, new_event: Box<Event>, event_loop: &mut EventLoop) {
        if self.is_already_ready() {
            event_loop.arm_breadth_first(new_event);
        } else {
            *self = OnReadyEvent::Full(new_event);
        }
    }

    fn arm(&mut self) {
        if self.is_empty() {
            *self = OnReadyEvent::AlreadyReady;
        } else {
            let old_self = ::std::mem::replace(self, OnReadyEvent::Empty);
            match old_self {
                OnReadyEvent::Full(event) => {
                    with_current_event_loop(|event_loop| {
                        event_loop.arm_depth_first(event);
                    });
                }
                _ => {
                    panic!("armed an event twice?");
                }
            }
        }
    }
}

pub struct PromiseAndFulfillerHub<T> where T: 'static {
    result: Option<Result<T>>,
    on_ready_event: OnReadyEvent,
}

impl <T> PromiseFulfiller<T> for PromiseAndFulfillerHub<T> where T: 'static {
    fn fulfill(&mut self, value: T) {
        if self.result.is_none() {
            self.result = Some(Ok(value));
        }
        self.on_ready_event.arm();
    }

    fn reject(&mut self, error: Error) {
        if self.result.is_none() {
            self.result = Some(Err(error));
        }
    }
}

/*
pub struct WrapperPromiseNode<T> where T: 'static {
    hub: ::std::rc::Rc<::std::cell::RefCell<PromiseAndFulfillerHub<T>>>,
}
*/

impl <T> PromiseNode<T> for ::std::rc::Rc<::std::cell::RefCell<PromiseAndFulfillerHub<T>>> where T: 'static {
    fn on_ready(&mut self, event: Box<Event>, event_loop: &mut EventLoop) {
        self.borrow_mut().on_ready_event.init(event, event_loop);
    }
    fn get(self: Box<Self>) -> Result<T> {
        match ::std::mem::replace(&mut self.borrow_mut().result, None) {
            None => panic!("no result!"),
            Some(r) => r
        }
    }
}

impl <T> PromiseFulfiller<T> for ::std::rc::Rc<::std::cell::RefCell<PromiseAndFulfillerHub<T>>> where T: 'static {
    fn fulfill(&mut self, value: T) {
        self.borrow_mut().fulfill(value);
    }

    fn reject(&mut self, error: Error) {
        self.borrow_mut().reject(error);
    }
}

pub fn new_promise_and_fulfiller<T>() -> (Promise<T>, Box<PromiseFulfiller<T>>) where T: 'static {
    let result = ::std::rc::Rc::new(::std::cell::RefCell::new(
        PromiseAndFulfillerHub { result: None::<Result<T>>, on_ready_event: OnReadyEvent::Empty }));
    let result_promise : Promise<T> = Promise { node: Box::new(result.clone())};
    (result_promise, Box::new(result))
}
<commit_msg>Interior mutability for EventLoop.<commit_after>#![allow(dead_code)]

use std::cell::RefCell;

pub mod io;

thread_local!(static EVENT_LOOP: RefCell<Option<EventLoop>> = RefCell::new(None));

fn with_current_event_loop<F, R>(f: F) -> R
    where F: FnOnce(&EventLoop) -> R {
        EVENT_LOOP.with(|maybe_event_loop| {
            match &*maybe_event_loop.borrow() {
                &None => panic!("current thread has no event loop"),
                &Some(ref event_loop) => f(event_loop),
            }
        })
    }

pub type Error = Box<::std::error::Error>;
pub type Result<T> = ::std::result::Result<T, Error>;

pub struct Promise<T> where T: 'static {
    pub node : Box<PromiseNode<T>>,
}

impl <T> Promise <T> where T: 'static {
    pub fn then<F, R>(self, func: F) -> Promise<R>
        where F: 'static + FnOnce(T) -> Result<Promise<R>>,
              R: 'static {
                  self.then_else(func, |e| { return Err(e); })
        }

    pub fn then_else<F, G, R>(self, _func: F, _error_handler: G) -> Promise<R>
        where F: 'static + FnOnce(T) -> Result<Promise<R>>,
              G: 'static + FnOnce(Error) -> Result<R>,
              R: 'static {
                  unimplemented!();
        }

    pub fn map<F, R>(self, func: F) -> Promise<R>
        where F: 'static + FnOnce(T) -> Result<R>,
              R: 'static {
            self.map_else(func, |e| { return Err(e); })
        }

    pub fn map_else<F, G, R>(self, func: F, error_handler: G) -> Promise<R>
        where F: 'static + FnOnce(T) -> Result<R>,
              G: 'static + FnOnce(Error) -> Result<R>,
              R: 'static {
            let node : Box<PromiseNode<R>> = Box::new(TransformPromiseNode::new(self.node, func, error_handler));
            Promise { node: node }
        }

    pub fn wait(mut self) -> Result<T> {
        with_current_event_loop(move |event_loop| {
            let fired = ::std::rc::Rc::new(::std::cell::Cell::new(false));
            let done_event = BoolEvent { fired: fired.clone()};
            self.node.on_ready(Box::new(done_event));

            //event_loop.running = true;

            while !fired.get() {
                if !event_loop.turn() {
                    // No events in the queue.
                    panic!("need to implement EventPort");
                }
            }

            self.node.get()
        })
    }

    pub fn fulfilled(value: T) -> Promise<T> {
        return Promise { node: Box::new(ImmediatePromiseNode { result: Ok(value) }) };
    }

    pub fn rejected(error: Error) -> Promise<T> {
        return Promise { node: Box::new(ImmediatePromiseNode { result: Err(error) }) };
    }
}

pub trait Event {
    fn fire(&mut self);

    /* TODO why doesn't this worked? Something about Sized?
    fn arm_breadth_first(self: Box<Self>) {
        with_current_event_loop(|event_loop| {
     //       event_loop.borrow_mut().arm_breadth_first(self);
        });
    } */
}

struct BoolEvent {
    fired: ::std::rc::Rc<::std::cell::Cell<bool>>,
}

impl Event for BoolEvent {
    fn fire(&mut self) {
        self.fired.set(true);
    }
}

pub trait PromiseNode<T> {
    /// Arms the given event when the promised value is ready.
    fn on_ready(&mut self, event: Box<Event>);

    fn set_self_pointer(&mut self) {}
    fn get(self: Box<Self>) -> Result<T>;
}

/// A PromiseNode that transforms the result of another PromiseNode through an application-provided
/// function (implements `then()`).
pub struct TransformPromiseNode<T, DepT, Func, ErrorFunc>
where Func: FnOnce(DepT) -> Result<T>, ErrorFunc: FnOnce(Error) -> Result<T> {
    dependency: Box<PromiseNode<DepT>>,
    func: Func,
    error_handler: ErrorFunc,
}

impl <T, DepT, Func, ErrorFunc> TransformPromiseNode<T, DepT, Func, ErrorFunc>
where Func: FnOnce(DepT) -> Result<T>, ErrorFunc: FnOnce(Error) -> Result<T> {
    fn new(dependency: Box<PromiseNode<DepT>>, func: Func, error_handler: ErrorFunc)
           -> TransformPromiseNode<T, DepT, Func, ErrorFunc> {
        TransformPromiseNode { dependency : dependency,
                               func: func, error_handler: error_handler }
    }
}

impl <T, DepT, Func, ErrorFunc> PromiseNode<T> for TransformPromiseNode<T, DepT, Func, ErrorFunc>
where Func: FnOnce(DepT) -> Result<T>, ErrorFunc: FnOnce(Error) -> Result<T> {
    fn on_ready(&mut self, event: Box<Event>) {
        self.dependency.on_ready(event);
    }
    fn get(self: Box<Self>) -> Result<T> {
        let tmp = *self;
        let TransformPromiseNode {dependency, func, error_handler} = tmp;
        match dependency.get() {
            Ok(value) => {
                func(value)
            }
            Err(e) => {
                error_handler(e)
            }
        }
    }
}

/// A promise that has already been resolved to an immediate value or error.
pub struct ImmediatePromiseNode<T> {
    result: Result<T>,
}

impl <T> PromiseNode<T> for ImmediatePromiseNode<T> {

    fn on_ready(&mut self, event: Box<Event>) {
        with_current_event_loop(|event_loop| {
            event_loop.arm_breadth_first(event);
        });
    }
    fn get(self: Box<Self>) -> Result<T> {
        self.result
    }
}

trait ErrorHandler {
    fn task_failed(error: Error);
}

struct TaskSetImpl {
    error_handler: Box<ErrorHandler>,
}

/// A queue of events being executed in a loop.
pub struct EventLoop {
//    daemons: TaskSetImpl,
    running: bool,
    last_runnable_state: bool,
    events: RefCell<::std::collections::VecDeque<Box<Event>>>,
    depth_first_events: RefCell<::std::collections::VecDeque<Box<Event>>>,
}

impl EventLoop {
    pub fn init() {
        EVENT_LOOP.with(|maybe_event_loop| {
            let event_loop = EventLoop {
                running: false,
                last_runnable_state: false,
                events: RefCell::new(::std::collections::VecDeque::new()),
                depth_first_events: RefCell::new(::std::collections::VecDeque::new()) };

            *maybe_event_loop.borrow_mut() = Some(event_loop);
        });
    }

    fn arm_depth_first(&self, event: Box<Event>) {
        self.depth_first_events.borrow_mut().push_front(event);
    }

    fn arm_breadth_first(&self, event: Box<Event>) {
        self.events.borrow_mut().push_back(event);
    }

    /// Run the event loop for `max_turn_count` turns or until there is nothing left to be done,
    /// whichever comes first. This never calls the `EventPort`'s `sleep()` or `poll()`. It will
    /// call the `EventPort`'s `set_runnable(false)` if the queue becomes empty.
    pub fn run(&mut self, max_turn_count : u32) {
        self.running = true;

        for _ in 0..max_turn_count {
            if !self.turn() {
                break;
            }
        }
    }

    fn turn(&self) -> bool {
        assert!(self.depth_first_events.borrow().is_empty());
        match self.events.borrow_mut().pop_front() {
            None => return false,
            Some(mut event) => {
                // event->firing = true ?
                event.fire();
            }
        }
        while !self.depth_first_events.borrow().is_empty() {
            let event = self.depth_first_events.borrow_mut().pop_back().unwrap();
            self.events.borrow_mut().push_front(event);
        }
        return true;
    }
}

/// A callback which can be used to fulfill a promise.
pub trait PromiseFulfiller<T> where T: 'static {
    fn fulfill(&mut self, value: T);
    fn reject(&mut self, error: Error);
}

pub enum OnReadyEvent {
    Empty,
    AlreadyReady,
    Full(Box<Event>),
}

impl OnReadyEvent {
    fn is_already_ready(&self) -> bool {
        match self {
            &OnReadyEvent::AlreadyReady => return true,
            _ => return false,
        }
    }

    fn is_empty(&self) -> bool {
        match self {
            &OnReadyEvent::Empty => return true,
            _ => return false,
        }
    }

    fn init(&mut self, new_event: Box<Event>) {
        with_current_event_loop(|event_loop| {
            if self.is_already_ready() {
                event_loop.arm_breadth_first(new_event);
            } else {
                *self = OnReadyEvent::Full(new_event);
            }
        });
    }

    fn arm(&mut self) {
        if self.is_empty() {
            *self = OnReadyEvent::AlreadyReady;
        } else {
            let old_self = ::std::mem::replace(self, OnReadyEvent::Empty);
            match old_self {
                OnReadyEvent::Full(event) => {
                    with_current_event_loop(|event_loop| {
                        event_loop.arm_depth_first(event);
                    });
                }
                _ => {
                    panic!("armed an event twice?");
                }
            }
        }
    }
}

pub struct PromiseAndFulfillerHub<T> where T: 'static {
    result: Option<Result<T>>,
    on_ready_event: OnReadyEvent,
}

impl <T> PromiseFulfiller<T> for PromiseAndFulfillerHub<T> where T: 'static {
    fn fulfill(&mut self, value: T) {
        if self.result.is_none() {
            self.result = Some(Ok(value));
        }
        self.on_ready_event.arm();
    }

    fn reject(&mut self, error: Error) {
        if self.result.is_none() {
            self.result = Some(Err(error));
        }
    }
}

/*
pub struct WrapperPromiseNode<T> where T: 'static {
    hub: ::std::rc::Rc<::std::cell::RefCell<PromiseAndFulfillerHub<T>>>,
}
*/

impl <T> PromiseNode<T> for ::std::rc::Rc<::std::cell::RefCell<PromiseAndFulfillerHub<T>>> where T: 'static {
    fn on_ready(&mut self, event: Box<Event>) {
        self.borrow_mut().on_ready_event.init(event);
    }
    fn get(self: Box<Self>) -> Result<T> {
        match ::std::mem::replace(&mut self.borrow_mut().result, None) {
            None => panic!("no result!"),
            Some(r) => r
        }
    }
}

impl <T> PromiseFulfiller<T> for ::std::rc::Rc<::std::cell::RefCell<PromiseAndFulfillerHub<T>>> where T: 'static {
    fn fulfill(&mut self, value: T) {
        self.borrow_mut().fulfill(value);
    }

    fn reject(&mut self, error: Error) {
        self.borrow_mut().reject(error);
    }
}

pub fn new_promise_and_fulfiller<T>() -> (Promise<T>, Box<PromiseFulfiller<T>>) where T: 'static {
    let result = ::std::rc::Rc::new(::std::cell::RefCell::new(
        PromiseAndFulfillerHub { result: None::<Result<T>>, on_ready_event: OnReadyEvent::Empty }));
    let result_promise : Promise<T> = Promise { node: Box::new(result.clone())};
    (result_promise, Box::new(result))
}
<|endoftext|>


<commit_before>// Copyright 2016 Itoa Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(html_root_url = "https://docs.rs/itoa/0.3.3")]

#![cfg_attr(feature = "i128", feature(i128_type, i128))]

#[cfg(feature = "i128")]
mod udiv128;

use std::{io, mem, ptr, slice};

#[inline]
pub fn write<W: io::Write, V: Integer>(wr: W, value: V) -> io::Result<usize> {
    value.write(wr)
}

pub trait Integer {
    fn write<W: io::Write>(self, W) -> io::Result<usize>;
}

trait IntegerPrivate {
    fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8];
}

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

const MAX_LEN: usize = 40; // i128::MIN (including minus sign)

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_Integer {
    ($($t:ident),* as $conv_fn:ident) => ($(
    impl Integer for $t {
        fn write<W: io::Write>(self, mut wr: W) -> io::Result<usize> {
            let mut buf = unsafe { mem::uninitialized() };
            let bytes = self.write_to(&mut buf);
            try!(wr.write_all(bytes));
            Ok(bytes.len())
        }
    }

    impl IntegerPrivate for $t {
        #[allow(unused_comparisons)]
        fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
            let is_nonnegative = self >= 0;
            let mut n = if is_nonnegative {
                self as $conv_fn
            } else {
                // convert the negative num to positive by summing 1 to it's 2 complement
                (!(self as $conv_fn)).wrapping_add(1)
            };
            let mut curr = buf.len() as isize;
            let buf_ptr = buf.as_mut_ptr();
            let lut_ptr = DEC_DIGITS_LUT.as_ptr();

            unsafe {
                // eagerly decode 4 characters at a time
                if <$t>::max_value() as u64 >= 10000 {
                    while n >= 10000 {
                        let rem = (n % 10000) as isize;
                        n /= 10000;

                        let d1 = (rem / 100) << 1;
                        let d2 = (rem % 100) << 1;
                        curr -= 4;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                        ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                    }
                }

                // if we reach here numbers are <= 9999, so at most 4 chars long
                let mut n = n as isize; // possibly reduce 64bit math

                // decode 2 more chars, if > 2 chars
                if n >= 100 {
                    let d1 = (n % 100) << 1;
                    n /= 100;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }

                // decode last 1 or 2 chars
                if n < 10 {
                    curr -= 1;
                    *buf_ptr.offset(curr) = (n as u8) + b'0';
                } else {
                    let d1 = n << 1;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }

                if !is_nonnegative {
                    curr -= 1;
                    *buf_ptr.offset(curr) = b'-';
                }
            }

            let len = buf.len() - curr as usize;
            unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) }
        }
    })*);
}

impl_Integer!(i8, u8, i16, u16, i32, u32 as u32);
impl_Integer!(i64, u64 as u64);
#[cfg(target_pointer_width = "16")]
impl_Integer!(isize, usize as u16);
#[cfg(target_pointer_width = "32")]
impl_Integer!(isize, usize as u32);
#[cfg(target_pointer_width = "64")]
impl_Integer!(isize, usize as u64);

#[cfg(all(feature = "i128"))]
macro_rules! impl_Integer128 {
    ($($t:ident),*) => {$(
        impl Integer for $t {
            fn write<W: io::Write>(self, mut wr: W) -> io::Result<usize> {
                let mut buf = unsafe { mem::uninitialized() };
                let bytes = self.write_to(&mut buf);
                try!(wr.write_all(bytes));
                Ok(bytes.len())
            }
        }

        impl IntegerPrivate for $t {
            #[allow(unused_comparisons)]
            fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let n = if is_nonnegative {
                    self as u128
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as u128)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();

                unsafe {
                    // Divide by 10^19 which is the highest power less than 2^64.
                    let (n, rem) = udiv128::udivmod_1e19(n);
                    curr -= rem.write_to(buf).len() as isize;

                    if n != 0 {
                        // Memset the base10 leading zeros of rem.
                        let target = buf.len() as isize - 19;
                        ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                        curr = target;

                        // Divide by 10^19 again.
                        let (n, rem) = udiv128::udivmod_1e19(n);
                        let buf2 = buf_ptr.offset(curr - buf.len() as isize) as *mut _;
                        curr -= rem.write_to(&mut *buf2).len() as isize;

                        if n != 0 {
                            // Memset the leading zeros.
                            let target = buf.len() as isize - 38;
                            ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                            curr = target;

                            // There is at most one digit left
                            // because u128::max / 10^19 / 10^19 is 3.
                            curr -= 1;
                            *buf_ptr.offset(curr) = (n as u8) + b'0';
                        }
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }

                    let len = buf.len() - curr as usize;
                    slice::from_raw_parts(buf_ptr.offset(curr), len)
                }
            }
        }
    )*};
}

#[cfg(all(feature = "i128"))]
impl_Integer128!(i128, u128);
<commit_msg>Indent macro body<commit_after>// Copyright 2016 Itoa Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(html_root_url = "https://docs.rs/itoa/0.3.3")]

#![cfg_attr(feature = "i128", feature(i128_type, i128))]

#[cfg(feature = "i128")]
mod udiv128;

use std::{io, mem, ptr, slice};

#[inline]
pub fn write<W: io::Write, V: Integer>(wr: W, value: V) -> io::Result<usize> {
    value.write(wr)
}

pub trait Integer {
    fn write<W: io::Write>(self, W) -> io::Result<usize>;
}

trait IntegerPrivate {
    fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8];
}

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

const MAX_LEN: usize = 40; // i128::MIN (including minus sign)

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_Integer {
    ($($t:ident),* as $conv_fn:ident) => {$(
        impl Integer for $t {
            fn write<W: io::Write>(self, mut wr: W) -> io::Result<usize> {
                let mut buf = unsafe { mem::uninitialized() };
                let bytes = self.write_to(&mut buf);
                try!(wr.write_all(bytes));
                Ok(bytes.len())
            }
        }

        impl IntegerPrivate for $t {
            #[allow(unused_comparisons)]
            fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let mut n = if is_nonnegative {
                    self as $conv_fn
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as $conv_fn)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();
                let lut_ptr = DEC_DIGITS_LUT.as_ptr();

                unsafe {
                    // eagerly decode 4 characters at a time
                    if <$t>::max_value() as u64 >= 10000 {
                        while n >= 10000 {
                            let rem = (n % 10000) as isize;
                            n /= 10000;

                            let d1 = (rem / 100) << 1;
                            let d2 = (rem % 100) << 1;
                            curr -= 4;
                            ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                            ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                        }
                    }

                    // if we reach here numbers are <= 9999, so at most 4 chars long
                    let mut n = n as isize; // possibly reduce 64bit math

                    // decode 2 more chars, if > 2 chars
                    if n >= 100 {
                        let d1 = (n % 100) << 1;
                        n /= 100;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    // decode last 1 or 2 chars
                    if n < 10 {
                        curr -= 1;
                        *buf_ptr.offset(curr) = (n as u8) + b'0';
                    } else {
                        let d1 = n << 1;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }
                }

                let len = buf.len() - curr as usize;
                unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) }
            }
        }
    )*};
}

impl_Integer!(i8, u8, i16, u16, i32, u32 as u32);
impl_Integer!(i64, u64 as u64);
#[cfg(target_pointer_width = "16")]
impl_Integer!(isize, usize as u16);
#[cfg(target_pointer_width = "32")]
impl_Integer!(isize, usize as u32);
#[cfg(target_pointer_width = "64")]
impl_Integer!(isize, usize as u64);

#[cfg(all(feature = "i128"))]
macro_rules! impl_Integer128 {
    ($($t:ident),*) => {$(
        impl Integer for $t {
            fn write<W: io::Write>(self, mut wr: W) -> io::Result<usize> {
                let mut buf = unsafe { mem::uninitialized() };
                let bytes = self.write_to(&mut buf);
                try!(wr.write_all(bytes));
                Ok(bytes.len())
            }
        }

        impl IntegerPrivate for $t {
            #[allow(unused_comparisons)]
            fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let n = if is_nonnegative {
                    self as u128
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as u128)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();

                unsafe {
                    // Divide by 10^19 which is the highest power less than 2^64.
                    let (n, rem) = udiv128::udivmod_1e19(n);
                    curr -= rem.write_to(buf).len() as isize;

                    if n != 0 {
                        // Memset the base10 leading zeros of rem.
                        let target = buf.len() as isize - 19;
                        ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                        curr = target;

                        // Divide by 10^19 again.
                        let (n, rem) = udiv128::udivmod_1e19(n);
                        let buf2 = buf_ptr.offset(curr - buf.len() as isize) as *mut _;
                        curr -= rem.write_to(&mut *buf2).len() as isize;

                        if n != 0 {
                            // Memset the leading zeros.
                            let target = buf.len() as isize - 38;
                            ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                            curr = target;

                            // There is at most one digit left
                            // because u128::max / 10^19 / 10^19 is 3.
                            curr -= 1;
                            *buf_ptr.offset(curr) = (n as u8) + b'0';
                        }
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }

                    let len = buf.len() - curr as usize;
                    slice::from_raw_parts(buf_ptr.offset(curr), len)
                }
            }
        }
    )*};
}

#[cfg(all(feature = "i128"))]
impl_Integer128!(i128, u128);
<|endoftext|>


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

use gtk::{self, IsA, Object};

use super::{Relm, run};
use relm_state::Update;

/// Trait to implement to manage widget's events.
pub trait Widget
    where Self: Update,
          Self::Root: Clone + IsA<Object> + IsA<gtk::Widget>,
{
    /// The type of the root widget.
    type Root;

    /// Update the view after it is initially created.
    /// This method is only useful when using the `#[widget]` attribute, because when not using it,
    /// you can use the [`view()`](trait.Widget.html#tymethod.view) method instead.
    fn init_view(&mut self) {
    }

    /// Method called when the widget is added to its parent.
    fn on_add<W: IsA<gtk::Widget> + IsA<Object>>(&self, _parent: W) {
    }

    /// Get the parent ID.
    /// This is useful for custom Container implementation: when you implement the
    /// [`Container::add_widget()`](trait.Container.html#tymethod.add_widget), you might want to
    /// insert widgets elsewhere depending of this id.
    fn parent_id() -> Option<&'static str> {
        None
    }

    // TODO: ajouter une méthode param() pour déterminer des paramètres qui seront pris en compte à
    // l’ajout du widget.

    /// Get the root widget of the view.e. the root widget of the view.
    fn root(&self) -> Self::Root;

    /// Create the window from this widget and start the main loop.
    fn run(model_param: Self::ModelParam) -> Result<(), ()>
        where Self: 'static,
    {
        run::<Self>(model_param)
    }

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

use gtk::{self, IsA, Object};

use super::{Relm, run};
use relm_state::Update;

/// Trait to implement to manage widget's events.
pub trait Widget
    where Self: Update,
          Self::Root: Clone + IsA<Object> + IsA<gtk::Widget>,
{
    /// The type of the root widget.
    type Root;

    /// Update the view after it is initially created.
    /// This method is only useful when using the `#[widget]` attribute, because when not using it,
    /// you can use the [`view()`](trait.Widget.html#tymethod.view) method instead.
    fn init_view(&mut self) {
    }

    /// Method called when the widget is added to its parent.
    fn on_add<W: IsA<gtk::Widget> + IsA<Object>>(&self, _parent: W) {
    }

    /// Get the parent ID.
    /// This is useful for custom Container implementation: when you implement the
    /// [`Container::add_widget()`](trait.Container.html#tymethod.add_widget), you might want to
    /// insert widgets elsewhere depending of this id.
    fn parent_id() -> Option<&'static str> {
        None
    }

    // TODO: ajouter une méthode param() pour déterminer des paramètres qui seront pris en compte à
    // l’ajout du widget.

    /// Get the root widget of the view.
    fn root(&self) -> Self::Root;

    /// Create the window from this widget and start the main loop.
    fn run(model_param: Self::ModelParam) -> Result<(), ()>
        where Self: 'static,
    {
        run::<Self>(model_param)
    }

    /// Create the initial view.
    fn view(relm: &Relm<Self>, model: Self::Model) -> Self;
}
<|endoftext|>