<commit_before>use {CreationError, Event};
use CreationError::OsError;
use libc;

#[cfg(feature = "window")]
use WindowBuilder;

#[cfg(feature = "headless")]
use HeadlessRendererBuilder;

use cocoa::base::{id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar};
use cocoa::base::{object_setInstanceVariable, object_getInstanceVariable};
use cocoa::appkit;
use cocoa::appkit::*;

use core_foundation::base::TCFType;
use core_foundation::string::CFString;
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};

use std::c_str::CString;
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicBool, Relaxed};

use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput};
use events::ElementState::{Pressed, Released};
use events::MouseButton::{LeftMouseButton, RightMouseButton};
use events;

pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};

mod monitor;
mod event;

static mut shift_pressed: bool = false;
static mut ctrl_pressed: bool = false;
static mut win_pressed: bool = false;
static mut alt_pressed: bool = false;

static DELEGATE_NAME: &'static [u8] = b"glutin_window_delegate\0";
static DELEGATE_THIS_IVAR: &'static [u8] = b"glutin_this";

struct InternalState {
    is_closed: AtomicBool,
}

impl InternalState {
    fn new() -> InternalState {
        InternalState {
            is_closed: AtomicBool::new(false),
        }
    }
}

pub struct Window {
    view: id,
    window: id,
    context: id,
    state: Box<InternalState>,
}

pub struct HeadlessContext(Window);

impl Deref<Window> for HeadlessContext {
    fn deref(&self) -> &Window {
        &self.0
    }
}

#[cfg(feature = "window")]
impl Window {
    pub fn new(builder: WindowBuilder) -> Result<Window, CreationError> {
        Window::new_impl(builder.dimensions, builder.title.as_slice(), builder.monitor, true)
    }
}

#[cfg(feature = "headless")]
impl HeadlessContext {
    pub fn new(builder: HeadlessRendererBuilder) -> Result<HeadlessContext, CreationError> {
        Window::new_impl(Some(builder.dimensions), "", None, false)
            .map(|w| HeadlessContext(w))
    }
}

extern fn window_should_close(this: id, _: id) -> id {
    unsafe {
        let mut stored_value = ptr::null_mut();
        object_getInstanceVariable(this, DELEGATE_THIS_IVAR.as_ptr() as *const i8, &mut stored_value);
        let state = stored_value as *mut InternalState;
        (*state).is_closed.store(true, Relaxed);
    }
    0
}

impl Window {
    fn new_impl(dimensions: Option<(uint, uint)>, title: &str, monitor: Option<MonitorID>, visible: bool) -> Result<Window, CreationError> {
        let app = match Window::create_app() {
            Some(app) => app,
            None      => { return Err(OsError(format!("Couldn't create NSApplication"))); },
        };
        let window = match Window::create_window(dimensions.unwrap_or((800, 600)), title, monitor) {
            Some(window) => window,
            None         => { return Err(OsError(format!("Couldn't create NSWindow"))); },
        };
        let view = match Window::create_view(window) {
            Some(view) => view,
            None       => { return Err(OsError(format!("Couldn't create NSView"))); },
        };

        let context = match Window::create_context(view) {
            Some(context) => context,
            None          => { return Err(OsError(format!("Couldn't create OpenGL context"))); },
        };

        unsafe {
            app.activateIgnoringOtherApps_(true);
            window.makeKeyAndOrderFront_(nil);
        }

        let window = Window {
            view: view,
            window: window,
            context: context,
            state: box InternalState::new(),
        };

        // Set up the window delegate to receive events
        let ptr_size = mem::size_of::<libc::intptr_t>() as u64;
        let ns_object = class("NSObject");

        unsafe {
            // Create a delegate class, add callback methods and store InternalState as user data.
            let delegate = objc_allocateClassPair(ns_object, DELEGATE_NAME.as_ptr() as *const i8, 0);
            class_addMethod(delegate, selector("windowShouldClose:"), window_should_close, "B@:@".to_c_str().as_ptr());
            class_addIvar(delegate, DELEGATE_THIS_IVAR.as_ptr() as *const i8, ptr_size, 3, "?".to_c_str().as_ptr());
            objc_registerClassPair(delegate);

            let del_obj = msg_send()(delegate, selector("alloc"));
            let del_obj: id = msg_send()(del_obj, selector("init"));
            object_setInstanceVariable(del_obj, DELEGATE_THIS_IVAR.as_ptr() as *const i8,
                                        &*window.state as *const InternalState as *mut libc::c_void);
            let _: id = msg_send()(window.window, selector("setDelegate:"), del_obj);
        }

        Ok(window)
    }

    fn create_app() -> Option<id> {
        unsafe {
            let app = NSApp();
            if app == nil {
                None
            } else {
                app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
                app.finishLaunching();
                Some(app)
            }
        }
    }

    fn create_window(dimensions: (uint, uint), title: &str, monitor: Option<MonitorID>) -> Option<id> {
        unsafe {
            let scr_frame = match monitor {
                Some(_) => {
                    let screen = NSScreen::mainScreen(nil);
                    NSScreen::frame(screen)
                }
                None    => {
                    let (width, height) = dimensions;
                    NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64))
                }
            };

             let masks = match monitor {
                Some(_) => NSBorderlessWindowMask as NSUInteger,
                None    => NSTitledWindowMask as NSUInteger |
                           NSClosableWindowMask as NSUInteger |
                           NSMiniaturizableWindowMask as NSUInteger |
                           NSResizableWindowMask as NSUInteger,
            };

            let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
                scr_frame,
                masks,
                NSBackingStoreBuffered,
                false,
            );

            if window == nil {
                None
            } else {
                let title = NSString::alloc(nil).init_str(title);
                window.setTitle_(title);
                window.center();
                window.setAcceptsMouseMovedEvents_(true);
                if monitor.is_some() {
                    window.setLevel_(NSMainMenuWindowLevel as i64 + 1);
                }
                Some(window)
            }
        }
    }

    fn create_view(window: id) -> Option<id> {
        unsafe {
            let view = NSView::alloc(nil).init();
            if view == nil {
                None
            } else {
                view.setWantsBestResolutionOpenGLSurface_(true);
                window.setContentView_(view);
                Some(view)
            }
        }
    }

    fn create_context(view: id) -> Option<id> {
        unsafe {
            let attributes = [
                NSOpenGLPFADoubleBuffer as uint,
                NSOpenGLPFAClosestPolicy as uint,
                NSOpenGLPFAColorSize as uint, 24,
                NSOpenGLPFAAlphaSize as uint, 8,
                NSOpenGLPFADepthSize as uint, 24,
                NSOpenGLPFAStencilSize as uint, 8,
                0
            ];

            let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes);
            if pixelformat == nil {
                return None;
            }

            let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
            if context == nil {
                None
            } else {
                context.setView_(view);
                Some(context)
            }
        }
    }

    pub fn is_closed(&self) -> bool {
        self.state.is_closed.load(Relaxed)
    }

    pub fn set_title(&self, title: &str) {
        unsafe {
            let title = NSString::alloc(nil).init_str(title);
            self.window.setTitle_(title);
        }
    }

    pub fn show(&self) {
    }

    pub fn hide(&self) {
    }

    pub fn get_position(&self) -> Option<(int, int)> {
        unimplemented!()
    }

    pub fn set_position(&self, _x: int, _y: int) {
        unimplemented!()
    }

    pub fn get_inner_size(&self) -> Option<(uint, uint)> {
        unimplemented!()
    }

    pub fn get_outer_size(&self) -> Option<(uint, uint)> {
        unimplemented!()
    }

    pub fn set_inner_size(&self, _x: uint, _y: uint) {
        unimplemented!()
    }

    pub fn poll_events(&self) -> Vec<Event> {
        let mut events = Vec::new();

        loop {
            unsafe {
                let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                    NSAnyEventMask as u64,
                    NSDate::distantPast(nil),
                    NSDefaultRunLoopMode,
                    true);
                if event == nil { break; }
                NSApp().sendEvent_(event);

                match event.get_type() {
                    NSLeftMouseDown         => { events.push(MouseInput(Pressed, LeftMouseButton)); },
                    NSLeftMouseUp           => { events.push(MouseInput(Released, LeftMouseButton)); },
                    NSRightMouseDown        => { events.push(MouseInput(Pressed, RightMouseButton)); },
                    NSRightMouseUp          => { events.push(MouseInput(Released, RightMouseButton)); },
                    NSMouseMoved            => {
                        let window_point = event.locationInWindow();
                        let view_point = self.view.convertPoint_fromView_(window_point, nil);
                        events.push(MouseMoved((view_point.x as int, view_point.y as int)));
                    },
                    NSKeyDown               => {
                        let received_str = CString::new(event.characters().UTF8String(), false);
                        for received_char in received_str.as_str().unwrap().chars() {
                            if received_char.is_ascii() {
                                events.push(ReceivedCharacter(received_char));
                            }
                        }

                        let vkey =  event::vkeycode_to_element(event.keycode());
                        events.push(KeyboardInput(Pressed, event.keycode() as u8, vkey));
                    },
                    NSKeyUp                 => {
                        let vkey =  event::vkeycode_to_element(event.keycode());
                        events.push(KeyboardInput(Released, event.keycode() as u8, vkey));
                    },
                    NSFlagsChanged          => {
                        let shift_modifier = Window::modifier_event(event, appkit::NSShiftKeyMask as u64, events::VirtualKeyCode::LShift, shift_pressed);
                        if shift_modifier.is_some() {
                            shift_pressed = !shift_pressed;
                            events.push(shift_modifier.unwrap());
                        }
                        let ctrl_modifier = Window::modifier_event(event, appkit::NSControlKeyMask as u64, events::VirtualKeyCode::LControl, ctrl_pressed);
                        if ctrl_modifier.is_some() {
                            ctrl_pressed = !ctrl_pressed;
                            events.push(ctrl_modifier.unwrap());
                        }
                        let win_modifier = Window::modifier_event(event, appkit::NSCommandKeyMask as u64, events::VirtualKeyCode::LWin, win_pressed);
                        if win_modifier.is_some() {
                            win_pressed = !win_pressed;
                            events.push(win_modifier.unwrap());
                        }
                        let alt_modifier = Window::modifier_event(event, appkit::NSAlternateKeyMask as u64, events::VirtualKeyCode::LAlt, alt_pressed);
                        if alt_modifier.is_some() {
                            alt_pressed = !alt_pressed;
                            events.push(alt_modifier.unwrap());
                        }
                    },
                    NSScrollWheel           => { },
                    NSOtherMouseDown        => { },
                    NSOtherMouseUp          => { },
                    NSOtherMouseDragged     => { },
                    _                       => { },
                }
            }
        }
        events
    }

    unsafe fn modifier_event(event: id, keymask: u64, key: events::VirtualKeyCode, key_pressed: bool) -> Option<Event> {
        if !key_pressed && Window::modifier_key_pressed(event, keymask) {
            return Some(KeyboardInput(Pressed, event.keycode() as u8, Some(key)));
        }
        else if key_pressed && !Window::modifier_key_pressed(event, keymask) {
            return Some(KeyboardInput(Released, event.keycode() as u8, Some(key)));
        }

        return None;
    }

    unsafe fn modifier_key_pressed(event: id, modifier: u64) -> bool {
        event.modifierFlags() & modifier != 0
    }

    pub fn wait_events(&self) -> Vec<Event> {
        unsafe {
            let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                NSAnyEventMask as u64,
                NSDate::distantFuture(nil),
                NSDefaultRunLoopMode,
                false);
            NSApp().sendEvent_(event);

            self.poll_events()
        }
    }

    pub unsafe fn make_current(&self) {
        self.context.makeCurrentContext();
    }

    pub fn get_proc_address(&self, _addr: &str) -> *const () {
        let symbol_name: CFString = from_str(_addr).unwrap();
        let framework_name: CFString = from_str("com.apple.opengl").unwrap();
        let framework = unsafe {
            CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
        };
        let symbol = unsafe {
            CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
        };
        symbol as *const ()
    }

    pub fn swap_buffers(&self) {
        unsafe { self.context.flushBuffer(); }
    }

    pub fn platform_display(&self) -> *mut libc::c_void {
        unimplemented!()
    }
}
<commit_msg>Implement get_inner_size() for mac.<commit_after>use {CreationError, Event};
use CreationError::OsError;
use libc;

#[cfg(feature = "window")]
use WindowBuilder;

#[cfg(feature = "headless")]
use HeadlessRendererBuilder;

use cocoa::base::{id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar};
use cocoa::base::{object_setInstanceVariable, object_getInstanceVariable};
use cocoa::appkit;
use cocoa::appkit::*;

use core_foundation::base::TCFType;
use core_foundation::string::CFString;
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};

use std::c_str::CString;
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicBool, Relaxed};

use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput};
use events::ElementState::{Pressed, Released};
use events::MouseButton::{LeftMouseButton, RightMouseButton};
use events;

pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};

mod monitor;
mod event;

static mut shift_pressed: bool = false;
static mut ctrl_pressed: bool = false;
static mut win_pressed: bool = false;
static mut alt_pressed: bool = false;

static DELEGATE_NAME: &'static [u8] = b"glutin_window_delegate\0";
static DELEGATE_THIS_IVAR: &'static [u8] = b"glutin_this";

struct InternalState {
    is_closed: AtomicBool,
}

impl InternalState {
    fn new() -> InternalState {
        InternalState {
            is_closed: AtomicBool::new(false),
        }
    }
}

pub struct Window {
    view: id,
    window: id,
    context: id,
    state: Box<InternalState>,
}

pub struct HeadlessContext(Window);

impl Deref<Window> for HeadlessContext {
    fn deref(&self) -> &Window {
        &self.0
    }
}

#[cfg(feature = "window")]
impl Window {
    pub fn new(builder: WindowBuilder) -> Result<Window, CreationError> {
        Window::new_impl(builder.dimensions, builder.title.as_slice(), builder.monitor, true)
    }
}

#[cfg(feature = "headless")]
impl HeadlessContext {
    pub fn new(builder: HeadlessRendererBuilder) -> Result<HeadlessContext, CreationError> {
        Window::new_impl(Some(builder.dimensions), "", None, false)
            .map(|w| HeadlessContext(w))
    }
}

extern fn window_should_close(this: id, _: id) -> id {
    unsafe {
        let mut stored_value = ptr::null_mut();
        object_getInstanceVariable(this, DELEGATE_THIS_IVAR.as_ptr() as *const i8, &mut stored_value);
        let state = stored_value as *mut InternalState;
        (*state).is_closed.store(true, Relaxed);
    }
    0
}

impl Window {
    fn new_impl(dimensions: Option<(uint, uint)>, title: &str, monitor: Option<MonitorID>, visible: bool) -> Result<Window, CreationError> {
        let app = match Window::create_app() {
            Some(app) => app,
            None      => { return Err(OsError(format!("Couldn't create NSApplication"))); },
        };
        let window = match Window::create_window(dimensions.unwrap_or((800, 600)), title, monitor) {
            Some(window) => window,
            None         => { return Err(OsError(format!("Couldn't create NSWindow"))); },
        };
        let view = match Window::create_view(window) {
            Some(view) => view,
            None       => { return Err(OsError(format!("Couldn't create NSView"))); },
        };

        let context = match Window::create_context(view) {
            Some(context) => context,
            None          => { return Err(OsError(format!("Couldn't create OpenGL context"))); },
        };

        unsafe {
            app.activateIgnoringOtherApps_(true);
            window.makeKeyAndOrderFront_(nil);
        }

        let window = Window {
            view: view,
            window: window,
            context: context,
            state: box InternalState::new(),
        };

        // Set up the window delegate to receive events
        let ptr_size = mem::size_of::<libc::intptr_t>() as u64;
        let ns_object = class("NSObject");

        unsafe {
            // Create a delegate class, add callback methods and store InternalState as user data.
            let delegate = objc_allocateClassPair(ns_object, DELEGATE_NAME.as_ptr() as *const i8, 0);
            class_addMethod(delegate, selector("windowShouldClose:"), window_should_close, "B@:@".to_c_str().as_ptr());
            class_addIvar(delegate, DELEGATE_THIS_IVAR.as_ptr() as *const i8, ptr_size, 3, "?".to_c_str().as_ptr());
            objc_registerClassPair(delegate);

            let del_obj = msg_send()(delegate, selector("alloc"));
            let del_obj: id = msg_send()(del_obj, selector("init"));
            object_setInstanceVariable(del_obj, DELEGATE_THIS_IVAR.as_ptr() as *const i8,
                                        &*window.state as *const InternalState as *mut libc::c_void);
            let _: id = msg_send()(window.window, selector("setDelegate:"), del_obj);
        }

        Ok(window)
    }

    fn create_app() -> Option<id> {
        unsafe {
            let app = NSApp();
            if app == nil {
                None
            } else {
                app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
                app.finishLaunching();
                Some(app)
            }
        }
    }

    fn create_window(dimensions: (uint, uint), title: &str, monitor: Option<MonitorID>) -> Option<id> {
        unsafe {
            let scr_frame = match monitor {
                Some(_) => {
                    let screen = NSScreen::mainScreen(nil);
                    NSScreen::frame(screen)
                }
                None    => {
                    let (width, height) = dimensions;
                    NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64))
                }
            };

             let masks = match monitor {
                Some(_) => NSBorderlessWindowMask as NSUInteger,
                None    => NSTitledWindowMask as NSUInteger |
                           NSClosableWindowMask as NSUInteger |
                           NSMiniaturizableWindowMask as NSUInteger |
                           NSResizableWindowMask as NSUInteger,
            };

            let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
                scr_frame,
                masks,
                NSBackingStoreBuffered,
                false,
            );

            if window == nil {
                None
            } else {
                let title = NSString::alloc(nil).init_str(title);
                window.setTitle_(title);
                window.center();
                window.setAcceptsMouseMovedEvents_(true);
                if monitor.is_some() {
                    window.setLevel_(NSMainMenuWindowLevel as i64 + 1);
                }
                Some(window)
            }
        }
    }

    fn create_view(window: id) -> Option<id> {
        unsafe {
            let view = NSView::alloc(nil).init();
            if view == nil {
                None
            } else {
                view.setWantsBestResolutionOpenGLSurface_(true);
                window.setContentView_(view);
                Some(view)
            }
        }
    }

    fn create_context(view: id) -> Option<id> {
        unsafe {
            let attributes = [
                NSOpenGLPFADoubleBuffer as uint,
                NSOpenGLPFAClosestPolicy as uint,
                NSOpenGLPFAColorSize as uint, 24,
                NSOpenGLPFAAlphaSize as uint, 8,
                NSOpenGLPFADepthSize as uint, 24,
                NSOpenGLPFAStencilSize as uint, 8,
                0
            ];

            let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes);
            if pixelformat == nil {
                return None;
            }

            let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
            if context == nil {
                None
            } else {
                context.setView_(view);
                Some(context)
            }
        }
    }

    pub fn is_closed(&self) -> bool {
        self.state.is_closed.load(Relaxed)
    }

    pub fn set_title(&self, title: &str) {
        unsafe {
            let title = NSString::alloc(nil).init_str(title);
            self.window.setTitle_(title);
        }
    }

    pub fn show(&self) {
    }

    pub fn hide(&self) {
    }

    pub fn get_position(&self) -> Option<(int, int)> {
        unimplemented!()
    }

    pub fn set_position(&self, _x: int, _y: int) {
        unimplemented!()
    }

    pub fn get_inner_size(&self) -> Option<(uint, uint)> {
        let rect = unsafe { NSView::frame(self.view) };
        Some((rect.size.width as uint, rect.size.height as uint))
    }

    pub fn get_outer_size(&self) -> Option<(uint, uint)> {
        unimplemented!()
    }

    pub fn set_inner_size(&self, _x: uint, _y: uint) {
        unimplemented!()
    }

    pub fn poll_events(&self) -> Vec<Event> {
        let mut events = Vec::new();

        loop {
            unsafe {
                let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                    NSAnyEventMask as u64,
                    NSDate::distantPast(nil),
                    NSDefaultRunLoopMode,
                    true);
                if event == nil { break; }
                NSApp().sendEvent_(event);

                match event.get_type() {
                    NSLeftMouseDown         => { events.push(MouseInput(Pressed, LeftMouseButton)); },
                    NSLeftMouseUp           => { events.push(MouseInput(Released, LeftMouseButton)); },
                    NSRightMouseDown        => { events.push(MouseInput(Pressed, RightMouseButton)); },
                    NSRightMouseUp          => { events.push(MouseInput(Released, RightMouseButton)); },
                    NSMouseMoved            => {
                        let window_point = event.locationInWindow();
                        let view_point = self.view.convertPoint_fromView_(window_point, nil);
                        events.push(MouseMoved((view_point.x as int, view_point.y as int)));
                    },
                    NSKeyDown               => {
                        let received_str = CString::new(event.characters().UTF8String(), false);
                        for received_char in received_str.as_str().unwrap().chars() {
                            if received_char.is_ascii() {
                                events.push(ReceivedCharacter(received_char));
                            }
                        }

                        let vkey =  event::vkeycode_to_element(event.keycode());
                        events.push(KeyboardInput(Pressed, event.keycode() as u8, vkey));
                    },
                    NSKeyUp                 => {
                        let vkey =  event::vkeycode_to_element(event.keycode());
                        events.push(KeyboardInput(Released, event.keycode() as u8, vkey));
                    },
                    NSFlagsChanged          => {
                        let shift_modifier = Window::modifier_event(event, appkit::NSShiftKeyMask as u64, events::VirtualKeyCode::LShift, shift_pressed);
                        if shift_modifier.is_some() {
                            shift_pressed = !shift_pressed;
                            events.push(shift_modifier.unwrap());
                        }
                        let ctrl_modifier = Window::modifier_event(event, appkit::NSControlKeyMask as u64, events::VirtualKeyCode::LControl, ctrl_pressed);
                        if ctrl_modifier.is_some() {
                            ctrl_pressed = !ctrl_pressed;
                            events.push(ctrl_modifier.unwrap());
                        }
                        let win_modifier = Window::modifier_event(event, appkit::NSCommandKeyMask as u64, events::VirtualKeyCode::LWin, win_pressed);
                        if win_modifier.is_some() {
                            win_pressed = !win_pressed;
                            events.push(win_modifier.unwrap());
                        }
                        let alt_modifier = Window::modifier_event(event, appkit::NSAlternateKeyMask as u64, events::VirtualKeyCode::LAlt, alt_pressed);
                        if alt_modifier.is_some() {
                            alt_pressed = !alt_pressed;
                            events.push(alt_modifier.unwrap());
                        }
                    },
                    NSScrollWheel           => { },
                    NSOtherMouseDown        => { },
                    NSOtherMouseUp          => { },
                    NSOtherMouseDragged     => { },
                    _                       => { },
                }
            }
        }
        events
    }

    unsafe fn modifier_event(event: id, keymask: u64, key: events::VirtualKeyCode, key_pressed: bool) -> Option<Event> {
        if !key_pressed && Window::modifier_key_pressed(event, keymask) {
            return Some(KeyboardInput(Pressed, event.keycode() as u8, Some(key)));
        }
        else if key_pressed && !Window::modifier_key_pressed(event, keymask) {
            return Some(KeyboardInput(Released, event.keycode() as u8, Some(key)));
        }

        return None;
    }

    unsafe fn modifier_key_pressed(event: id, modifier: u64) -> bool {
        event.modifierFlags() & modifier != 0
    }

    pub fn wait_events(&self) -> Vec<Event> {
        unsafe {
            let event = NSApp().nextEventMatchingMask_untilDate_inMode_dequeue_(
                NSAnyEventMask as u64,
                NSDate::distantFuture(nil),
                NSDefaultRunLoopMode,
                false);
            NSApp().sendEvent_(event);

            self.poll_events()
        }
    }

    pub unsafe fn make_current(&self) {
        self.context.makeCurrentContext();
    }

    pub fn get_proc_address(&self, _addr: &str) -> *const () {
        let symbol_name: CFString = from_str(_addr).unwrap();
        let framework_name: CFString = from_str("com.apple.opengl").unwrap();
        let framework = unsafe {
            CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
        };
        let symbol = unsafe {
            CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
        };
        symbol as *const ()
    }

    pub fn swap_buffers(&self) {
        unsafe { self.context.flushBuffer(); }
    }

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


<commit_before>use command::Command;
use vm::VM;

pub struct Program {
    instructions: Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

#[derive(Clone, Copy, Debug)]
pub struct ProgramPatch {
    pub instruction_pointer: usize,
    pub current_depth: u64,
    pub status: ProgramStatus,
}

fn find_by<T, F>(list: &[T], start: Option<usize>, mut predicate: F) -> Option<usize>
where F: FnMut(&T) -> bool {
    let start = start.unwrap_or(0);
    for (offset, element) in list.iter().enumerate() {
        if predicate(element) { return Some(start + offset); }
    }

    return None;
}

impl Program {
    pub fn new() -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() {
            self.instruction_pointer = Some(0);
        }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match (self.instruction_pointer, self.status) {
            (Some(index), ProgramStatus::Seeking(goal)) if index < self.instructions.len() => {
                let patch = Program::attempt_forward_jump(&self.instructions, index, goal, self.current_depth);
                println!("SEEKING BRANCH\n{:?}\n", patch);
                return self.update(patch).execute(vm)
            }

            (Some(start), ProgramStatus::Normal) if start < self.instructions.len() => {
                for index in start..self.instructions.len() {
                    match self.instructions[index] {
                        Command::JumpBackward => {
                            if vm.cells[vm.data_pointer] == 0 {
                                self.current_depth -= 1;
                                continue;
                            }

                            let patch = Program::backward_jump(&self.instructions, index, self.current_depth);
                            println!("BACKWARD BRANCH\n{:?}\n", patch);
                            return self.update(patch).execute(vm);
                        },

                        Command::JumpForward => {
                            if vm.cells[vm.data_pointer] != 0 {
                                self.current_depth += 1;
                                continue;
                            }

                            let patch = Program::attempt_forward_jump(&self.instructions, index, self.current_depth, self.current_depth);
                            println!("FORWARD BRANCH\n{:?}\n", patch);
                            return self.update(patch).execute(vm);
                        },

                        command if start < self.instructions.len() => vm.apply(command),

                        _ => {},
                    }
                }
            }

            _ => {}
        }
    }

    fn update (&mut self, patch: ProgramPatch) -> &mut Self {
        self.instruction_pointer = Some(patch.instruction_pointer);
        self.current_depth = patch.current_depth;
        self.status = patch.status;
        return self;
    }

    fn backward_jump(commands: &Vec<Command>, start: usize, depth: u64) -> ProgramPatch {
        let goal_depth = depth - 1;
        let mut current_depth = depth;
        for index in (0..start).rev() {
            match commands[index] {
                Command::JumpBackward => current_depth += 1,
                Command::JumpForward => current_depth -= 1,
                _ => {},
            }
            if goal_depth == current_depth {
                return ProgramPatch { instruction_pointer: index, status: ProgramStatus::Normal, current_depth };
            }
        }
        panic!("No opening bracket found?");
    }

    fn attempt_forward_jump(commands: &Vec<Command>, index: usize, goal_depth: u64, mut current_depth: u64) -> ProgramPatch {
        let index = find_by(commands, Some(index), |command| {
            match command {
                &Command::JumpBackward => current_depth -= 1,
                &Command::JumpForward => current_depth += 1,
                _ => {},
            };
            return current_depth == goal_depth;
        });

        return match index {
            Some(index) => ProgramPatch {
                instruction_pointer: index,
                status: ProgramStatus::Normal,
                current_depth
            },

            None => ProgramPatch {
                instruction_pointer: commands.len(),
                status: ProgramStatus::Seeking(goal_depth),
                current_depth,
            }
        };
    }
}
<commit_msg>Run cargo fmt<commit_after>use command::Command;
use vm::VM;

pub struct Program {
    instructions: Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

#[derive(Clone, Copy, Debug)]
pub struct ProgramPatch {
    pub instruction_pointer: usize,
    pub current_depth: u64,
    pub status: ProgramStatus,
}

fn find_by<T, F>(list: &[T], start: Option<usize>, mut predicate: F) -> Option<usize>
where
    F: FnMut(&T) -> bool,
{
    let start = start.unwrap_or(0);
    for (offset, element) in list.iter().enumerate() {
        if predicate(element) {
            return Some(start + offset);
        }
    }

    return None;
}

impl Program {
    pub fn new() -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() {
            self.instruction_pointer = Some(0);
        }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match (self.instruction_pointer, self.status) {
            (Some(index), ProgramStatus::Seeking(goal)) if index < self.instructions.len() => {
                let patch = Program::attempt_forward_jump(
                    &self.instructions,
                    index,
                    goal,
                    self.current_depth,
                );
                println!("SEEKING BRANCH\n{:?}\n", patch);
                return self.update(patch).execute(vm);
            }

            (Some(start), ProgramStatus::Normal) if start < self.instructions.len() => {
                for index in start..self.instructions.len() {
                    match self.instructions[index] {
                        Command::JumpBackward => {
                            if vm.cells[vm.data_pointer] == 0 {
                                self.current_depth -= 1;
                                continue;
                            }

                            let patch = Program::backward_jump(
                                &self.instructions,
                                index,
                                self.current_depth,
                            );
                            println!("BACKWARD BRANCH\n{:?}\n", patch);
                            return self.update(patch).execute(vm);
                        }

                        Command::JumpForward => {
                            if vm.cells[vm.data_pointer] != 0 {
                                self.current_depth += 1;
                                continue;
                            }

                            let patch = Program::attempt_forward_jump(
                                &self.instructions,
                                index,
                                self.current_depth,
                                self.current_depth,
                            );
                            println!("FORWARD BRANCH\n{:?}\n", patch);
                            return self.update(patch).execute(vm);
                        }

                        command if start < self.instructions.len() => vm.apply(command),

                        _ => {}
                    }
                }
            }

            _ => {}
        }
    }

    fn update(&mut self, patch: ProgramPatch) -> &mut Self {
        self.instruction_pointer = Some(patch.instruction_pointer);
        self.current_depth = patch.current_depth;
        self.status = patch.status;
        return self;
    }

    fn backward_jump(commands: &Vec<Command>, start: usize, depth: u64) -> ProgramPatch {
        let goal_depth = depth - 1;
        let mut current_depth = depth;
        for index in (0..start).rev() {
            match commands[index] {
                Command::JumpBackward => current_depth += 1,
                Command::JumpForward => current_depth -= 1,
                _ => {}
            }
            if goal_depth == current_depth {
                return ProgramPatch {
                    instruction_pointer: index,
                    status: ProgramStatus::Normal,
                    current_depth,
                };
            }
        }
        panic!("No opening bracket found?");
    }

    fn attempt_forward_jump(
        commands: &Vec<Command>,
        index: usize,
        goal_depth: u64,
        mut current_depth: u64,
    ) -> ProgramPatch {
        let index = find_by(commands, Some(index), |command| {
            match command {
                &Command::JumpBackward => current_depth -= 1,
                &Command::JumpForward => current_depth += 1,
                _ => {}
            };
            return current_depth == goal_depth;
        });

        return match index {
            Some(index) => ProgramPatch {
                instruction_pointer: index,
                status: ProgramStatus::Normal,
                current_depth,
            },

            None => ProgramPatch {
                instruction_pointer: commands.len(),
                status: ProgramStatus::Seeking(goal_depth),
                current_depth,
            },
        };
    }
}
<|endoftext|>


<commit_before>//! Iron's Middleware and Handler System
//!
//! Iron's Middleware system is best modeled with a diagram.
//!
//! ```ignore
//! [b] = BeforeMiddleware
//! [a] = AfterMiddleware
//! [[h]] = AroundMiddleware
//! [h] = Handler
//! ```
//!
//! With no errors, the flow looks like:
//!
//! ```ignore
//! [b] -> [b] -> [b] -> [[[[h]]]] -> [a] -> [a] -> [a] -> [a]
//! ```
//!
//! A request first travels through all BeforeMiddleware, then a Response is generated
//! by the Handler, which can be an arbitrary nesting of AroundMiddleware, then all AfterMiddleware
//! are called with both the Request and Response. After all AfterMiddleware have been fired,
//! the response is written back to the client.
//!
//! Not all too surprising. Of note is that AfterMiddleware and BeforeMiddleware
//! are completely separate, unlike in many other web frameworks.
//!
//! Iron's flexibility comes into play with its novel approach to error handling, which encourages
//! not just reporting errors, but *handling* them. An error is not meant to be fatal in Iron, but
//! is instead likely to be handled by downstream Middleware. Middleware authors should keep this
//! in mind when designing their APIs.
//!
//! Iron's error propagation and handling scheme is inspired by two primary rules:
//!
//!   * Errors should persist and be propagated along the same route as successes until they are
//!     handled.
//!
//!   * If an error is fully handled, control flow should resume just after the error was thrown
//!     or, if that is not possible flow should resume as close as possible to the origin of the
//!     error.
//!
//! Returning Ok from an IronResult-producing method indicates no error or that a passed-in error
//! has been handled. Err indicates that an error is either being created or propagated.
//!
//! Imagine an Err is returned by a second BeforeMiddleware. Following rule 1, it is propagated
//! to all further BeforeMiddleware by calling their `catch` methods, looking for any that could
//! handle the error. If none can, then the error is propagated to the Handler, which can attempt
//! to handle it through its `catch` method. If the Handler cannot handle the error, then it is
//! propagated to all AfterMiddleware.
//!
//! Following rule 2, if any BeforeMiddleware can handle an error thrown by a previous
//! BeforeMiddleware, the control flow returns to the BeforeMiddleware directly after the
//! BeforeMiddleware that threw the Error.
//!
//! If no BeforeMiddleware can handle a propagated error, but the Handler handles it, then
//! it is no longer possible to go back to BeforeMiddleware, so control-flow resumes with
//! the first AfterMiddleware.
//!
//! If an error is handled in AfterMiddleware, then if the error was generated by a previous
//! AfterMiddleware, control-flow resumes with the AfterMiddleware after the one which threw the
//! error. If the error occurred during or before the Handler, control-flow resumes with the
//! first AfterMiddleware.
//!

use std::sync::Arc;
use error::Error;

use super::{Request, Response, IronResult, status};

/// `Handler`s are responsible for handling requests by creating Responses from Requests.
///
/// By default, bare functions and variants of Chain implement `Handler`.
///
/// `Handler`s are allowed to return errors, and if they do, their `catch` method is called and the
/// error is propagated to `AfterMiddleware`.
pub trait Handler: Send + Sync {
    /// Produce a `Response` from a Request, with the possibility of error.
    ///
    /// If this returns an Err, `catch` is called with the error.
    fn call(&self, &mut Request) -> IronResult<Response>;

    /// If `Handler`'s call method produces an Err, then this method is called
    /// to produce a `Response` and possibly handle the error.
    ///
    /// If the passed-in error is not handled, it should be returned as the second
    /// item in the returned tuple. If it is handled, then `Ok(())` can be returned
    /// instead to indicate that all is good with the Response and the error has
    /// been dealt with.
    fn catch(&self, _: &mut Request, err: Box<Error + Send>) -> (Response, IronResult<()>) {
        (Response::status(status::InternalServerError), Err(err))
    }
}

/// `BeforeMiddleware` are fired before a `Handler` is called inside of a Chain.
///
/// `BeforeMiddleware` are responsible for doing request pre-processing that requires
/// the ability to change control-flow, such as authorization middleware, or for editing
/// the request by modifying the headers.
///
/// `BeforeMiddleware` only have access to the Request, if you need to modify or read a Response,
/// you will need `AfterMiddleware`.
pub trait BeforeMiddleware: Send + Sync {
    /// Do whatever work this middleware should do with a `Request` object.
    ///
    /// An error here is propagated by the containing Chain to, first, this Middleware's
    /// `catch` method, then every subsequent `BeforeMiddleware`'s `catch` methods until one returns
    /// Ok(()) or the Chain's `Handler` is reached, at which point the `Handler`'s `catch` method is
    /// called to produce an error Response.
    fn before(&self, &mut Request) -> IronResult<()>;

    /// Try to `catch` an error thrown by this Middleware or a previous `BeforeMiddleware`.
    ///
    /// Should only return Ok(()) if the error has been completely handled and a Chain
    /// can proceed as normal.
    fn catch(&self, _: &mut Request, err: Box<Error + Send>) -> IronResult<()> {
        Err(err)
    }
}

/// `AfterMiddleware` are fired after a `Handler` is called inside of a Chain.
///
/// `AfterMiddleware` receive both a `Request` and a `Response` and are responsible for doing
/// any response post-processing.
///
/// `AfterMiddleware` should *not* overwrite the contents of a Response. In
/// the common case, a complete response is generated by the Chain's `Handler` and
/// `AfterMiddleware` simply do post-processing of that Response, such as
/// adding headers or logging.
pub trait AfterMiddleware: Send + Sync {
    /// Do whatever work this middleware needs to do with both a `Request` and `Response` objects.
    ///
    /// An error here is propagated by the containing Chain down to this and any later
    /// `AfterMiddleware`'s `catch` methods, which can attempt to handle the error or modify
    /// the `Response` to indicate to a client that something went wrong.
    fn after(&self, &mut Request, &mut Response) -> IronResult<()>;

    /// Try to catch an error thrown by previous `AfterMiddleware`, the `Handler`, or a previous
    /// `BeforeMiddleware`.
    ///
    /// This indicates that the `Response` is abnormal in some way, either because it was
    /// generated by a `Handler`s `catch` method or because a previous `AfterMiddleware`
    /// errored.
    fn catch(&self, _: &mut Request, _: &mut Response, err: Box<Error + Send>) -> IronResult<()> {
        Err(err)
    }
}

/// AroundMiddleware are used to wrap and replace the `Handler` in a Chain.
///
/// AroundMiddleware must themselves be `Handler`s, and can integrate an existing
/// `Handler` through the `with_handler` method, which is called once on insertion
/// into a Chain.
pub trait AroundMiddleware: Handler {
    /// Incorporate another `Handler` into this `AroundMiddleware`.
    ///
    /// Usually this means wrapping the handler and editing the `Request` on the
    /// way in and the `Response` on the way out.
    ///
    /// This is called only once, when an `AroundMiddleware` is added to a `Chain`
    /// using `Chain::around`, it is passed the `Chain`'s current `Handler`.
    fn with_handler(&mut self, handler: Box<Handler + Send + Sync>);
}

/// Chain's hold `BeforeMiddleware`, a `Handler`, and `AfterMiddleware` and are responsible
/// for correctly dispatching a `Request` through them.
///
/// Chain's are handlers, and most of their work is done in the call method of their
/// `Handler` implementation.
pub trait Chain: Handler {
    /// Create a new Chain from a `Handler`.
    fn new<H: Handler>(H) -> Self;

    // FIXME: Reduce code duplication in these methods, if possible.

    /// Link both a before and after middleware to the chain at once.
    ///
    /// Middleware that have a Before and After piece should have a constructor
    /// which returns both as a tuple, so it can be passed directly to link.
    fn link<B, A>(&mut self, (B, A)) where A: AfterMiddleware, B: BeforeMiddleware;

    /// Link a `BeforeMiddleware` to the Chain.
    fn link_before<B>(&mut self, B) where B: BeforeMiddleware;

    /// Link a `AfterMiddleware` to the Chain.
    fn link_after<A>(&mut self, A) where A: AfterMiddleware;

    /// Wrap the Chain's `Handler` using an AroundMiddleware.
    fn around<A>(&mut self, A) where A: AroundMiddleware;
}

/// The default Chain used in Iron.
///
/// For almost all intents and purposes, this is synonymous with the
/// Chain trait and is the canonical implementation. Chain
/// is left as a trait for future interoperability with other
/// frameworks.
pub struct ChainBuilder {
    befores: Vec<Box<BeforeMiddleware + Send + Sync>>,
    afters: Vec<Box<AfterMiddleware + Send + Sync>>,
    handler: Box<Handler + Send + Sync>
}

impl ChainBuilder {
    /// Construct a new ChainBuilder from a `Handler`.
    pub fn new<H: Handler>(handler: H) -> ChainBuilder {
        ChainBuilder {
            befores: vec![],
            afters: vec![],
            handler: box handler as Box<Handler + Send + Sync>
        }
    }
}

impl Chain for ChainBuilder {
    fn new<H: Handler>(handler: H) -> ChainBuilder {
        ChainBuilder {
            befores: vec![],
            afters: vec![],
            handler: box handler as Box<Handler + Send + Sync>
        }
    }

    fn link<B, A>(&mut self, link: (B, A))
    where A: AfterMiddleware, B: BeforeMiddleware {
        let (before, after) = link;
        self.befores.push(box before as Box<BeforeMiddleware + Send + Sync>);
        self.afters.push(box after as Box<AfterMiddleware + Send + Sync>);
    }

    fn link_before<B>(&mut self, before: B) where B: BeforeMiddleware {
        self.befores.push(box before as Box<BeforeMiddleware + Send + Sync>);
    }

    fn link_after<A>(&mut self, after: A) where A: AfterMiddleware {
        self.afters.push(box after as Box<AfterMiddleware + Send + Sync>);
    }

    fn around<A>(&mut self, mut around: A) where A: AroundMiddleware {
        use std::mem;

        let old = mem::replace(&mut self.handler, box Nop as Box<Handler + Send + Sync>);
        around.with_handler(old);
        self.handler = box around as Box<Handler + Send + Sync>;
    }
}

impl Handler for ChainBuilder {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        let before_result = helpers::run_befores(req, self.befores.as_slice(), None);

        let (res, err) = match before_result {
            Ok(()) => match self.handler.call(req) {
                Ok(res) => (res, None),
                Err(e) => helpers::run_handler_catch(req, e, &self.handler)
            },
            Err(e) => helpers::run_handler_catch(req, e, &self.handler)
        };

        helpers::run_afters(req, res, err, self.afters.as_slice())
    }

    fn catch(&self, req: &mut Request, err: Box<Error + Send>) -> (Response, IronResult<()>) {
        let before_result = helpers::run_befores(req, self.befores.as_slice(), Some(err));

        let (res, err) = match before_result {
            Ok(()) => match self.handler.call(req) {
                Ok(res) => (res, None),
                Err(e) => helpers::run_handler_catch(req, e, &self.handler)
            },
            Err(e) => helpers::run_handler_catch(req, e, &self.handler)
        };

        match helpers::run_afters(req, res, err, self.afters.as_slice()) {
            Ok(res) => (res, Ok(())),
            Err(err) => (Response::status(status::InternalServerError), Err(err))
        }
    }
}

impl Handler for fn(&mut Request) -> IronResult<Response> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        (*self)(req)
    }

    fn catch(&self, _: &mut Request, err: Box<Error + Send>) -> (Response, IronResult<()>) {
        (Response::status(status::InternalServerError), Err(err))
    }
}

pub struct Nop;

impl Handler for Nop {
    fn call(&self, _: &mut Request) -> IronResult<Response> {
        Ok(Response::new())
    }

    fn catch(&self, _: &mut Request, err: Box<Error + Send>) -> (Response, IronResult<()>) {
        (Response::status(status::InternalServerError), Err(err))
    }
}

impl Handler for Box<Handler + Send + Sync> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, req: &mut Request, err: Box<Error + Send>) -> (Response, IronResult<()>) {
        self.catch(req, err)
    }
}

impl Handler for Arc<Box<Handler + Send + Sync>> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, req: &mut Request, err: Box<Error + Send>) -> (Response, IronResult<()>) {
        self.catch(req, err)
    }
}

mod helpers {
    use super::super::{Request, Response, IronResult};
    use super::{AfterMiddleware, BeforeMiddleware, Handler};
    use error::Error;

    pub fn run_befores(req: &mut Request, befores: &[Box<BeforeMiddleware>], err: Option<Box<Error + Send>>) -> IronResult<()> {
        match err {
            Some(mut e) => {
                for (i, before) in befores.iter().enumerate() {
                    match before.catch(req, e) {
                        Ok(_) => return run_befores(req, befores, None),
                        Err(new) => e = new
                    }
                }
                Err(e)
            },

            None => {
                for (i, before) in befores.iter().enumerate() {
                    match before.before(req) {
                        Ok(_) => (),
                        Err(err) => return run_befores(req, befores.slice_from(i), Some(err))
                    }
                }
                Ok(())
            }
        }
    }

    pub fn run_afters(req: &mut Request, mut res: Response, err: Option<Box<Error + Send>>,
                  afters: &[Box<AfterMiddleware>]) -> IronResult<Response> {
        match err {
            Some(mut e) => {
                for (i, after) in afters.iter().enumerate() {
                    match after.catch(req, &mut res, e) {
                        Ok(_) => return run_afters(req, res, None, afters),
                        Err(new) => e = new
                    }
                }
                Err(e)
            },

            None => {
                for (i, after) in afters.iter().enumerate() {
                    match after.after(req, &mut res) {
                        Ok(_) => (),
                        Err(err) => return run_afters(req, res, Some(err), afters.slice_from(i))
                    }
                }
                Ok(res)
            }
        }
    }

    pub fn run_handler_catch(req: &mut Request, err: Box<Error + Send>,
                         handler: &Box<Handler>) -> (Response, Option<Box<Error + Send>>) {
        match handler.catch(req, err) {
            (res, Ok(())) => (res, None),
            (res, Err(e)) => (res, Some(e))
        }
    }
}

<commit_msg>(feat) Convenience impl of Before and After Middleware for bare functions.<commit_after>//! Iron's Middleware and Handler System
//!
//! Iron's Middleware system is best modeled with a diagram.
//!
//! ```ignore
//! [b] = BeforeMiddleware
//! [a] = AfterMiddleware
//! [[h]] = AroundMiddleware
//! [h] = Handler
//! ```
//!
//! With no errors, the flow looks like:
//!
//! ```ignore
//! [b] -> [b] -> [b] -> [[[[h]]]] -> [a] -> [a] -> [a] -> [a]
//! ```
//!
//! A request first travels through all BeforeMiddleware, then a Response is generated
//! by the Handler, which can be an arbitrary nesting of AroundMiddleware, then all AfterMiddleware
//! are called with both the Request and Response. After all AfterMiddleware have been fired,
//! the response is written back to the client.
//!
//! Not all too surprising. Of note is that AfterMiddleware and BeforeMiddleware
//! are completely separate, unlike in many other web frameworks.
//!
//! Iron's flexibility comes into play with its novel approach to error handling, which encourages
//! not just reporting errors, but *handling* them. An error is not meant to be fatal in Iron, but
//! is instead likely to be handled by downstream Middleware. Middleware authors should keep this
//! in mind when designing their APIs.
//!
//! Iron's error propagation and handling scheme is inspired by two primary rules:
//!
//!   * Errors should persist and be propagated along the same route as successes until they are
//!     handled.
//!
//!   * If an error is fully handled, control flow should resume just after the error was thrown
//!     or, if that is not possible flow should resume as close as possible to the origin of the
//!     error.
//!
//! Returning Ok from an IronResult-producing method indicates no error or that a passed-in error
//! has been handled. Err indicates that an error is either being created or propagated.
//!
//! Imagine an Err is returned by a second BeforeMiddleware. Following rule 1, it is propagated
//! to all further BeforeMiddleware by calling their `catch` methods, looking for any that could
//! handle the error. If none can, then the error is propagated to the Handler, which can attempt
//! to handle it through its `catch` method. If the Handler cannot handle the error, then it is
//! propagated to all AfterMiddleware.
//!
//! Following rule 2, if any BeforeMiddleware can handle an error thrown by a previous
//! BeforeMiddleware, the control flow returns to the BeforeMiddleware directly after the
//! BeforeMiddleware that threw the Error.
//!
//! If no BeforeMiddleware can handle a propagated error, but the Handler handles it, then
//! it is no longer possible to go back to BeforeMiddleware, so control-flow resumes with
//! the first AfterMiddleware.
//!
//! If an error is handled in AfterMiddleware, then if the error was generated by a previous
//! AfterMiddleware, control-flow resumes with the AfterMiddleware after the one which threw the
//! error. If the error occurred during or before the Handler, control-flow resumes with the
//! first AfterMiddleware.
//!

use std::sync::Arc;
use error::Error;

use super::{Request, Response, IronResult, status};

/// `Handler`s are responsible for handling requests by creating Responses from Requests.
///
/// By default, bare functions and variants of Chain implement `Handler`.
///
/// `Handler`s are allowed to return errors, and if they do, their `catch` method is called and the
/// error is propagated to `AfterMiddleware`.
pub trait Handler: Send + Sync {
    /// Produce a `Response` from a Request, with the possibility of error.
    ///
    /// If this returns an Err, `catch` is called with the error.
    fn call(&self, &mut Request) -> IronResult<Response>;

    /// If `Handler`'s call method produces an Err, then this method is called
    /// to produce a `Response` and possibly handle the error.
    ///
    /// If the passed-in error is not handled, it should be returned as the second
    /// item in the returned tuple. If it is handled, then `Ok(())` can be returned
    /// instead to indicate that all is good with the Response and the error has
    /// been dealt with.
    fn catch(&self, _: &mut Request, err: Box<Error + Send>) -> (Response, IronResult<()>) {
        (Response::status(status::InternalServerError), Err(err))
    }
}

/// `BeforeMiddleware` are fired before a `Handler` is called inside of a Chain.
///
/// `BeforeMiddleware` are responsible for doing request pre-processing that requires
/// the ability to change control-flow, such as authorization middleware, or for editing
/// the request by modifying the headers.
///
/// `BeforeMiddleware` only have access to the Request, if you need to modify or read a Response,
/// you will need `AfterMiddleware`.
pub trait BeforeMiddleware: Send + Sync {
    /// Do whatever work this middleware should do with a `Request` object.
    ///
    /// An error here is propagated by the containing Chain to, first, this Middleware's
    /// `catch` method, then every subsequent `BeforeMiddleware`'s `catch` methods until one returns
    /// Ok(()) or the Chain's `Handler` is reached, at which point the `Handler`'s `catch` method is
    /// called to produce an error Response.
    fn before(&self, &mut Request) -> IronResult<()>;

    /// Try to `catch` an error thrown by this Middleware or a previous `BeforeMiddleware`.
    ///
    /// Should only return Ok(()) if the error has been completely handled and a Chain
    /// can proceed as normal.
    fn catch(&self, _: &mut Request, err: Box<Error + Send>) -> IronResult<()> {
        Err(err)
    }
}

/// `AfterMiddleware` are fired after a `Handler` is called inside of a Chain.
///
/// `AfterMiddleware` receive both a `Request` and a `Response` and are responsible for doing
/// any response post-processing.
///
/// `AfterMiddleware` should *not* overwrite the contents of a Response. In
/// the common case, a complete response is generated by the Chain's `Handler` and
/// `AfterMiddleware` simply do post-processing of that Response, such as
/// adding headers or logging.
pub trait AfterMiddleware: Send + Sync {
    /// Do whatever work this middleware needs to do with both a `Request` and `Response` objects.
    ///
    /// An error here is propagated by the containing Chain down to this and any later
    /// `AfterMiddleware`'s `catch` methods, which can attempt to handle the error or modify
    /// the `Response` to indicate to a client that something went wrong.
    fn after(&self, &mut Request, &mut Response) -> IronResult<()>;

    /// Try to catch an error thrown by previous `AfterMiddleware`, the `Handler`, or a previous
    /// `BeforeMiddleware`.
    ///
    /// This indicates that the `Response` is abnormal in some way, either because it was
    /// generated by a `Handler`s `catch` method or because a previous `AfterMiddleware`
    /// errored.
    fn catch(&self, _: &mut Request, _: &mut Response, err: Box<Error + Send>) -> IronResult<()> {
        Err(err)
    }
}

/// AroundMiddleware are used to wrap and replace the `Handler` in a Chain.
///
/// AroundMiddleware must themselves be `Handler`s, and can integrate an existing
/// `Handler` through the `with_handler` method, which is called once on insertion
/// into a Chain.
pub trait AroundMiddleware: Handler {
    /// Incorporate another `Handler` into this `AroundMiddleware`.
    ///
    /// Usually this means wrapping the handler and editing the `Request` on the
    /// way in and the `Response` on the way out.
    ///
    /// This is called only once, when an `AroundMiddleware` is added to a `Chain`
    /// using `Chain::around`, it is passed the `Chain`'s current `Handler`.
    fn with_handler(&mut self, handler: Box<Handler + Send + Sync>);
}

/// Chain's hold `BeforeMiddleware`, a `Handler`, and `AfterMiddleware` and are responsible
/// for correctly dispatching a `Request` through them.
///
/// Chain's are handlers, and most of their work is done in the call method of their
/// `Handler` implementation.
pub trait Chain: Handler {
    /// Create a new Chain from a `Handler`.
    fn new<H: Handler>(H) -> Self;

    // FIXME: Reduce code duplication in these methods, if possible.

    /// Link both a before and after middleware to the chain at once.
    ///
    /// Middleware that have a Before and After piece should have a constructor
    /// which returns both as a tuple, so it can be passed directly to link.
    fn link<B, A>(&mut self, (B, A)) where A: AfterMiddleware, B: BeforeMiddleware;

    /// Link a `BeforeMiddleware` to the Chain.
    fn link_before<B>(&mut self, B) where B: BeforeMiddleware;

    /// Link a `AfterMiddleware` to the Chain.
    fn link_after<A>(&mut self, A) where A: AfterMiddleware;

    /// Wrap the Chain's `Handler` using an AroundMiddleware.
    fn around<A>(&mut self, A) where A: AroundMiddleware;
}

/// The default Chain used in Iron.
///
/// For almost all intents and purposes, this is synonymous with the
/// Chain trait and is the canonical implementation. Chain
/// is left as a trait for future interoperability with other
/// frameworks.
pub struct ChainBuilder {
    befores: Vec<Box<BeforeMiddleware + Send + Sync>>,
    afters: Vec<Box<AfterMiddleware + Send + Sync>>,
    handler: Box<Handler + Send + Sync>
}

impl ChainBuilder {
    /// Construct a new ChainBuilder from a `Handler`.
    pub fn new<H: Handler>(handler: H) -> ChainBuilder {
        ChainBuilder {
            befores: vec![],
            afters: vec![],
            handler: box handler as Box<Handler + Send + Sync>
        }
    }
}

impl Chain for ChainBuilder {
    fn new<H: Handler>(handler: H) -> ChainBuilder {
        ChainBuilder {
            befores: vec![],
            afters: vec![],
            handler: box handler as Box<Handler + Send + Sync>
        }
    }

    fn link<B, A>(&mut self, link: (B, A))
    where A: AfterMiddleware, B: BeforeMiddleware {
        let (before, after) = link;
        self.befores.push(box before as Box<BeforeMiddleware + Send + Sync>);
        self.afters.push(box after as Box<AfterMiddleware + Send + Sync>);
    }

    fn link_before<B>(&mut self, before: B) where B: BeforeMiddleware {
        self.befores.push(box before as Box<BeforeMiddleware + Send + Sync>);
    }

    fn link_after<A>(&mut self, after: A) where A: AfterMiddleware {
        self.afters.push(box after as Box<AfterMiddleware + Send + Sync>);
    }

    fn around<A>(&mut self, mut around: A) where A: AroundMiddleware {
        use std::mem;

        let old = mem::replace(&mut self.handler, box Nop as Box<Handler + Send + Sync>);
        around.with_handler(old);
        self.handler = box around as Box<Handler + Send + Sync>;
    }
}

impl Handler for ChainBuilder {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        let before_result = helpers::run_befores(req, self.befores.as_slice(), None);

        let (res, err) = match before_result {
            Ok(()) => match self.handler.call(req) {
                Ok(res) => (res, None),
                Err(e) => helpers::run_handler_catch(req, e, &self.handler)
            },
            Err(e) => helpers::run_handler_catch(req, e, &self.handler)
        };

        helpers::run_afters(req, res, err, self.afters.as_slice())
    }

    fn catch(&self, req: &mut Request, err: Box<Error + Send>) -> (Response, IronResult<()>) {
        let before_result = helpers::run_befores(req, self.befores.as_slice(), Some(err));

        let (res, err) = match before_result {
            Ok(()) => match self.handler.call(req) {
                Ok(res) => (res, None),
                Err(e) => helpers::run_handler_catch(req, e, &self.handler)
            },
            Err(e) => helpers::run_handler_catch(req, e, &self.handler)
        };

        match helpers::run_afters(req, res, err, self.afters.as_slice()) {
            Ok(res) => (res, Ok(())),
            Err(err) => (Response::status(status::InternalServerError), Err(err))
        }
    }
}

impl Handler for fn(&mut Request) -> IronResult<Response> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        (*self)(req)
    }

    fn catch(&self, _: &mut Request, err: Box<Error + Send>) -> (Response, IronResult<()>) {
        (Response::status(status::InternalServerError), Err(err))
    }
}

pub struct Nop;

impl Handler for Nop {
    fn call(&self, _: &mut Request) -> IronResult<Response> {
        Ok(Response::new())
    }

    fn catch(&self, _: &mut Request, err: Box<Error + Send>) -> (Response, IronResult<()>) {
        (Response::status(status::InternalServerError), Err(err))
    }
}

impl Handler for Box<Handler + Send + Sync> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, req: &mut Request, err: Box<Error + Send>) -> (Response, IronResult<()>) {
        self.catch(req, err)
    }
}

impl Handler for Arc<Box<Handler + Send + Sync>> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, req: &mut Request, err: Box<Error + Send>) -> (Response, IronResult<()>) {
        self.catch(req, err)
    }
}

impl BeforeMiddleware for fn(&mut Request) -> IronResult<()> {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        (*self)(req)
    }
}

impl AfterMiddleware for fn(&mut Request, &mut Response) -> IronResult<()> {
    fn after(&self, req: &mut Request, res: &mut Response) -> IronResult<()> {
        (*self)(req, res)
    }
}

mod helpers {
    use super::super::{Request, Response, IronResult};
    use super::{AfterMiddleware, BeforeMiddleware, Handler};
    use error::Error;

    pub fn run_befores(req: &mut Request, befores: &[Box<BeforeMiddleware>], err: Option<Box<Error + Send>>) -> IronResult<()> {
        match err {
            Some(mut e) => {
                for (i, before) in befores.iter().enumerate() {
                    match before.catch(req, e) {
                        Ok(_) => return run_befores(req, befores, None),
                        Err(new) => e = new
                    }
                }
                Err(e)
            },

            None => {
                for (i, before) in befores.iter().enumerate() {
                    match before.before(req) {
                        Ok(_) => (),
                        Err(err) => return run_befores(req, befores.slice_from(i), Some(err))
                    }
                }
                Ok(())
            }
        }
    }

    pub fn run_afters(req: &mut Request, mut res: Response, err: Option<Box<Error + Send>>,
                  afters: &[Box<AfterMiddleware>]) -> IronResult<Response> {
        match err {
            Some(mut e) => {
                for (i, after) in afters.iter().enumerate() {
                    match after.catch(req, &mut res, e) {
                        Ok(_) => return run_afters(req, res, None, afters),
                        Err(new) => e = new
                    }
                }
                Err(e)
            },

            None => {
                for (i, after) in afters.iter().enumerate() {
                    match after.after(req, &mut res) {
                        Ok(_) => (),
                        Err(err) => return run_afters(req, res, Some(err), afters.slice_from(i))
                    }
                }
                Ok(res)
            }
        }
    }

    pub fn run_handler_catch(req: &mut Request, err: Box<Error + Send>,
                         handler: &Box<Handler>) -> (Response, Option<Box<Error + Send>>) {
        match handler.catch(req, err) {
            (res, Ok(())) => (res, None),
            (res, Err(e)) => (res, Some(e))
        }
    }
}

<|endoftext|>


<commit_before>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::path::Path;
use std::result::Result;

use module::todo::TodoModule;

mod todo;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
}

impl ModuleError {
    fn mk(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub type ModuleResult = Result<(), ModuleError>;

pub trait Module {

    fn new(rt : &Runtime) -> Self;
    fn callnames() -> &'static [&'static str];
    fn name(&self) -> &'static str;

    fn execute(&self, rt : &Runtime) -> ModuleResult;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

}

<commit_msg>Add file header types<commit_after>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::path::Path;
use std::result::Result;

use module::todo::TodoModule;

mod todo;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
}

impl ModuleError {
    fn mk(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub type ModuleResult = Result<(), ModuleError>;

pub trait Module {

    fn new(rt : &Runtime) -> Self;
    fn callnames() -> &'static [&'static str];
    fn name(&self) -> &'static str;

    fn execute(&self, rt : &Runtime) -> ModuleResult;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

}

pub mod file {

    pub struct ParserError {
        summary: String,
        parsertext: String,
        index: i32,
        explanation: Option<String>,
    }

    pub mod header {

        pub enum FileHeaderSpec {
            Null,
            Bool,
            Integer,
            UInteger,
            Float,
            Text,
            Key { name: String, value_type: Box<FileHeaderSpec> },
            Array { allowed_types: Box<Vec<FileHeaderSpec>> },
        }

        pub enum FileHeaderData {
            Null,
            Bool(bool),
            Integer(i64),
            UInteger(u64),
            Float(f64),
            Text(String),
            Key { name: String, value: Box<FileHeaderData> },
            Array { values: Box<Vec<FileHeaderData>> },
        }

        pub trait FileHeaderParser {
            fn new(spec: &FileHeaderSpec) -> Self;
            fn read(&self, string: &String) -> Result<FileHeaderData, super::ParserError>;
            fn write(&self, data: &FileHeaderData) -> Result<String, super::ParserError>;
        }

    }

    pub trait FileData {
        fn get_fulltext(&self) -> String;
        fn get_abbrev(&self) -> String;
    }

    pub trait FileParser {
        fn new(header_parser: &header::FileHeaderParser) -> FileParser;
        fn read(&self, string: String) -> (header::FileHeaderData, FileData);
        fn write(&self, hdr: &header::FileHeaderData, data: &FileData) -> Result<String, ParserError>;
    }

}
<|endoftext|>


<commit_before>use std::char;
use std::cell::Cell;

#[derive(Debug)]
pub enum Value {
    Int(String),
    Str(String),
}

#[derive(Debug, PartialEq)]
pub enum TokenType {
    ILLEGAL,
    EOF,
    IDENT,
    INT,
    ASSIGN,
    PLUS,
    MINUS,
    COMMA,
    SEMICOLON,
    LPAREN,
    RPAREN,
    LBRACE,
    RBRACE,
    FUNCTION,
    LET,
}

impl TokenType {
    pub fn from_string(s: String) -> TokenType {
        match s.trim().as_ref() {
            "\n" => TokenType::EOF,
            "=" => TokenType::ASSIGN,
            "(" => TokenType::LPAREN,
            ")" => TokenType::RPAREN,
            "let" => TokenType::LET,
            "+" => TokenType::PLUS,
            "-" => TokenType::MINUS,
            "," => TokenType::COMMA,
            ";" => TokenType::SEMICOLON,
            "{" => TokenType::LBRACE,
            "}" => TokenType::RBRACE,
            "func" => TokenType::FUNCTION,
            c => TokenType::ILLEGAL
        }
    }
}

#[derive(Debug)]
pub struct Token {
    pub token_type: TokenType,
    pub value: Option<Value>,
}

pub struct Lexer {
    input: String,
    position: Cell<usize>,
    read_position: Cell<usize>,
}

impl Lexer {
    pub fn new(input: String) -> Lexer {
        return Lexer {
            input: input,
            position: Cell::new(0),
            read_position: Cell::new(0),
        };
    }

    pub fn read_char(&self) -> char {
        if self.read_position.get() >= self.input.len() {
            return '0';
        } else {
            let c = self.input.chars().nth(self.read_position.get()).unwrap();
            self.position.set(self.read_position.get());
            self.read_position.set(self.read_position.get() + 1);
            return c;
        }
    }

    pub fn next_token(&self) -> Token {
        let c = self.read_char();
        let token_type = TokenType::from_string(c.to_string());
        return Token {
            token_type: token_type,
            value: Some(Value::Str(c.to_string()))
        };
    }

    pub fn peek_char(&self) -> char {
        if self.read_position.get() >= self.input.len() {
            return '0';
        } else {
            return self.input.chars().nth(self.read_position.get()).unwrap();
        }
    }
}

#[test]
fn read_char() {
    let input = String::from("=!");
    let l = &Lexer::new(input);
    assert_eq!('=', l.read_char());
    assert_eq!('!', l.read_char());
    assert_eq!('0', l.read_char());
}

#[test]
fn peek_char() {
    let input = String::from("!=");
    let l = &Lexer::new(input);
    assert_eq!('!', l.peek_char());
    assert_eq!('!', l.peek_char());
}

#[test]
fn next_token() {
    let input = String::from("=()");
    let l = &Lexer::new(input);
    assert_eq!(l.next_token().token_type, TokenType::ASSIGN);
    assert_eq!(l.next_token().token_type, TokenType::LPAREN);
    assert_eq!(l.next_token().token_type, TokenType::RPAREN);
}

#[test]
fn from_string() {
    assert_eq!(TokenType::from_string(String::from("=")), TokenType::ASSIGN);
    assert_eq!(TokenType::from_string(String::from("(")), TokenType::LPAREN);
}
<commit_msg>add code<commit_after>use std::char;
use std::cell::Cell;

#[derive(Debug)]
pub enum Value {
    Int(String),
    Str(String),
}

#[derive(Debug, PartialEq)]
pub enum TokenType {
    ILLEGAL,
    EOF,
    IDENT,
    INT,
    ASSIGN,
    PLUS,
    MINUS,
    COMMA,
    SEMICOLON,
    LPAREN,
    RPAREN,
    LBRACE,
    RBRACE,
    FUNCTION,
    LET,
}

impl TokenType {
    pub fn from_string(s: String) -> TokenType {
        match s.trim().as_ref() {
            "\n" => TokenType::EOF,
            "=" => TokenType::ASSIGN,
            "(" => TokenType::LPAREN,
            ")" => TokenType::RPAREN,
            "let" => TokenType::LET,
            "+" => TokenType::PLUS,
            "-" => TokenType::MINUS,
            "," => TokenType::COMMA,
            ";" => TokenType::SEMICOLON,
            "{" => TokenType::LBRACE,
            "}" => TokenType::RBRACE,
            "func" => TokenType::FUNCTION,
            c => TokenType::ILLEGAL
        }
    }
}

#[derive(Debug)]
pub struct Token {
    pub token_type: TokenType,
    pub value: Option<Value>,
}

pub struct Lexer {
    input: String,
    position: Cell<usize>,
    read_position: Cell<usize>,
}

impl Lexer {
    pub fn new(input: String) -> Lexer {
        return Lexer {
            input: input,
            position: Cell::new(0),
            read_position: Cell::new(0),
        };
    }

    pub fn read_char(&self) -> char {
        if self.read_position.get() >= self.input.len() {
            return '0';
        } else {
            let c = self.input.chars().nth(self.read_position.get()).unwrap();
            self.position.set(self.read_position.get());
            self.read_position.set(self.read_position.get() + 1);
            return c;
        }
    }

    pub fn next_token(&self) -> Token {
        let c = self.read_char();
        let token_type = TokenType::from_string(c.to_string());
        return Token {
            token_type: token_type,
            value: Some(Value::Str(c.to_string()))
        };
    }

    pub fn peek_char(&self) -> char {
        if self.read_position.get() >= self.input.len() {
            return '0';
        } else {
            return self.input.chars().nth(self.read_position.get()).unwrap();
        }
    }

    pub fn read_number(&self) {
        let ch = self.peek_char();
        while is_digit(ch) {
            self.read_char();
        }
        // 途中まで実装
//        return self.input.chars().nth(self.position.get()).unwrap();
    }

    pub fn skip_white_space(&self) {
        let ch = self.peek_char();
        while ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' {
            self.read_char();
        }
    }
}

fn is_letter(ch: char) -> bool {
    return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_'
}

fn is_digit(ch: char) -> bool {
    return '0' <= ch && ch <= '9';
}

#[test]
fn read_char() {
    let input = String::from("=!");
    let l = &Lexer::new(input);
    assert_eq!('=', l.read_char());
    assert_eq!('!', l.read_char());
    assert_eq!('0', l.read_char());
}

#[test]
fn peek_char() {
    let input = String::from("!=");
    let l = &Lexer::new(input);
    assert_eq!('!', l.peek_char());
    assert_eq!('!', l.peek_char());
}

#[test]
fn next_token() {
    let input = String::from("=()");
    let l = &Lexer::new(input);
    assert_eq!(l.next_token().token_type, TokenType::ASSIGN);
    assert_eq!(l.next_token().token_type, TokenType::LPAREN);
    assert_eq!(l.next_token().token_type, TokenType::RPAREN);
}

#[test]
fn from_string() {
    assert_eq!(TokenType::from_string(String::from("=")), TokenType::ASSIGN);
    assert_eq!(TokenType::from_string(String::from("(")), TokenType::LPAREN);
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::marker::PhantomData;
use std::sync::Arc;

use buffer::TypedBuffer;
use descriptor_set::descriptor::DescriptorType;
use descriptor_set::descriptor::DescriptorWrite;

#[macro_export]
macro_rules! pipeline_layout {
    ($($name:ident: { $($field:ident: $ty:ty),* }),*) => {
        use std::sync::Arc;
        use std::vec::IntoIter as VecIntoIter;
        use $crate::OomError;
        use $crate::device::Device;
        use $crate::descriptor_set::descriptor::DescriptorDesc;
        use $crate::descriptor_set::pipeline_layout::PipelineLayout;
        use $crate::descriptor_set::pipeline_layout::PipelineLayoutDesc;
        use $crate::descriptor_set::pipeline_layout::UnsafePipelineLayout;

        pub struct CustomPipeline {
            inner: UnsafePipelineLayout
        }

        impl CustomPipeline {
            #[allow(unsafe_code)]
            pub fn new(device: &Arc<Device>) -> Result<Arc<CustomPipeline>, OomError> {
                let layouts = vec![
                    $(
                        try!($name::build_set_layout(device))
                    ),*
                ];

                let inner = unsafe {
                    try!(UnsafePipelineLayout::new(device, layouts.iter()))
                };

                Ok(Arc::new(CustomPipeline {
                    inner: inner
                }))
            }
        }

        #[allow(unsafe_code)]
        unsafe impl PipelineLayout for CustomPipeline {
            #[inline]
            fn inner_pipeline_layout(&self) -> &UnsafePipelineLayout {
                &self.inner
            }
        }

        #[allow(unsafe_code)]
        unsafe impl PipelineLayoutDesc for CustomPipeline {
            type SetsIter = VecIntoIter<Self::DescIter>;
            type DescIter = VecIntoIter<DescriptorDesc>;

            fn descriptors_desc(&self) -> Self::SetsIter {
                // FIXME:
                vec![].into_iter()
            }
        }

        pipeline_layout!{__inner__ (0) $($name: {$($field: $ty),*}),*}
    };

    (__inner__ ($num:expr) $name:ident: { $($field:ident: $ty:ty),* } $($rest:tt)*) => {
        pub mod $name {
            use std::sync::Arc;
            use super::CustomPipeline;
            use $crate::OomError;
            use $crate::device::Device;
            use $crate::descriptor_set::descriptor::DescriptorDesc;
            use $crate::descriptor_set::descriptor::DescriptorWrite;
            use $crate::descriptor_set::descriptor::ShaderStages;
            use $crate::descriptor_set::descriptor_set::DescriptorPool;
            use $crate::descriptor_set::descriptor_set::DescriptorSet;
            use $crate::descriptor_set::descriptor_set::UnsafeDescriptorSet;
            use $crate::descriptor_set::descriptor_set::UnsafeDescriptorSetLayout;
            use $crate::descriptor_set::pipeline_layout::PipelineLayout;
            use $crate::descriptor_set::pipeline_layout::custom_pipeline_macro::DescriptorMarker;
            use $crate::descriptor_set::pipeline_layout::custom_pipeline_macro::ValidParameter;
            use $crate::descriptor_set::pipeline_layout::custom_pipeline_macro::UniformBuffer;

            pub const SET_NUM: u32 = $num;

            pub struct Descriptors<$($field),*> {
                $(
                    pub $field: $field
                ),*
            }

            impl<$($field: ValidParameter<$ty>),*> Descriptors<$($field),*> {
                pub fn writes(&self) -> Vec<DescriptorWrite> {
                    let mut writes = Vec::new();
                    let mut binding = 0;
                    $(
                        writes.push(self.$field.write(binding));
                        binding += 1;
                    )*
                    writes
                }
            }

            pub struct Set {
                inner: UnsafeDescriptorSet
            }

            impl Set {
                #[inline]
                pub fn new<$($field: ValidParameter<$ty>),*>
                          (pool: &Arc<DescriptorPool>, layout: &Arc<CustomPipeline>,
                           descriptors: &Descriptors<$($field)*>)
                           -> Result<Arc<Set>, OomError>
                {
                    #![allow(unsafe_code)]
                    unsafe {
                        let layout = layout.inner_pipeline_layout().descriptor_set_layout($num).unwrap();
                        let mut set = try!(UnsafeDescriptorSet::uninitialized(pool, layout));
                        set.write(descriptors.writes());
                        Ok(Arc::new(Set { inner: set }))
                    }
                }
            }

            #[allow(unsafe_code)]
            unsafe impl DescriptorSet for Set {
                #[inline]
                fn inner_descriptor_set(&self) -> &UnsafeDescriptorSet {
                    &self.inner
                }
            }

            pub fn build_set_layout(device: &Arc<Device>)
                                    -> Result<Arc<UnsafeDescriptorSetLayout>, OomError>
            {
                let mut descriptors = Vec::new();
                let mut binding = 0;

                $(
                    descriptors.push(DescriptorDesc {
                        binding: binding,
                        ty: <$ty as DescriptorMarker>::descriptor_type(),
                        array_count: 1,                     // TODO:
                        stages: ShaderStages::all(),        // TODO:
                    });

                    binding += 1;
                )*

                UnsafeDescriptorSetLayout::new(device, descriptors.into_iter())
            }
        }

        pipeline_layout!{__inner__ ($num+1) $($rest)*}
    };

    (__inner__ ($num:expr)) => {};
}

pub unsafe trait ValidParameter<Target> {
    fn write(&self, binding: u32) -> DescriptorWrite;
}

pub unsafe trait DescriptorMarker {
    fn descriptor_type() -> DescriptorType;
}

pub struct UniformBuffer<T: ?Sized>(PhantomData<T>);
unsafe impl<T: ?Sized> DescriptorMarker for UniformBuffer<T> {
    #[inline]
    fn descriptor_type() -> DescriptorType {
        DescriptorType::UniformBuffer
    }
}

unsafe impl<'a, B, T: ?Sized + 'static> ValidParameter<UniformBuffer<T>> for &'a Arc<B>
    where B: TypedBuffer<Content = T>
{
    #[inline]
    fn write(&self, binding: u32) -> DescriptorWrite {
        DescriptorWrite::uniform_buffer(binding, *self)
    }
}
<commit_msg>Fix some warnings generated by the pipeline_layout! macro<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::marker::PhantomData;
use std::sync::Arc;

use buffer::TypedBuffer;
use descriptor_set::descriptor::DescriptorType;
use descriptor_set::descriptor::DescriptorWrite;

#[macro_export]
macro_rules! pipeline_layout {
    ($($name:ident: { $($field:ident: $ty:ty),* }),*) => {
        use std::sync::Arc;
        use std::vec::IntoIter as VecIntoIter;
        use $crate::OomError;
        use $crate::device::Device;
        use $crate::descriptor_set::descriptor::DescriptorDesc;
        use $crate::descriptor_set::pipeline_layout::PipelineLayout;
        use $crate::descriptor_set::pipeline_layout::PipelineLayoutDesc;
        use $crate::descriptor_set::pipeline_layout::UnsafePipelineLayout;

        pub struct CustomPipeline {
            inner: UnsafePipelineLayout
        }

        impl CustomPipeline {
            #[allow(unsafe_code)]
            pub fn new(device: &Arc<Device>) -> Result<Arc<CustomPipeline>, OomError> {
                let layouts = vec![
                    $(
                        try!($name::build_set_layout(device))
                    ),*
                ];

                let inner = unsafe {
                    try!(UnsafePipelineLayout::new(device, layouts.iter()))
                };

                Ok(Arc::new(CustomPipeline {
                    inner: inner
                }))
            }
        }

        #[allow(unsafe_code)]
        unsafe impl PipelineLayout for CustomPipeline {
            #[inline]
            fn inner_pipeline_layout(&self) -> &UnsafePipelineLayout {
                &self.inner
            }
        }

        #[allow(unsafe_code)]
        unsafe impl PipelineLayoutDesc for CustomPipeline {
            type SetsIter = VecIntoIter<Self::DescIter>;
            type DescIter = VecIntoIter<DescriptorDesc>;

            fn descriptors_desc(&self) -> Self::SetsIter {
                // FIXME:
                vec![].into_iter()
            }
        }

        pipeline_layout!{__inner__ (0) $($name: {$($field: $ty),*}),*}
    };

    (__inner__ ($num:expr) $name:ident: { $($field:ident: $ty:ty),* } $($rest:tt)*) => {
        pub mod $name {
            use std::sync::Arc;
            use super::CustomPipeline;
            use $crate::OomError;
            use $crate::device::Device;
            use $crate::descriptor_set::descriptor::DescriptorDesc;
            use $crate::descriptor_set::descriptor::DescriptorWrite;
            use $crate::descriptor_set::descriptor::ShaderStages;
            use $crate::descriptor_set::descriptor_set::DescriptorPool;
            use $crate::descriptor_set::descriptor_set::DescriptorSet;
            use $crate::descriptor_set::descriptor_set::UnsafeDescriptorSet;
            use $crate::descriptor_set::descriptor_set::UnsafeDescriptorSetLayout;
            use $crate::descriptor_set::pipeline_layout::PipelineLayout;
            use $crate::descriptor_set::pipeline_layout::custom_pipeline_macro::DescriptorMarker;
            use $crate::descriptor_set::pipeline_layout::custom_pipeline_macro::ValidParameter;
            use $crate::descriptor_set::pipeline_layout::custom_pipeline_macro::UniformBuffer;

            // This constant is part of the API, but Rust sees it as dead code.
            #[allow(dead_code)]
            pub const SET_NUM: u32 = $num;

            #[allow(non_camel_case_types)]
            pub struct Descriptors<$($field),*> {
                $(
                    pub $field: $field
                ),*
            }

            #[allow(non_camel_case_types)]
            #[allow(unused_assignments)]
            impl<$($field: ValidParameter<$ty>),*> Descriptors<$($field),*> {
                pub fn writes(&self) -> Vec<DescriptorWrite> {
                    let mut writes = Vec::new();
                    let mut binding = 0;
                    $(
                        writes.push(self.$field.write(binding));
                        binding += 1;
                    )*
                    writes
                }
            }

            pub struct Set {
                inner: UnsafeDescriptorSet
            }

            impl Set {
                #[inline]
                #[allow(non_camel_case_types)]
                pub fn new<$($field: ValidParameter<$ty>),*>
                          (pool: &Arc<DescriptorPool>, layout: &Arc<CustomPipeline>,
                           descriptors: &Descriptors<$($field)*>)
                           -> Result<Arc<Set>, OomError>
                {
                    #![allow(unsafe_code)]
                    unsafe {
                        let layout = layout.inner_pipeline_layout().descriptor_set_layout($num).unwrap();
                        let mut set = try!(UnsafeDescriptorSet::uninitialized(pool, layout));
                        set.write(descriptors.writes());
                        Ok(Arc::new(Set { inner: set }))
                    }
                }
            }

            #[allow(unsafe_code)]
            unsafe impl DescriptorSet for Set {
                #[inline]
                fn inner_descriptor_set(&self) -> &UnsafeDescriptorSet {
                    &self.inner
                }
            }

            #[allow(unused_assignments)]
            pub fn build_set_layout(device: &Arc<Device>)
                                    -> Result<Arc<UnsafeDescriptorSetLayout>, OomError>
            {
                let mut descriptors = Vec::new();
                let mut binding = 0;

                $(
                    descriptors.push(DescriptorDesc {
                        binding: binding,
                        ty: <$ty as DescriptorMarker>::descriptor_type(),
                        array_count: 1,                     // TODO:
                        stages: ShaderStages::all(),        // TODO:
                    });

                    binding += 1;
                )*

                UnsafeDescriptorSetLayout::new(device, descriptors.into_iter())
            }
        }

        pipeline_layout!{__inner__ ($num+1) $($rest)*}
    };

    (__inner__ ($num:expr)) => {};
}

pub unsafe trait ValidParameter<Target> {
    fn write(&self, binding: u32) -> DescriptorWrite;
}

pub unsafe trait DescriptorMarker {
    fn descriptor_type() -> DescriptorType;
}

pub struct UniformBuffer<T: ?Sized>(PhantomData<T>);
unsafe impl<T: ?Sized> DescriptorMarker for UniformBuffer<T> {
    #[inline]
    fn descriptor_type() -> DescriptorType {
        DescriptorType::UniformBuffer
    }
}

unsafe impl<'a, B, T: ?Sized + 'static> ValidParameter<UniformBuffer<T>> for &'a Arc<B>
    where B: TypedBuffer<Content = T>
{
    #[inline]
    fn write(&self, binding: u32) -> DescriptorWrite {
        DescriptorWrite::uniform_buffer(binding, *self)
    }
}
<|endoftext|>