<commit_before>#![cfg(target_os = "linux")]
#![allow(unused_variables, dead_code)]

use self::wayland::egl::{EGLSurface, is_egl_available};
use self::wayland::core::Surface;
use self::wayland::core::output::Output;
use self::wayland::core::shell::{ShellSurface, ShellFullscreenMethod};

use self::wayland_window::{DecoratedSurface, SurfaceGuard, substract_borders};

use libc;
use api::dlopen;
use api::egl;
use api::egl::Context as EglContext;

use BuilderAttribs;
use ContextError;
use CreationError;
use Event;
use PixelFormat;
use CursorState;
use MouseCursor;
use GlContext;

use std::collections::VecDeque;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex};
use std::ffi::CString;

use platform::MonitorID as PlatformMonitorID;

use self::context::WaylandContext;

extern crate wayland_client as wayland;
extern crate wayland_kbd;
extern crate wayland_window;

mod context;
mod keyboard;

lazy_static! {
    static ref WAYLAND_CONTEXT: Option<WaylandContext> = {
        WaylandContext::new()
    };
}

pub fn is_available() -> bool {
    WAYLAND_CONTEXT.is_some()
}

enum ShellWindow {
    Plain(ShellSurface<EGLSurface>),
    Decorated(DecoratedSurface<EGLSurface>)
}

impl ShellWindow {
    fn get_shell(&mut self) -> ShellGuard {
        match self {
            &mut ShellWindow::Plain(ref mut s) => {
                ShellGuard::Plain(s)
            },
            &mut ShellWindow::Decorated(ref mut s) => {
                ShellGuard::Decorated(s.get_shell())
            }
        }
    }

    fn resize(&mut self, w: i32, h: i32, x: i32, y: i32) {
        match self {
            &mut ShellWindow::Plain(ref s) => s.resize(w, h, x, y),
            &mut ShellWindow::Decorated(ref mut s) => {
                s.resize(w, h);
                s.get_shell().resize(w, h, x, y);
            }
        }
    }

    fn set_cfg_callback(&mut self, arc: Arc<Mutex<(i32, i32, bool)>>) {
        match self {
            &mut ShellWindow::Decorated(ref mut s) => {
                s.get_shell().set_configure_callback(move |_, w, h| {
                    let (w, h) = substract_borders(w, h);
                    let mut guard = arc.lock().unwrap();
                    *guard = (w, h, true);
                })
            }
            _ => {}
        }
    }
}

enum ShellGuard<'a> {
    Plain(&'a mut ShellSurface<EGLSurface>),
    Decorated(SurfaceGuard<'a, EGLSurface>)
}

impl<'a> Deref for ShellGuard<'a> {
    type Target = ShellSurface<EGLSurface>;
    fn deref(&self) -> &ShellSurface<EGLSurface> {
        match self {
            &ShellGuard::Plain(ref s) => s,
            &ShellGuard::Decorated(ref s) => s.deref()
        }
    }
}

impl<'a> DerefMut for ShellGuard<'a> {
    fn deref_mut(&mut self) -> &mut ShellSurface<EGLSurface> {
        match self {
            &mut ShellGuard::Plain(ref mut s) => s,
            &mut ShellGuard::Decorated(ref mut s) => s.deref_mut()
        }
    }
}

pub struct Window {
    shell_window: Mutex<ShellWindow>,
    pending_events: Arc<Mutex<VecDeque<Event>>>,
    need_resize: Arc<Mutex<(i32, i32, bool)>>,
    resize_callback: Option<fn(u32, u32)>,
    pub context: EglContext,
}

// private methods of wayalnd windows

impl Window {
    fn resize_if_needed(&self) -> bool {
        let mut guard = self.need_resize.lock().unwrap();
        let (w, h, b) = *guard;
        *guard = (0, 0, false);
        if b {
            let mut guard = self.shell_window.lock().unwrap();
            guard.resize(w, h, 0, 0);
            if let Some(f) = self.resize_callback {
                f(w as u32, h as u32);
            }
        }
        b
    }
}

#[derive(Clone)]
pub struct WindowProxy;

impl WindowProxy {
    pub fn wakeup_event_loop(&self) {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            ctxt.display.sync();
        }
    }
}

#[derive(Clone)]
pub struct MonitorID {
    output: Arc<Output>
}

pub fn get_available_monitors() -> VecDeque<MonitorID> {
    WAYLAND_CONTEXT.as_ref().unwrap().outputs.iter().map(|o| MonitorID::new(o.clone())).collect()
}
pub fn get_primary_monitor() -> MonitorID {
    match WAYLAND_CONTEXT.as_ref().unwrap().outputs.iter().next() {
        Some(o) => MonitorID::new(o.clone()),
        None => panic!("No monitor is available.")
    }
}

impl MonitorID {
    fn new(output: Arc<Output>) -> MonitorID {
        MonitorID {
            output: output
        }
    }

    pub fn get_name(&self) -> Option<String> {
        Some(format!("{} - {}", self.output.manufacturer(), self.output.model()))
    }

    pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId {
        ::native_monitor::NativeMonitorId::Unavailable
    }

    pub fn get_dimensions(&self) -> (u32, u32) {
        let (w, h) = self.output.modes()
                                .into_iter()
                                .find(|m| m.is_current())
                                .map(|m| (m.width, m.height))
                                .unwrap();
        (w as u32, h as u32)
    }
}

pub struct PollEventsIterator<'a> {
    window: &'a Window,
}

impl<'a> Iterator for PollEventsIterator<'a> {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            ctxt.display.dispatch_pending();
        }
        if self.window.resize_if_needed() {
            Some(Event::Refresh)
        } else {
            self.window.pending_events.lock().unwrap().pop_front()
        }
    }
}

pub struct WaitEventsIterator<'a> {
    window: &'a Window,
}

impl<'a> Iterator for WaitEventsIterator<'a> {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        let mut evt = None;
        while evt.is_none() {
            if let Some(ref ctxt) = *WAYLAND_CONTEXT {
                ctxt.display.dispatch();
            }
            evt = if self.window.resize_if_needed() {
                Some(Event::Refresh)
            } else {
                self.window.pending_events.lock().unwrap().pop_front()
            };
        }
        evt
    }
}

impl Window {
    pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
        use self::wayland::internals::FFI;

        let wayland_context = match *WAYLAND_CONTEXT {
            Some(ref c) => c,
            None => return Err(CreationError::NotSupported),
        };

        if !is_egl_available() { return Err(CreationError::NotSupported) }

        let (w, h) = builder.dimensions.unwrap_or((800, 600));

        let surface = EGLSurface::new(
            wayland_context.compositor.create_surface(),
            w as i32,
            h as i32
        );

        let mut shell_window = if let Some(PlatformMonitorID::Wayland(ref monitor)) = builder.monitor {
            let shell_surface = wayland_context.shell.get_shell_surface(surface);
            shell_surface.set_fullscreen(ShellFullscreenMethod::Default, Some(&monitor.output));
            ShellWindow::Plain(shell_surface)
        } else {
            ShellWindow::Decorated(match DecoratedSurface::new(
                surface,
                w as i32,
                h as i32,
                &wayland_context.registry,
                Some(&wayland_context.seat)
            ) {
                Ok(s) => s,
                Err(_) => return Err(CreationError::NotSupported)
            })
        };

        let context = {
            let libegl = unsafe { dlopen::dlopen(b"libEGL.so\0".as_ptr() as *const _, dlopen::RTLD_NOW) };
            if libegl.is_null() {
                return Err(CreationError::NotSupported);
            }
            let egl = ::api::egl::ffi::egl::Egl::load_with(|sym| {
                let sym = CString::new(sym).unwrap();
                unsafe { dlopen::dlsym(libegl, sym.as_ptr()) }
            });
            try!(EglContext::new(
                egl,
                &builder,
                egl::NativeDisplay::Wayland(Some(wayland_context.display.ptr() as *const _)))
                .and_then(|p| p.finish((**shell_window.get_shell()).ptr() as *const _))
            )
        };

        // create a queue already containing a refresh event to trigger first draw
        // it's harmless and a removes the need to do a first swap_buffers() before
        // starting the event loop
        let events = Arc::new(Mutex::new({
            let mut v = VecDeque::new();
            v.push_back(Event::Refresh);
            v
        }));

        wayland_context.register_surface(shell_window.get_shell().get_wsurface().get_id(),
                                         events.clone());

        let need_resize = Arc::new(Mutex::new((0, 0, false)));

        shell_window.set_cfg_callback(need_resize.clone());

        wayland_context.display.flush().unwrap();

        Ok(Window {
            shell_window: Mutex::new(shell_window),
            pending_events: events,
            need_resize: need_resize,
            resize_callback: None,
            context: context
        })
    }

    pub fn set_title(&self, title: &str) {
        let ctitle = CString::new(title).unwrap();
        // intermediate variable is forced,
        // see https://github.com/rust-lang/rust/issues/22921
        let mut guard = self.shell_window.lock().unwrap();
        guard.get_shell().set_title(&ctitle);
    }

    pub fn show(&self) {
        // TODO
    }

    pub fn hide(&self) {
        // TODO
    }

    pub fn get_position(&self) -> Option<(i32, i32)> {
        // not available with wayland
        None
    }

    pub fn set_position(&self, _x: i32, _y: i32) {
        // not available with wayland
    }

    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        // intermediate variables are forced,
        // see https://github.com/rust-lang/rust/issues/22921
        let mut guard = self.shell_window.lock().unwrap();
        let shell = guard.get_shell();
        let (w, h) = shell.get_attached_size();
        Some((w as u32, h as u32))
    }

    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        // maybe available if we draw the border ourselves ?
        // but for now, no.
        None
    }

    pub fn set_inner_size(&self, x: u32, y: u32) {
        self.shell_window.lock().unwrap().resize(x as i32, y as i32, 0, 0)
    }

    pub fn create_window_proxy(&self) -> WindowProxy {
        WindowProxy
    }

    pub fn poll_events(&self) -> PollEventsIterator {
        PollEventsIterator {
            window: self
        }
    }

    pub fn wait_events(&self) -> WaitEventsIterator {
        WaitEventsIterator {
            window: self
        }
    }

    pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
        self.resize_callback = callback;
    }

    pub fn set_cursor(&self, cursor: MouseCursor) {
        // TODO
    }

    pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
        // TODO
        Ok(())
    }

    pub fn hidpi_factor(&self) -> f32 {
        1.0
    }

    pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
        // TODO
        Ok(())
    }

    pub fn platform_display(&self) -> *mut libc::c_void {
        unimplemented!()
    }

    pub fn platform_window(&self) -> *mut libc::c_void {
        unimplemented!()
    }
}

impl GlContext for Window {
    unsafe fn make_current(&self) -> Result<(), ContextError> {
        self.context.make_current()
    }

    fn is_current(&self) -> bool {
        self.context.is_current()
    }

    fn get_proc_address(&self, addr: &str) -> *const libc::c_void {
        self.context.get_proc_address(addr)
    }

    fn swap_buffers(&self) -> Result<(), ContextError> {
        self.context.swap_buffers()
    }

    fn get_api(&self) -> ::Api {
        self.context.get_api()
    }

    fn get_pixel_format(&self) -> PixelFormat {
        self.context.get_pixel_format().clone()
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            // intermediate variable is forced,
            // see https://github.com/rust-lang/rust/issues/22921
            let mut guard = self.shell_window.lock().unwrap();
            let shell = guard.get_shell();
            ctxt.deregister_surface(
                shell.get_wsurface().get_id()
            )
        }
    }
}
<commit_msg>wayland: properly handle 'decorated' option.<commit_after>#![cfg(target_os = "linux")]
#![allow(unused_variables, dead_code)]

use self::wayland::egl::{EGLSurface, is_egl_available};
use self::wayland::core::Surface;
use self::wayland::core::output::Output;
use self::wayland::core::shell::{ShellSurface, ShellFullscreenMethod};

use self::wayland_window::{DecoratedSurface, SurfaceGuard, substract_borders};

use libc;
use api::dlopen;
use api::egl;
use api::egl::Context as EglContext;

use BuilderAttribs;
use ContextError;
use CreationError;
use Event;
use PixelFormat;
use CursorState;
use MouseCursor;
use GlContext;

use std::collections::VecDeque;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex};
use std::ffi::CString;

use platform::MonitorID as PlatformMonitorID;

use self::context::WaylandContext;

extern crate wayland_client as wayland;
extern crate wayland_kbd;
extern crate wayland_window;

mod context;
mod keyboard;

lazy_static! {
    static ref WAYLAND_CONTEXT: Option<WaylandContext> = {
        WaylandContext::new()
    };
}

pub fn is_available() -> bool {
    WAYLAND_CONTEXT.is_some()
}

enum ShellWindow {
    Plain(ShellSurface<EGLSurface>),
    Decorated(DecoratedSurface<EGLSurface>)
}

impl ShellWindow {
    fn get_shell(&mut self) -> ShellGuard {
        match self {
            &mut ShellWindow::Plain(ref mut s) => {
                ShellGuard::Plain(s)
            },
            &mut ShellWindow::Decorated(ref mut s) => {
                ShellGuard::Decorated(s.get_shell())
            }
        }
    }

    fn resize(&mut self, w: i32, h: i32, x: i32, y: i32) {
        match self {
            &mut ShellWindow::Plain(ref s) => s.resize(w, h, x, y),
            &mut ShellWindow::Decorated(ref mut s) => {
                s.resize(w, h);
                s.get_shell().resize(w, h, x, y);
            }
        }
    }

    fn set_cfg_callback(&mut self, arc: Arc<Mutex<(i32, i32, bool)>>) {
        match self {
            &mut ShellWindow::Decorated(ref mut s) => {
                s.get_shell().set_configure_callback(move |_, w, h| {
                    let (w, h) = substract_borders(w, h);
                    let mut guard = arc.lock().unwrap();
                    *guard = (w, h, true);
                })
            }
            _ => {}
        }
    }
}

enum ShellGuard<'a> {
    Plain(&'a mut ShellSurface<EGLSurface>),
    Decorated(SurfaceGuard<'a, EGLSurface>)
}

impl<'a> Deref for ShellGuard<'a> {
    type Target = ShellSurface<EGLSurface>;
    fn deref(&self) -> &ShellSurface<EGLSurface> {
        match self {
            &ShellGuard::Plain(ref s) => s,
            &ShellGuard::Decorated(ref s) => s.deref()
        }
    }
}

impl<'a> DerefMut for ShellGuard<'a> {
    fn deref_mut(&mut self) -> &mut ShellSurface<EGLSurface> {
        match self {
            &mut ShellGuard::Plain(ref mut s) => s,
            &mut ShellGuard::Decorated(ref mut s) => s.deref_mut()
        }
    }
}

pub struct Window {
    shell_window: Mutex<ShellWindow>,
    pending_events: Arc<Mutex<VecDeque<Event>>>,
    need_resize: Arc<Mutex<(i32, i32, bool)>>,
    resize_callback: Option<fn(u32, u32)>,
    pub context: EglContext,
}

// private methods of wayalnd windows

impl Window {
    fn resize_if_needed(&self) -> bool {
        let mut guard = self.need_resize.lock().unwrap();
        let (w, h, b) = *guard;
        *guard = (0, 0, false);
        if b {
            let mut guard = self.shell_window.lock().unwrap();
            guard.resize(w, h, 0, 0);
            if let Some(f) = self.resize_callback {
                f(w as u32, h as u32);
            }
        }
        b
    }
}

#[derive(Clone)]
pub struct WindowProxy;

impl WindowProxy {
    pub fn wakeup_event_loop(&self) {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            ctxt.display.sync();
        }
    }
}

#[derive(Clone)]
pub struct MonitorID {
    output: Arc<Output>
}

pub fn get_available_monitors() -> VecDeque<MonitorID> {
    WAYLAND_CONTEXT.as_ref().unwrap().outputs.iter().map(|o| MonitorID::new(o.clone())).collect()
}
pub fn get_primary_monitor() -> MonitorID {
    match WAYLAND_CONTEXT.as_ref().unwrap().outputs.iter().next() {
        Some(o) => MonitorID::new(o.clone()),
        None => panic!("No monitor is available.")
    }
}

impl MonitorID {
    fn new(output: Arc<Output>) -> MonitorID {
        MonitorID {
            output: output
        }
    }

    pub fn get_name(&self) -> Option<String> {
        Some(format!("{} - {}", self.output.manufacturer(), self.output.model()))
    }

    pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId {
        ::native_monitor::NativeMonitorId::Unavailable
    }

    pub fn get_dimensions(&self) -> (u32, u32) {
        let (w, h) = self.output.modes()
                                .into_iter()
                                .find(|m| m.is_current())
                                .map(|m| (m.width, m.height))
                                .unwrap();
        (w as u32, h as u32)
    }
}

pub struct PollEventsIterator<'a> {
    window: &'a Window,
}

impl<'a> Iterator for PollEventsIterator<'a> {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            ctxt.display.dispatch_pending();
        }
        if self.window.resize_if_needed() {
            Some(Event::Refresh)
        } else {
            self.window.pending_events.lock().unwrap().pop_front()
        }
    }
}

pub struct WaitEventsIterator<'a> {
    window: &'a Window,
}

impl<'a> Iterator for WaitEventsIterator<'a> {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        let mut evt = None;
        while evt.is_none() {
            if let Some(ref ctxt) = *WAYLAND_CONTEXT {
                ctxt.display.dispatch();
            }
            evt = if self.window.resize_if_needed() {
                Some(Event::Refresh)
            } else {
                self.window.pending_events.lock().unwrap().pop_front()
            };
        }
        evt
    }
}

impl Window {
    pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
        use self::wayland::internals::FFI;

        let wayland_context = match *WAYLAND_CONTEXT {
            Some(ref c) => c,
            None => return Err(CreationError::NotSupported),
        };

        if !is_egl_available() { return Err(CreationError::NotSupported) }

        let (w, h) = builder.dimensions.unwrap_or((800, 600));

        let surface = EGLSurface::new(
            wayland_context.compositor.create_surface(),
            w as i32,
            h as i32
        );

        let mut shell_window = if let Some(PlatformMonitorID::Wayland(ref monitor)) = builder.monitor {
            let shell_surface = wayland_context.shell.get_shell_surface(surface);
            shell_surface.set_fullscreen(ShellFullscreenMethod::Default, Some(&monitor.output));
            ShellWindow::Plain(shell_surface)
        } else {
            if builder.decorations {
                ShellWindow::Decorated(match DecoratedSurface::new(
                    surface,
                    w as i32,
                    h as i32,
                    &wayland_context.registry,
                    Some(&wayland_context.seat)
                ) {
                    Ok(s) => s,
                    Err(_) => return Err(CreationError::NotSupported)
                })
            } else {
                ShellWindow::Plain(wayland_context.shell.get_shell_surface(surface))
            }
        };

        let context = {
            let libegl = unsafe { dlopen::dlopen(b"libEGL.so\0".as_ptr() as *const _, dlopen::RTLD_NOW) };
            if libegl.is_null() {
                return Err(CreationError::NotSupported);
            }
            let egl = ::api::egl::ffi::egl::Egl::load_with(|sym| {
                let sym = CString::new(sym).unwrap();
                unsafe { dlopen::dlsym(libegl, sym.as_ptr()) }
            });
            try!(EglContext::new(
                egl,
                &builder,
                egl::NativeDisplay::Wayland(Some(wayland_context.display.ptr() as *const _)))
                .and_then(|p| p.finish((**shell_window.get_shell()).ptr() as *const _))
            )
        };

        // create a queue already containing a refresh event to trigger first draw
        // it's harmless and a removes the need to do a first swap_buffers() before
        // starting the event loop
        let events = Arc::new(Mutex::new({
            let mut v = VecDeque::new();
            v.push_back(Event::Refresh);
            v
        }));

        wayland_context.register_surface(shell_window.get_shell().get_wsurface().get_id(),
                                         events.clone());

        let need_resize = Arc::new(Mutex::new((0, 0, false)));

        shell_window.set_cfg_callback(need_resize.clone());

        wayland_context.display.flush().unwrap();

        Ok(Window {
            shell_window: Mutex::new(shell_window),
            pending_events: events,
            need_resize: need_resize,
            resize_callback: None,
            context: context
        })
    }

    pub fn set_title(&self, title: &str) {
        let ctitle = CString::new(title).unwrap();
        // intermediate variable is forced,
        // see https://github.com/rust-lang/rust/issues/22921
        let mut guard = self.shell_window.lock().unwrap();
        guard.get_shell().set_title(&ctitle);
    }

    pub fn show(&self) {
        // TODO
    }

    pub fn hide(&self) {
        // TODO
    }

    pub fn get_position(&self) -> Option<(i32, i32)> {
        // not available with wayland
        None
    }

    pub fn set_position(&self, _x: i32, _y: i32) {
        // not available with wayland
    }

    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        // intermediate variables are forced,
        // see https://github.com/rust-lang/rust/issues/22921
        let mut guard = self.shell_window.lock().unwrap();
        let shell = guard.get_shell();
        let (w, h) = shell.get_attached_size();
        Some((w as u32, h as u32))
    }

    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        // maybe available if we draw the border ourselves ?
        // but for now, no.
        None
    }

    pub fn set_inner_size(&self, x: u32, y: u32) {
        self.shell_window.lock().unwrap().resize(x as i32, y as i32, 0, 0)
    }

    pub fn create_window_proxy(&self) -> WindowProxy {
        WindowProxy
    }

    pub fn poll_events(&self) -> PollEventsIterator {
        PollEventsIterator {
            window: self
        }
    }

    pub fn wait_events(&self) -> WaitEventsIterator {
        WaitEventsIterator {
            window: self
        }
    }

    pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
        self.resize_callback = callback;
    }

    pub fn set_cursor(&self, cursor: MouseCursor) {
        // TODO
    }

    pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
        // TODO
        Ok(())
    }

    pub fn hidpi_factor(&self) -> f32 {
        1.0
    }

    pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
        // TODO
        Ok(())
    }

    pub fn platform_display(&self) -> *mut libc::c_void {
        unimplemented!()
    }

    pub fn platform_window(&self) -> *mut libc::c_void {
        unimplemented!()
    }
}

impl GlContext for Window {
    unsafe fn make_current(&self) -> Result<(), ContextError> {
        self.context.make_current()
    }

    fn is_current(&self) -> bool {
        self.context.is_current()
    }

    fn get_proc_address(&self, addr: &str) -> *const libc::c_void {
        self.context.get_proc_address(addr)
    }

    fn swap_buffers(&self) -> Result<(), ContextError> {
        self.context.swap_buffers()
    }

    fn get_api(&self) -> ::Api {
        self.context.get_api()
    }

    fn get_pixel_format(&self) -> PixelFormat {
        self.context.get_pixel_format().clone()
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            // intermediate variable is forced,
            // see https://github.com/rust-lang/rust/issues/22921
            let mut guard = self.shell_window.lock().unwrap();
            let shell = guard.get_shell();
            ctxt.deregister_surface(
                shell.get_wsurface().get_id()
            )
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Moveing libstd's truncate() here<commit_after><|endoftext|>


<commit_before><commit_msg>Add an `handshake` unit test in `connection`<commit_after><|endoftext|>


<commit_before><commit_msg>Set the flip uniform before starting the font pass<commit_after><|endoftext|>


<commit_before><commit_msg>rustfmt bigpack<commit_after><|endoftext|>


<commit_before><commit_msg>Verify if the OpenGL context is compatible as soon as possible<commit_after><|endoftext|>


<commit_before>use redox::ops::DerefMut;
use redox::string::*;
use redox::vec::Vec;
use redox::boxed::Box;
use redox::fs::*;
use redox::io::*;
use redox::env::*;
use redox::time::Duration;
use redox::to_num::*;

/* Magic Macros { */
static mut application: *mut Application<'static> = 0 as *mut Application;

/// Execute a command
macro_rules! exec {
    ($cmd:expr) => ({
        unsafe {
            (*application).on_command(&$cmd.to_string());
        }
    })
}
/* } Magic Macros */

/// A command
pub struct Command<'a> {
    pub name: &'a str,
    pub main: Box<Fn(&Vec<String>)>,
}

impl<'a> Command<'a> {
    /// Return the vector of the commands
    // TODO: Use a more efficient collection instead
    pub fn vec() -> Vec<Self> {
        let mut commands: Vec<Self> = Vec::new();

        commands.push(Command {
            name: "cat",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read: {}", path),
                    }
                } else {
                    println!("Failed to open file: {}", path);
                }
            },
        });

        commands.push(Command {
            name: "cd",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(path) => {
                        if !change_cwd(&path) {
                            println!("Bad path: {}", path);
                        }
                    }
                    None => println!("No path given")
                }
            },
        });

        commands.push(Command {
            name: "echo",
            main: box |args: &Vec<String>| {
                let echo = args.iter()
                    .skip(1)
                    .fold(String::new(), |string, arg| string + " " + arg);
                println!("{}", echo.trim());
            },
        });

        commands.push(Command {
            name: "else",
            main: box |_: &Vec<String>| {},
        });

        commands.push(Command {
            name: "exec",
            main: box |args: &Vec<String>| {
                if let Some(arg) = args.get(1) {
                    File::exec(arg);
                }
            },
        });

        commands.push(Command {
            name: "exit",
            main: box |_: &Vec<String>| {},
        });

        commands.push(Command {
            name: "fi",
            main: box |_: &Vec<String>| {},
        });

        commands.push(Command {
            name: "if",
            main: box |_: &Vec<String>| {},
        });

        commands.push(Command {
            name: "ls",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(dir) = read_dir(&path) {
                    for entry in dir {
                        println!("{}", entry.path());
                    }
                } else {
                    println!("Failed to open directory: {}", path);
                }
            }
        });

        commands.push(Command {
            name: "pwd",
            main: box |_: &Vec<String>| {
                let mut err = false;
                if let Some(file) = File::open("") {
                    if let Some(path) = file.path() {
                        println!("{}", path);
                    } else {
                        println!("Could not get the path");
                    }
                } else {
                    println!("Could not open the working directory");
                }
            },
        });

        commands.push(Command {
            name: "read",
            main: box |_: &Vec<String>| {},
        });

        commands.push(Command {
            name: "run",
            main: box |args: &Vec<String>| {
                if let Some(path) = args.get(1) {

                    let mut commands = String::new();
                    if let Some(mut file) = File::open(path) {
                        file.read_to_string(&mut commands);
                    }

                    for command in commands.split('\n') {
                        exec!(command);
                    }
                }
            },
        });

        commands.push(Command {
            name: "sleep",
            main: box |args: &Vec<String>| {
                let secs = {
                    match args.get(1) {
                        Some(arg) => arg.to_num() as i64,
                        None => 0,
                    }
                };

                let nanos = {
                    match args.get(2) {
                        Some(arg) => arg.to_num() as i32,
                        None => 0,
                    }
                };

                println!("Sleep: {} {}", secs, nanos);
                let remaining = Duration::new(secs, nanos).sleep();
                println!("Remaining: {} {}", remaining.secs, remaining.nanos);
            },
        });

        commands.push(Command {
            name: "send",
            main: box |args: &Vec<String>| {
                if args.len() < 3 {
                    println!("Error: incorrect arguments");
                    println!("Usage: send [url] [data]");
                    return;
                }

                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let string: String = args.iter()
                        .skip(2)
                        .fold(String::new(), |s, arg| s + " " + arg)
                        + "\r\n\r\n";

                    match file.write(string.trim_left().as_bytes()) {
                        Some(size) => println!("Wrote {} bytes", size),
                        None => println!("Failed to write"),
                    }

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        // Simple command to create a file, in the current directory
        // The file has got the name given as the first argument of the command
        // If the command have no arguments, the command don't create the file
        commands.push(Command {
            name: "touch",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(file_name) => if File::create(file_name).is_none() {
                        println!("Failed to create: {}", file_name);
                    }
                    None => println!("No name provided")
                }
            }
        });

        commands.push(Command {
            name: "url_hex",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    let mut vec: Vec<u8> = Vec::new();
                    match file.read_to_end(&mut vec) {
                        Some(_) => {
                            let mut line = "HEX:".to_string();
                            for byte in vec.iter() {
                                line = line + " " + &format!("{:X}", *byte);
                            }
                            println!("{}", line);
                        }
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "wget",
            main: box |args: &Vec<String>| {
                if let Some(host) = args.get(1) {
                    if let Some(req) = args.get(2) {
                        if let Some(mut con) = File::open(&("tcp://".to_string() + host)) {
                            con.write(("GET ".to_string() + req + " HTTP/1.1").as_bytes());

                            let mut res = Vec::new();
                            con.read_to_end(&mut res);

                            if let Some(mut file) = File::open(&req) {
                                file.write(&res);
                            }
                        }
                    } else {
                        println!("No request given");
                    }
                } else {
                    println!("No url given");
                }
            },
        });

        let command_list = commands.iter().fold(String::new(), |l , c| l + " " + c.name);

        commands.push(Command {
            name: "help",
            main: box move |_: &Vec<String>| {
                println!("Commands:{}", command_list);
            },
         });

        commands
    }
}

/// A (env) variable
pub struct Variable {
    pub name: String,
    pub value: String,
}

pub struct Mode {
    value: bool,
}

/// An application
pub struct Application<'a> {
    commands: Vec<Command<'a>>,
    variables: Vec<Variable>,
    modes: Vec<Mode>,
}

impl<'a> Application<'a> {
    /// Create a new empty application
    pub fn new() -> Self {
        return Application {
            commands: Command::vec(),
            variables: Vec::new(),
            modes: Vec::new(),
        };
    }

    fn on_command(&mut self, command_string: &str) {
        //Comment
        if command_string.starts_with('#') {
            return;
        }

        //Show variables
        if command_string == "$" {
            for variable in self.variables.iter() {
                println!("{}={}", variable.name, variable.value);
            }
            return;
        }

        //Explode into arguments, replace variables
        let mut args: Vec<String> = Vec::<String>::new();
        for arg in command_string.split(' ') {
            if !arg.is_empty() {
                if arg.starts_with('$') {
                    let name = arg[1 .. arg.len()].to_string();
                    for variable in self.variables.iter() {
                        if variable.name == name {
                            args.push(variable.value.clone());
                            break;
                        }
                    }
                } else {
                    args.push(arg.to_string());
                }
            }
        }

        //Execute commands
        if let Some(cmd) = args.get(0) {
            if cmd == "if" {
                let mut value = false;

                if let Some(left) = args.get(1) {
                    if let Some(cmp) = args.get(2) {
                        if let Some(right) = args.get(3) {
                            if cmp == "==" {
                                value = *left == *right;
                            } else if cmp == "!=" {
                                value = *left != *right;
                            } else if cmp == ">" {
                                value = left.to_num_signed() > right.to_num_signed();
                            } else if cmp == ">=" {
                                value = left.to_num_signed() >= right.to_num_signed();
                            } else if cmp == "<" {
                                value = left.to_num_signed() < right.to_num_signed();
                            } else if cmp == "<=" {
                                value = left.to_num_signed() <= right.to_num_signed();
                            } else {
                                println!("Unknown comparison: {}", cmp);
                            }
                        } else {
                            println!("No right hand side");
                        }
                    } else {
                        println!("No comparison operator");
                    }
                } else {
                    println!("No left hand side");
                }

                self.modes.insert(0, Mode { value: value });
                return;
            }

            if cmd == "else" {
                let mut syntax_error = false;
                match self.modes.get_mut(0) {
                    Some(mode) => mode.value = !mode.value,
                    None => syntax_error = true,
                }
                if syntax_error {
                    println!("Syntax error: else found with no previous if");
                }
                return;
            }

            if cmd == "fi" {
                let mut syntax_error = false;
                if !self.modes.is_empty() {
                    self.modes.remove(0);
                } else {
                    syntax_error = true;
                }
                if syntax_error {
                    println!("Syntax error: fi found with no previous if");
                }
                return;
            }

            for mode in self.modes.iter() {
                if !mode.value {
                    return;
                }
            }

            if cmd == "read" {
                for i in 1..args.len() {
                    if let Some(arg_original) = args.get(i) {
                        let arg = arg_original.trim();
                        print!("{}=", arg);
                        if let Some(value_original) = readln!() {
                            let value = value_original.trim();
                            self.set_var(arg, value);
                        }
                    }
                }
            }

            //Set variables
            if let Some(i) = cmd.find('=') {
                let name = cmd[0 .. i].trim();
                let mut value = cmd[i + 1 .. cmd.len()].trim().to_string();

                for i in 1..args.len() {
                    if let Some(arg) = args.get(i) {
                        value = value + " " + &arg;
                    }
                }

                self.set_var(name, &value);
                return;
            }

            //Commands
            for command in self.commands.iter() {
                if &command.name == cmd {
                    (*command.main)(&args);
                    return;
                }
            }

            println!("Unknown command: '{}'", cmd);
        }
    }

    pub fn set_var(&mut self, name: &str, value: &str){
        if name.is_empty() {
            return;
        }

        if value.is_empty() {
            let mut remove = -1;
            for i in 0..self.variables.len() {
                match self.variables.get(i) {
                    Some(variable) => if variable.name == name {
                        remove = i as isize;
                        break;
                    },
                    None => break,
                }
            }

            if remove >= 0 {
                self.variables.remove(remove as usize);
            }
        } else {
            for variable in self.variables.iter_mut() {
                if variable.name == name {
                    variable.value = value.to_string();
                    return;
                }
            }

            self.variables.push(Variable {
                name: name.to_string(),
                value: value.to_string(),
            });
        }
    }

    /// Run the application
    pub fn main(&mut self) {
        println!("Type help for a command list");
        if let Some(arg) = args().get(1) {
            let command = "run ".to_string() + arg;
            println!("# {}", command);
            self.on_command(&command);
        }

        loop {
            for mode in self.modes.iter().rev() {
                if mode.value {
                    print!("+ ");
                } else {
                    print!("- ");
                }
            }
            print!("# ");
            if let Some(command_original) = readln!() {
                let command = command_original.trim();
                if command == "exit" {
                    println!("Exit temporarily blocked (due to using terminal as init)")
                    //break;
                } else if !command.is_empty() {
                    self.on_command(&command);
                }
            } else {
                println!("Failed to read from stdin");
            }
        }
    }
}

pub fn main() {
    unsafe {
        let mut app = box Application::new();
        application = app.deref_mut();
        app.main();
    }
}
<commit_msg>Fix syntax<commit_after>use redox::ops::DerefMut;
use redox::string::*;
use redox::vec::Vec;
use redox::boxed::Box;
use redox::fs::*;
use redox::io::*;
use redox::env::*;
use redox::time::Duration;
use redox::to_num::*;

/* Magic Macros { */
static mut application: *mut Application<'static> = 0 as *mut Application;

/// Execute a command
macro_rules! exec {
    ($cmd:expr) => ({
        unsafe {
            (*application).on_command(&$cmd.to_string());
        }
    })
}
/* } Magic Macros */

/// A command
pub struct Command<'a> {
    pub name: &'a str,
    pub main: Box<Fn(&Vec<String>)>,
}

impl<'a> Command<'a> {
    /// Return the vector of the commands
    // TODO: Use a more efficient collection instead
    pub fn vec() -> Vec<Self> {
        let mut commands: Vec<Self> = Vec::new();

        commands.push(Command {
            name: "cat",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read: {}", path),
                    }
                } else {
                    println!("Failed to open file: {}", path);
                }
            },
        });

        commands.push(Command {
            name: "cd",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(path) => {
                        if !change_cwd(&path) {
                            println!("Bad path: {}", path);
                        }
                    }
                    None => println!("No path given")
                }
            },
        });

        commands.push(Command {
            name: "echo",
            main: box |args: &Vec<String>| {
                let echo = args.iter()
                    .skip(1)
                    .fold(String::new(), |string, arg| string + " " + arg);
                println!("{}", echo.trim());
            },
        });

        commands.push(Command {
            name: "else",
            main: box |_: &Vec<String>| {},
        });

        commands.push(Command {
            name: "exec",
            main: box |args: &Vec<String>| {
                if let Some(arg) = args.get(1) {
                    File::exec(arg);
                }
            },
        });

        commands.push(Command {
            name: "exit",
            main: box |_: &Vec<String>| {},
        });

        commands.push(Command {
            name: "fi",
            main: box |_: &Vec<String>| {},
        });

        commands.push(Command {
            name: "if",
            main: box |_: &Vec<String>| {},
        });

        commands.push(Command {
            name: "ls",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(dir) = read_dir(&path) {
                    for entry in dir {
                        println!("{}", entry.path());
                    }
                } else {
                    println!("Failed to open directory: {}", path);
                }
            }
        });

        commands.push(Command {
            name: "pwd",
            main: box |_: &Vec<String>| {
                if let Some(file) = File::open("") {
                    if let Some(path) = file.path() {
                        println!("{}", path);
                    } else {
                        println!("Could not get the path");
                    }
                } else {
                    println!("Could not open the working directory");
                }
            },
        });

        commands.push(Command {
            name: "read",
            main: box |_: &Vec<String>| {},
        });

        commands.push(Command {
            name: "run",
            main: box |args: &Vec<String>| {
                if let Some(path) = args.get(1) {

                    let mut commands = String::new();
                    if let Some(mut file) = File::open(path) {
                        file.read_to_string(&mut commands);
                    }

                    for command in commands.split('\n') {
                        exec!(command);
                    }
                }
            },
        });

        commands.push(Command {
            name: "sleep",
            main: box |args: &Vec<String>| {
                let secs = {
                    match args.get(1) {
                        Some(arg) => arg.to_num() as i64,
                        None => 0,
                    }
                };

                let nanos = {
                    match args.get(2) {
                        Some(arg) => arg.to_num() as i32,
                        None => 0,
                    }
                };

                println!("Sleep: {} {}", secs, nanos);
                let remaining = Duration::new(secs, nanos).sleep();
                println!("Remaining: {} {}", remaining.secs, remaining.nanos);
            },
        });

        commands.push(Command {
            name: "send",
            main: box |args: &Vec<String>| {
                if args.len() < 3 {
                    println!("Error: incorrect arguments");
                    println!("Usage: send [url] [data]");
                    return;
                }

                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let string: String = args.iter()
                        .skip(2)
                        .fold(String::new(), |s, arg| s + " " + arg)
                        + "\r\n\r\n";

                    match file.write(string.trim_left().as_bytes()) {
                        Some(size) => println!("Wrote {} bytes", size),
                        None => println!("Failed to write"),
                    }

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        // Simple command to create a file, in the current directory
        // The file has got the name given as the first argument of the command
        // If the command have no arguments, the command don't create the file
        commands.push(Command {
            name: "touch",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(file_name) => if File::create(file_name).is_none() {
                        println!("Failed to create: {}", file_name);
                    },
                    None => println!("No name provided")
                }
            }
        });

        commands.push(Command {
            name: "url_hex",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    let mut vec: Vec<u8> = Vec::new();
                    match file.read_to_end(&mut vec) {
                        Some(_) => {
                            let mut line = "HEX:".to_string();
                            for byte in vec.iter() {
                                line = line + " " + &format!("{:X}", *byte);
                            }
                            println!("{}", line);
                        }
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "wget",
            main: box |args: &Vec<String>| {
                if let Some(host) = args.get(1) {
                    if let Some(req) = args.get(2) {
                        if let Some(mut con) = File::open(&("tcp://".to_string() + host)) {
                            con.write(("GET ".to_string() + req + " HTTP/1.1").as_bytes());

                            let mut res = Vec::new();
                            con.read_to_end(&mut res);

                            if let Some(mut file) = File::open(&req) {
                                file.write(&res);
                            }
                        }
                    } else {
                        println!("No request given");
                    }
                } else {
                    println!("No url given");
                }
            },
        });

        let command_list = commands.iter().fold(String::new(), |l , c| l + " " + c.name);

        commands.push(Command {
            name: "help",
            main: box move |_: &Vec<String>| {
                println!("Commands:{}", command_list);
            },
         });

        commands
    }
}

/// A (env) variable
pub struct Variable {
    pub name: String,
    pub value: String,
}

pub struct Mode {
    value: bool,
}

/// An application
pub struct Application<'a> {
    commands: Vec<Command<'a>>,
    variables: Vec<Variable>,
    modes: Vec<Mode>,
}

impl<'a> Application<'a> {
    /// Create a new empty application
    pub fn new() -> Self {
        return Application {
            commands: Command::vec(),
            variables: Vec::new(),
            modes: Vec::new(),
        };
    }

    fn on_command(&mut self, command_string: &str) {
        //Comment
        if command_string.starts_with('#') {
            return;
        }

        //Show variables
        if command_string == "$" {
            for variable in self.variables.iter() {
                println!("{}={}", variable.name, variable.value);
            }
            return;
        }

        //Explode into arguments, replace variables
        let mut args: Vec<String> = Vec::<String>::new();
        for arg in command_string.split(' ') {
            if !arg.is_empty() {
                if arg.starts_with('$') {
                    let name = arg[1 .. arg.len()].to_string();
                    for variable in self.variables.iter() {
                        if variable.name == name {
                            args.push(variable.value.clone());
                            break;
                        }
                    }
                } else {
                    args.push(arg.to_string());
                }
            }
        }

        //Execute commands
        if let Some(cmd) = args.get(0) {
            if cmd == "if" {
                let mut value = false;

                if let Some(left) = args.get(1) {
                    if let Some(cmp) = args.get(2) {
                        if let Some(right) = args.get(3) {
                            if cmp == "==" {
                                value = *left == *right;
                            } else if cmp == "!=" {
                                value = *left != *right;
                            } else if cmp == ">" {
                                value = left.to_num_signed() > right.to_num_signed();
                            } else if cmp == ">=" {
                                value = left.to_num_signed() >= right.to_num_signed();
                            } else if cmp == "<" {
                                value = left.to_num_signed() < right.to_num_signed();
                            } else if cmp == "<=" {
                                value = left.to_num_signed() <= right.to_num_signed();
                            } else {
                                println!("Unknown comparison: {}", cmp);
                            }
                        } else {
                            println!("No right hand side");
                        }
                    } else {
                        println!("No comparison operator");
                    }
                } else {
                    println!("No left hand side");
                }

                self.modes.insert(0, Mode { value: value });
                return;
            }

            if cmd == "else" {
                let mut syntax_error = false;
                match self.modes.get_mut(0) {
                    Some(mode) => mode.value = !mode.value,
                    None => syntax_error = true,
                }
                if syntax_error {
                    println!("Syntax error: else found with no previous if");
                }
                return;
            }

            if cmd == "fi" {
                let mut syntax_error = false;
                if !self.modes.is_empty() {
                    self.modes.remove(0);
                } else {
                    syntax_error = true;
                }
                if syntax_error {
                    println!("Syntax error: fi found with no previous if");
                }
                return;
            }

            for mode in self.modes.iter() {
                if !mode.value {
                    return;
                }
            }

            if cmd == "read" {
                for i in 1..args.len() {
                    if let Some(arg_original) = args.get(i) {
                        let arg = arg_original.trim();
                        print!("{}=", arg);
                        if let Some(value_original) = readln!() {
                            let value = value_original.trim();
                            self.set_var(arg, value);
                        }
                    }
                }
            }

            //Set variables
            if let Some(i) = cmd.find('=') {
                let name = cmd[0 .. i].trim();
                let mut value = cmd[i + 1 .. cmd.len()].trim().to_string();

                for i in 1..args.len() {
                    if let Some(arg) = args.get(i) {
                        value = value + " " + &arg;
                    }
                }

                self.set_var(name, &value);
                return;
            }

            //Commands
            for command in self.commands.iter() {
                if &command.name == cmd {
                    (*command.main)(&args);
                    return;
                }
            }

            println!("Unknown command: '{}'", cmd);
        }
    }

    pub fn set_var(&mut self, name: &str, value: &str){
        if name.is_empty() {
            return;
        }

        if value.is_empty() {
            let mut remove = -1;
            for i in 0..self.variables.len() {
                match self.variables.get(i) {
                    Some(variable) => if variable.name == name {
                        remove = i as isize;
                        break;
                    },
                    None => break,
                }
            }

            if remove >= 0 {
                self.variables.remove(remove as usize);
            }
        } else {
            for variable in self.variables.iter_mut() {
                if variable.name == name {
                    variable.value = value.to_string();
                    return;
                }
            }

            self.variables.push(Variable {
                name: name.to_string(),
                value: value.to_string(),
            });
        }
    }

    /// Run the application
    pub fn main(&mut self) {
        println!("Type help for a command list");
        if let Some(arg) = args().get(1) {
            let command = "run ".to_string() + arg;
            println!("# {}", command);
            self.on_command(&command);
        }

        loop {
            for mode in self.modes.iter().rev() {
                if mode.value {
                    print!("+ ");
                } else {
                    print!("- ");
                }
            }
            print!("# ");
            if let Some(command_original) = readln!() {
                let command = command_original.trim();
                if command == "exit" {
                    println!("Exit temporarily blocked (due to using terminal as init)")
                    //break;
                } else if !command.is_empty() {
                    self.on_command(&command);
                }
            } else {
                println!("Failed to read from stdin");
            }
        }
    }
}

pub fn main() {
    unsafe {
        let mut app = box Application::new();
        application = app.deref_mut();
        app.main();
    }
}
<|endoftext|>


<commit_before><commit_msg>tests(Unified Help): uses new sorted category in tests<commit_after><|endoftext|>


<commit_before><commit_msg>Regression test for issue 55552.<commit_after>// compile-pass

// rust-lang/rust#55552: The strategy pnkfelix landed in PR #55274
// (for ensuring that NLL respects user-provided lifetime annotations)
// did not handle the case where the ascribed type has some expliit
// wildcards (`_`) mixed in, and it caused an internal compiler error
// (ICE).
//
// This test is just checking that we do not ICE when such things
// occur.

struct X;
struct Y;
struct Z;

struct Pair { x: X, y: Y }

pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
where A: FnOnce() -> RA + Send,
      B: FnOnce() -> RB + Send,
      RA: Send,
      RB: Send
{
    (oper_a(), oper_b())
}

fn main() {
    let ((_x, _y), _z): (_, Z) = join(|| (X, Y), || Z);

    let (Pair { x: _x, y: _y }, Z): (_, Z) = join(|| Pair { x: X, y: Y }, || Z);
}
<|endoftext|>


<commit_before><commit_msg>Add initial db.rs<commit_after>// Copyright (c) 2017 Jason White
//
// 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.

//! In order to track changes to the build graph and nodes, we need to persist
//! the graph to disk. Each invocation of the build must read this in and do a
//! comparison to figure out what has changed since the last run.
//!
//! The persistent storage needs to store the following types of data:
//!
//!  1. **Nodes**
//!
//!     This is a generic data type and can be subdivided into two main types:
//!
//!      (a) Resources
//!      (b) Tasks
//!
//!     It should be possible to generically serialize these into a single SQL
//!     table. We are only interested in storing the node *identifiers* here.
//!     State associated with resources is stored in a separate table for
//!     reasons described later.
//!
//!     It may be better to split the resources and tasks into separate tables
//!     to further ensure that the graph remains bipartite. Note that, if this
//!     is done, the `edges` table and `pending` table must also be split up.
//!
//!  2. **Edges**
//!
//!     The edges between nodes must also be stored. This table is pretty
//!     trivial. We only need to store a pair of node IDs and some data
//!     associated with the edge (e.g., if it is an implicit or explicit edge).
//!
//!  3. **Resource State**
//!
//!     The resource state can be "Unknown", "Missing", or a 32-byte array. It
//!     is up to the implementation of the resource how the bytes in the array
//!     are interpreted. Most of the time, this will probably be a SHA256 hash.
//!     However, the 32-byte array can be packed however the implementation
//!     wishes. For example, tracking changes by timestamp may just choose to
//!     pack the buffer with a 64-bit timestamp, 64-bit length, and fill the
//!     rest with zeroes. In such a case, computing the checksum would be
//!     computationally wasteful.
//!
//!     Thus, this table is very simple: a node ID and a 32-byte array.
//!
//!     The first row in this table is special. It is the state of the build
//!     description. This is to avoid loading the build description if it hasn't
//!     changed.
//!
//!  4. **Pending Nodes**
//!
//!     This table shall contain a list of nodes that must be visited upon the
//!     next graph traversal. To understand why this is needed, consider the
//!     following scenario:
//!
//!      1. An initial build is started.
//!      2. The build fails.
//!      3. We fix the problem.
//!      4. We run the build again.
//!
//!     Now, we expect that only the failed tasks will get executed, not the
//!     entire build. Between steps (1) and (2), a number of important things
//!     must happen:
//!
//!      1. The stored build state is loaded from the database and into a graph
//!         data structure.
//!      2. The graph constructed from the list of rules is merged into the
//!         graph from (1). We do this by figuring out the "diff" between the
//!         two graphs (i.e., added/removed nodes and edges). Any new nodes must
//!         be visited in the build graph traversal.
//!      3. The updated build state is committed to disk.
//!
//!     After this point, the build can fail or get `kill -9`'d and things
//!     should be fine. However, the build system must not forget which nodes
//!     need to be visited in the traversal.

/// The storage medium for the build system that persists between builds,
/// implemented as a SQLite database. Also known as the build state.
///
/// The main operations we are interested in with this database are:
///
///  1. Loading or creating a database if it doesn't exist.
///  2. Adding nodes and edges
///  3. Creating a graph from the nodes and edges.
///  4. Getting the state associated with a node.
///  5. Getting the list of pending nodes.
///
struct Database {
    // TODO:
}
<|endoftext|>


<commit_before>use redox::{Vec, String, ToString};
use redox::collections::{BTreeMap, VecDeque};

use super::dvaddr::DVAddr;
use super::zio;

// Our implementation of the Adaptive Replacement Cache (ARC) is set up to allocate
// its buffer on the heap rather than in a private pool thing. This makes it much
// simpler to implement, but defers the fragmentation problem to the heap allocator.
// We named the type `ArCache` to avoid confusion with Rust's `Arc` reference type.
pub struct ArCache {
    // MRU
    // TODO: keep track of use counts. So mru_map becomes (use_count: u64, Vec<u8>)
    mru_map: BTreeMap<DVAddr, Vec<u8>>, // Most recently used cache
    mru_queue: VecDeque<DVAddr>, // Oldest DVAddrs are at the end
    mru_size: usize, // Max mru cache size in bytes
    mru_used: usize, // Used bytes in mru cache

    // MFU
    // TODO: Keep track of use counts. So mfu_map becomes (use_count: u64, Vec<u8>). Reset the use
    // count every once in a while. For instance, every 1000 reads. This will probably end up being
    // a knob for the user.
    mfu_map: BTreeMap<DVAddr, Vec<u8>>, // Most frequently used cache
    // TODO: Keep track of minimum frequency.
    mfu_min_freq: u64,
    mfu_size: usize, // Max mfu cache size in bytes
    mfu_used: usize, // Used bytes in mfu cache
}

impl ArCache {
    pub fn new() -> Self {
        ArCache {
            mru_map: BTreeMap::new(),
            mru_queue: VecDeque::new(),
            mru_size: 10,
            mru_used: 0,

            mfu_map: BTreeMap::new(),
            mfu_size: 10,
            mfu_used: 0,
        }
    }

    pub fn read(&mut self, reader: &mut zio::Reader, dva: &DVAddr) -> Result<Vec<u8>, String> {
        if let Some(block) = self.mru_map.get(dva) {
            // TODO: Keep track of MRU DVA use count. If it gets used a second time, move the block into
            // the MFU cache.

            // Block is cached
            return Ok(block.clone());
        }
        if let Some(block) = self.mfu_map.get(dva) {
            // TODO: keep track of DVA use count
            // Block is cached
            return Ok(block.clone());
        }

        // Block isn't cached, have to read it from disk
        let block = reader.read(dva.sector() as usize, dva.asize() as usize);
        self.cache_block(block);
    }

    fn mru_cache_block(&mut self, block: Vec<u8>) {
        // If necessary, make room for the block in the cache
        while self.mru_used + block.len() > self.mru_size {
            let last_dva = match self.mru_queue.pop_back()
            {
                Some(dva) => dva,
                None => return Err("No more ARC MRU items to free".to_string()),
            };
            self.mru_map.remove(&last_dva);
            self.mru_used -= last_dva.asize() as usize;
        }

        // Add the block to the cache
        self.mru_used += block.len();
        self.mru_map.insert(*dva, block);
        self.mru_queue.push_front(*dva);
        Ok(self.mru_map.get(dva).unwrap().clone())
    }

    // TODO: mfu_cache_block
}
<commit_msg>fixed arc todos<commit_after>use redox::{Vec, String, ToString};
use redox::collections::{BTreeMap, VecDeque};

use super::dvaddr::DVAddr;
use super::zio;

// Our implementation of the Adaptive Replacement Cache (ARC) is set up to allocate
// its buffer on the heap rather than in a private pool thing. This makes it much
// simpler to implement, but defers the fragmentation problem to the heap allocator.
// We named the type `ArCache` to avoid confusion with Rust's `Arc` reference type.
pub struct ArCache {
    // MRU
    // TODO: keep track of use counts. So mru_map becomes (use_count: u64, Vec<u8>)
    mru_map: BTreeMap<DVAddr, Vec<u8>>, // Most recently used cache
    mru_queue: VecDeque<DVAddr>, // Oldest DVAddrs are at the end
    mru_size: usize, // Max mru cache size in bytes
    mru_used: usize, // Used bytes in mru cache

    // MFU
    // TODO: Keep track of use counts. So mfu_map becomes (use_count: u64, Vec<u8>). Reset the use
    // count every once in a while. For instance, every 1000 reads. This will probably end up being
    // a knob for the user.
    // TODO: Keep track of minimum frequency and corresponding DVA
    mfu_map: BTreeMap<DVAddr, Vec<u8>>, // Most frequently used cache
    mfu_size: usize, // Max mfu cache size in bytes
    mfu_used: usize, // Used bytes in mfu cache
}

impl ArCache {
    pub fn new() -> Self {
        ArCache {
            mru_map: BTreeMap::new(),
            mru_queue: VecDeque::new(),
            mru_size: 10,
            mru_used: 0,

            mfu_map: BTreeMap::new(),
            mfu_size: 10,
            mfu_used: 0,
        }
    }

    pub fn read(&mut self, reader: &mut zio::Reader, dva: &DVAddr) -> Result<Vec<u8>, String> {
        if let Some(block) = self.mru_map.get(dva) {
            // TODO: Keep track of MRU DVA use count. If it gets used a second time, move the block into
            // the MFU cache.

            // Block is cached
            return Ok(block.clone());
        }
        if let Some(block) = self.mfu_map.get(dva) {
            // TODO: keep track of DVA use count
            // Block is cached
            return Ok(block.clone());
        }

        // Block isn't cached, have to read it from disk
        let block = reader.read(dva.sector() as usize, dva.asize() as usize);

        // Blocks start in MRU cache
        self.mru_cache_block(dva, block)
    }

    fn mru_cache_block(&mut self, dva: &DVAddr, block: Vec<u8>) -> Result<Vec<u8>, String>{
        // If necessary, make room for the block in the cache
        while self.mru_used + block.len() > self.mru_size {
            let last_dva = match self.mru_queue.pop_back()
            {
                Some(dva) => dva,
                None => return Err("No more ARC MRU items to free".to_string()),
            };
            self.mru_map.remove(&last_dva);
            self.mru_used -= last_dva.asize() as usize;
        }

        // Add the block to the cache
        self.mru_used += block.len();
        self.mru_map.insert(*dva, block);
        self.mru_queue.push_front(*dva);
        Ok(self.mru_map.get(dva).unwrap().clone())
    }

    // TODO: mfu_cache_block. Remove the DVA with the lowest frequency
}
<|endoftext|>


<commit_before><commit_msg>WIP: Add file dialog example<commit_after>extern crate orbtk;

use orbtk::{ Color, Window, List, Rect, Entry, Label };
use orbtk::traits::{ Place, Text, Click };

use std::{fs, io, path};
use std::cell::RefCell;
use std::ops::Deref;
use std::rc::Rc;

fn folder_items<P: AsRef<path::Path>>(path: P) -> io::Result<Vec<Result<String, String>>> {
    let mut items = vec![];

    if path.as_ref().parent().is_some() {
        items.push(Ok("..".to_string()));
    }

    for entry_res in fs::read_dir(path)? {
        let item = match entry_res {
            Ok(entry) => match entry.file_name().into_string() {
                Ok(name) => match entry.file_type() {
                    Ok(file_type) => if file_type.is_dir() {
                        Ok(format!("{}/", name))
                    } else {
                        Ok(name)
                    },
                    Err(err) => Err(format!("{}", err))
                },
                Err(os_str) => Err(format!("Invalid filename: {:?}", os_str))
            },
            Err(err) => Err(format!("{}", err))
        };

        items.push(item);
    }

    items.sort();

    Ok(items)
}

fn main() {
    let path_opt = Rc::new(RefCell::new(
        Some(path::PathBuf::from("."))
    ));

    loop {
        let path = match path_opt.borrow_mut().take() {
            Some(path) => path,
            None => return
        };

        let w = 640;
        let h = 480;

        let mut window = Box::new(Window::new(Rect::new(-1, -1, w, h), "File Dialog"));

        let list = List::new();
        list.position(2, 2).size(w - 4, h - 4);

        match folder_items(&path) {
            Ok(items) => for item in items {
                let entry = Entry::new(24);

                let label = Label::new();
                label.position(2, 2).size(w - 8, 20).text_offset(2, 2);
                label.bg.set(Color::rgb(255, 255, 255));
                entry.add(&label);

                match item {
                    Ok(name) => {
                        {
                            let window = window.deref() as *const Window;
                            let path_opt = path_opt.clone();
                            let path = {
                                let mut p = path.clone();
                                p.push(&name);
                                p
                            };
                            let name = name.clone();
                            entry.on_click(move |_, _| {
                                println!("{}", name);
                                *path_opt.borrow_mut() = Some(path.clone());
                                unsafe { (*window).close(); }
                            });
                        }

                        label.text(name);
                    },
                    Err(err) => {
                        label.text(err);
                    }
                }

                list.push(&entry);
            },
            Err(err) => {
                let entry = Entry::new(24);

                let label = Label::new();
                label.position(2, 2).size(w - 8, 20).text_offset(2, 2);
                label.bg.set(Color::rgb(242, 222, 222));
                entry.add(&label);

                label.text(format!("{}", err));

                list.push(&entry);
            }
        }

        window.add(&list);

        window.exec();
    }
}
<|endoftext|>


<commit_before><commit_msg>languages/rust/learn-rust/3-chapter/19-code.rs<commit_after><|endoftext|>


<commit_before><commit_msg> removed filter for testing<commit_after><|endoftext|>


<commit_before><commit_msg>an empy message<commit_after><|endoftext|>