<commit_before>use sync::Arc;
use libc::c_void;

use glfw::{WindowEvent, Key, MouseButton, Glfw, Context};
use glfw::{Press, Release, KeyEvent, MouseButtonEvent, CursorPosEvent};
use glfw::{CloseEvent, FocusEvent, FullScreen};
use glfw::{Windowed, RenderContext};
use glfw;
use gl;

use semver;
use collections::{HashSet, TrieMap};

use cgmath::quaternion::Quaternion;

use ovr;

pub type WindowId = uint;

#[deriving(Clone)]
struct InputHistory {
    older: Option<Arc<InputHistory>>,
    time: Option<f64>,
    event: WindowEvent
}

#[deriving(Clone)]
pub struct InputState {
    history: Option<Arc<InputHistory>>,
    keyboard: HashSet<Key>,
    mouse: HashSet<MouseButton>,
    should_close: bool,
    focus: bool,
    framebuffer_size: (i32, i32),
    screen_size: (i32, i32),
    predicted: Quaternion<f32>,
}

struct InputHistoryIterator {
    current: Option<Arc<InputHistory>>
}

impl Iterator<(Option<f64>, WindowEvent)> for InputHistoryIterator {
    fn next(&mut self) -> Option<(Option<f64>, WindowEvent)> {
        let (next, res) = match self.current {
            Some(ref next) => {
                let next = next.deref();
                (next.older.clone(), Some((next.time.clone(), next.event.clone())))
            },
            None => (None, None)
        };

        self.current = next;
        res
    }
}

pub struct DeltaIterator {
    current: Option<Arc<InputHistory>>,
    origin: Option<Arc<InputHistory>>
}

impl Iterator<(Option<f64>, WindowEvent)> for DeltaIterator {
    fn next(&mut self) -> Option<(Option<f64>, WindowEvent)> {
        match (&self.current, &self.origin) {
            (&None, &None) => return None,
            (&Some(ref a), &Some(ref b)) => {
                if a.deref() as *InputHistory == b.deref() as *InputHistory {
                    return None
                }
            }
            _ => ()
        }

        let (next, res) = match self.current {
            Some(ref next) => {
                let next = next.deref();
                (next.older.clone(), Some((next.time.clone(), next.event.clone())))
            },
            None => (None, None)
        };

        self.current = next;
        res
    }
}

impl InputState {
    fn new(win: &glfw::Window) -> InputState {
        InputState {
            history: None,
            keyboard: HashSet::new(),
            mouse: HashSet::new(),
            should_close: false,
            focus: win.is_focused(),
            framebuffer_size: win.get_framebuffer_size(),
            screen_size: win.get_size(),
            predicted: Quaternion::identity()
        }
    }

    fn event(&mut self, time: Option<f64>, event: WindowEvent) {
        self.history = Some(Arc::new( InputHistory{
            older: self.history.clone(),
            time: time,
            event: event.clone()
        }));

        match event {
            KeyEvent(key, _, Press, _) => { self.keyboard.insert(key); },
            KeyEvent(key, _, Release, _) => { self.keyboard.remove(&key); },
            MouseButtonEvent(key, Press, _) => { self.mouse.insert(key); },
            MouseButtonEvent(key, Release, _) => { self.mouse.remove(&key); },
            CloseEvent => { self.should_close = true; },
            FocusEvent(s) => { self.focus = s; },
            _ => ()
        }
    }

    fn iter(&self) -> InputHistoryIterator {
        InputHistoryIterator {
            current: self.history.clone()
        }
    }

    pub fn key_down(&self, key: Key) -> bool
    {
        self.keyboard.contains(&key)
    }

    pub fn mouse_up(&self, button: MouseButton) -> bool
    {
        self.mouse.contains(&button)
    }

    pub fn time(&self) -> f64 {
        for (t, _) in self.iter() {
            match t {
                Some(t) => return t,
                None => ()
            }
        }
        0.
    }

    pub fn cursor_delta(&self, epoc: f64) -> Option<(f64, f64)> {
        let mut latest = None;
        let mut old = (0f64, 0f64);
        let mut iter = self.iter();

        // find the latest cursor position
        for (time, event) in iter {
            // no change found
            if time.is_none() || time.unwrap() <= epoc {
                return None;
            }
            match event {
                CursorPosEvent(x, y) => {
                    latest = Some((x, y));
                    break;
                },
                _ => ()
            }
        }

        // no change found
        if latest.is_none() {
            return None;
        }

        let (nx, ny) = latest.unwrap();

        // find the first cursor positon before
        for (time, event) in iter {
            if time.is_none() || time.unwrap() <= epoc {
                match event {
                    CursorPosEvent(x, y) => {
                        old = (x, y);
                        break;
                    },
                    _ => ()
                }
            }
        }

        let (x, y) = old;
        Some((nx-x, ny-y))
    }

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

    pub fn is_focused(&self) -> bool {
        self.focus
    }

    pub fn screen_size(&self) -> (i32, i32) {
        self.screen_size.clone()
    }

    pub fn framebuffer_size(&self) -> (i32, i32) {
        self.framebuffer_size.clone()
    }

    pub fn iter_delta(&self, old: &InputState) -> DeltaIterator {
        DeltaIterator {
            current: self.history.clone(),
            origin: old.history.clone()
        }
    }
}

struct WindowHandle {
    window: glfw::Window,
    receiver: Receiver<(f64, WindowEvent)>,
    state: InputState
}

pub struct IOManager {
    glfw: Glfw,
    ovr: Option<ovr::Ovr>,
    windows: TrieMap<WindowHandle>,
    window_id: uint
}

impl IOManager {
    pub fn new(glfw: glfw::Glfw) -> IOManager {
        IOManager {
            glfw: glfw,
            ovr: None,
            windows: TrieMap::new(),
            window_id: 0
        }
    }

    fn add_window(&mut self, window: glfw::Window, recv: Receiver<(f64, WindowEvent)>) -> InputHandle {
        let id = self.window_id;
        self.window_id += 1;

        let state = InputState::new(&window);

        self.windows.insert(id, {
            WindowHandle {
                window: window,
                receiver: recv,
                state: state
            }
        });

        InputHandle{ handle: id }
    }

    pub fn window(&mut self, size: (u32, u32)) -> Option<Window> {
        let (width, height) = size;
        let win_opt = self.glfw.create_window(width, height, "Snowmew", Windowed);
        let (mut window, events) = match win_opt {
            Some((window, events)) => (window, events),
            None => return None
        };

        window.make_current();
        gl::load_with(|name| self.glfw.get_proc_address(name));
        self.glfw.set_swap_interval(1);
        glfw::make_context_current(None);

        window.set_all_polling(true);
        window.show();
        let version = window.get_context_version();
        let rc = window.render_context();
        let handle = self.add_window(window, events);

        Some(Window {
            handle: handle,
            render: rc,
            version: version,
            hmd: None,
            display: self.glfw.get_x11_display()
        })
    }

    #[cfg(target_os="linux")]
    fn create_hmd_window(&self, hmd: &ovr::HmdDescription) -> Option<(glfw::Window, Receiver<(f64,WindowEvent)>)> {
        self.glfw.with_connected_monitors(|monitors| {
            for m in monitors.iter() {
                let (x, y) = m.get_pos();
                if x == hmd.window_position.x &&
                   y == hmd.window_position.y {
                    let (width, height) = (hmd.resolution.x, hmd.resolution.y);
                    let win_opt = self.glfw.create_window(width as u32, height as u32, "Snowmew Fullscreen", FullScreen(m));
                    let (window, events) = match win_opt {
                        Some((window, events)) => (window, events),
                        None => return None
                    };

                    return Some((window, events));
                }
            }

            // fallback if we could not guess at the screen
            let (width, height) = (hmd.resolution.x, hmd.resolution.y);
            let win_opt = self.glfw.create_window(width as u32, height as u32, "Snowmew", Windowed);
            let (window, events) = match win_opt {
                Some((window, events)) => (window, events),
                None => return None
            };

            // move viewport
            let (dx, dy) = (hmd.window_position.x, hmd.window_position.y);
            window.set_pos(dx as i32, dy as i32);

            Some((window, events))

        })
    }

    #[cfg(target_os="macos")]
    fn create_hmd_window(&self, hmd: &ovr::HmdDescription) -> Option<(glfw::Window, Receiver<(f64,WindowEvent)>)> {
        self.glfw.with_connected_monitors(|monitors| {
            for m in monitors.iter() {
                if !m.get_name().as_slice().contains("Rift") {
                    continue;
                }

                let (width, height) = hmd.resolution();
                let win_opt = self.glfw.create_window(width as u32, height as u32, "Snowmew Fullscreen", FullScreen(m));
                let (window, events) = match win_opt {
                    Some((window, events)) => (window, events),
                    None => return None
                };

                return Some((window, events));
            }
            None
        })
    }

    pub fn hmd(&mut self) -> Option<Window> {
        if !self.setup_ovr() {
            return None;
        }

        let (window, events, rc, hmd) = {
            let hmd = match self.ovr.as_ref().unwrap().first_hmd() {
                Some(hmd) => hmd,
                None => return None
            };
            let hmdinfo = hmd.get_description();

            let (mut window, events) = match self.create_hmd_window(&hmdinfo) {
                Some((window, events)) => (window, events),
                None => return None
            };

            window.make_current();
            gl::load_with(|name| self.glfw.get_proc_address(name));
            self.glfw.set_swap_interval(1);
            glfw::make_context_current(None);

            window.set_all_polling(true);
            window.show();

            let rc = window.render_context();
            (window, events, rc, hmd)
        };

        let version = window.get_context_version();
        let handle = self.add_window(window, events);

        Some(Window {
            handle: handle,
            render: rc,
            version: version,
            hmd: Some(Arc::new(hmd)),
            display: self.glfw.get_x11_display()
        })
    }

    pub fn get(&self, handle: &InputHandle) -> InputState {
        self.windows.find(&handle.handle).unwrap().state.clone()
    }

    fn update(&mut self) {
        for (_, win) in self.windows.mut_iter() {
            for (time, event) in glfw::flush_messages(&win.receiver) {
                win.state.event(Some(time), event);
            }
        }
    }

    pub fn wait(&mut self) {
        self.glfw.wait_events();
        self.update();
    }

    pub fn poll(&mut self) {
        self.glfw.poll_events();
        self.update();
    }

    pub fn setup_ovr(&mut self) -> bool {
        if self.ovr.is_some() &&
           self.ovr.as_ref().unwrap().detect() > 0 {
            return true;
        }

        if self.ovr.is_none() {
            self.ovr = ovr::Ovr::init();
        }

        self.ovr.is_some() && self.ovr.as_ref().unwrap().detect() > 0
    }
}

#[deriving(Clone)]
pub struct InputHandle {
    handle: uint,
}

pub struct Window {
    handle: InputHandle,
    render: RenderContext,
    version: semver::Version,
    hmd: Option<Arc<ovr::Hmd>>,
    display: *c_void
}

impl Window {
    pub fn swap_buffers(&self) {
        self.render.swap_buffers()
    }

    pub fn make_context_current(&self) {
        self.render.make_current()
    }

    pub fn get_context_version(&self) -> (uint, uint) {
        let version = self.version.clone();
        (version.major, version.minor)
    }

    pub fn handle(&self) -> InputHandle {
        self.handle.clone()
    }

    pub fn is_hmd(&self) -> bool {
        self.hmd.is_some()
    }

    pub fn get_hmd<'a>(&'a self) -> Arc<ovr::Hmd> {
        self.hmd.as_ref().expect("no hmd device found!").clone()
    }

    /// Wrapper for `glfwGetWin32Window`
    #[cfg(target_os="win32")]
    pub fn get_win32_window(&self) -> *c_void {
        self.render.get_win32_window()
    }

    /// Wrapper for `glfwGetWGLContext`
    #[cfg(target_os="win32")]
    pub fn get_wgl_context(&self) -> *c_void {
        self.render.get_wgl_context()
    }

    /// Wrapper for `glfwGetCocoaWindow`
    #[cfg(target_os="macos")]
    pub fn get_cocoa_window(&self) -> *c_void {
        self.render.get_cocoa_window()
    }

    /// Wrapper for `glfwGetNSGLContext`
    #[cfg(target_os="macos")]
    pub fn get_nsgl_context(&self) -> *c_void {
        self.render.get_nsgl_context()
    }

    /// Wrapper for `glfwGetX11Window`
    #[cfg(target_os="linux")]
    pub fn get_x11_window(&self) -> *c_void {
        self.render.get_x11_window()
    }

    /// Wrapper for `glfwGetGLXContext`
    #[cfg(target_os="linux")]
    pub fn get_glx_context(&self) -> *c_void {
        self.render.get_glx_context()
    }

    /// Wrapper for `glfwGetGLXContext`
    #[cfg(target_os="linux")]
    pub fn get_x11_display(&self) -> *c_void {
        self.display
    }

}<commit_msg>removed some functions from io that were breaking the local build<commit_after>use sync::Arc;
use libc::c_void;

use glfw::{WindowEvent, Key, MouseButton, Glfw, Context};
use glfw::{Press, Release, KeyEvent, MouseButtonEvent, CursorPosEvent};
use glfw::{CloseEvent, FocusEvent, FullScreen};
use glfw::{Windowed, RenderContext};
use glfw;
use gl;

use semver;
use collections::{HashSet, TrieMap};

use cgmath::quaternion::Quaternion;

use ovr;

pub type WindowId = uint;

#[deriving(Clone)]
struct InputHistory {
    older: Option<Arc<InputHistory>>,
    time: Option<f64>,
    event: WindowEvent
}

#[deriving(Clone)]
pub struct InputState {
    history: Option<Arc<InputHistory>>,
    keyboard: HashSet<Key>,
    mouse: HashSet<MouseButton>,
    should_close: bool,
    focus: bool,
    framebuffer_size: (i32, i32),
    screen_size: (i32, i32),
    predicted: Quaternion<f32>,
}

struct InputHistoryIterator {
    current: Option<Arc<InputHistory>>
}

impl Iterator<(Option<f64>, WindowEvent)> for InputHistoryIterator {
    fn next(&mut self) -> Option<(Option<f64>, WindowEvent)> {
        let (next, res) = match self.current {
            Some(ref next) => {
                let next = next.deref();
                (next.older.clone(), Some((next.time.clone(), next.event.clone())))
            },
            None => (None, None)
        };

        self.current = next;
        res
    }
}

pub struct DeltaIterator {
    current: Option<Arc<InputHistory>>,
    origin: Option<Arc<InputHistory>>
}

impl Iterator<(Option<f64>, WindowEvent)> for DeltaIterator {
    fn next(&mut self) -> Option<(Option<f64>, WindowEvent)> {
        match (&self.current, &self.origin) {
            (&None, &None) => return None,
            (&Some(ref a), &Some(ref b)) => {
                if a.deref() as *InputHistory == b.deref() as *InputHistory {
                    return None
                }
            }
            _ => ()
        }

        let (next, res) = match self.current {
            Some(ref next) => {
                let next = next.deref();
                (next.older.clone(), Some((next.time.clone(), next.event.clone())))
            },
            None => (None, None)
        };

        self.current = next;
        res
    }
}

impl InputState {
    fn new(win: &glfw::Window) -> InputState {
        InputState {
            history: None,
            keyboard: HashSet::new(),
            mouse: HashSet::new(),
            should_close: false,
            focus: win.is_focused(),
            framebuffer_size: win.get_framebuffer_size(),
            screen_size: win.get_size(),
            predicted: Quaternion::identity()
        }
    }

    fn event(&mut self, time: Option<f64>, event: WindowEvent) {
        self.history = Some(Arc::new( InputHistory{
            older: self.history.clone(),
            time: time,
            event: event.clone()
        }));

        match event {
            KeyEvent(key, _, Press, _) => { self.keyboard.insert(key); },
            KeyEvent(key, _, Release, _) => { self.keyboard.remove(&key); },
            MouseButtonEvent(key, Press, _) => { self.mouse.insert(key); },
            MouseButtonEvent(key, Release, _) => { self.mouse.remove(&key); },
            CloseEvent => { self.should_close = true; },
            FocusEvent(s) => { self.focus = s; },
            _ => ()
        }
    }

    fn iter(&self) -> InputHistoryIterator {
        InputHistoryIterator {
            current: self.history.clone()
        }
    }

    pub fn key_down(&self, key: Key) -> bool
    {
        self.keyboard.contains(&key)
    }

    pub fn mouse_up(&self, button: MouseButton) -> bool
    {
        self.mouse.contains(&button)
    }

    pub fn time(&self) -> f64 {
        for (t, _) in self.iter() {
            match t {
                Some(t) => return t,
                None => ()
            }
        }
        0.
    }

    pub fn cursor_delta(&self, epoc: f64) -> Option<(f64, f64)> {
        let mut latest = None;
        let mut old = (0f64, 0f64);
        let mut iter = self.iter();

        // find the latest cursor position
        for (time, event) in iter {
            // no change found
            if time.is_none() || time.unwrap() <= epoc {
                return None;
            }
            match event {
                CursorPosEvent(x, y) => {
                    latest = Some((x, y));
                    break;
                },
                _ => ()
            }
        }

        // no change found
        if latest.is_none() {
            return None;
        }

        let (nx, ny) = latest.unwrap();

        // find the first cursor positon before
        for (time, event) in iter {
            if time.is_none() || time.unwrap() <= epoc {
                match event {
                    CursorPosEvent(x, y) => {
                        old = (x, y);
                        break;
                    },
                    _ => ()
                }
            }
        }

        let (x, y) = old;
        Some((nx-x, ny-y))
    }

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

    pub fn is_focused(&self) -> bool {
        self.focus
    }

    pub fn screen_size(&self) -> (i32, i32) {
        self.screen_size.clone()
    }

    pub fn framebuffer_size(&self) -> (i32, i32) {
        self.framebuffer_size.clone()
    }

    pub fn iter_delta(&self, old: &InputState) -> DeltaIterator {
        DeltaIterator {
            current: self.history.clone(),
            origin: old.history.clone()
        }
    }
}

struct WindowHandle {
    window: glfw::Window,
    receiver: Receiver<(f64, WindowEvent)>,
    state: InputState
}

pub struct IOManager {
    glfw: Glfw,
    ovr: Option<ovr::Ovr>,
    windows: TrieMap<WindowHandle>,
    window_id: uint
}

impl IOManager {
    pub fn new(glfw: glfw::Glfw) -> IOManager {
        IOManager {
            glfw: glfw,
            ovr: None,
            windows: TrieMap::new(),
            window_id: 0
        }
    }

    fn add_window(&mut self, window: glfw::Window, recv: Receiver<(f64, WindowEvent)>) -> InputHandle {
        let id = self.window_id;
        self.window_id += 1;

        let state = InputState::new(&window);

        self.windows.insert(id, {
            WindowHandle {
                window: window,
                receiver: recv,
                state: state
            }
        });

        InputHandle{ handle: id }
    }

    pub fn window(&mut self, size: (u32, u32)) -> Option<Window> {
        let (width, height) = size;
        let win_opt = self.glfw.create_window(width, height, "Snowmew", Windowed);
        let (mut window, events) = match win_opt {
            Some((window, events)) => (window, events),
            None => return None
        };

        window.make_current();
        gl::load_with(|name| self.glfw.get_proc_address(name));
        self.glfw.set_swap_interval(1);
        glfw::make_context_current(None);

        window.set_all_polling(true);
        window.show();
        let version = window.get_context_version();
        let rc = window.render_context();
        let handle = self.add_window(window, events);

        Some(Window {
            handle: handle,
            render: rc,
            version: version,
            hmd: None,
            display: self.glfw.get_x11_display()
        })
    }

    #[cfg(target_os="linux")]
    fn create_hmd_window(&self, hmd: &ovr::HmdDescription) -> Option<(glfw::Window, Receiver<(f64,WindowEvent)>)> {
        self.glfw.with_connected_monitors(|monitors| {
            for m in monitors.iter() {
                let (x, y) = m.get_pos();
                if x == hmd.window_position.x &&
                   y == hmd.window_position.y {
                    let (width, height) = (hmd.resolution.x, hmd.resolution.y);
                    let win_opt = self.glfw.create_window(width as u32, height as u32, "Snowmew Fullscreen", FullScreen(m));
                    let (window, events) = match win_opt {
                        Some((window, events)) => (window, events),
                        None => return None
                    };

                    return Some((window, events));
                }
            }

            // fallback if we could not guess at the screen
            let (width, height) = (hmd.resolution.x, hmd.resolution.y);
            let win_opt = self.glfw.create_window(width as u32, height as u32, "Snowmew", Windowed);
            let (window, events) = match win_opt {
                Some((window, events)) => (window, events),
                None => return None
            };

            // move viewport
            let (dx, dy) = (hmd.window_position.x, hmd.window_position.y);
            window.set_pos(dx as i32, dy as i32);

            Some((window, events))

        })
    }

    #[cfg(target_os="macos")]
    fn create_hmd_window(&self, hmd: &ovr::HmdDescription) -> Option<(glfw::Window, Receiver<(f64,WindowEvent)>)> {
        self.glfw.with_connected_monitors(|monitors| {
            for m in monitors.iter() {
                if !m.get_name().as_slice().contains("Rift") {
                    continue;
                }

                let (width, height) = hmd.resolution();
                let win_opt = self.glfw.create_window(width as u32, height as u32, "Snowmew Fullscreen", FullScreen(m));
                let (window, events) = match win_opt {
                    Some((window, events)) => (window, events),
                    None => return None
                };

                return Some((window, events));
            }
            None
        })
    }

    pub fn hmd(&mut self) -> Option<Window> {
        if !self.setup_ovr() {
            return None;
        }

        let (window, events, rc, hmd) = {
            let hmd = match self.ovr.as_ref().unwrap().first_hmd() {
                Some(hmd) => hmd,
                None => return None
            };
            let hmdinfo = hmd.get_description();

            let (mut window, events) = match self.create_hmd_window(&hmdinfo) {
                Some((window, events)) => (window, events),
                None => return None
            };

            window.make_current();
            gl::load_with(|name| self.glfw.get_proc_address(name));
            self.glfw.set_swap_interval(1);
            glfw::make_context_current(None);

            window.set_all_polling(true);
            window.show();

            let rc = window.render_context();
            (window, events, rc, hmd)
        };

        let version = window.get_context_version();
        let handle = self.add_window(window, events);

        Some(Window {
            handle: handle,
            render: rc,
            version: version,
            hmd: Some(Arc::new(hmd)),
            display: self.glfw.get_x11_display()
        })
    }

    pub fn get(&self, handle: &InputHandle) -> InputState {
        self.windows.find(&handle.handle).unwrap().state.clone()
    }

    fn update(&mut self) {
        for (_, win) in self.windows.mut_iter() {
            for (time, event) in glfw::flush_messages(&win.receiver) {
                win.state.event(Some(time), event);
            }
        }
    }

    pub fn wait(&mut self) {
        self.glfw.wait_events();
        self.update();
    }

    pub fn poll(&mut self) {
        self.glfw.poll_events();
        self.update();
    }

    pub fn setup_ovr(&mut self) -> bool {
        if self.ovr.is_some() &&
           self.ovr.as_ref().unwrap().detect() > 0 {
            return true;
        }

        if self.ovr.is_none() {
            self.ovr = ovr::Ovr::init();
        }

        self.ovr.is_some() && self.ovr.as_ref().unwrap().detect() > 0
    }
}

#[deriving(Clone)]
pub struct InputHandle {
    handle: uint,
}

pub struct Window {
    handle: InputHandle,
    render: RenderContext,
    version: semver::Version,
    hmd: Option<Arc<ovr::Hmd>>,
    display: *c_void
}

impl Window {
    pub fn swap_buffers(&self) {
        self.render.swap_buffers()
    }

    pub fn make_context_current(&self) {
        self.render.make_current()
    }

    pub fn get_context_version(&self) -> (uint, uint) {
        let version = self.version.clone();
        (version.major, version.minor)
    }

    pub fn handle(&self) -> InputHandle {
        self.handle.clone()
    }

    pub fn is_hmd(&self) -> bool {
        self.hmd.is_some()
    }

    pub fn get_hmd<'a>(&'a self) -> Arc<ovr::Hmd> {
        self.hmd.as_ref().expect("no hmd device found!").clone()
    }

    /// Wrapper for `glfwGetGLXContext`
    #[cfg(target_os="linux")]
    pub fn get_x11_display(&self) -> *c_void {
        self.display
    }

}<|endoftext|>


<commit_before>use std::{cmp, fmt, ptr};
use std::os::raw::c_int;
use std::os::unix::io::RawFd;
use std::collections::HashMap;
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::time::Duration;

use libc::{self, time_t};

use {io, event, Ready, PollOpt, Token, Event};
use sys::cvt;
use sys::io::set_cloexec;

/// Each Selector has a globally unique(ish) ID associated with it. This ID
/// gets tracked by `TcpStream`, `TcpListener`, etc... when they are first
/// registered with the `Selector`. If a type that is previously associated with
/// a `Selector` attempts to register itself with a different `Selector`, the
/// operation will return with an error. This matches windows behavior.
static NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;

macro_rules! kevent {
    ($id: expr, $filter: expr, $flags: expr, $data: expr) => {
        libc::kevent {
            ident: $id as ::libc::uintptr_t,
            filter: $filter,
            flags: $flags,
            fflags: 0,
            data: 0,
            udata: $data as *mut _,
        }
    }
}

pub struct Selector {
    id: usize,
    kq: RawFd,
}

impl Selector {
    pub fn new() -> io::Result<Selector> {
        // offset by 1 to avoid choosing 0 as the id of a selector
        let id = NEXT_ID.fetch_add(1, Ordering::Relaxed) + 1;
        let kq = unsafe { try!(cvt(libc::kqueue())) };
        drop(set_cloexec(kq));

        Ok(Selector {
            id: id,
            kq: kq,
        })
    }

    pub fn id(&self) -> usize {
        self.id
    }

    pub fn select(&self, evts: &mut Events, awakener: Token, timeout: Option<Duration>) -> io::Result<bool> {
        let timeout = timeout.map(|to| {
            libc::timespec {
                tv_sec: cmp::min(to.as_secs(), time_t::max_value() as u64) as time_t,
                tv_nsec: to.subsec_nanos() as libc::c_long,
            }
        });
        let timeout = timeout.as_ref().map(|s| s as *const _).unwrap_or(ptr::null_mut());

        unsafe {
            let cnt = try!(cvt(libc::kevent(self.kq,
                                            ptr::null(),
                                            0,
                                            evts.sys_events.0.as_mut_ptr(),
            // FIXME: needs a saturating cast here.
                                            evts.sys_events.0.capacity() as c_int,
                                            timeout)));
            evts.sys_events.0.set_len(cnt as usize);
            Ok(evts.coalesce(awakener))
        }
    }

    pub fn register(&self, fd: RawFd, token: Token, interests: Ready, opts: PollOpt) -> io::Result<()> {
        trace!("registering; token={:?}; interests={:?}", token, interests);

        let flags = if opts.contains(PollOpt::edge()) { libc::EV_CLEAR } else { 0 } |
                    if opts.contains(PollOpt::oneshot()) { libc::EV_ONESHOT } else { 0 } |
                    libc::EV_RECEIPT;

        unsafe {
            let r = if interests.contains(Ready::readable()) { libc::EV_ADD } else { libc::EV_DELETE };
            let w = if interests.contains(Ready::writable()) { libc::EV_ADD } else { libc::EV_DELETE };
            let mut changes = [
                kevent!(fd, libc::EVFILT_READ, flags | r, usize::from(token)),
                kevent!(fd, libc::EVFILT_WRITE, flags | w, usize::from(token)),
            ];
            try!(cvt(libc::kevent(self.kq, changes.as_ptr(), changes.len() as c_int,
                                           changes.as_mut_ptr(), changes.len() as c_int,
                                           ::std::ptr::null())));
            for change in changes.iter() {
                debug_assert_eq!(change.flags & libc::EV_ERROR, libc::EV_ERROR);
                /*
                if change.data != 0 {
                    // there’s some error, but we want to ignore ENOENT error for EV_DELETE
                    let orig_flags = if change.filter == libc::EVFILT_READ { r } else { w };
                    if !(change.data as i32 == libc::ENOENT && orig_flags & libc::EV_DELETE != 0) {
                        return Err(::std::io::Error::from_raw_os_error(change.data as i32));
                    }
                }
                */
                if change.data == 0 {
                    continue
                }

                if change.data as i32 == libc::EPIPE && change.filter == libc::EVFILT_WRITE {
                    continue
                }

                let orig_flags = if change.filter == libc::EVFILT_READ { r } else { w };
                if change.data as i32 == libc::ENOENT && orig_flags & libc::EV_DELETE != 0 {
                    continue
                }

                return Err(::std::io::Error::from_raw_os_error(change.data as i32));
            }
            Ok(())
        }
    }

    pub fn reregister(&self, fd: RawFd, token: Token, interests: Ready, opts: PollOpt) -> io::Result<()> {
        // Just need to call register here since EV_ADD is a mod if already
        // registered
        self.register(fd, token, interests, opts)
    }

    pub fn deregister(&self, fd: RawFd) -> io::Result<()> {
        unsafe {
            // EV_RECEIPT is a nice way to apply changes and get back per-event results while not
            // draining the actual changes.
            let filter = libc::EV_DELETE | libc::EV_RECEIPT;
            let mut changes = [
                kevent!(fd, libc::EVFILT_READ, filter, ptr::null_mut()),
                kevent!(fd, libc::EVFILT_WRITE, filter, ptr::null_mut()),
            ];
            try!(cvt(libc::kevent(self.kq, changes.as_ptr(), changes.len() as c_int,
                                           changes.as_mut_ptr(), changes.len() as c_int,
                                           ::std::ptr::null())).map(|_| ()));
            if changes[0].data as i32 == libc::ENOENT && changes[1].data as i32 == libc::ENOENT {
                return Err(::std::io::Error::from_raw_os_error(changes[0].data as i32));
            }
            for change in changes.iter() {
                debug_assert_eq!(libc::EV_ERROR & change.flags, libc::EV_ERROR);
                if change.data != 0 && change.data as i32 != libc::ENOENT {
                    return Err(::std::io::Error::from_raw_os_error(changes[0].data as i32));
                }
            }
            Ok(())
        }
    }
}

impl fmt::Debug for Selector {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Selector")
            .field("id", &self.id)
            .field("kq", &self.kq)
            .finish()
    }
}

impl Drop for Selector {
    fn drop(&mut self) {
        unsafe {
            let _ = libc::close(self.kq);
        }
    }
}

pub struct Events {
    sys_events: KeventList,
    events: Vec<Event>,
    event_map: HashMap<Token, usize>,
}

struct KeventList(Vec<libc::kevent>);

unsafe impl Send for KeventList {}
unsafe impl Sync for KeventList {}

impl Events {
    pub fn with_capacity(cap: usize) -> Events {
        Events {
            sys_events: KeventList(Vec::with_capacity(cap)),
            events: Vec::with_capacity(cap),
            event_map: HashMap::with_capacity(cap)
        }
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.events.len()
    }

    #[inline]
    pub fn capacity(&self) -> usize {
        self.events.capacity()
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.events.is_empty()
    }

    pub fn get(&self, idx: usize) -> Option<Event> {
        self.events.get(idx).map(|e| *e)
    }

    fn coalesce(&mut self, awakener: Token) -> bool {
        let mut ret = false;
        self.events.clear();
        self.event_map.clear();

        for e in self.sys_events.0.iter() {
            let token = Token(e.udata as usize);
            let len = self.events.len();

            if token == awakener {
                // TODO: Should this return an error if event is an error. It
                // is not critical as spurious wakeups are permitted.
                ret = true;
                continue;
            }

            let idx = *self.event_map.entry(token)
                .or_insert(len);

            if idx == len {
                // New entry, insert the default
                self.events.push(Event::new(Ready::empty(), token));

            }

            if e.flags & libc::EV_ERROR != 0 {
                event::kind_mut(&mut self.events[idx]).insert(Ready::error());
            }

            if e.filter == libc::EVFILT_READ {
                event::kind_mut(&mut self.events[idx]).insert(Ready::readable());
            } else if e.filter == libc::EVFILT_WRITE {
                event::kind_mut(&mut self.events[idx]).insert(Ready::writable());
            }

            if e.flags & libc::EV_EOF != 0 {
                event::kind_mut(&mut self.events[idx]).insert(Ready::hup());

                // When the read end of the socket is closed, EV_EOF is set on
                // flags, and fflags contains the error if there is one.
                if e.fflags != 0 {
                    event::kind_mut(&mut self.events[idx]).insert(Ready::error());
                }
            }
        }

        ret
    }

    pub fn push_event(&mut self, event: Event) {
        self.events.push(event);
    }
}

impl fmt::Debug for Events {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Events {{ len: {} }}", self.sys_events.0.len())
    }
}
<commit_msg>Delete redundant comments<commit_after>use std::{cmp, fmt, ptr};
use std::os::raw::c_int;
use std::os::unix::io::RawFd;
use std::collections::HashMap;
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::time::Duration;

use libc::{self, time_t};

use {io, event, Ready, PollOpt, Token, Event};
use sys::cvt;
use sys::io::set_cloexec;

/// Each Selector has a globally unique(ish) ID associated with it. This ID
/// gets tracked by `TcpStream`, `TcpListener`, etc... when they are first
/// registered with the `Selector`. If a type that is previously associated with
/// a `Selector` attempts to register itself with a different `Selector`, the
/// operation will return with an error. This matches windows behavior.
static NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;

macro_rules! kevent {
    ($id: expr, $filter: expr, $flags: expr, $data: expr) => {
        libc::kevent {
            ident: $id as ::libc::uintptr_t,
            filter: $filter,
            flags: $flags,
            fflags: 0,
            data: 0,
            udata: $data as *mut _,
        }
    }
}

pub struct Selector {
    id: usize,
    kq: RawFd,
}

impl Selector {
    pub fn new() -> io::Result<Selector> {
        // offset by 1 to avoid choosing 0 as the id of a selector
        let id = NEXT_ID.fetch_add(1, Ordering::Relaxed) + 1;
        let kq = unsafe { try!(cvt(libc::kqueue())) };
        drop(set_cloexec(kq));

        Ok(Selector {
            id: id,
            kq: kq,
        })
    }

    pub fn id(&self) -> usize {
        self.id
    }

    pub fn select(&self, evts: &mut Events, awakener: Token, timeout: Option<Duration>) -> io::Result<bool> {
        let timeout = timeout.map(|to| {
            libc::timespec {
                tv_sec: cmp::min(to.as_secs(), time_t::max_value() as u64) as time_t,
                tv_nsec: to.subsec_nanos() as libc::c_long,
            }
        });
        let timeout = timeout.as_ref().map(|s| s as *const _).unwrap_or(ptr::null_mut());

        unsafe {
            let cnt = try!(cvt(libc::kevent(self.kq,
                                            ptr::null(),
                                            0,
                                            evts.sys_events.0.as_mut_ptr(),
            // FIXME: needs a saturating cast here.
                                            evts.sys_events.0.capacity() as c_int,
                                            timeout)));
            evts.sys_events.0.set_len(cnt as usize);
            Ok(evts.coalesce(awakener))
        }
    }

    pub fn register(&self, fd: RawFd, token: Token, interests: Ready, opts: PollOpt) -> io::Result<()> {
        trace!("registering; token={:?}; interests={:?}", token, interests);

        let flags = if opts.contains(PollOpt::edge()) { libc::EV_CLEAR } else { 0 } |
                    if opts.contains(PollOpt::oneshot()) { libc::EV_ONESHOT } else { 0 } |
                    libc::EV_RECEIPT;

        unsafe {
            let r = if interests.contains(Ready::readable()) { libc::EV_ADD } else { libc::EV_DELETE };
            let w = if interests.contains(Ready::writable()) { libc::EV_ADD } else { libc::EV_DELETE };
            let mut changes = [
                kevent!(fd, libc::EVFILT_READ, flags | r, usize::from(token)),
                kevent!(fd, libc::EVFILT_WRITE, flags | w, usize::from(token)),
            ];
            try!(cvt(libc::kevent(self.kq, changes.as_ptr(), changes.len() as c_int,
                                           changes.as_mut_ptr(), changes.len() as c_int,
                                           ::std::ptr::null())));
            for change in changes.iter() {
                debug_assert_eq!(change.flags & libc::EV_ERROR, libc::EV_ERROR);

                if change.data == 0 {
                    continue
                }

                if change.data as i32 == libc::EPIPE && change.filter == libc::EVFILT_WRITE {
                    continue
                }

                let orig_flags = if change.filter == libc::EVFILT_READ { r } else { w };
                if change.data as i32 == libc::ENOENT && orig_flags & libc::EV_DELETE != 0 {
                    continue
                }

                return Err(::std::io::Error::from_raw_os_error(change.data as i32));
            }
            Ok(())
        }
    }

    pub fn reregister(&self, fd: RawFd, token: Token, interests: Ready, opts: PollOpt) -> io::Result<()> {
        // Just need to call register here since EV_ADD is a mod if already
        // registered
        self.register(fd, token, interests, opts)
    }

    pub fn deregister(&self, fd: RawFd) -> io::Result<()> {
        unsafe {
            // EV_RECEIPT is a nice way to apply changes and get back per-event results while not
            // draining the actual changes.
            let filter = libc::EV_DELETE | libc::EV_RECEIPT;
            let mut changes = [
                kevent!(fd, libc::EVFILT_READ, filter, ptr::null_mut()),
                kevent!(fd, libc::EVFILT_WRITE, filter, ptr::null_mut()),
            ];
            try!(cvt(libc::kevent(self.kq, changes.as_ptr(), changes.len() as c_int,
                                           changes.as_mut_ptr(), changes.len() as c_int,
                                           ::std::ptr::null())).map(|_| ()));
            if changes[0].data as i32 == libc::ENOENT && changes[1].data as i32 == libc::ENOENT {
                return Err(::std::io::Error::from_raw_os_error(changes[0].data as i32));
            }
            for change in changes.iter() {
                debug_assert_eq!(libc::EV_ERROR & change.flags, libc::EV_ERROR);
                if change.data != 0 && change.data as i32 != libc::ENOENT {
                    return Err(::std::io::Error::from_raw_os_error(changes[0].data as i32));
                }
            }
            Ok(())
        }
    }
}

impl fmt::Debug for Selector {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Selector")
            .field("id", &self.id)
            .field("kq", &self.kq)
            .finish()
    }
}

impl Drop for Selector {
    fn drop(&mut self) {
        unsafe {
            let _ = libc::close(self.kq);
        }
    }
}

pub struct Events {
    sys_events: KeventList,
    events: Vec<Event>,
    event_map: HashMap<Token, usize>,
}

struct KeventList(Vec<libc::kevent>);

unsafe impl Send for KeventList {}
unsafe impl Sync for KeventList {}

impl Events {
    pub fn with_capacity(cap: usize) -> Events {
        Events {
            sys_events: KeventList(Vec::with_capacity(cap)),
            events: Vec::with_capacity(cap),
            event_map: HashMap::with_capacity(cap)
        }
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.events.len()
    }

    #[inline]
    pub fn capacity(&self) -> usize {
        self.events.capacity()
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.events.is_empty()
    }

    pub fn get(&self, idx: usize) -> Option<Event> {
        self.events.get(idx).map(|e| *e)
    }

    fn coalesce(&mut self, awakener: Token) -> bool {
        let mut ret = false;
        self.events.clear();
        self.event_map.clear();

        for e in self.sys_events.0.iter() {
            let token = Token(e.udata as usize);
            let len = self.events.len();

            if token == awakener {
                // TODO: Should this return an error if event is an error. It
                // is not critical as spurious wakeups are permitted.
                ret = true;
                continue;
            }

            let idx = *self.event_map.entry(token)
                .or_insert(len);

            if idx == len {
                // New entry, insert the default
                self.events.push(Event::new(Ready::empty(), token));

            }

            if e.flags & libc::EV_ERROR != 0 {
                event::kind_mut(&mut self.events[idx]).insert(Ready::error());
            }

            if e.filter == libc::EVFILT_READ {
                event::kind_mut(&mut self.events[idx]).insert(Ready::readable());
            } else if e.filter == libc::EVFILT_WRITE {
                event::kind_mut(&mut self.events[idx]).insert(Ready::writable());
            }

            if e.flags & libc::EV_EOF != 0 {
                event::kind_mut(&mut self.events[idx]).insert(Ready::hup());

                // When the read end of the socket is closed, EV_EOF is set on
                // flags, and fflags contains the error if there is one.
                if e.fflags != 0 {
                    event::kind_mut(&mut self.events[idx]).insert(Ready::error());
                }
            }
        }

        ret
    }

    pub fn push_event(&mut self, event: Event) {
        self.events.push(event);
    }
}

impl fmt::Debug for Events {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Events {{ len: {} }}", self.sys_events.0.len())
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::marker::PhantomData;
use std::net::SocketAddr;
use std::sync::Arc;
use std::thread;

use BindServer;
use futures::stream::Stream;
use net2;
use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::reactor::{Core, Handle};
use tokio_service::NewService;

// TODO: Add more options, e.g.:
// - max concurrent requests
// - request timeout
// - read timeout
// - write timeout
// - max idle time
// - max lifetime

/// A builder for TCP servers.
///
/// Setting up a server needs, at minimum:
///
/// - A server protocol implementation
/// - An address
/// - A service to provide
///
/// In addition to those basics, the builder provides some additional
/// configuration, which is expected to grow over time.
///
/// See the crate docs for an example.
pub struct TcpServer<Kind, P> {
    _kind: PhantomData<Kind>,
    proto: Arc<P>,
    threads: usize,
    addr: SocketAddr,
}

impl<Kind, P> TcpServer<Kind, P> where
    P: BindServer<Kind, TcpStream> + Send + Sync + 'static
{
    /// Starts building a server for the given protocol and address, with
    /// default configuration.
    ///
    /// Generally, a protocol is implemented *not* by implementing the
    /// `BindServer` trait directly, but instead by implementing one of the
    /// protocol traits:
    ///
    /// - `pipeline::Server`
    /// - `multiplex::Server`
    /// - `streaming::pipeline::Server`
    /// - `streaming::multiplex::Server`
    ///
    /// See the crate documentation for more details on those traits.
    pub fn new(protocol: P, addr: SocketAddr) -> TcpServer<Kind, P> {
        TcpServer {
            _kind: PhantomData,
            proto: Arc::new(protocol),
            threads: 1,
            addr: addr,
        }
    }

    /// Set the address for the server.
    pub fn addr(&mut self, addr: SocketAddr) {
        self.addr = addr;
    }

    /// Set the number of threads running simultaneous event loops (Unix only).
    pub fn threads(&mut self, threads: usize) {
        assert!(threads > 0);
        if cfg!(unix) {
            self.threads = threads;
        }
    }

    /// Start up the server, providing the given service on it.
    ///
    /// This method will block the current thread until the server is shut down.
    pub fn serve<S>(&self, new_service: S) where
        S: NewService<Request = P::ServiceRequest,
                      Response = P::ServiceResponse,
                      Error = P::ServiceError> + Send + Sync + 'static,
    {
        let proto = self.proto.clone();
        let new_service = Arc::new(new_service);
        let addr = self.addr;
        let workers = self.threads;

        let threads = (0..self.threads - 1).map(|i| {
            let proto = proto.clone();
            let new_service = new_service.clone();

            thread::Builder::new().name(format!("worker{}", i)).spawn(move || {
                serve(proto, addr, workers, &new_service)
            }).unwrap()
        }).collect::<Vec<_>>();

        serve(proto, addr, workers, &new_service);

        for thread in threads {
            thread.join().unwrap();
        }
    }
}

fn serve<P, Kind, S>(binder: Arc<P>, addr: SocketAddr, workers: usize, new_service: &S)
    where P: BindServer<Kind, TcpStream>,
          S: NewService<Request = P::ServiceRequest,
                        Response = P::ServiceResponse,
                        Error = P::ServiceError> + 'static,
{
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let listener = listener(&addr, workers, &handle).unwrap();

    let server = listener.incoming().for_each(move |(socket, _)| {
        // Create the service
        let service = try!(new_service.new_service());

        // Bind it!
        binder.bind_server(&handle, socket, service);

        Ok(())
    });

    core.run(server).unwrap();
}

fn listener(addr: &SocketAddr,
            workers: usize,
            handle: &Handle) -> io::Result<TcpListener> {
    let listener = try!(net2::TcpBuilder::new_v4());
    try!(configure_tcp(workers, &listener));
    try!(listener.reuse_address(true));
    try!(listener.bind(addr));
    listener.listen(1024).and_then(|l| {
        TcpListener::from_listener(l, addr, handle)
    })
}

#[cfg(unix)]
fn configure_tcp(workers: usize, tcp: &net2::TcpBuilder) -> io::Result<()> {
    use net2::unix::*;

    if workers > 1 {
        try!(tcp.reuse_port(true));
    }

    Ok(())
}

#[cfg(windows)]
fn configure_tcp(workers: usize, _tcp: &net2::TcpBuilder) -> io::Result<()> {
    Ok(())
}
<commit_msg>Fix listening on an ipv6 address<commit_after>use std::io;
use std::marker::PhantomData;
use std::net::SocketAddr;
use std::sync::Arc;
use std::thread;

use BindServer;
use futures::stream::Stream;
use net2;
use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::reactor::{Core, Handle};
use tokio_service::NewService;

// TODO: Add more options, e.g.:
// - max concurrent requests
// - request timeout
// - read timeout
// - write timeout
// - max idle time
// - max lifetime

/// A builder for TCP servers.
///
/// Setting up a server needs, at minimum:
///
/// - A server protocol implementation
/// - An address
/// - A service to provide
///
/// In addition to those basics, the builder provides some additional
/// configuration, which is expected to grow over time.
///
/// See the crate docs for an example.
pub struct TcpServer<Kind, P> {
    _kind: PhantomData<Kind>,
    proto: Arc<P>,
    threads: usize,
    addr: SocketAddr,
}

impl<Kind, P> TcpServer<Kind, P> where
    P: BindServer<Kind, TcpStream> + Send + Sync + 'static
{
    /// Starts building a server for the given protocol and address, with
    /// default configuration.
    ///
    /// Generally, a protocol is implemented *not* by implementing the
    /// `BindServer` trait directly, but instead by implementing one of the
    /// protocol traits:
    ///
    /// - `pipeline::Server`
    /// - `multiplex::Server`
    /// - `streaming::pipeline::Server`
    /// - `streaming::multiplex::Server`
    ///
    /// See the crate documentation for more details on those traits.
    pub fn new(protocol: P, addr: SocketAddr) -> TcpServer<Kind, P> {
        TcpServer {
            _kind: PhantomData,
            proto: Arc::new(protocol),
            threads: 1,
            addr: addr,
        }
    }

    /// Set the address for the server.
    pub fn addr(&mut self, addr: SocketAddr) {
        self.addr = addr;
    }

    /// Set the number of threads running simultaneous event loops (Unix only).
    pub fn threads(&mut self, threads: usize) {
        assert!(threads > 0);
        if cfg!(unix) {
            self.threads = threads;
        }
    }

    /// Start up the server, providing the given service on it.
    ///
    /// This method will block the current thread until the server is shut down.
    pub fn serve<S>(&self, new_service: S) where
        S: NewService<Request = P::ServiceRequest,
                      Response = P::ServiceResponse,
                      Error = P::ServiceError> + Send + Sync + 'static,
    {
        let proto = self.proto.clone();
        let new_service = Arc::new(new_service);
        let addr = self.addr;
        let workers = self.threads;

        let threads = (0..self.threads - 1).map(|i| {
            let proto = proto.clone();
            let new_service = new_service.clone();

            thread::Builder::new().name(format!("worker{}", i)).spawn(move || {
                serve(proto, addr, workers, &new_service)
            }).unwrap()
        }).collect::<Vec<_>>();

        serve(proto, addr, workers, &new_service);

        for thread in threads {
            thread.join().unwrap();
        }
    }
}

fn serve<P, Kind, S>(binder: Arc<P>, addr: SocketAddr, workers: usize, new_service: &S)
    where P: BindServer<Kind, TcpStream>,
          S: NewService<Request = P::ServiceRequest,
                        Response = P::ServiceResponse,
                        Error = P::ServiceError> + 'static,
{
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let listener = listener(&addr, workers, &handle).unwrap();

    let server = listener.incoming().for_each(move |(socket, _)| {
        // Create the service
        let service = try!(new_service.new_service());

        // Bind it!
        binder.bind_server(&handle, socket, service);

        Ok(())
    });

    core.run(server).unwrap();
}

fn listener(addr: &SocketAddr,
            workers: usize,
            handle: &Handle) -> io::Result<TcpListener> {
    let listener = match *addr {
        SocketAddr::V4(_) => try!(net2::TcpBuilder::new_v4()),
        SocketAddr::V6(_) => try!(net2::TcpBuilder::new_v6()),
    };
    try!(configure_tcp(workers, &listener));
    try!(listener.reuse_address(true));
    try!(listener.bind(addr));
    listener.listen(1024).and_then(|l| {
        TcpListener::from_listener(l, addr, handle)
    })
}

#[cfg(unix)]
fn configure_tcp(workers: usize, tcp: &net2::TcpBuilder) -> io::Result<()> {
    use net2::unix::*;

    if workers > 1 {
        try!(tcp.reuse_port(true));
    }

    Ok(())
}

#[cfg(windows)]
fn configure_tcp(workers: usize, _tcp: &net2::TcpBuilder) -> io::Result<()> {
    Ok(())
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Prime_decomposition

#[cfg(not(test))]
fn factor(mut nb: i32) -> Vec<i32> {
	let mut result = vec!();

	// First we take out all even factors.
	while nb % 2 == 0 {
		result.push(2);
		nb /= 2;
	}

	// Then (if any left) we take out the odd ones.
	let mut cand = 3;
	let mut max_bound = (nb as f32).sqrt() as i32 + 1;

	while cand <= max_bound {
		while nb % cand == 0 {
			result.push(cand);
			nb /= cand;
		}
		max_bound = (nb as f32).sqrt() as i32 + 1;
		cand += 2;
	}

	if nb > 1 {
		result.push(nb);
	}

	result
}

#[cfg(not(test))]
fn main() {
	println!("Factors of 5: {}", factor(5));
	println!("Factors of 15: {}", factor(15));
	println!("Factors of 16: {}", factor(16));
	println!("Factors of 10287: {}", factor(10287));
}

#[test]
fn test_basic() {
    assert!(factor(5) == vec!(5));
    assert!(factor(15) == vec!(3, 5));
    assert!(factor(16) == vec!(2, 2, 2, 2));
    assert!(factor(10287) == vec!(3, 3, 3, 3, 127));
}
<commit_msg>remove cfg attribute which prevents compilation<commit_after>// Implements http://rosettacode.org/wiki/Prime_decomposition

fn factor(mut nb: i32) -> Vec<i32> {
	let mut result = vec!();

	// First we take out all even factors.
	while nb % 2 == 0 {
		result.push(2);
		nb /= 2;
	}

	// Then (if any left) we take out the odd ones.
	let mut cand = 3;
	let mut max_bound = (nb as f32).sqrt() as i32 + 1;

	while cand <= max_bound {
		while nb % cand == 0 {
			result.push(cand);
			nb /= cand;
		}
		max_bound = (nb as f32).sqrt() as i32 + 1;
		cand += 2;
	}

	if nb > 1 {
		result.push(nb);
	}

	result
}

#[cfg(not(test))]
fn main() {
	println!("Factors of 5: {}", factor(5));
	println!("Factors of 15: {}", factor(15));
	println!("Factors of 16: {}", factor(16));
	println!("Factors of 10287: {}", factor(10287));
}

#[test]
fn test_basic() {
    assert!(factor(5) == vec!(5));
    assert!(factor(15) == vec!(3, 5));
    assert!(factor(16) == vec!(2, 2, 2, 2));
    assert!(factor(10287) == vec!(3, 3, 3, 3, 127));
}
<|endoftext|>


<commit_before>#![deny(unused_must_use)]

extern crate d7staticfs;

use std::env;
use std::fs::{File, OpenOptions};
use std::io::{prelude::*, SeekFrom};
use std::u32;

use d7staticfs::*;

fn round_up_sector(p: u64) -> u64 {
    (p + SECTOR_SIZE - 1) / SECTOR_SIZE
}

fn main() {
    let args: Vec<String> = env::args().skip(1).collect();

    if args.len() == 0 {
        println!("usage: disk.img kernel_skip_index [filename=filepath ...]");
        return;
    }

    let disk_img_path = &args[0];
    let kernel_skip_index = args[1]
        .parse::<u32>()
        .expect("kernel_skip_index: Integer required");

    let mut files: Vec<(String, FileEntry, u32)> = Vec::new();
    for filearg in args.iter().skip(2) {
        let halfs = filearg.splitn(2, '=').collect::<Vec<_>>();
        assert_eq!(halfs.len(), 2);

        let fs_filename = halfs[0].trim();
        let rl_filename = halfs[1].trim();

        for (_, e, _) in &files {
            assert!(!e.name_matches(fs_filename), "Duplicate names not allowed");
        }

        let f = File::open(rl_filename).expect(&format!("File not found: {:?}", rl_filename));
        let meta = f.metadata().expect("Metadata not found");
        assert!(meta.is_file());

        let size_sectors = round_up_sector(meta.len());
        assert!(size_sectors <= u32::MAX as u64);

        let fe = FileEntry::new(fs_filename, size_sectors as u32);
        files.push((rl_filename.to_owned(), fe, 0));
    }

    let meta = {
        let f = File::open(disk_img_path).expect("Target file not found");
        f.metadata().expect("Target file metadata not available")
    };
    let size_sectors = round_up_sector(meta.len());
    assert!(size_sectors <= u32::MAX as u64);
    assert_eq!(meta.len(), size_sectors * SECTOR_SIZE);

    // Check that the file is big enough
    // TODO: lt or lte?
    let required_size_sectors = kernel_skip_index as u64
        + round_up_sector(16 + files.len() as u64 * 16)
        + files.iter().map(|(_, e, _)| e.size as u64).sum::<u64>();
    assert!(
        required_size_sectors < size_sectors,
        "File is not large enough, sectors required: {}, got only {}",
        required_size_sectors,
        size_sectors
    );

    {
        // Check placeholder magic
        let mut f = File::open(disk_img_path).expect("Target file not found");
        let mut magic_check: [u8; 4] = [0; 4];
        f.seek(SeekFrom::Start(MBR_POSITION as u64)).unwrap();
        f.read(&mut magic_check).unwrap();
        assert_eq!(
            magic_check,
            HEADER_MAGIC.to_le_bytes(),
            "Magic placeholder missing"
        );
    }

    {
        // Check kernel skip index
        let mut f = File::open(disk_img_path).expect("Target file not found");
        let mut empty_check: [u8; 4] = [0; 4];
        f.seek(SeekFrom::Start((kernel_skip_index as u64) * SECTOR_SIZE))
            .unwrap();
        f.read(&mut empty_check).unwrap();
        assert_eq!(empty_check, [0; 4]);
    }

    {
        // Set LBA pointer
        let mut f = OpenOptions::new() // overwrite, don't insert in middle
            .read(false)
            .write(true)
            .create(false)
            .open(disk_img_path)
            .unwrap();

        let mut lba_ptr: [u8; 4] = (kernel_skip_index as u32).to_le_bytes();
        f.seek(SeekFrom::Start(MBR_POSITION as u64)).unwrap();
        f.write_all(&mut lba_ptr).unwrap();
    }

    {
        // Write file table and file contents
        let mut f = OpenOptions::new() // overwrite, don't insert in middle
            .read(false)
            .write(true)
            .create(false)
            .open(disk_img_path)
            .unwrap();

        let header_0: [u8; 4] = HEADER_MAGIC.to_le_bytes();
        let header_1: [u8; 4] = ONLY_VERSION.to_le_bytes();
        let header_2: [u8; 4] = (files.len() as u32).to_le_bytes();
        let header_3: [u8; 4] = 0u32.to_le_bytes();
        f.seek(SeekFrom::Start(kernel_skip_index as u64 * SECTOR_SIZE))
            .unwrap();

        // Header
        f.write_all(&header_0).unwrap();
        f.write_all(&header_1).unwrap();
        f.write_all(&header_2).unwrap();
        f.write_all(&header_3).unwrap();

        // Entries
        for (_, entry, _) in &files {
            f.write_all(&entry.to_bytes()).unwrap();
        }

        // Align to sector boundary
        let files_start_pos =
            kernel_skip_index as u64 + round_up_sector(16 + files.len() as u64 * 16);

        f.seek(SeekFrom::Start(files_start_pos * SECTOR_SIZE))
            .unwrap();
        let mut files_sectors_count: u64 = 0;

        // Copy files to disk image
        for (i, (path, entry, _)) in files.clone().iter().enumerate() {
            let mut rf = File::open(path).expect(&format!("Source file '{}' not found", path));

            files[i].2 = files_sectors_count as u32;

            let mut counter: u64 = 0;
            let mut buffer = [0u8; 0x200];
            loop {
                let bytes_read = rf.read(&mut buffer).unwrap();
                if bytes_read == 0 {
                    break;
                }
                counter += bytes_read as u64;
                f.write_all(&buffer[..bytes_read]).unwrap();
            }

            // Zero-pad to sector boundary
            f.write_all(&vec![0; (SECTOR_SIZE - (counter % SECTOR_SIZE)) as usize].as_slice())
                .unwrap();

            assert_eq!(round_up_sector(counter), entry.size as u64);
            files_sectors_count += entry.size as u64;
        }

        assert_eq!(
            files_sectors_count,
            files.iter().map(|(_, e, _)| e.size as u64).sum::<u64>()
        );
    }

    println!(" File Name    | Offset (hex) | Size (hex) | Host Path ");
    println!("--------------|--------------|------------|-----------");
    for (host_path, file, offset) in files {
        println!(
            " {:<12} |     {:>8x} |   {:>8x} | {}",
            std::str::from_utf8(&file.name).unwrap(),
            offset,
            file.size,
            host_path
        );
    }
    println!("");
}
<commit_msg>Fix padding bug<commit_after>#![deny(unused_must_use)]

extern crate d7staticfs;

use std::env;
use std::fs::{File, OpenOptions};
use std::io::{prelude::*, SeekFrom};
use std::u32;

use d7staticfs::*;

fn round_up_sector(p: u64) -> u64 {
    (p + SECTOR_SIZE - 1) / SECTOR_SIZE
}

fn main() {
    let args: Vec<String> = env::args().skip(1).collect();

    if args.len() == 0 {
        println!("usage: disk.img kernel_skip_index [filename=filepath ...]");
        return;
    }

    let disk_img_path = &args[0];
    let kernel_skip_index = args[1]
        .parse::<u32>()
        .expect("kernel_skip_index: Integer required");

    let mut files: Vec<(String, FileEntry, u32)> = Vec::new();
    for filearg in args.iter().skip(2) {
        let halfs = filearg.splitn(2, '=').collect::<Vec<_>>();
        assert_eq!(halfs.len(), 2);

        let fs_filename = halfs[0].trim();
        let rl_filename = halfs[1].trim();

        for (_, e, _) in &files {
            assert!(!e.name_matches(fs_filename), "Duplicate names not allowed");
        }

        let f = File::open(rl_filename).expect(&format!("File not found: {:?}", rl_filename));
        let meta = f.metadata().expect("Metadata not found");
        assert!(meta.is_file());

        let size_sectors = round_up_sector(meta.len());
        assert!(size_sectors <= u32::MAX as u64);

        let fe = FileEntry::new(fs_filename, size_sectors as u32);
        files.push((rl_filename.to_owned(), fe, 0));
    }

    let meta = {
        let f = File::open(disk_img_path).expect("Target file not found");
        f.metadata().expect("Target file metadata not available")
    };
    let size_sectors = round_up_sector(meta.len());
    assert!(size_sectors <= u32::MAX as u64);
    assert_eq!(meta.len(), size_sectors * SECTOR_SIZE);

    // Check that the file is big enough
    // TODO: lt or lte?
    let required_size_sectors = kernel_skip_index as u64
        + round_up_sector(16 + files.len() as u64 * 16)
        + files.iter().map(|(_, e, _)| e.size as u64).sum::<u64>();
    assert!(
        required_size_sectors < size_sectors,
        "File is not large enough, sectors required: {}, got only {}",
        required_size_sectors,
        size_sectors
    );

    {
        // Check placeholder magic
        let mut f = File::open(disk_img_path).expect("Target file not found");
        let mut magic_check: [u8; 4] = [0; 4];
        f.seek(SeekFrom::Start(MBR_POSITION as u64)).unwrap();
        f.read(&mut magic_check).unwrap();
        assert_eq!(
            magic_check,
            HEADER_MAGIC.to_le_bytes(),
            "Magic placeholder missing"
        );
    }

    {
        // Check kernel skip index
        let mut f = File::open(disk_img_path).expect("Target file not found");
        let mut empty_check: [u8; 4] = [0; 4];
        f.seek(SeekFrom::Start((kernel_skip_index as u64) * SECTOR_SIZE))
            .unwrap();
        f.read(&mut empty_check).unwrap();
        assert_eq!(empty_check, [0; 4]);
    }

    {
        // Set LBA pointer
        let mut f = OpenOptions::new() // overwrite, don't insert in middle
            .read(false)
            .write(true)
            .create(false)
            .open(disk_img_path)
            .unwrap();

        let mut lba_ptr: [u8; 4] = (kernel_skip_index as u32).to_le_bytes();
        f.seek(SeekFrom::Start(MBR_POSITION as u64)).unwrap();
        f.write_all(&mut lba_ptr).unwrap();
    }

    {
        // Write file table and file contents
        let mut f = OpenOptions::new() // overwrite, don't insert in middle
            .read(false)
            .write(true)
            .create(false)
            .open(disk_img_path)
            .unwrap();

        let header_0: [u8; 4] = HEADER_MAGIC.to_le_bytes();
        let header_1: [u8; 4] = ONLY_VERSION.to_le_bytes();
        let header_2: [u8; 4] = (files.len() as u32).to_le_bytes();
        let header_3: [u8; 4] = 0u32.to_le_bytes();
        f.seek(SeekFrom::Start(kernel_skip_index as u64 * SECTOR_SIZE))
            .unwrap();

        // Header
        f.write_all(&header_0).unwrap();
        f.write_all(&header_1).unwrap();
        f.write_all(&header_2).unwrap();
        f.write_all(&header_3).unwrap();

        // Entries
        for (_, entry, _) in &files {
            f.write_all(&entry.to_bytes()).unwrap();
        }

        // Align to sector boundary
        let files_start_pos =
            kernel_skip_index as u64 + round_up_sector(16 + files.len() as u64 * 16);

        f.seek(SeekFrom::Start(files_start_pos * SECTOR_SIZE))
            .unwrap();
        let mut files_sectors_count: u64 = 0;

        // Copy files to disk image
        for (i, (path, entry, _)) in files.clone().iter().enumerate() {
            let mut rf = File::open(path).expect(&format!("Source file '{}' not found", path));

            files[i].2 = files_sectors_count as u32;

            let mut counter: u64 = 0;
            let mut buffer = [0u8; 0x200];
            loop {
                let bytes_read = rf.read(&mut buffer).unwrap();
                if bytes_read == 0 {
                    break;
                }
                counter += bytes_read as u64;
                f.write_all(&buffer[..bytes_read]).unwrap();
            }

            // Zero-pad to sector boundary
            let mut pad_count = SECTOR_SIZE - (counter % SECTOR_SIZE);
            if pad_count == SECTOR_SIZE {
                pad_count = 0;
            }
            f.write_all(&vec![0; pad_count as usize].as_slice())
                .unwrap();

            assert_eq!(round_up_sector(counter), entry.size as u64);
            files_sectors_count += entry.size as u64;
        }

        assert_eq!(
            files_sectors_count,
            files.iter().map(|(_, e, _)| e.size as u64).sum::<u64>()
        );
    }

    println!(" File Name    | Offset (hex) | Size (hex) | Host Path ");
    println!("--------------|--------------|------------|-----------");
    for (host_path, file, offset) in files {
        println!(
            " {:<12} |     {:>8x} |   {:>8x} | {}",
            std::str::from_utf8(&file.name).unwrap(),
            offset,
            file.size,
            host_path
        );
    }
    println!("");
}
<|endoftext|>


<commit_before>//! Checks for needless boolean results of if-else expressions
//!
//! This lint is **warn** by default

use crate::utils::sugg::Sugg;
use crate::utils::{in_macro, span_lint, span_lint_and_sugg};
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use syntax::ast::LitKind;
use syntax::source_map::Spanned;

declare_clippy_lint! {
    /// **What it does:** Checks for expressions of the form `if c { true } else {
    /// false }`
    /// (or vice versa) and suggest using the condition directly.
    ///
    /// **Why is this bad?** Redundant code.
    ///
    /// **Known problems:** Maybe false positives: Sometimes, the two branches are
    /// painstakingly documented (which we of course do not detect), so they *may*
    /// have some value. Even then, the documentation can be rewritten to match the
    /// shorter code.
    ///
    /// **Example:**
    /// ```rust
    /// if x {
    ///     false
    /// } else {
    ///     true
    /// }
    /// ```
    pub NEEDLESS_BOOL,
    complexity,
    "if-statements with plain booleans in the then- and else-clause, e.g., `if p { true } else { false }`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for expressions of the form `x == true`,
    /// `x != true` and order comparisons such as `x < true` (or vice versa) and
    /// suggest using the variable directly.
    ///
    /// **Why is this bad?** Unnecessary code.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// if x == true {} // could be `if x { }`
    /// ```
    pub BOOL_COMPARISON,
    complexity,
    "comparing a variable to a boolean, e.g., `if x == true` or `if x != true`"
}

declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        use self::Expression::*;
        if let ExprKind::If(ref pred, ref then_block, Some(ref else_expr)) = e.node {
            let reduce = |ret, not| {
                let mut applicability = Applicability::MachineApplicable;
                let snip = Sugg::hir_with_applicability(cx, pred, "<predicate>", &mut applicability);
                let mut snip = if not { !snip } else { snip };

                if ret {
                    snip = snip.make_return();
                }

                if parent_node_is_if_expr(&e, &cx) {
                    snip = snip.blockify()
                }

                span_lint_and_sugg(
                    cx,
                    NEEDLESS_BOOL,
                    e.span,
                    "this if-then-else expression returns a bool literal",
                    "you can reduce it to",
                    snip.to_string(),
                    applicability,
                );
            };
            if let ExprKind::Block(ref then_block, _) = then_block.node {
                match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) {
                    (RetBool(true), RetBool(true)) | (Bool(true), Bool(true)) => {
                        span_lint(
                            cx,
                            NEEDLESS_BOOL,
                            e.span,
                            "this if-then-else expression will always return true",
                        );
                    },
                    (RetBool(false), RetBool(false)) | (Bool(false), Bool(false)) => {
                        span_lint(
                            cx,
                            NEEDLESS_BOOL,
                            e.span,
                            "this if-then-else expression will always return false",
                        );
                    },
                    (RetBool(true), RetBool(false)) => reduce(true, false),
                    (Bool(true), Bool(false)) => reduce(false, false),
                    (RetBool(false), RetBool(true)) => reduce(true, true),
                    (Bool(false), Bool(true)) => reduce(false, true),
                    _ => (),
                }
            } else {
                panic!("IfExpr 'then' node is not an ExprKind::Block");
            }
        }
    }
}

fn parent_node_is_if_expr<'a, 'b>(expr: &Expr, cx: &LateContext<'a, 'b>) -> bool {
    let parent_id = cx.tcx.hir().get_parent_node_by_hir_id(expr.hir_id);
    let parent_node = cx.tcx.hir().get_by_hir_id(parent_id);

    if let rustc::hir::Node::Expr(e) = parent_node {
        if let ExprKind::If(_, _, _) = e.node {
            return true;
        }
    }

    false
}

declare_lint_pass!(BoolComparison => [BOOL_COMPARISON]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        if in_macro(e.span) {
            return;
        }

        if let ExprKind::Binary(Spanned { node, .. }, ..) = e.node {
            let ignore_case = None::<(fn(_) -> _, &str)>;
            let ignore_no_literal = None::<(fn(_, _) -> _, &str)>;
            match node {
                BinOpKind::Eq => {
                    let true_case = Some((|h| h, "equality checks against true are unnecessary"));
                    let false_case = Some((
                        |h: Sugg<'_>| !h,
                        "equality checks against false can be replaced by a negation",
                    ));
                    check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal)
                },
                BinOpKind::Ne => {
                    let true_case = Some((
                        |h: Sugg<'_>| !h,
                        "inequality checks against true can be replaced by a negation",
                    ));
                    let false_case = Some((|h| h, "inequality checks against false are unnecessary"));
                    check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal)
                },
                BinOpKind::Lt => check_comparison(
                    cx,
                    e,
                    ignore_case,
                    Some((|h| h, "greater than checks against false are unnecessary")),
                    Some((
                        |h: Sugg<'_>| !h,
                        "less than comparison against true can be replaced by a negation",
                    )),
                    ignore_case,
                    Some((
                        |l: Sugg<'_>, r: Sugg<'_>| (!l).bit_and(&r),
                        "order comparisons between booleans can be simplified",
                    )),
                ),
                BinOpKind::Gt => check_comparison(
                    cx,
                    e,
                    Some((
                        |h: Sugg<'_>| !h,
                        "less than comparison against true can be replaced by a negation",
                    )),
                    ignore_case,
                    ignore_case,
                    Some((|h| h, "greater than checks against false are unnecessary")),
                    Some((
                        |l: Sugg<'_>, r: Sugg<'_>| l.bit_and(&(!r)),
                        "order comparisons between booleans can be simplified",
                    )),
                ),
                _ => (),
            }
        }
    }
}

fn check_comparison<'a, 'tcx>(
    cx: &LateContext<'a, 'tcx>,
    e: &'tcx Expr,
    left_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>,
    left_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>,
    right_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>,
    right_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>,
    no_literal: Option<(impl FnOnce(Sugg<'a>, Sugg<'a>) -> Sugg<'a>, &str)>,
) {
    use self::Expression::*;

    if let ExprKind::Binary(_, ref left_side, ref right_side) = e.node {
        let (l_ty, r_ty) = (cx.tables.expr_ty(left_side), cx.tables.expr_ty(right_side));
        if l_ty.is_bool() && r_ty.is_bool() {
            let mut applicability = Applicability::MachineApplicable;
            match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) {
                (Bool(true), Other) => left_true.map_or((), |(h, m)| {
                    suggest_bool_comparison(cx, e, right_side, applicability, m, h)
                }),
                (Other, Bool(true)) => right_true.map_or((), |(h, m)| {
                    suggest_bool_comparison(cx, e, left_side, applicability, m, h)
                }),
                (Bool(false), Other) => left_false.map_or((), |(h, m)| {
                    suggest_bool_comparison(cx, e, right_side, applicability, m, h)
                }),
                (Other, Bool(false)) => right_false.map_or((), |(h, m)| {
                    suggest_bool_comparison(cx, e, left_side, applicability, m, h)
                }),
                (Other, Other) => no_literal.map_or((), |(h, m)| {
                    let left_side = Sugg::hir_with_applicability(cx, left_side, "..", &mut applicability);
                    let right_side = Sugg::hir_with_applicability(cx, right_side, "..", &mut applicability);
                    span_lint_and_sugg(
                        cx,
                        BOOL_COMPARISON,
                        e.span,
                        m,
                        "try simplifying it as shown",
                        h(left_side, right_side).to_string(),
                        applicability,
                    )
                }),
                _ => (),
            }
        }
    }
}

fn suggest_bool_comparison<'a, 'tcx>(
    cx: &LateContext<'a, 'tcx>,
    e: &'tcx Expr,
    expr: &Expr,
    mut applicability: Applicability,
    message: &str,
    conv_hint: impl FnOnce(Sugg<'a>) -> Sugg<'a>,
) {
    let hint = Sugg::hir_with_applicability(cx, expr, "..", &mut applicability);
    span_lint_and_sugg(
        cx,
        BOOL_COMPARISON,
        e.span,
        message,
        "try simplifying it as shown",
        conv_hint(hint).to_string(),
        applicability,
    );
}

enum Expression {
    Bool(bool),
    RetBool(bool),
    Other,
}

fn fetch_bool_block(block: &Block) -> Expression {
    match (&*block.stmts, block.expr.as_ref()) {
        (&[], Some(e)) => fetch_bool_expr(&**e),
        (&[ref e], None) => {
            if let StmtKind::Semi(ref e) = e.node {
                if let ExprKind::Ret(_) = e.node {
                    fetch_bool_expr(&**e)
                } else {
                    Expression::Other
                }
            } else {
                Expression::Other
            }
        },
        _ => Expression::Other,
    }
}

fn fetch_bool_expr(expr: &Expr) -> Expression {
    match expr.node {
        ExprKind::Block(ref block, _) => fetch_bool_block(block),
        ExprKind::Lit(ref lit_ptr) => {
            if let LitKind::Bool(value) = lit_ptr.node {
                Expression::Bool(value)
            } else {
                Expression::Other
            }
        },
        ExprKind::Ret(Some(ref expr)) => match fetch_bool_expr(expr) {
            Expression::Bool(value) => Expression::RetBool(value),
            _ => Expression::Other,
        },
        _ => Expression::Other,
    }
}
<commit_msg>Fix needless_bool.rs<commit_after>//! Checks for needless boolean results of if-else expressions
//!
//! This lint is **warn** by default

use crate::utils::sugg::Sugg;
use crate::utils::{higher, in_macro, span_lint, span_lint_and_sugg};
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use syntax::ast::LitKind;
use syntax::source_map::Spanned;

declare_clippy_lint! {
    /// **What it does:** Checks for expressions of the form `if c { true } else {
    /// false }`
    /// (or vice versa) and suggest using the condition directly.
    ///
    /// **Why is this bad?** Redundant code.
    ///
    /// **Known problems:** Maybe false positives: Sometimes, the two branches are
    /// painstakingly documented (which we of course do not detect), so they *may*
    /// have some value. Even then, the documentation can be rewritten to match the
    /// shorter code.
    ///
    /// **Example:**
    /// ```rust
    /// if x {
    ///     false
    /// } else {
    ///     true
    /// }
    /// ```
    pub NEEDLESS_BOOL,
    complexity,
    "if-statements with plain booleans in the then- and else-clause, e.g., `if p { true } else { false }`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for expressions of the form `x == true`,
    /// `x != true` and order comparisons such as `x < true` (or vice versa) and
    /// suggest using the variable directly.
    ///
    /// **Why is this bad?** Unnecessary code.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// if x == true {} // could be `if x { }`
    /// ```
    pub BOOL_COMPARISON,
    complexity,
    "comparing a variable to a boolean, e.g., `if x == true` or `if x != true`"
}

declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        use self::Expression::*;
        if let Some((ref pred, ref then_block, Some(ref else_expr))) = higher::if_block(&e) {
            let reduce = |ret, not| {
                let mut applicability = Applicability::MachineApplicable;
                let snip = Sugg::hir_with_applicability(cx, pred, "<predicate>", &mut applicability);
                let mut snip = if not { !snip } else { snip };

                if ret {
                    snip = snip.make_return();
                }

                if parent_node_is_if_expr(&e, &cx) {
                    snip = snip.blockify()
                }

                span_lint_and_sugg(
                    cx,
                    NEEDLESS_BOOL,
                    e.span,
                    "this if-then-else expression returns a bool literal",
                    "you can reduce it to",
                    snip.to_string(),
                    applicability,
                );
            };
            if let ExprKind::Block(ref then_block, _) = then_block.node {
                match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) {
                    (RetBool(true), RetBool(true)) | (Bool(true), Bool(true)) => {
                        span_lint(
                            cx,
                            NEEDLESS_BOOL,
                            e.span,
                            "this if-then-else expression will always return true",
                        );
                    },
                    (RetBool(false), RetBool(false)) | (Bool(false), Bool(false)) => {
                        span_lint(
                            cx,
                            NEEDLESS_BOOL,
                            e.span,
                            "this if-then-else expression will always return false",
                        );
                    },
                    (RetBool(true), RetBool(false)) => reduce(true, false),
                    (Bool(true), Bool(false)) => reduce(false, false),
                    (RetBool(false), RetBool(true)) => reduce(true, true),
                    (Bool(false), Bool(true)) => reduce(false, true),
                    _ => (),
                }
            } else {
                panic!("IfExpr 'then' node is not an ExprKind::Block");
            }
        }
    }
}

fn parent_node_is_if_expr<'a, 'b>(expr: &Expr, cx: &LateContext<'a, 'b>) -> bool {
    let parent_id = cx.tcx.hir().get_parent_node_by_hir_id(expr.hir_id);
    let parent_node = cx.tcx.hir().get_by_hir_id(parent_id);

    if let rustc::hir::Node::Expr(e) = parent_node {
        if higher::if_block(&e).is_some() {
            return true;
        }
    }

    false
}

declare_lint_pass!(BoolComparison => [BOOL_COMPARISON]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        if in_macro(e.span) {
            return;
        }

        if let ExprKind::Binary(Spanned { node, .. }, ..) = e.node {
            let ignore_case = None::<(fn(_) -> _, &str)>;
            let ignore_no_literal = None::<(fn(_, _) -> _, &str)>;
            match node {
                BinOpKind::Eq => {
                    let true_case = Some((|h| h, "equality checks against true are unnecessary"));
                    let false_case = Some((
                        |h: Sugg<'_>| !h,
                        "equality checks against false can be replaced by a negation",
                    ));
                    check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal)
                },
                BinOpKind::Ne => {
                    let true_case = Some((
                        |h: Sugg<'_>| !h,
                        "inequality checks against true can be replaced by a negation",
                    ));
                    let false_case = Some((|h| h, "inequality checks against false are unnecessary"));
                    check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal)
                },
                BinOpKind::Lt => check_comparison(
                    cx,
                    e,
                    ignore_case,
                    Some((|h| h, "greater than checks against false are unnecessary")),
                    Some((
                        |h: Sugg<'_>| !h,
                        "less than comparison against true can be replaced by a negation",
                    )),
                    ignore_case,
                    Some((
                        |l: Sugg<'_>, r: Sugg<'_>| (!l).bit_and(&r),
                        "order comparisons between booleans can be simplified",
                    )),
                ),
                BinOpKind::Gt => check_comparison(
                    cx,
                    e,
                    Some((
                        |h: Sugg<'_>| !h,
                        "less than comparison against true can be replaced by a negation",
                    )),
                    ignore_case,
                    ignore_case,
                    Some((|h| h, "greater than checks against false are unnecessary")),
                    Some((
                        |l: Sugg<'_>, r: Sugg<'_>| l.bit_and(&(!r)),
                        "order comparisons between booleans can be simplified",
                    )),
                ),
                _ => (),
            }
        }
    }
}

fn check_comparison<'a, 'tcx>(
    cx: &LateContext<'a, 'tcx>,
    e: &'tcx Expr,
    left_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>,
    left_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>,
    right_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>,
    right_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>,
    no_literal: Option<(impl FnOnce(Sugg<'a>, Sugg<'a>) -> Sugg<'a>, &str)>,
) {
    use self::Expression::*;

    if let ExprKind::Binary(_, ref left_side, ref right_side) = e.node {
        let (l_ty, r_ty) = (cx.tables.expr_ty(left_side), cx.tables.expr_ty(right_side));
        if l_ty.is_bool() && r_ty.is_bool() {
            let mut applicability = Applicability::MachineApplicable;
            match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) {
                (Bool(true), Other) => left_true.map_or((), |(h, m)| {
                    suggest_bool_comparison(cx, e, right_side, applicability, m, h)
                }),
                (Other, Bool(true)) => right_true.map_or((), |(h, m)| {
                    suggest_bool_comparison(cx, e, left_side, applicability, m, h)
                }),
                (Bool(false), Other) => left_false.map_or((), |(h, m)| {
                    suggest_bool_comparison(cx, e, right_side, applicability, m, h)
                }),
                (Other, Bool(false)) => right_false.map_or((), |(h, m)| {
                    suggest_bool_comparison(cx, e, left_side, applicability, m, h)
                }),
                (Other, Other) => no_literal.map_or((), |(h, m)| {
                    let left_side = Sugg::hir_with_applicability(cx, left_side, "..", &mut applicability);
                    let right_side = Sugg::hir_with_applicability(cx, right_side, "..", &mut applicability);
                    span_lint_and_sugg(
                        cx,
                        BOOL_COMPARISON,
                        e.span,
                        m,
                        "try simplifying it as shown",
                        h(left_side, right_side).to_string(),
                        applicability,
                    )
                }),
                _ => (),
            }
        }
    }
}

fn suggest_bool_comparison<'a, 'tcx>(
    cx: &LateContext<'a, 'tcx>,
    e: &'tcx Expr,
    expr: &Expr,
    mut applicability: Applicability,
    message: &str,
    conv_hint: impl FnOnce(Sugg<'a>) -> Sugg<'a>,
) {
    let hint = Sugg::hir_with_applicability(cx, expr, "..", &mut applicability);
    span_lint_and_sugg(
        cx,
        BOOL_COMPARISON,
        e.span,
        message,
        "try simplifying it as shown",
        conv_hint(hint).to_string(),
        applicability,
    );
}

enum Expression {
    Bool(bool),
    RetBool(bool),
    Other,
}

fn fetch_bool_block(block: &Block) -> Expression {
    match (&*block.stmts, block.expr.as_ref()) {
        (&[], Some(e)) => fetch_bool_expr(&**e),
        (&[ref e], None) => {
            if let StmtKind::Semi(ref e) = e.node {
                if let ExprKind::Ret(_) = e.node {
                    fetch_bool_expr(&**e)
                } else {
                    Expression::Other
                }
            } else {
                Expression::Other
            }
        },
        _ => Expression::Other,
    }
}

fn fetch_bool_expr(expr: &Expr) -> Expression {
    match expr.node {
        ExprKind::Block(ref block, _) => fetch_bool_block(block),
        ExprKind::Lit(ref lit_ptr) => {
            if let LitKind::Bool(value) = lit_ptr.node {
                Expression::Bool(value)
            } else {
                Expression::Other
            }
        },
        ExprKind::Ret(Some(ref expr)) => match fetch_bool_expr(expr) {
            Expression::Bool(value) => Expression::RetBool(value),
            _ => Expression::Other,
        },
        _ => Expression::Other,
    }
}
<|endoftext|>